Self-Improvement

Heap 메모리 구조 (chunk 구조, bins, fd, bk, malloc, free) 본문

리버싱 기초

Heap 메모리 구조 (chunk 구조, bins, fd, bk, malloc, free)

JoGeun 2020. 5. 14. 15:29

https://bpsecblog.wordpress.com/2016/10/06/heap_vuln/

https://linarena.github.io/linux_0x06

https://y0ubat.tistory.com/222


스택과 달리 낮은 주소에서 높은 주소로 할당되어진다.

 

동적메모리 할당할 시 malloc()사용되며 반환값은 eax로 반환된다. eax가 가르키고 있는 주소는 힙영역에서의 데이터 부분이며 -8 주소 값을 할시에 prev_size, size 데이터 값도 확인할 수 있다. ex) x/10x $eax-8

 

buf1 변수를 malloc()하게되면 힙메모리에는 |prev_size size data|로 나타난다. 이 묶음을 chunk라고 불른다.

 

A라는 Chunk의 구조를 보도록 한다.

1. prev_size는 이전 chunk의 크기를 나타내주며 free() 시에 생성 됩니다. 당연히 첫 chunk는 이전 chunk가 없기에 0이 들어가있습니다.

2. size는 현재 chunk의 크기를 담고 있으며 malloc() 시에 생성 됩니다.

3. AMP는 플래그 필드이며 각 플래그는 아래와 같습니다.

 - A : NON_MAIN_ARENA multi thread application에서 각 thread 마다 다른 heap 영역을 사용하는 경우 현재 chunk가 main heap( arena)에 속하는지 여부를 나타냅니다. (main heap = 0 / mmap’d memory = 1)

 - M : IS_MMAPPED chunk 자체가 단일 mmap() 시스템 콜을 통해 할당되었을 때 셋팅 됩니다.

 - P : PREV_INUSE 이전 chunk의 상태를 나타내줍니다. (chunk using = 1 / chunk free = 0)

4. data는 실제로 데이터가 들어가는 영역입니다. 입력값이 들어간다 생각하면 편하겠습니다.

 

Malloc()

실제로 gdb에서 malloc() 후의 chunk를 보도록 한다.

addr=0x804b008은 data의 시작 주소이며 size는 0x18 10진수로 24, flags는 PREV_INUSE로 되어있다.

이번엔 힙 메모리를 확인해 본다.

 

prev_size, size 데이터 값까지 확인할라면 -8을 해줘야한다.

해당 chunk는 첫 chunk 임으로 prev_size는 0으로 채워져 있다.

size는 0x19로 되어있는데 위에서 봤던 0x18로 안되어있다. 이는 flags의 PREV_INUSE 1바이트를 포함해서 0x19로 되어있는 것이다.

그리고는 "AAAAAAA" 데이터가 들어가있다.


Free()

Free()을 수행해주면 Chunk가 아래 사진처럼 변경이 된다. 

기존 prev_size, size는 그대로이며 data 부분에서 fd, bk가 새롭게 생성된다.

fd : (forward pointer) free된 다음 chunk를 가리킵니다.

bk : (backward pointer) free된 이전 chunk를 가리킵니다.

※ Fastbin에서는 single-linked-list 구조라 BK는 쓰여지지 않는다.

 

free(mod2)부터 데이터영역의 4바이트가 FD로 바뀌면서 첫 free한 chunk의 시작주소를 나타내고있다.

 

※ 동적할당 크기에 따라 bin도 달라지며 free할 시의 fd,bk유무도 달라진다

 

다른 블로그에선 UAF 취약점할 시 동일한 크기로 재할당할 시 기존 데이터를 출력한다고 하는데...
free될때 힙 메모리의 데이터 영역 앞 4바이트를 fd로 변경하기 때문에 데이터가 날라갈텐데... 
모가 맞는지 몰르겠다.