learn_to_write_a_C2_by_Go
近况:
清明假期第二天、还有些昨天哪些负面情绪😢。很难受,也很累
昨天发现自己在写东西的时候,可以让自己的暂时忽略掉这种负面情绪。
前几天chromos2me分享了一个新的C2框架,然后就想到了去年年底给chromos2me说过的要写一个极其简单的C2来着。 一直没写来着,今天趁机写了顺便放松一下自己吧。。。。。 😁
🔍什么是C2?
C2即Command and Control
C2服务器的概念基于命令和控制模型。攻击者扮演指挥官的角色,而受感染的设备则充当实现攻击者恶意命令的棋子
C2服务器充当攻击者和受感染设备之间通信的桥梁。出金各方之间的双向通信以及数据的传输
远控木马RAT
RAT(Remote Access Trojan)是攻击者用来在受感染的计算机上远程执行操作的工具。
🔍什么是RPC?
RPC(Remote Procedure Call) 远程过程调用:
它是一种计算机通信协议。 允许程序在一个计算机上面调用另一个函数
从本地函数调用来说,我们在程序中调用一个函数。比如: add(2,3)
,程序会跳转到add()
函数的定义去执行,然后返回结果。这个过程发生在我们自己的计算机上,也是你的程序内部
而远程过程调用则是我们像平时那样调用函数一样去调用它。它会自动将请求发送给远程服务器。执行之后返回结果。 这个观察没有发生在我们自己的计算机上面。
🔍什么是gRPC
gRPC是Google开发的一个现代化的RPC框架。是一个
:white_check_mark: “一个更快、更强、更智能的RPC工具“。 😊
特性 | gRPC |
---|---|
🔄 通信协议 | 用的是 HTTP/2 |
📦 数据格式 | 用的是 Protocol Buffers(protobuf) |
🧠 多语言支持 | 支持 Python、Go、Java、C++ 等十几种语言 |
🚰 支持流式通信 | 不只是请求-响应,还可以实时双向传输数据 |
🛡 安全 & 验证 | 内建支持 TLS,加密传输 |
🎯代码
项目结构
1 | C2_by_Yliken_in_20250405 |
📌定义和构建gRPC API
代码
1 | syntax = "proto3"; //指定使用Protocol Buffers的版本3语法 |
message
名称以及他的字段名称可以随便取、Protobuf不强制要求具体名称。但是message
的的每一个字段必须分配一个唯一的数字。这些数字用于在序列化后的二进制数据中标识字段。而不是字段的值 同时这也是下面这个问题的答案
为什么字段
In
和Out
的数据类型是字符串,后面缺跟着数字?答:
- 这些数字不是子弹的值,而是字段的编号。Protobuf使用这些编号来区分消息中的字段。而不是直接使用字段名来区分
- 这些代码只是
.proto
文件的一个模式定义,只描述数据结构,不涉及具体实现或者赋值。实际赋值是在代码中完成的。
Empty
这个消息中不包含任何字段。可以将其理解为null
,即为空.
为什么要这样定义一个message类型呢?
答:
- 事实上,Protobuf不支持直接传递
null
或者空值给RPC方法(比如 :rpc SomeMethod(Null) returns (Null)
。这种写法是错误的)- 因此定义一个空message类型来绕过这种限制
在编写好.proto
文件之后,使用protoc -I . --go_out=. --go-grpc_out=. implant.proto
将.proto
文件转换为Go语言代码
protoc
- 这是
Protocol Buffers
编译器的可执行文件。它负责读取.proto
文件并生成目标语言代码。
- 这是
-I .
-I
是--proto_path
的缩写,表示指定.proto
文件的搜索路径。这里执行搜索路径是.
.
表示当前目录
--go_out=./
--go_out
是一个标志,告诉protoc
生Go语言代码,并指定输出目录./
表示将生成的代码输出到当前目录- 这个选项需要
protoc-gen-go
插件的支持。
--go-grpc_out=.
--go-grpc_out
参数用于指定生成的gRPC代码的输出目录。.
同样表示当前目录- 这个参数会为
.proto
文件中的服务定义生成 gRPC 相关的代码,比如服务的客户端和服务器端的接口。
implant.proto
- 这个是输入文件,也就是要编译的
.proto
文件
- 这个是输入文件,也就是要编译的
命令执行以后会生成一个implant.pb.go
与implant_grpc.pb.go
文件
1 | grpcapi/ |
📌创建服务器
1 | package main |
写这个server.go的时候可能会出现一个无法导入
grpcapi
包中的方法的问题。这是因为
protoc
生成的implant_grpc.pb.go
的package
是__
需要手动将其改成
package grpcapi
implantServer
用于从work
通道中 非阻塞的获取命令。SendOutput
则将命令执行的结果发送到output
通道。RunCommand
将命令发送到work通道,然后在output通道中等待处理结果main
方法主要功能- 初始化 gRPC 服务器和相应的 TCP 监听器
- 注册处理命令的服务(
implantServer
和adminServer
) - 启动服务器并开始接收和处理客户端请求,从而提供命令的获取和执行功能。
📌客户端植入程序
1 | package main |
这段代码实现了一个简单的植入客户端,它可以:
- 持续与远程 C2 服务器保持连接;
- 接收远程发送的命令;
- 在本地执行命令;
- 将输出结果发送回服务器。
📌构建管理组件
client.go也是管理客户端
1 | package main |
因为本文只是编写一个最简单的框架。这个client模块也写的很单一。client只能在运行的时候接收一次命令参数。不是交互形式
💻测试
在您开始测试您的代码之前 请确保您的ip地址以及端口都配置正确
运行server.go
文件之后 ,在受害机器上面运行implant.go
之后
运行 client.go
然后再传入想要执行的命令