IT/Wargame

[System Hacking] fho ㅡ Hook overwrite

kykyky 2024. 5. 17. 14:50

Hook Overwrite란

 

malloc, free, realloc 함수는 각각 훅 변수가 존재하며,

이 함수들은 시작할 때 해당 훅 변수가 존재하는지 검사하고, 존재하면 이를 호출한다.

이때, 이 변수들은 libc bss 섹션에 위치하여 쓰기 가능하므로, 실행 중에 덮어쓰는 것이 가능하며,

이에 성공하면, malloc/free/realloc 함수를 호출할 때 조작되어버린 훅을 호출하여, 조작된 주소로 jump하게 되므로, 실행 흐름이 조작되는 것이다.

게다가, 훅을 실행할 때는 기존 malloc/free/realloc 함수에 전달한 인자를 같이 전달해 주기 때문에,   

예를 들어 __malloc_hook를 system 함수의 주소로 덮고, malloc(“/bin/sh”) 을 호출하면,

"/bin/sh"이 system 함수로 전달되어, system("/bin/sh")이 실행되고 셸 획득이 가능하다.

 

 

Hook Overwrite 실습

 

vulnerable program 소스 코드

 

 

exploit 과정

✅1. libc의 base address 구하기

 

gdb의 backtrace를 통해, main 함수의 return address를 확인해 보자.

 

main의 return address는 #1의 0x00007ffff7a03c87이다.

 

이 주소의 어셈블리를 확인해보니

__libc_start_main 함수의 +231 임을 알수 있다.

 

이 함수는 libc에 포함돼있으므로, 

이 함수의 주소 (0x00007ffff7a03c87)로부터 231과 이 함수의 libc에서의 offset을 빼면, 

libc의 base address를 알 수 있다.

 

이 함수의 offset을 확인하기 위해, readelf에서 "__libc_start_main@"을 찾자.

offset = 0x21ba0임을 알 수 있다.

 

결론적으로, libc의 base address는

0x00007ffff7a03c87 - 231 - 0x21ba0

= 0x7FFFF79E20E7 - 0xe7

= 0x7FFFF79E2000이다.

 

system(), __free_hook, "/bin/sh"의 주소는 libc base address에 각각의 offset을 더해 구하면 되며,

offset은 readelf에서 각각을 검색하여 찾을 수 있다.

 

 

위 과정을 exploit code로 구현해보자.

 

vul program의 line 16~19에서 buffer에 입력받고 이를 print해주므로,

 

이를 이용해

buffer를 통해 return address 직전까지 채우고, 이것이 print되면,

return address 부분까지 leak하여 알아낼 수 있다.

 

다만, return address까지 몇 byte가 필요한지 알려면 스택 프레임을 확인해봐야 한다.

 

read 함수는 rsi에다가 buffer의 주소를 받는다.

그런데 assembly를 확인해보면, rsi에 rbp - 0x40이 전달됐음을 알 수 있다.

그러므로 buffer의 주소는 rbp - 0x40인 것이다.

 

따라서,  rbp 직전까지 0x40바이트, rbp 자리를 채우는 0x8바이트 ㅡ 총합 0x48바이트를 주면, return address 직전까지 찬다.

 

아래는 buffer overflow를 통한 leak이 일어난 모습이다.

 

여기서 __libc_start_main의 주소와 231을 빼면, libc의 base address가 나올 것이다.

 

system(), __free_hook, "/bin/sh"의 주소는 libc base address에 각각의 offset을 더해 구하면 된다.

 

 

 

✅2. free()의 hook 함수의 주소를 system 함수의 주소로 overwrite

vul program의 line 21~27에서 addr, value 변수에 각각 입력을 받고, *addr에 value를 대입하므로, 

 

이를 이용해 free()의 hook 함수의 주소를 system()의 주소로 overwrite하려면, 

*addr = free()의 hook 함수의 주소 = __free_hook,

그럼 addr = __free_hook의 주소 = free_hook_addr,

value = system()의 주소여야 한다.

 

✅3. Exploit: system("/bin/sh")

vul program에서 line 29~32에서 addr 변수에 입력을 받고, 이것을 전달받은 free 함수를 실행한다.

 

이때, free 함수는 이미 system 함수로 overwrite되었으니,

여기에 전달되는 인자를 "/bin/sh"로 설정해주기만 하면, system("/bin/sh")이 실행되어 공격에 성공하는 것이다.

이를 위해서는 addr 변수에 bin_sh_addr를 넣어주면 된다.

 

 

✅4. 전체 exploit 코드

 

 

exploit 결과