Windbg로 Heap 분석하기

Hunjison·2024년 1월 19일

Pwnable

목록 보기
3/3

개인 정리용 글이라, 명령어 위주로만 간단히 작성한다.
NTHeap, LFH(Low Fragmentation Heap)에 대한 정리글이다.

PEB -> Heap 오브젝트

  • dt _PEB @$peb NumberOfHeaps ProcessHeaps: PEB 구조체로부터 힙오브젝트의 개수와 힙오브젝트의 포인터 주소 획득

  • dq 0x00007ffbdd315060: 위에서 보았던 2개 힙오브젝트의 포인터값 확인 가능

  • dt _HEAP 000001e6d73c0000: 첫번째 힙오브젝트(_HEAP 구조) 덤프. 힙오브젝트에 속한 첫번째 메모리 블록의 위치를 FirstEntry 값으로부터 알 수 있음.

  • dt _HEAP_ENTRY 0x000001e6d73c0740: FirstEntry 값을 덤프. 그런데 여기에서 다음 Entry에 대한 정보를 얻을 수가 없는 것을 발견할 수 있다.

HEAP 헤더 인코딩 해제

_HEAP_Entry 는 XOR 인코딩된 상태로 저장되기 때문에, 값을 계산해서 풀어줄 필요가 있다. 즉, 바로 위에서 보았던 _HEAP_UNPACKED_ENTRY 하위에 나열된 값들은 모두 정상이 아니다.

  • dq (_HEAP 구조 + 0x80) L2: _HEAP 구조의 Encoding 필드(0x80) 데이터를 qword로 2개 읽음
    • dd (_HEAP 구조 + 0x50) L2: 32비트 분석할 때, 위와 동일.

  • dq _HEAP_ENTRY L2: _HEAP_ENTRY 주소에서 qword로 2개 읽음

  • 각각 XOR로 계산: 000...0 끼리의 XOR은 의미가 없으니 뒤에 것만 해도 무방. 계삳된 값이 디코딩된 헤더인데, 해당 값을 읽기 위해서 빈 공간에 값을 쓰고 그 값을 읽을 예정이다.

  • dq 000001e6d73c0000 L100: 대충 근처 주소에서 빈 공간을 탐색.

  • eq <빈주소> <값>: 값을 써주고, dq를 통해 값을 확인.

  • dt _HEAP_ENTRY <값>: _HEAP_ENTRY 구조 덤프. 1) 블록의 크기와 2) 이전 블록의 크기를 구할 수 있다. 이 때 1) 2)는 축약된 값으로 실제 값을 알아내야 한다.

  • ?? sizeof(_HEAP_ENTRY): 1) 2)는 각각 여기에서 출력된 값을 곱해야 원래 값이 된다. 64비트 컴퓨터에서는 해당 값이 0x10이고, 1)은 5 * 0x10 = 0x50, 2)는 0x74 * 0x10 = 0x740이다.

  • 따라서 첫번째 _HEAP_ENTRY 주소였던 0x000001e6d73c0740에서 0x740을 빼면, _HEAP 구조가 나오고, 0x50을 더하면 두번째 _HEAP_ENTRY 주소를 구할 수 있다.

출처

profile
비전공자 출신 화이트햇 해커

0개의 댓글