엄범


https://github.com/umbum/Python/blob/master/exploit/0ctf_babyheap.py


2. Fill에서 Size를 지정할 때, chunk의 size보다 크게 지정할 수 있기 때문에 다음 chunk의 fd를 덮어 쓸 수 있고, 이를 이용해 원하는 곳에 chunk를 만들어 반환하도록 할 수 있다. ( fastbin attack )

1. Allocate로 원하는 곳(execution point)에 chunk를 만든 다음, 2. Fill로 원하는 데이터를 쓴다.


execution point로는 GOT는 못쓰고(FULL RELRO), hooking function pointer인 `` __malloc_hook``을 사용할 수 있다.


execution point addr을 알아내기 위해 leak이 필수적이다.

free'd small bin chunk의 `` fd``를 leak해서 libc_base를 얻어내야 한다. 

그러기 위해서는 small bin chunk와 다른 chunk를 overlap시키고 나서 small bin chunk를 free해야 한다.

small bin chunk의 위치를 모르기 때문에, heap이 `` 00``으로 시작한다는 점과 chunk들의 크기를 이용해 small bin chunk의 위치를 예측하고 fastbin attack을 사용해 fastbin chunk를 overlap해야 한다.

leak한 주소를 기점으로 `` __malloc_hook``의 주소를 알아낸다.

* 어차피 offset으로 접근하는 거니까, libc 주소를 구한 다음 거기에 `` __malloc_hook`` offset을 더해도 된다.

* 테스트 환경에서는 main_arena를 알아내기 위해 ``bash $ find top chunk ptr``을 사용해도 좋다.


그 다음 smallbin의 fd를 overwrite하고 두 번 1. Allocate 해서 `` __malloc_hook`` 근처 size field를 만족하는 적절한 곳에 chunk를 생성하고, one gadget을 가리키도록 3. Fill 하면 one gadget이 실행된다.

* shellcode를 넘기려면 fastbin chunk를 하나 생성하고 거기다 shellcode를 넘긴 후 one gadget 대신 ``c mprotect()``를 가리키도록 해서 chunk가 포함된 page에 `` x``권한을 준 다음, 다시 shellcode를 가리키게 하는 방법을 생각해 볼 수 있지만 파라미터 푸시가 어렵다.


로컬 환경에서 테스트

main : `` 0x55555555511d``

allocated 직후 : `` 0x555555554dd1``


heap : `` 0x555555757000``

fastbin, fastbin, smallbin, fastbin(brk방지) 네 개를 Allocate하고,

smallbin을 free해주면 다음과 같이 `` fd/bk``가 생성된다.

```bash

0x555555757000: 0x0000000000000000      0x0000000000000031

0x555555757010: 0x0000000000000000      0x0000000000000000

0x555555757020: 0x0000000000000000      0x0000000000000000

0x555555757030: 0x0000000000000000      0x0000000000000031

0x555555757040: 0x0000000000000000      0x0000000000000000

0x555555757050: 0x0000000000000000      0x0000000000000000

0x555555757060: 0x0000000000000000      0x0000000000000091

0x555555757070: 0x00007ffff7dd37b8      0x00007ffff7dd37b8

0x555555757080: 0x0000000000000000      0x0000000000000000

0x555555757090: 0x0000000000000000      0x0000000000000000

0x5555557570a0: 0x0000000000000000      0x0000000000000000

0x5555557570b0: 0x0000000000000000      0x0000000000000000

0x5555557570c0: 0x0000000000000000      0x0000000000000000

0x5555557570d0: 0x0000000000000000      0x0000000000000000

0x5555557570e0: 0x0000000000000000      0x0000000000000000

0x5555557570f0: 0x0000000000000090      0x0000000000000030


gdb-peda$ x/4x 0x00007ffff7dd37b8

0x7ffff7dd37b8 <main_arena+88>: 0x00005555557571b0   

```


`` main_arena``를 기점으로 `` fd``를 overwrite할 주소인 `` __malloc_hook``의 근처에 size field로 쓸만한 적당한 곳을 모색한다.

```bash

0x7ffff7dd3730 <__realloc_hook>:        0x00007ffff7a98b40      0x0000000000000000

0x7ffff7dd3740 <__malloc_hook>: 0x0000000000000000      0x0000000000000000


gdb-peda$ x/4x 0x00007ffff7dd372d

0x7ffff7dd372d: 0xfff7a98b40000000      0x000000000000007f

0x7ffff7dd373d: 0x0000000000000000      0x0000000000000000

```

실제로 remote에서 수행할 때는 ``bash 0x7ffff7dd372d`` 의 주소를 특정할 수 없기 때문에

leak한 ``bash <main_arena+88>``의 주소와 ``bash 0x7ffff7dd372d`` 주소의 차이를 계산해두거나, libc base로부터 얼마나 떨어져 있는지 offset을 게산해 두어야 한다.

어차피 나중에 one gadget 사용하기 위해서는 libc base addr이 있어야 하므로 libc base를 기준으로 offset을 구하면

libc base addr : `` 0x00007ffff7a15000``

leak으로 얻는 주소 : libc base addr ``c + 0x3be7b8``

`` __malloc_hook`` 근처 mchunkptr : libc base addr ``c + 0x3be72d``

* ``c malloc()``이 반환하는 주소는 ``c 0x3d``이며 `` __malloc_hook`` 주소는 ``c 0x40``이라는 점 주의.

one_gadget offset : libc base addr ``c + 0xe66bd``



Note) smallbin chunk의 `` fd``를 `` __malloc_hook`` 주소로 변경하고, Allocate해도 chunk가 생성되지 않는다.

smallbin chunk의 size는 `` 0x91``인데 execution point chunk의 size는 `` 0x7f``로 fastbin의 size이기 때문.

따라서 또 다시 fastbin attack을 수행해야 한다. 아니면, 처음부터 `` 71`` size의 fast bin을 small bin chunk와 overlap 해서 추가적인 fastin attack을 수행하지 않도록 하는 방법도 있다.


`` Size : 96``짜리 chunk를 두 개 Allocation하고,

다시 두 개를 Free하여 생성된 `` fd``를 `` __malloc_hook`` 근처 mchunkptr로 덮어 쓴 다음

다시 두 번 Allocation해서 `` __malloc_hook`` 근처 mchunkptr에 chunk를 생성하고

여기에 one_gadget 주소를 Fill 한 다음 [ Fill 할 때 align이 안된 곳에서 부터 쓰기 때문에 주의. ]

Allocation 아무 주소 하면 ``c malloc()``이 호출되면서 hooking function이 동작해 one_gadget이 실행된다.