首页 > 其他分享 >golang sliver二次开发自定义命令(格式乱后面再调)

golang sliver二次开发自定义命令(格式乱后面再调)

时间:2024-08-07 11:53:44浏览次数:11  
标签:sliverpb 再调 err protobuf con go 二次开发 sliver 自定义

准备工作
sliver客户端和服务端之间命令的通信采用的grpc, 服务端和和植入程序通信使用的protobuf,所以在开发之前需要了解 grpc和protobuf, 相关文档:
https://jergoo.gitbooks.io/go-grpc-practice-guide/content/chapter2/hello-grpc.html
https://jergoo.gitbooks.io/go-grpc-practice-guide/content/chapter1/protobuf.html
安装grpc protobuf相关工具:
https://jergoo.gitbooks.io/go-grpc-practice-guide/content/chapter1/install.html

定义自定义rpc服务

首先定义proto文件中的服务和相关数据类型:
在文件 sliver/protobuf/rpcpb/services.proto 增加PortScan方法:
rpc PortScan(sliverpb.PortScanReq) returns(sliverpb.PortScanResp);

然后在 sliver/protobuf/sliverpb/sliver.proto 增加 PortScan的请求参数和响应:

// 端口扫描请求参数
message PortScanReq {
  string Targets = 1;
  string Ports = 2;
  commonpb.Request Request = 9;
}

// 端口扫描返回数据
message PortScanResp {
  repeated string result = 1;
  commonpb.Response Response = 9;
}

编译proto文件
在 sliver/Makefile 已经有写好的makefile, 直接执行make pb则可以自动重新编译.proto文件

如图所示,已经成功生成对应的go代码 sliver/protobuf/rpcpb/services_grpc.pb.go

在server端编写rpc服务go代码
新建文件 sliver/server/rpc/rpc-portscan.go, 写入以下代码:

package rpc

import (
	"context"
	"github.com/bishopfox/sliver/protobuf/commonpb"
	"github.com/bishopfox/sliver/protobuf/sliverpb"
)

func (rpc *Server) PortScan(ctx context.Context, req *sliverpb.PortScanReq) (*sliverpb.PortScanResp, error) {
	resp := &sliverpb.PortScanResp{Response: &commonpb.Response{}}
	err := rpc.GenericHandler(req, resp)
	if err != nil {
		return nil, err
	}
	return resp, nil
}


这时候服务端定义就完成了
添加客户端命令
注意: 客户端和服务端命令是公用的,只需在客户端中定义相应命令即可
在文件 sliver/client/constants/constants.go 增加我们的命令port_scan
然后创建文件夹 sliver/client/command/portscan 新建portscan.go文件,加入以下代码:


package portscan

import (
	"context"
	"fmt"
	"github.com/bishopfox/sliver/client/console"
	"github.com/bishopfox/sliver/protobuf/sliverpb"
	"github.com/desertbit/grumble"
)

func PortScanCmd(ctx *grumble.Context, con *console.SliverConsoleClient) {
	targets := ctx.Args.String("targets")
	ports := ctx.Args.String("ports")
	_, _ = con.Println(fmt.Sprintf("正在扫描 %s, 端口: %s", targets, ports))
	resp, err := con.Rpc.PortScan(context.Background(), &sliverpb.PortScanReq{
		Targets: targets,
		Ports:   ports,
		Request: con.ActiveTarget.Request(ctx),
	})
	if err != nil {
		_, _ = con.PrintErrorf("%s\n", err)
		return
	}
	_, _ = con.Println("端口扫描完成, 结果: ")
	for _, line := range resp.Result {
		_, _ = con.Println(line)
	}
}

然后在 sliver/client/command/commands.go 定义portscan命令


// 自定义端口扫描命令
	con.App.AddCommand(&grumble.Command{
		Name:     consts.PortScanStr,
		Help:     "自定义端口扫描命令",
		LongHelp: help.GetHelpFor([]string{consts.PortScanStr}),
		Flags: func(f *grumble.Flags) {
			f.Int("t", "timeout", defaultTimeout, "command timeout in seconds")
		},
		Args: func(a *grumble.Args) {
			a.String("targets", "待扫描的目标, 例:192.168.1.1,8.8.8.8")
			a.String("ports", "待扫描的端口,例: 80,443,22", grumble.Default("80,443,22"))
		},
		Run: func(ctx *grumble.Context) error {
			_, _ = con.Println()
			portscan.PortScanCmd(ctx, con)
			_, _ = con.Println()
			return nil
		},
		HelpGroup: consts.SliverHelpGroup,
	})

这时候客户端和服务端交互相关代码已经全部编写完毕了,执行make 重新编译客户端和服务端


这时候可以看到portscan命令已经成功加入进去了,但是还没有在植入程序实现具体的端口扫描功能,所以返回 rpc error: code = Unknown desc = unknown message type

在植入程序中实现portscan功能
修改 sliver/protobuf/sliverpb/constants.go 增加消息类型常量,根据植入程序收到的消息类型返回MsgPortScan

创建目录 sliver/implant/sliver/portscan/ 新建port_scan.go文件,代码如下

package portscan

import (
	"fmt"
	"github.com/panjf2000/ants/v2"
	"net"
	"strings"
	"sync"
	"time"
)

type Task struct {
	Ip   string
	Port string
}

func isOpen(ip, port string) bool {
	_, err := net.DialTimeout("tcp", fmt.Sprintf("%v:%v", ip, port), 4*time.Second)
	if err != nil {
		return false
	}
	return true
}

func ScanPort(targets, ports string) []string {
	scanTargets := strings.Split(targets, ",")
	scanPorts := strings.Split(ports, ",")
	var ret []string
	var lock sync.Mutex
	wg := new(sync.WaitGroup)
	defer ants.Release()
	p, _ := ants.NewPoolWithFunc(20, func(param interface{}) {
		defer wg.Done()
		task := param.(Task)
		if isOpen(task.Ip, task.Port) {
			lock.Lock()
			ret = append(ret, fmt.Sprintf("%s:%s", task.Ip, task.Port))
			lock.Unlock()
		}
	})

	defer p.Release()
	for _, target := range scanTargets {
		for _, port := range scanPorts {
			p.Invoke(Task{
				Ip:   target,
				Port: port,
			})
			wg.Add(1)
		}
	}
	wg.Wait()
	return ret

}

然后在 sliver/implant/sliver/handlers/rpc-handlers.go 添加如下代码


// 端口扫描
func portscanHandler(data []byte, resp RPCResponse) {
	sc := &sliverpb.PortScanReq{}
	err := proto.Unmarshal(data, sc)
	if err != nil {
		// {{if .Config.Debug}}
		log.Printf("error decoding message: %v", err)
		// {{end}}
		return
	}
	res := &sliverpb.PortScanResp{}
	res.Result = portscan.ScanPort(sc.Targets, sc.Ports)
	data, err = proto.Marshal(res)

	resp(data, err)
}

如图所示,调用了porscan具体的功能,并将结果通过protobuf序列化并返回给服务端

然后需要将功能注册到对应的操作系统,例如我的功能只能在macos下运行,则需要在对应的文件下注册功能
sliver/implant/sliver/handlers/handlers_操作系统类型.go

标签:sliverpb,再调,err,protobuf,con,go,二次开发,sliver,自定义
From: https://www.cnblogs.com/gatling/p/18346764

相关文章

  • Cython将Numpy数组转为自定义结构体
    技术背景前面我们写过几篇关于Cython的文章,例如Cython计算谐振势、Cython与C语言的结合、Cython调用CUDAKernel函数。Cython有着非常Pythonic的编程范式,又具备着接近于C语言的性能,因此在很多对于性能有要求的Python软件中都会使用到Cython的性能优化。Cython的基本工作流程是,先......
  • 从多个方面了解工作流自定义表单的优势
    进入流程化办公新时代,需要借助低代码技术平台、工作流自定义表单的诸多优势特点,打破信息孤岛,做好各部门之间的沟通协调工作,实现高效率发展。很多大中型企业都想了解工作流自定义表单究竟有什么样的优势和特点,现在,我们通过分析它的优势和特点,来进一步深入了解工作流自定义表单吧。......
  • 数据同步的艺术:在SQL Server中打造自定义同步引擎
    数据同步的艺术:在SQLServer中打造自定义同步引擎在企业级应用中,数据同步是确保数据一致性的关键技术。SQLServer提供了多种数据同步机制,包括事务复制、合并复制和数据仓库等。然而,在特定场景下,我们可能需要实现更灵活的自定义数据同步机制。本文将深入探讨如何在SQLServ......
  • 帝国CMS自定义页面动态设置
    帝国CMS提供灵活的自定义页面功能,允许用户创建和管理动态内容页面。以下步骤介绍如何设置帝国CMS自定义页面动态:1.创建自定义页面在帝国CMS管理后台,导航到"栏目">>"自定义页面">>"添加自定义页面"。输入页面标题和页面内容,然后单击"提交"保存页面。2.定义字段转到"栏目">>"......
  • 记一次 Android 自定义相机拍照奔溃bug事件
    最近在开发一个美颜的相机功能,需要自定义抓取相机回调的数,生成照片并保存到相册,需要自定义保存照片。相机开始使用时没有任何问题,测试拍照几次后突然奔溃,跟踪代码日志发现是图片保存失败,同样的代码,同样的逻辑,正常使用很多次以后才奔溃报错,根据日志找到报错的位置,ContentValue......
  • 织梦dedecms调用文章列表时候判断文章自定义属性
    有时候我们需要通过判断文章的属性来给相应的属性以相应的样式,例如为推荐的文章添加推荐的标志等等。例如以下代码就可以判断出文章是否是推荐和图片这两个属性,并作不同的样式输出:[field:arrayrunphp=&#39;yes&#39;]if(@me[&#39;flag&#39;]==&#39;c,p&#39;)@me=&#39;<em>......
  • wordpress教程栏目给大家介绍自定义wordpress文件上传路径的方法
    自WordPress3.5版本开始,隐藏了后台媒体设置页面的“默认上传路径和文件的完整URL地址”选项,可以通过下面的代码将该选项调出来。将下面的代码添加到当前主题functions.php文件中,就可以调出该选项:if(get_option(&#39;upload_path&#39;)==&#39;wp-content/uploads&#39;||get_op......
  • 在 jupyter Notebook 中导入自定义模块的问题
    假设我们有一个如下的文件结构,#注意:不是实际的目录结构,而是类似的root../tests../src../__init__.pyutils../__init__.pydata.pypipeline.pysqlal../__init__.pysql_alchm.pytest.pyprocess.ipynb......
  • 呆滞料分析报表二开增加自定义字段
     业务背景物料资料添加了自定义字段,在呆滞料分析无法直观看到,同时不能直观看到物料在仓库多久了。 业务需求在呆滞料分析报表显示物料的品牌型号,以及计算物料库龄。 方案设计二开标准产品,添加字段,创建插件继承标准产品插件,重写方法,自定义临时表获取初步查询......
  • linux进程篇总结——实战——自定义shell
        前言:经过过去两章十二篇文章的学习,我们已经知道了进程的基本概念以及进程的控制方法。本篇内容就是使用过去学习的内容自己写一个功能简单的shell外壳程序,也就是我们使用的bash命令行。本篇内容是过去进程知识的集大成者。我们在这个实战程序中,将过去学过的......