ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

源码探秘:OWASP ZSC的Stack推栈生成器与寄存器使用技巧

源码探秘:OWASP ZSC的Stack推栈生成器与寄存器使用技巧

源码探秘:OWASP ZSC的Stack推栈生成器与寄存器使用技巧

【免费下载链接】ZSCOWASP ZSC - Shellcode/Obfuscate Code Generator https://www.secologist.com/项目地址: https://gitcode.com/gh_mirrors/zs/ZSC

OWASP ZSC 是一款开源的 Shellcode/代码混淆生成器,专为安全研究者和渗透测试人员设计。本文带你深入源码,揭开OWASP ZSCStack推栈生成器的工作奥秘,并解析它在生成 shellcode 时巧妙运用 x86 寄存器的技巧。无论你是刚接触 shellcode 的初学者,还是想借鉴开源实现思路的开发者,这篇源码解析都能帮你快速建立对"汇编指令如何变成机器码"的完整认知。


为什么需要 Stack推栈生成器?

在 x86 架构下,系统调用(如execvechmod)要求把参数放在寄存器里。但 shellcode 最大的痛点是:不能出现\x00空字节,且要尽量短小精悍。字符串如何塞进寄存器?答案就是——通过栈

push指令可以把 4 字节的立即数压入栈顶,随后mov %esp, %ebx就能让寄存器指向这段字符串,这就是经典的"推栈传参"技巧。OWASP ZSC 的核心模块 core/stack.py 里的generate()函数,就是专门把字符串或整数自动翻译成一段"压栈 + 移位"汇编序列的自动化引擎。

探秘核心:generate() 是如何工作的?

打开 core/stack.py,generate(data, register, gtype)接收三个参数:

  • data:要压入栈的字符串或数字
  • register:最终指向栈数据的寄存器,如%ebx%ecx
  • gtype:数据类型,stringint

它的处理逻辑非常清晰:

  1. 类型转换:字符串先经st()反向并转成十六进制(因为 x86 栈是小端序);八进制/十六进制数字则统一转为0x前缀的 hex。
  2. 短数据处理:长度 ≤ 3 字节时,直接push立即数,并用pop+shr(逻辑右移)把高位多余的0x90(NOP 空指令)"洗掉",再压回栈。
  3. 长数据分块:长度 ≥ 4 字节时,把字符串按 8 个十六进制字符(即 4 字节)切成一块,从尾部开始依次 push,保证栈顶正好是字符串开头。如果块数不是整数,就用0x90补齐空位,再配合shr微调,最终只保留有效数据。

举个例子,往%ebx压入短字符串时,生成的典型汇编是这样的:

push $0x6e69622f pop %ebx shr $0x8,%ebx push %ebx

整个过程完全自动化,这也是为什么它能同时支持 Linux、Windows、macOS(OSX)多平台。

寄存器使用技巧:谁该用哪个寄存器?

在 x86 的 Linux 系统调用约定里,eax存放系统调用号,ebx/ecx/edx依次存放第 1~3 个参数。OWASP ZSC 的生成器模板深谙此道,把寄存器分工写进了各个功能模块:

功能模板寄存器用途源码位置
执行文件execve字符串进%ebx,调用号0xb%allib/generator/linux_x86/exec.py
修改权限chmod权限数字进%ecx,文件路径进%ebxlib/generator/linux_x86/chmod.py
执行系统命令整条命令字符串进%ecxlib/generator/linux_x86/system.py
下载并执行拼接后的 wget 命令进%ecxlib/generator/linux_x86/download_execute.py

细看 exec.py 的模板:先用mov $0x46,%al设置setuid调用号,然后mov %esp,%ebxebx指向栈上的文件名,最后mov $0xb,%al; int $0x80触发execve一个寄存器干一件事,参数顺序与内核约定一一对应,这种清晰的分工正是 shellcode 稳定运行的关键。

从汇编到机器码:opcoder 的魔法

stack.generate()产出的只是汇编文本,真正变成\x31\xc0这样的字节码,靠的是 lib/opcoder/linux_x86.py 中的convert()函数。它的实现思路堪称教科书级:

  1. 静态字典替换:维护一张"汇编指令 → 机器码"的映射表,比如xor %eax,%eax31 c0int $0x80cd 80,一次遍历全部替换。
  2. 动态指令编码:对push $0x...mov $0x...xor大立即数等,按指令长度分情况编码。例如push $0x后跟 8 位 hex 时编码为6a xx,16 位时编码为68 xx xx xx xx
  3. 统一收尾:最后调用stack.shellcoder(),把连续字节拼成\x6a\x0f的标准 shellcode 字符串格式。

Windows 平台还有独立的 lib/opcoder/windows_x86.py,额外支持lodscall *%edxmov %fs:0x30(%ecx),%eax(PEB 遍历)等 Windows 特有指令,甚至能处理jne的相对跳转偏移计算。入口统一由 core/opcoder.py 的op()按操作系统分发,扩展新平台只需在lib/opcoder/下新增一个文件。

一条 shellcode 的完整诞生流水线

把整个链路串起来,OWASP ZSC 生成一条 shellcode 的过程是:

用户输入参数 → generator 模板(选定功能 + 寄存器分工) → stack.generate()(字符串/数字 → 压栈汇编) → opcoder.convert()(汇编 → 机器码字节) → shellcoder()(字节 → \x 格式输出)

chmod 777 /tmp/a为例,文件路径会先被 core/stack.py 的推栈逻辑变成一串push $0x...777这个八进制数字则转成0x1ff压入%ecx,最终由 opcoder 输出可直接注入的字节码。整个过程用户无需手写一行汇编,这正是OWASP ZSC 这类 Shellcode 生成器对新手最大的价值。

写在最后:给学习者的三点建议

  1. 先读 core/stack.py:它是整个项目最精巧的模块,读懂了"推栈 + 移位"的思路,你就掌握了 x86 shellcode 最常用的数据装载手法。
  2. 对照 opcoder 字典表:把 lib/opcoder/linux_x86.py 里的静态映射表当作"汇编速查手册",逐条用objdump验证,记忆会非常牢固。
  3. 动手改模板:在 lib/generator/linux_x86/ 下仿照exec.py写一个自己的功能模板,很快你就能独立设计 shellcode 了。

OWASP ZSC 的代码量不大,却把"栈、寄存器、系统调用、机器码"四大主题浓缩在几百行 Python 里。希望这篇源码解析,能成为你探索 Shellcode 世界的一块好用的敲门砖。🚀

【免费下载链接】ZSCOWASP ZSC - Shellcode/Obfuscate Code Generator https://www.secologist.com/项目地址: https://gitcode.com/gh_mirrors/zs/ZSC

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

返回列表