Post

(SecuInside 2017) BABYHEAP - realloc(ptr, 0) / UAF

clue
  1. read()에서 변수 크기보다 큰 10byte를 받는다.
  2. -가 들어가 음수가 될 수 있다.
  3. 10byte를 받지만, 1byte만 비교한다. ==> 첫 번째 byte가 0xff를 초과하도록 만들 수 있다.
1
2
3
4
5
6
7
8
9
10
11
babyheap: ELF 64-bit LSB  shared object, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.32, stripped

  

CANARY    : ENABLED
FORTIFY   : ENABLED
NX        : ENABLED
PIE       : ENABLED
RELRO     : disabled

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
0x555555757000: 0x0000000000000000      0x0000000000000021    [description]
0x555555757010: 0x0000000a34333231      0x0000000000000000
0x555555757020: 0x0000000000000000      0x0000000000000021    [team]
0x555555757030: 0x0000555555757010<p\_description>      0x0000000000000010 <# of member>
0x555555757040: 0x0000555555757050<p\_member>           0x0000000000000091 [member\_list]
0x555555757050: 0x00005555557570e0      0x00005555557571b0
...

  

after realloc(ptr, 0);

  

0x555555757000: 0x0000000000000000      0x0000000000000021
0x555555757010: 0x0000000a34333231      0x0000000000000000
0x555555757020: 0x0000000000000000      0x0000000000000021
0x555555757030: 0x0000555555757010      0x0000000000000010
0x555555757040: 0x0000555555757050      0x0000000000000091
0x555555757050: 0x00007ffff7dd37b8      0x00007ffff7dd37b8
0x555555757060: 0x0000555555757280      0x0000555555757350
...

[0ctf] BABYHEAP 은 이 지점에서 leak을 이용해 execution point인 \_\_malloc\_hook의 offset을 계산하고 여기에 chunk를 할당하기 위해 fastbin attack을 사용했지만, 이 문제는 fastbin attack을 사용할 필요가 없는게, 그냥 [member\_list] size만 맞춰주면 chunk를 다시 할당 할 수있어 member의 위치를 조작할 수 있고, member의 description을 설정하는 메뉴를 이용해 해당 위치에 값을 그냥 쓸 수 있어 더 간단하다.

leak

#1 vulnerability을 사용하는 방법
  1. [member\_list]free()하기 위해 vuln사용.
  2. 그 자리에 chunk를 할당하기 위해 1. Create team을 이용하며 [description]이 그 자리에 할당된다.
  3. [description]을 할당하는 과정에서 문자열을 입력해야 하지만 read()로 받으니까 개행문자 신경 안써도 되며, 개행문자가 같이 들어간다고 하더라도 null 만날 때 까지 출력하는 함수를 사용하기 때문에 상관없다.
#2 vulnerability를 사용하지 않는 방법
  1. memberfree()하기 위해 2. Delete member를 사용. 이 때 member는 top chunk가 아니어야 함!
  2. 그 다음 과정은 크기만 member의 크기인 0xc8로 맞춰주고 위와 같이 1. Create team을 사용해도 좋고, 어차피 member를 다시 할당하는 거니까 그냥 1. Add member를 사용해도 좋다.

execution point , executed code

#1 __malloc_hook , one_gadget
1
2
3
4
gdb-peda$ x/4x 0x7ffff7dd37b8 -88 -0x20
0x7ffff7dd3740 <\_\_malloc\_hook>: 0x0000000000000000

no RELRO라서 .fini\_array로 잡아도 되는데, Entry point leak하기가 애매해서… 그냥 fd/bk leak으로 구할 수 있는 \_\_malloc\_hook을 사용. 물론 \_\_free\_hook을 사용해도 된다.

1
2
3
4
$ ./find \_\_malloc\_hook 740
ubuntu-trusty-amd64-libc6 (id libc6\_2.19-0ubuntu6.13\_amd64)

찾아낸 libc로 one_gadget 찾아 exploit.

#2 __free_hook, system

member의 desc에 "/bin/sh"넘겨서 system("/bin/sh")가 되도록 하는 방법.

https://github.com/umbum/pwn/blob/master/exploit/secu_babyheap.py

This post is licensed under CC BY 4.0 by the author.