1. 개요
HookingAPI의 호출 흐름을 중간에 가로채는 것을 말한다.
Kernel32.dll의 TerminateProcess API를 예시로 들면 정상적인 호출 흐름일 경우 Kernel32.dll의 TerminateProcess -> ntdll.dll의 NtTerminateProcess를 거쳐 시스템 콜을 실행하지만 TerminateProcess API를 후킹할 경우에는 Kernel32.dll의 TerminateProcess -> 후킹 함수 순서로 바뀌게 된다. 이후 후킹 함수에서 일정 처리 후 원래의 API를 호출한다.
주로 다른 프로세스의 API 호출을 가로채는 것이 목적이므로 후킹 DLL 파일을 대상 프로세스에 로드시키는 프로세스 인젝션도 함께 사용한다.
2. 방식
후킹 방식으로는 IAT, EAT, Code 이렇게 세가지 방식이 존재한다. 어떤 방식을 이용해서 후킹하느냐에 따라 난이도가 달라진다.- IAT (Import Address Table) 수정 - 프로세스는 외부 라이브러리의 API를 호출할 때 IAT라는 테이블을 참조하여 호출하게 되는데 IAT를 수정하여 타켓 함수의 주소를 후킹 함수의 주소로 바꾸는 방법이다. 후킹 방식 중에서 쉬운 방법이나 IAT에 없는 API는 후킹할 수 없다는 단점이 있다. (주로 동적으로 라이브러리를 로드하여 사용할 경우라면 그렇다.)
- EAT (Export Address Table) 수정 - IAT과 다르게 API의 EAT라는 테이블을 수정하는 방식이다.
- Code Patch - 직접 API의 코드를 패치하여 후킹 함수로 이동하도록 수정한다. 이 방식은 가장 강력한 방식이지만 코드 자체를 수정하므로 어셈블리어에 어느 정도 알고 있어야 하기에 난이도가 높고 CPU에 따라 잘 작동하지 않을 수 있다.[1]
만약 후킹 함수에서 원래 함수를 호출하려면 후킹 전 원래 함수의 주소를 구해야 한다. 단 Code Patch의 경우 패치 전 코드를 미리 저장해놓았다가 원래 함수를 호출해야할 상황이 되면 이를 이용하여 일시적으로 수정한 코드를 원래 코드로 되돌리고(언후킹) 원래 함수를 호출한 다음 다시 후킹하는 방식을 사용해야 한다.
[1] 예를 들어 32비트에서 후킹하는 방식을 64비트에서 그대로 사용하면 API 호출 시 오류가 발생하여 프로그램이 그대로 꺼진다.