Hook
원래 동장을 가로채서, 사용자 정의 동작을 실행하도록 끼워넣는 기법
가장 대표적으로 malloc, alloc이 존재한다.
malloc
glibc 2.23 버전의 malloc 코드이다.
__libc_malloc (size_t bytes)
{
mstate ar_ptr;
void *victim;
void *(*hook) (size_t, const void *)
= atomic_forced_read (__malloc_hook);
if (__builtin_expect (hook != NULL, 0))
return (*hook)(bytes, RETURN_ADDRESS (0));
arena_get (ar_ptr, bytes);
victim = _int_malloc (ar_ptr, bytes);
/* Retry with another arena only if we were able to find a usable arena
before. */
if (!victim && ar_ptr != NULL)
{
LIBC_PROBE (memory_malloc_retry, 1, bytes);
ar_ptr = arena_get_retry (ar_ptr, bytes);
victim = _int_malloc (ar_ptr, bytes);
}
if (ar_ptr != NULL)
(void) mutex_unlock (&ar_ptr->mutex);
assert (!victim || chunk_is_mmapped (mem2chunk (victim)) ||
ar_ptr == arena_for_chunk (mem2chunk (victim)));
return victim;
}
libc_hidden_def (__libc_malloc)
사용자가 malloc(bytes)를 호출하게 되면, 내부적으로 해당 코드인 libc_malloc(bytes)가 호출된다.
이 함수는 적절히 arena를 선택하여 bytes 크기만큼 메모리를 할당해준다.
hook이 설정되어 있게 되면, 실제 메모리 할당이 아니라 사용자 정의 함수가 실행될 수 있다.
이에 따라 디버깅, 로깅, 특정 동작 테스트할 때 사용된다.
RETRUN_ADDRESS(0) : 호출된 함수의 return addr를 가져와 hook에 전달한다.
Q) 왜 이런 기능을 만든걸까?
A) 라이브러리 수준에서 유연성을 높이기 위해 eg) malloc 동작을 유지하며 메모리 요청 정보를 로그에 남기고 싶다
위치
__malloc_hook, __free_hook 등 hook과 관련된 함수들은 대부분 libc에 정의되어있다.
libc.so는 bss, data에 포함된다.
해당 섹션들은 쓰기가 가능하기 때문에 조작될 수 있다.
* Full RELRO여도 쓰기가 가능하다
Hook Overwrite
if (__builtin_expect (hook != NULL, 0))
return (*hook)(bytes, RETURN_ADDRESS (0));
만약, hook을 system 함수로 overwrite한다고 가정해보자
그렇게 된다면, return system(bytes, RETURN_ADDRESS(0));이 실행이 될 것이다.
따라서, malloc('/bin/sh') => return system('/bin/sh')를 실행할 수 있게 된다.
이러한 단덤 때문에 Glivc 2.34버전 이후부터는 hook이 없어지게 되었다.
'Hacking > Pwnable' 카테고리의 다른 글
[Mitigation] RELRO | RELocation Read-Only (0) | 2025.05.15 |
---|---|
[Mitigation] PIE | Position Independent Executable (0) | 2025.05.12 |
[Exploit] Return Oriented Programming (ROP chain) (0) | 2024.09.19 |
[Exploit] Return to Library (0) | 2024.09.06 |
[Mitigation] ASLR (0) | 2024.08.25 |