DLL 인젝션을 통한 지뢰찾기 API 후킹 (Hooking) 구현
- 리버싱/리버싱
- 2020. 3. 22. 23:38
저번 포스팅에서는 지뢰찾기에서 클릭시 발생하는 이벤트핸들러 호출 부분 코드를 후킹해서 모든 지뢰가 표시되는 함수 실행이 되도록 해보았다. 이번에는 클릭 이벤트 핸들러 중간에 호출하는 win32u.dll의 NtUserSetCapture() API를 후킹해보도록 한다.
- 빌드 : VisualStudio 2015
- 환경 : Windows10 x64
후킹이 성공하면 아래와 같이 모든 지뢰가 표시되기 때문에 지뢰들을 피해서 게임을 진행할 수 있다 :)
타겟 API 선정
타겟 API는 win32u.dll의 NtUserSetCapture()로 정했는데, 클릭시 호출되는 클릭 이벤트핸들러를 트레이싱하다보면 마우스의 움직임을 감지하는 SetCapture함수를 호출(내부에서 NtUserSetCapture 호출)하는 것을 볼 수 있다. 이 win32u.dll의 NtUserSetCaptureAPI를 후킹해서 클릭 이벤트가 발생하면 게임 종료 직전에 모든 지뢰를 보여주는 함수 sub_1002F80가 실행되도록 해볼것이다.
참고로 클릭이벤트 함수와 지뢰를 보여주는 함수(sub_1002F80)는 이전 포스팅을 보면 알 수 있지만, 심볼을 못구해서 그냥 노가다로 찾았다.
DLL 인젝션을 통한 코드 후킹 (Code Hooking) 구현
API 후킹 코드 구성
참고로 sub_1002F80는 인자로 0xA를 받기 때문에 push 0xA도 같이 넣어주어야 하고 남는 바이트는 0x90(nop)으로 채워준다. 그리고 아래처럼만 코드를 변경하면 1002F80 함수 호출 후 리턴 시 call edx를 하게 되는데 구성된 인자가 맞지 않아서 세그폴트가 나기 때문에 nop으로 채워주었다. ( 총 12바이트 : [6A 0A 90 90 90 E8 56 FF 2D 8A 90 90] )
페이지 권한 확인
API 후킹을 하려면 코드를 패치해야 하기 때문에 해당 주소 영역에 WRITE 권한이 있어야 하는데 코드 영역이므로 당연하게도 WRITE 권한이 없다. 따라서 VirtualProtect 함수를 사용해 WRITE 권한을 주는 작업이 필요하다.
API 후킹을 수행하는 DLL 코드
DLLMain에서는 DLL이 로딩될 시 CreateThread로 APIHooking 스레드를 실행시킨다. APIHooking은 먼저 후킹이 필요한 12바이트에 대해 VirtualProtect를 사용해서 WRITE 권한을 추가한 후 sub_1002F80이 실행되도록 EP부터 한바이트씩 코드를 변경하게 된다. 그리고 코드를 전부 쓴 후에는 변경한 권한을 원래대로 복구한다.
#include "stdio.h"
#include "windows.h"
DWORD WINAPI APIHooking(LPVOID lParam)
{
HMODULE hMod;
LPVOID TargetAddr;
HANDLE hThread = NULL;
DWORD OldProtect = 0;
// NtUserSetTimer API 주소 구하기
hMod = GetModuleHandle(TEXT("win32u.dll"));
TargetAddr = (LPTHREAD_START_ROUTINE)GetProcAddress(hMod, "NtUserSetCapture");
// 12바이트 권한 PAGE_READWRITE로 변경
VirtualProtect(TargetAddr, 12, PAGE_READWRITE, &OldProtect);
// win32u.NtUserSetCapture API EP 코드 후킹
*((LPBYTE)TargetAddr + 0) = 0x6A;
*((LPBYTE)TargetAddr + 1) = 0x0A;
*((LPBYTE)TargetAddr + 2) = 0x90;
*((LPBYTE)TargetAddr + 3) = 0x90;
*((LPBYTE)TargetAddr + 4) = 0x90;
*((LPBYTE)TargetAddr + 5) = 0xE8;
*((LPBYTE)TargetAddr + 6) = 0x56;
*((LPBYTE)TargetAddr + 7) = 0xFF;
*((LPBYTE)TargetAddr + 8) = 0x2D;
*((LPBYTE)TargetAddr + 9) = 0x8A;
*((LPBYTE)TargetAddr + 10) = 0x90;
*((LPBYTE)TargetAddr + 11) = 0x90;
// 페이지 권한 복원
VirtualProtect(TargetAddr, 12, OldProtect, &OldProtect);
return 0;
}
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
HANDLE hThread = NULL;
switch (fdwReason)
{
case DLL_PROCESS_ATTACH:
hThread = CreateThread(NULL, 0, APIHooking, NULL, 0, NULL);
}
return TRUE;
}
DLL 인젝션 코드
DLL 인젝션 코드는 아래 포스팅에서 제작한 코드와 동일한 코드를 사용했다. 인젝션 관련 내용은 아래 포스팅을 참고하길 바란다.
CreateRemoteThread를 사용한 DLL 인젝션 구현
DLL 인젝션을 사용한 API 후킹 결과
클릭이벤트 함수 내부에서 호출되는 API를 후킹했기 때문에 첫 클릭시 모든 지뢰가 보이게 되고 그상태로 게임을 진행할 수 있게 된다.
'리버싱 > 리버싱' 카테고리의 다른 글
[크래쉬 분석] Access violation - code c0000005 (오디오편집 프로그램) (0) | 2020.03.25 |
---|---|
DLL 인젝션을 통한 지뢰찾기 IAT 후킹 (Hooking) 구현 (4) | 2020.03.24 |
DLL 인젝션을 통한 지뢰찾기 코드 후킹 (Code Hooking) 구현 (2) | 2020.03.21 |
CreateRemoteThread를 사용한 DLL 인젝션 구현 (10) | 2020.03.18 |
닷넷 디컴파일 툴 .Net Reflector, reflexil 추가 및 사용법 (0) | 2020.03.16 |