32장은 실행중인 프로세스의 IAT를 변경하여 API를 후킹하는 방식을 설명한다.
DLL의 함수들은 함수의 간접적으로 호출된다. 위 그림에서는 user32.dll의 SetWindowTextW 함수를 호출하는 장면이다. CALL DWORD PTR DS:[01001110]을 실행하고, 주소 01001110에는 user32.dll 내부의 SetWindowTextW 함수의 주소인 7E42960E가 저장되어있다.
프로세스 실행중 동적으로 IAT를 변경하여 간단하게 함수를 후킹할 수 있다. 후킹하려는 함수를 가리키는 곳(위에서는 01001110)에 저장된 함수의 주소를 우리가 새로 만든 DLL의 후킹용 함수로 변경하면 된다.
예제 소스
이 DLL은 계산기의 결과창에 출력되는 숫자를 변경한다. 변경된 숫자는 원본 숫자의 모든 자리의 수에 1을 더한 값이다.(1->2, ... 8->9, 9->0) 숫자를 출력하는 함수가 SetWindowTextW이기 때문에 이 함수를 후킹하는 것이 목적이다.
위의 예제는 3개의 함수로 구성되어있다.
main 함수는 user32.dll의 SetWindowTextW 함수의 주소를 가져오고, IAT를 변경하는 hook_iat 함수를 호출한다.
MySetWindowTextW 함수는 후킹되는 함수인 SetWindowTextW 함수 대신 실행되고, 자신의 코드를 실행한 후 SetWindowTextW 함수를 실행한다. 이 함수는 인자로 전달된 숫자의 모든 자리에 1을 더한다.
hook_iat 함수가 API 호출시 참조하는 곳을 변경한다. 이 함수가 IAT 후킹을 하기 위해 필요한 함수이다.
hook_iat 함수의 작동 방식은 아래와 같다.
프로세스에서 PIMAGE_IMPORT_DESCRIPTOR의 위치를 찾는다.
그중에서 user32.dll에 해당하는 것을 찾는다.
PIMAGE_THUNK_DATA를 찾는다.
PIMAGE_THUNK_DATA에서 SetWindowTextW의 주소가 저장된 곳을 찾는다.
그곳의 값을 새로운 함수인 MySetWindowTextW의 주소로 변경한다.
GetModuleHandle 함수로프로세스의 핸들을 가져온다. 인자로 NULL을 전달하면 함수를 실행한 프로세스의 핸들을 가져온다. 따라서 DLL이 인젝션된 후 실행되면 대상 프로세스의 핸들을 가져오게 된다.
46번 줄에서 pAddr은 프로세스의 ImageBase를 가진다.
48번 줄에서 60(0x3C)바이트 를 더해서 pAddr은 NT 헤더를 가리킨다.
50번 줄에서 dwRVA는 IMPORT TABLE의 위치(RVA)를 가리킨다.
52번 줄에서 최종적으로 pImportDesc가 IMPORT TABLE을 가리킨다.
2. user32.dll을 찾는다.
테이블의 각 원소를 hook_iat의 인자로 받은 user32.dll(szDllName)와 비교하여 user32.dll의 IID를 찾는다.
3. PIMAGE_THUNK_DATA를 찾는다.
59번 줄의 연산으로 인해 pThunk에 user32.dll의 IAT가 저장된다.
4. SetWindowTextW의 주소가 저장된 곳을 찾는다.
pfnOrg는 hook_iat의 인자로서 후킹하려는 함수의 주소가 저장되어있다. 이경우 SetWindowTextW가 저장되어있다.
5. 후킹하려는 함수의 주소를 새로운 함수의 주소로 변경한다.
71번 줄에서 IAT를 변경한다. 함수의 주소를 새로운 함수의 주소로 변경한다. 이를 위해서는 66번 줄처럼 VirtualProtect 함수를 사용하여 수정하려는 곳의 속성을 쓰기 가능하도록 변경한다. 변경 이후에는 73번 줄처럼 원래대로 복구한다.
DLL 인젝션을 실행하면 아래와 같은 결과를 볼 수 있다.
'리버싱핵심원리' 카테고리의 다른 글
Reverse Engineering Chap 3-6 (0) | 2016.01.27 |
---|---|
Reverse Engineering Chap 33 (0) | 2016.01.27 |
Reverse Engineering Chap 28 (0) | 2016.01.24 |
Reverse Engineering Chap 25~26 (0) | 2016.01.20 |
Reverse Engineering Chap 24 (0) | 2016.01.20 |