[翻译] glibc里的one gadget
字数 1327 2025-08-20 18:18:04
glibc中的one gadget技术详解
一、one gadget概念
one gadget是glibc中调用execve('/bin/sh', NULL, NULL)的一段非常有用的代码片段。在能够控制指令指针(IP/PC)时,使用one gadget可以方便地实现远程代码执行(RCE)。
典型应用场景
- 能够执行任意函数但无法控制第一个参数时
- 无法直接调用
system("sh")的情况 - 需要绕过某些安全限制执行shell时
二、one gadget识别条件
64位系统中的识别条件
- 能够访问到'/bin/sh'字符串
- 调用了exec*系列的函数
- 参数设置符合要求
示例分析(64位)
4526a: mov rax,QWORD PTR [rip+0x37dc47] # 3c2eb8 <_IO_file_jumps@@GLIBC_2.2.5+0x7d8>
45271: lea rdi,[rip+0x146eff] # 18c177 <_libc_intl_domainname@@GLIBC_2.2.5+0x197>
45278: lea rsi,[rsp+0x30]
45278: mov DWORD PTR [rip+0x380219],0x0 # 3c54a0 <__abort_msg@@GLIBC_PRIVATE+0x8c0>
45287: mov DWORD PTR [rip+0x380213],0x0 # 3c54a4 <__abort_msg@@GLIBC_PRIVATE+0x8c4>
45291: mov rdx,QWORD PTR [rax]
45294: call cbbc0 <execve@@GLIBC_2.2.5>
关键点:
rdi = libc_base + 0x18c177指向'/bin/sh'字符串rsi = rsp + 0x30设置第二个参数- 调用
execve函数 - 约束条件:
[rsp + 0x30] == NULL
三、32位与64位差异
主要区别
-
数据访问方式不同
- 64位:使用RIP相对偏移访问数据段
- 32位:使用
[<reg> - 0x??]形式访问只读数据
-
调用约定不同
- 64位:参数通过寄存器传递
- 32位:参数通过栈传递
32位示例分析
3ac69: mov eax,DWORD PTR [esi-0xb8]
3ac6f: add esp,0xc
3ac72: mov DWORD PTR [esi+0x1620],0x0
3ac7c: mov DWORD PTR [esi+0x1624],0x0
3ac86: push DWORD PTR [eax]
3ac88: lea eax,[esp+0x2c]
3ac8c: push eax
3ac8d: lea eax,[esi-0x567d5]
3ac93: push eax
3ac94: call b0670 <execve@@GLIBC_2.0>
关键点:
- 需要特定寄存器(ebx或esi)指向libc的GOT区域
- 参数通过push指令设置
- 栈操作复杂,需要仔细计算偏移
四、one_gadget工具
工具功能
- 自动查找glibc中的one gadget
- 分析并显示使用约束条件
- 支持符号执行分析复杂约束
安装方法
gem install one_gadget
查找策略
- 查找所有访问'/bin/sh'的代码
- 筛选附近调用execve的代码段
- 分析参数设置指令(如
lea rsi, [rsp+0x??]) - 使用符号执行确定约束条件
五、常见one gadget示例
glibc-2.19(64位)
0x4647c execve('/bin/sh', rsp+0x30, environ)
0xe5765 execve('/bin/sh', rsp+0x50, environ)
0xe66bd execve('/bin/sh', rsp+0x70, environ)
glibc-2.23(64位)
0x4526a execve('/bin/sh', rsp+0x30, environ)
0xef6c4 execve('/bin/sh', rsp+0x50, environ)
0xf0567 execve('/bin/sh', rsp+0x70, environ)
glibc-2.23(32位)
0x3ac69 execve('/bin/sh', esp+0x34, environ)
六、符号执行技术
实现原理
- 将寄存器和栈位置视为符号变量
- 模拟指令执行过程
- 跟踪数据流和约束条件
- 解析最终调用的参数形式
示例分析
对于以下汇编:
mov edx, [eax]
lea esi, [edx + 4]
push esi
call func
如果要func的第一个参数为0,约束条件就是[[eax]+4] == 0
七、实际应用建议
- 64位系统:优先使用one gadget,约束条件较简单
- 32位系统:需要确保特定寄存器指向GOT区域
- 多尝试:不同版本的glibc中one gadget位置不同
- 约束验证:使用工具提供的约束条件确保可用性
八、版本差异
不同glibc版本中的one gadget数量:
- glibc-2.23(64位):6个one gadget
- glibc-2.23(32位):3个one gadget
- glibc-2.19(64位):6个one gadget
- glibc-2.19(32位):4个one gadget
九、总结
one gadget技术是漏洞利用中的重要技巧,掌握其原理和使用方法可以:
- 绕过参数控制限制
- 简化ROP链构造
- 提高漏洞利用成功率
- 适应不同环境下的利用场景
建议结合one_gadget工具进行自动化查找和分析,特别是在面对不同版本的glibc时。