ARTICLE DETAIL

资讯详情

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

深入原理:OWASP ZSC如何将汇编一步步转换为机器码(Opcoder剖析)

深入原理:OWASP ZSC如何将汇编一步步转换为机器码(Opcoder剖析) 深入原理OWASP ZSC如何将汇编一步步转换为机器码Opcoder剖析【免费下载链接】ZSCOWASP ZSC - Shellcode/Obfuscate Code Generator https://www.secologist.com/项目地址: https://gitcode.com/gh_mirrors/zs/ZSC你写过汇编也见过\x31\xc0\x50\x68...这样的机器码但你知道 OWASP ZSC 这个 Shellcode 生成工具是如何在短短几百行代码里完成汇编 → 机器码的魔法转换吗今天我们就撕开Opcoder模块的外衣用最通俗的语言讲清楚它背后的三条核心技巧查表替换、字节序反转、栈魔法。读完你会发现所谓转换机器码本质就是一本写死的翻译词典加一点聪明的小算法。先看懂 ZSC 的流水线Opcoder 站在哪一环在动手剖析之前先认识一下 ZSC 的完整工作流。当你使用这个工具生成 shellcode 时数据会依次经过四个阶段生成器generator—— 根据你选的攻击功能如执行命令、下载文件拼出人类可读的汇编代码编码器encoder—— 对汇编做混淆如 xor、add对抗特征检测Opcoder—— 本文主角把汇编转换成机器码输出器file_out—— 输出为\x格式或 .c 文件入口在 core/run.py 的第 204 行一行代码shellcode_op op(encode_process(encode, shellcode, os, func), os)就把流水线串了起来。而真正的分发器是 core/opcoder.py它根据操作系统linux_x86、windows_x86、osx_x86、windows_x86_64动态加载对应的转换模块。是不是很像一个工厂的分拣员第一条核心技巧查表法一本写死的汇编翻译词典打开 lib/opcoder/linux_x86.py第一眼看到的就是一个巨大的 Python 字典replace_values_static这就是 ZSC 转换机器码的基石。它长这样节选汇编指令对应机器码含义xor %eax,%eax31 c0寄存器清零mov %esp,%ebx89 e3栈指针赋值int $0x80cd 80触发系统调用push %eax50压栈inc %ecx41自增cltd99符号扩展这几十条映射覆盖了生成器能输出的所有固定形态指令。转换逻辑简单粗暴先把每行汇编的空格、空行规整然后遍历字典做字符串替换。convert()函数开头就干这件事for data in replace_values_static: shellcode shellcode.replace(data, replace_values_static[data])一句replace完成翻译这就是查表法的精髓——汇编指令的机器码是固定的查字典即可。✅第二条核心技巧动态指令与字节序反转Little-Endian静态指令靠查表就够了但遇到带参数的指令怎么办比如push $0x41424344机器码还得考虑内存字节序。ZSC 的解法非常巧妙用字符串长度判断参数位数。在linux_x86.py的convert()里你会看到大量类似这样的分支逻辑push $0x...总长 9 或 10 个字符 → 参数是 1 字节直接拼6a前缀总长 15 或 16 个字符 → 参数是 4 字节需要调用stack.st()做小端反转看这段关键代码if len(line) is 16: rep str(68) stack.st(( binascii.a2b_hex((line.rsplit($0x)[1]).encode(latin-1)) ).decode(latin-1))流程拆开就是三步binascii.a2b_hex把十六进制文本转成字节 →stack.st()将字节序列倒序因为 x86 是小端存储→ 拼上68push imm32 的 opcode。stack.st()定义在 core/stack.pydef st(data): return binascii.b2a_hex(data[::-1].encode(latin-1)).decode(latin-1)data[::-1]一个切片就把字节序翻了过来。为什么要反转因为push 0x41424344在内存里要按44 43 42 41存放这个小细节正是新手最容易踩坑的地方。第三条核心技巧栈魔法把字符串变成入栈指令机器码转换只完成了一半。如果你的 shellcode 要执行/bin/sh这个字符串怎么放进程序里ZSC 的做法是用 core/stack.py 的stack.generate()函数把任意字符串切块压栈。原理其实很简单字符串按 8 个字符4 字节为一组每组生成一条push $0x...指令。由于 x86 栈是向下生长、且要求 4 字节对齐ZSC 会用0x90NOP 指令做填充凑足长度后再配合pop和shr指令把多余字节移掉。举个例子stack.generate(/bin/sh, %ebx, string)会生成类似这样的汇编push $0x68732f6e # hs/n push $0x69622f # ib/ 补 0x90 pop %ebx shr $0x8,%ebx push %ebx之后再经过 Opcoder 的查表和动态转换就变成了干净的机器码。这一整套切块 填充 移位的逻辑就是 ZSC 能处理任意长度字符串的秘密武器。彩蛋64 位平台的反向玩法有趣的是lib/opcoder/windows_x86_64.py 的字典方向是反的——键是机器码、值是汇编指令。这是因为 64 位 Windows 的 shellcode 通常直接用机器码编写如调用%gs:0x60解析 PEBZSC 通过这张反向表把现成的机器码还原成可读汇编方便开发者审查和修改然后再按需转换回去。一个模块两种用途这个设计相当聪明。最后一步输出\x格式的 Shellcode所有转换完成后convert()最后一行调用stack.shellcoder()把连续的十六进制串加工成标准的\x转义序列def shellcoder(shellcode): xshellcode \\x for w in shellcode: xshellcode str(w) ... return xshellcode[:-2]它每两个十六进制字符插入一个\x去掉结尾多余的尾巴最终输出你熟悉的\x31\xc0\x50...形态可以直接嵌入 C 语言或 Python 的 exploit 脚本中。总结Opcoder 的完整转化链路回顾整条链OWASP ZSC 转换机器码靠的是三个朴素而高效的思想查表法固定指令用字典直接替换零计算成本长度判定 小端反转动态指令按字符串长度判断参数宽度再反转字节序栈生成 转义输出字符串切块入栈最后统一输出\x格式下次再用 ZSC 生成 shellcode看到屏幕上的\x序列你就知道它背后走过了怎样的旅程——从生成器的汇编模板到编码器的混淆再到 Opcoder 的查表与字节序反转每一步都清晰可循。感兴趣的读者可以直接阅读 lib/opcoder/linux_x86.py、core/opcoder.py 和 core/stack.py 这三个核心文件全程不过几百行代码却完整诠释了汇编到机器码的全部奥秘。【免费下载链接】ZSCOWASP ZSC - Shellcode/Obfuscate Code Generator https://www.secologist.com/项目地址: https://gitcode.com/gh_mirrors/zs/ZSC创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表