_hook Overwrite
c 표준 라이브러리에서는 malloc, realloc, free와 같은 함수들의 동작을 수정할 수 있도록 __malloc_hook, __realloc_hook, __free_hook과 같은 변수를 제공합니다. 이러한 변수에 후킹 함수의 주소가 저장되어 있으면 함수가 호출될 때 기존의 함수가 아니라 후킹 함수가 호출됩니다.
__int64 __fastcall malloc(__int64 a1, __int64 a2, __int64 a3)
{
if ( _malloc_hook )
return _malloc_hook(a1, retaddr);
이런 후킹 변수들은 라이브러리의 쓰기 가능한 영역에 존재하기 때문에 후킹 변수를 사용하는 함수가 있다면 익스플로잇 과정에서 이를 실행 흐름을 조작하는 데 사용할 수 있습니다.
hook1.c
// gcc -o hook1 hook1.c
#include <stdio.h>
#include <malloc.h>
int main()
{
__malloc_hook = 0x41414141;
malloc(1);
}
hook1.c는 __malloc_hook을 0x41414141 값으로 덮어쓰고 malloc 함수를 호출하는 코드입니다.
gdb로 run을 하고 rip 값을 확인하면 0x41414141 값이 들어가 있습니다.
__malloc_hook 변수를 덮어씀으로써 malloc 함수가 호출될 때 pc가 0x41414141로 바뀐 것을 확인할 수 있습니다.
__malloc_hook, __realloc_hook, __free_hook과 같은 훅 변수들은 c code 상에서 지정하지 않는 한 기본값이 NULL로 되어있습니다. 그래서 익스플로잇 과정에서 훅 변수가 overwrite 한 시점 이후부터 훅 변수 값인 함수 or 코드가 호출됩니다.
hook2.c
// gcc -o hook2 hook2.c
#include <stdio.h>
#include <malloc.h>
int main()
{
long int *ptr;
printf("stdout@LIBC addr: %p\n", *&stdout);
for(int i=0; i < 10; i++) {
ptr = (long int *)malloc(1024);
read(0, ptr, 1024-1);
*(long int *)*ptr = *(long int *)(ptr+1);
free(ptr);
}
}
hook2.c는 라이브러리 주소를 출력한 후, 힙 버퍼를 할당하고 입력받아 이를 기반으로 임의 주소 쓰기를 수행하는 코드입니다.
공격자는 라이브러리 내에 존재하는 stdout 포인터를 통해 라이브러리의 베이스 주소를 알아낼 수 있고, 이를 통해
__malloc_hook 과 __free_hook의 주소를 알아낼 수 있습니다. 해당 주소를 알아냈다면 _hook을 덮어씀으로써 다음번 반복에서 malloc 혹은 free 함수가 호출될 때 pc를 조작할 수 있습니다.
__malloc_hook과 __free_hook의 주소 및 오프셋은 gdb를 이용해 알아낼 수 있습니다.
[그림 1-2] 참고하면 __malloc_hook 의 offset은 0xc30, __free_hook의 offset은 0x8e8 입니다.
이를 원샷 가젯으로 덮으로 쉘을 획득할 수 있습니다.
[그림 1-4]는 주어진 stdout 포인터를 통해 라이브러리의 베이스 주소를 구하고 __malloc_hook, 원샷 가젯의 주소를 알아냈습니다. 이후에 주어진 임의 주소 쓰기 취약점을 이용해 __malloc_hook을 원샷 가젯의 주소로 덮어쓰는 코드입니다.
hook2에서 반복문을 통해 malloc이 열 번 호출되기 때문에 덮어쓴 후에 malloc 함수가 호출되면 원샷 가젯의 코드가 실행되어 쉘을 획득할 수 있습니다.
참고
https://coding-factory.tistory.com/671
https://dreamhack.io/forum/qna/694
stdout_offset = lib.symbols['_IO_2_1_stdout_'] -> ['stdout'] 인 줄 알았다..
stdin_offset = lib.symbols['_IO_2_1_stdin_']
'Dreamhack - pwnable' 카테고리의 다른 글
fho (0) | 2023.01.19 |
---|---|
Hook Overwrite (2) (0) | 2023.01.19 |
PIE (Position-Independent Executable) (0) | 2023.01.16 |
RELRO (RELocation Read-Only) (0) | 2023.01.16 |
basic_rop_x86 (ret2main + bss 쓰기) (0) | 2023.01.15 |