exit handler overwrite란?
라이브러리에 aaw가 가능할 때 사용가능한 기법이다.
exit handler를 overwrite 하여 임의 주소 실행이 가능하다.
조건
libc base 필요(fs_base와 initial은 모두 libc에 있음),
최소 2번 이상의 aaw [or] 1번의 aar, 1번의 aaw
fs_base 구하는 법

initial 위치 구하는 법
objdump -D /lib/x86_64-linux-gnu/libc.so.6 | grep "initial"

익스 시나리오
- fs_base + 0x30의 위치에 p64(0) 덮기 or leak 만 해도 된다.
- initial+0x10에 p64(4)을 쓰고, initial+0x18에 호출하고 싶은 함수를 0x11 만큼 rotation left 한 값을 쓴다. 만약 aaw가 2번만 가능하면 1번 과정에서 leak만 한 후에 initial+0x18에 호출하고 싶은 함수' xor '1번에 leak한 값 에다가 rol 0x11을 하여 overwrite한다. initial + 0x20에 인자 주소를 덮는다.
- exit 함수를 실행한다.
- initial+0x18에 mangled 된 _dl_fini 값 leak한다.
- 원래의 _dl_fini의 값을 가지고 연산하여 fs_base + 0x30의 위치에 있는 key 알아낸다.
- 구한 key로 다시 호출하고 싶은 함수의 주소값을 mangling 하고 initial+0x18 에 write, initial + 0x20에 인자 주소를 넣는다.
- exit 함수를 실행한다.
<원리> exit함수 내부의 __run_exit_handler 의 루틴에 initial+0x18 포인터 값을 가져와 demangling을 한다. demangling 과정은 0x11만큼 rotation right를 하고 fs_base+0x30의 값과 xor 한다. 그래서 1번 과정에서 fs_base+0x30 값을 0으로 overwrite하려고 시도하고 만약 aaw가 2번만 가능하다면 leak만 하고 initial+0x18에 xor을 해주면 되는 것이다. (일반적으로 initial+0x18에는 _dl_fini의 주소가 mangling 되어 들어있다) 암튼 그렇게 나온 함수에 initial+0x20을 인자로 하여 실행된다.

rax에 rdx(fs_base)+0x18 에 값을 저장
r13에 rdx(fs_base)+0x20 에 값을 저장
ror rax, 0x11
xor rax, fs_base+0x30
이러면 rax는 최종적으로 함수 주소가 된다. 그리고

r13 값을 rdi에 넣고 call rax를 한다.
막는 법
exit함수로 종료하지 않고 인라인 어셈으로 exit syscall을 하는 방법이 있다. (좀 억지긴 함)
<틀린 부분이 있다면 비난과 욕설을 해주세요>
'Pwnable > Stack' 카테고리의 다른 글
| *ABS* overwrite (0) | 2025.09.16 |
|---|---|
| 로더 overwrite 할 때 가능한 기법 (1) | 2025.08.16 |
| FSOP (1) | 2023.10.23 |
| rtld global (1) | 2023.10.23 |
| __environ을 이용한 스택 주소 leak (1) | 2023.10.23 |