미친해커

[Reversing] Trampoline(Inline) Hooking x86 Step 1 본문

Reversing/Hooking

[Reversing] Trampoline(Inline) Hooking x86 Step 1

미친해커 2022. 4. 27. 14:49
반응형
 

[Reversing] Trampoline(Inline) Hooking x86 Step 0

Trampoline Hooking Trampoline Hooking 이란 타겟 API의 상위 n바이트를 jmp 어셈블리로 패치하여 후킹하는 기법을 말한다. Trampoline Hooking은 x86과 x64에서의 기술 구현 방법이 미세하게 다르다. 그렇기 때..

crazyhacker.tistory.com

저번 포스팅에서 간단히 Trampoline Hooking의 원리에 대해 공부했다. 이번 포스팅부터는 본격적으로 후킹을 하기 위해 사용할 함수들을 알아볼 생각이다.

How to get MessageBoxA address

#include <stdio.h>
#include <windows.h>

int main(int argc, char *argv[])
{
    PVOID pMessageBoxA = (PVOID)GetProcAddress(GetModuleHandleA("user32.dll"), "MessageBoxA");
    
    // IAT에서 주소를 가져옴
    printf("MessageBoxA : 0x%p\n", MessageBoxA);
    
    // GetProcAddress 함수를 이용해 주소를 가져옴
    printf("GetProcAddress MessageBoxA : 0x%p\n", pMessageBoxA);
    
    return 0;
}

main.exe
0.05MB

위 소스코드를 컴파일 해 실행해보면 다음과 같은 결과를 확인할 수 있다.

MessageBoxA : 0x74E00CA0
GetProcAddress MessageBoxA : 0x74E00CA0

이제 위 소스코드를 다음과 같이 변경하고 다시 실행해보자

#include <stdio.h>
#include <windows.h>

int main(int argc, char *argv[])
{
    PVOID pMessageBoxA = (PVOID)GetProcAddress(GetModuleHandleA("user32.dll"), "MessageBoxA");
    
    // GetProcAddress 함수를 이용해 주소를 가져옴
    printf("GetProcAddress MessageBoxA : 0x%p\n", pMessageBoxA);
    
    return 0;
}

main2.exe
0.05MB

이번에는 다음과 같은 결과를 확인할 수 있다.

GetProcAddress MessageBoxA : 0x00000000

왜 이런 경우가 발생할까? GetProcAddress는 HMODULE을 사용해 함수의 주소를 가져오는 함수이다. 하지만 이번에는 함수의 주소를 정상적으로 가져오지 못했다. 위와 같은 결과가 나오는 원인은 GetModuleHandleA 함수에 있다. 먼저 GetProcAddress의 문서를 읽어보면 이렇게 설명되어있다.

 

GetProcAddress function (libloaderapi.h) - Win32 apps

Retrieves the address of an exported function or variable from the specified dynamic-link library (DLL).

docs.microsoft.com

hModule은 함수 또는 변수를 포함하는 DLL 모듈에 대한 핸들이라고 설명되어 있고 LoadLibrary, GetModuleHandle 등의 함수들이 이 핸들은 반환한다고 한다. 우리는 여기서 GetModuleHandle 류의 함수를 사용했다. 이제 해당 함수의 문서를 읽어보자

 

GetModuleHandleA function (libloaderapi.h) - Win32 apps

Retrieves a module handle for the specified module. The module must have been loaded by the calling process.

docs.microsoft.com

lpModuleName으로 로드된 모듈의 이름을 입력받는다.라고 되어있다. 여기서 공부를 좀 한 사람이라면 눈치를 챘을 것이라고 생각한다. 바로 첫 번째 코드는 MessageBoxA를 정적으로 사용했기 때문에 IAT에 user32.dll이 등록되어 있어 프로세스가 실행됐을 때 user32.dll이 로드되었을 것이다. 그렇기에 GetModuleHandleA 함수를 사용했을 때 정상적으로 호출되었지만, 두 번째 코드에서는 MessageBoxA 함수를 사용하지 않았다. 그렇기 때문에 IAT에 user32.dll이 등록되어 있지 않아 프로세스가 실행됐을 때 user32.dll이 로드되지 않았던 것이다. 그래서 GetModuleHandleA 함수가 NULL 반환한 것이며 그로인해 GetProcAddress 역시 NULL을 반환한 것이다.

How to fixed source code?

GetModuleHandleA와 거의 동일한 LoadLibraryA 함수가 존재한다. 해당 함수는 인자로 들어온 DLL이 로드되어 있다면 HMODULE을 반환하고 로드되어 있지 않다면 해당 DLL을 로드하고 HMODULE을 반환한다. 이 함수를 사용하면 해당 문제를 해결할 수 있다.

#include <stdio.h>
#include <windows.h>

int main(int argc, char *argv[])
{
    // GetModuleHandleA 함수로 hModule을 구한다.
    HMODULE hModule = GetModuleHandleA("user32.dll");
    
    // 만약 GetModuleHandleA 함수로 구하지 못하였다면 LoadLibraryA 함수로 DLL을 로드한다.
    if (hModule == NULL)
    	hModule = LoadLibraryA("user32.dll");
    
    // GetProcAddress 함수를 이용해 주소를 가져옴
    PVOID pMessageBoxA = (PVOID)GetProcAddress(hModule, "MessageBoxA");
    
    printf("GetProcAddress MessageBoxA : 0x%p\n", pMessageBoxA);
    
    return 0;
}

main3.exe
0.05MB

이번엔 정상적으로 실행된 것을 확인할 수 있다.

GetProcAddress MessageBoxA : 0x74E00CA0

마무리

이번 포스팅에서는 Trampoline Hooking을 하기위해 해당 함수의 원본(IAT가 아닌) 주소를 구하는 방법을 알아보았다. 다음 포스팅에서는 드디어 Trampoline Hooking의 예제가 나온다.

반응형
Comments