Detours 라이브러리를 이용한 Win32 API - Sleep 호출 가로채기
엄밀히, 가로채기 자체는 이미 Detours 라이브러리에서 모두 해주기 때문에 이 글의 제목은 오히려 "Detours 소개" 라고 하는 것이 더 낫겠습니다. 그럼, 한 단계씩 살펴볼까요? ^^
우선, 다운로드를 받으셔야 합니다. ^^ 다음의 경로에서.
Microsoft Research Detours Package - DetoursExpress.msi (ver 2.1) ; http://research.microsoft.com/research/downloads/Details/d36340fb-4d3c-4ddd-bf5b-1db25d03713d/Details.aspx
보시는 것처럼, "Microsoft Research" 의 어느 팀에서 만든 것으로 보입니다. 오호... 누구보다도 마이크로소프트가 만들었기에 더욱 그 안정성을 믿을 수 있을 것 같습니다.
아쉬운 점이라면, "Express" 버전은 현실적으로 테스트 목적으로만 사용할 수 있을 뿐 상업용으로 사용할 수 있는 라이선스가 아닙니다. 즉, 만약 이를 바탕으로 제품을 개발했다면 "Professional" 버전을 구매하셔야 합니다. (자세한 사항은 "Detours" 에 방문하셔서 "Licensing" 탭에서 조회할 수 있습니다. 미리 말씀드리면... 개인이 구매하기에는 마이 비쌉니다. ^^;)
다운로드 받았으면 설치를 하는데, 저 같은 경우에는 다음의 경로에 설치했습니다. (앞으로의 진행은 기본적으로 다음의 경로를 포함합니다.)
C:\Research\Detours Express 2.1
그리고, 위의 폴더에는 다음과 같은 항목들을 포함합니다.
[그림 1: Detours 내용]
자! 보이시죠? Makefile!
고맙게도, Detours 소스 및 전체 samples 를 한꺼번에 빌드할 수 있는 Makefile 을 제공해 주고 있습니다. 빌드를 위해 도스 명령창을 띄우고 다음과 같이 입력하시면 자동으로 Makefile 이 빌드됩니다.
C:\Research\Detours Express 2.1>nmake
그럼, 폴더가 다음과 같이 생성됩니다.
[그림 2: Makefile 빌드 후]
\bin\ detoured.dll detoured.pdb ...[Samples 빌드 파일]... \include\ detours.h \lib\ detoured.exp detoured.lib detours.lib
끝났습니다. ^^ 이제 간단한 샘플을 하나 골라서 제대로 되는 지 확인을 해볼까요? "간단한" 걸로다가 "/samples/simple" 을 예로 들어보겠습니다. 폴더에는 다음과 같은 파일들이 있습니다.
\samples\simple\ Makefile simple.cpp sleep5.cpp
특이하게도, simple.cpp 하나가 곧 Win32 DLL 로 빌드되는 파일이고, sleep5.cpp 는 "Simple.dll" 을 사용(!)하는 Console 응용 프로그램입니다.
소스를 잠깐 살펴볼까요?
simple.cpp 는 다음과 같이 간단하고,
#include <stdio.h> #include <windows.h> #include "detours.h" static LONG dwSlept = 0; static VOID (WINAPI * TrueSleep)(DWORD dwMilliseconds) = Sleep; VOID WINAPI TimedSleep(DWORD dwMilliseconds) { DWORD dwBeg = GetTickCount(); TrueSleep(dwMilliseconds); DWORD dwEnd = GetTickCount(); InterlockedExchangeAdd(&dwSlept, dwEnd - dwBeg); } BOOL WINAPI DllMain(HINSTANCE hinst, DWORD dwReason, LPVOID reserved) { LONG error; (void)hinst; (void)reserved; if (dwReason == DLL_PROCESS_ATTACH) { ...[중간 생략]... if (error == NO_ERROR) { printf("simple.dll: Detoured Sleep().\n"); } else { printf("simple.dll: Error detouring Sleep(): %d\n", error); } } else if (dwReason == DLL_PROCESS_DETACH) { ...[중간 생략]... printf("simple.dll: Removed Sleep() (result=%d), slept %d ticks.\n", error, dwSlept); fflush(stdout); } return TRUE; }
sleep5.cpp 는 소스를 굳이 생략하지 않아도 될 만큼 다음과 같이 매우 간단합니다.
#include <windows.h> #include <stdio.h> int __cdecl main(int argc, char ** argv) { if (argc == 2) { Sleep(atoi(argv[1]) * 1000); } else { printf("sleep5.exe: Starting.\n"); Sleep(5000); printf("sleep5.exe: Done sleeping.\n"); } return 0; }
물론, 빌드된 결과물은 좀전에 했던 "nmake" 로 인해 "bin" 폴더에 있기 때문에 실행을 해보면 다음과 같이 나옵니다.
D:\workshop\XPaperBin\Research\Detours Express 2.1\bin>sleep5.exe sleep5.exe: Starting. sleep5.exe: Done sleeping.
잉! 바뀐 것이 없넹. ^^; detour 가 제대로 동작하지 않았습니다. 여기서, detour 의 단점(?) 이 하나 발견됩니다. 즉, detour 는 실행시간에 IAT(Import Address Table) 을 바꾸는 기능은 포함하지 않습니다. 그보다, 미리 바꿔놓아야 하는 쪽을 선택했습니다. 그래서, 역시 samples 폴더 중에 하나로 포함되어 있는 setdll 예제를 빌드하면 생성되는 "setdll.exe" 를 이용해서 대상 EXE 파일의 IAT 및 그 EXE 가 참조하고 있는 DLL 들의 IAT 내용을 미리 바꿔 놓아야 합니다. 다음은 그러한 과정을 포함한 sleep5.exe 실행 화면입니다.
C:\workshop\Research\Detours Express 2.1\bin>setdll Usage: setdll [options] binary_files Options: /d:file.dll : Add file.dll binary files /r : Remove extra DLLs from binary files /? : This help screen. C:\workshop\Research\Detours Express 2.1\bin>setdll /d:simple.dll sleep5.exe Adding simple.dll to binary files. sleep5.exe: simple.dll KERNEL32.dll -> KERNEL32.dll C:\workshop\Research\Detours Express 2.1\bin>sleep5.exe simple.dll: Starting. simple.dll: Detoured Sleep(). sleep5.exe: Starting. sleep5.exe: Done sleeping. simple.dll: Removed Sleep() (result=0), slept 5008 ticks. C:\workshop\Research\Detours Express 2.1\bin>
이것으로 설명은 끝이군요. 정리해 보면, 여러분들이 Detours 를 이용해 개발을 하기로 정했다면, API 가로채기를 정의할 DLL 을 하나 만들고, 모든 제품 빌드 후에는 대상 EXE 에 setdll.exe 를 이용하여 IAT 변경을 해줘야 합니다.
마지막으로 Detours 라이브러리 관련해서 몇가지 특이사항들을 정리해 보았습니다.
- 대상 응용 프로그램이 "Windows File Protection" 에 의해서 보호 받는 것이라면 IAT 가 변경된 대상 모듈들은 운영체제에 의해서 다시 복원이 되어집니다. 즉, 일반적인 상황이라면 그런 모듈들에 대해서는 Detours 는 무용지물입니다.
- IAT 변경으로 인해 해당 파일이 변경되기 때문에 "코드 인증" 이 깨집니다. 이것 역시 어쩔 수 없는 문제입니다.
- detours 라이브러리 자체는 static library 이지만, 하는 일 없이 marker 용도로 사용되는 detoured.dll 이 요구됩니다. 이것을 지우는 방법은 소스 코드를 수정하면 되는 데 이에 대해서는 다음의 글을 참고하세요.
Detours 에서 Detoured.dll 제거하기 ; http://www.securityproof.net/zboard/bbs/view.php?id=rv&page=1&sn1=&divpage=1&sn=off&ss=on&sc=on&select_arrange=headnum&desc=asc&no=4
- 현재 (2008년 12월 10) 2.1 버전의 makefile 은 VS.NET 2008 과 함께 설치되는 VC++ 빌드에서는 다음과 같은 오류가 발생합니다.
cl /nologo /Zi /MT /Gm- /W4 /WX /O1 "/I..\..\include" "/I..\include" /Gs /DDETOURS_X86=1 /D_X86_ /Fe..\..\bin\symtest.exe /Fd..\..\bin\symtest.pdb symte st.cpp /link /release /machine:x86 "..\lib\syelog.lib" "..\..\lib\detours.lib" "..\..\lib\detoured.lib" kernel32.lib gdi32.lib user32.lib shell32.lib /subsys tem:console /incremental:no /fixed:no ..\..\bin\target.lib symtest.cpp symtest.cpp(270) : error C2664: 'BOOL (HANDLE,PSYM_ENUMMODULES_CALLBACK64,PVOID) ' : cannot convert parameter 2 from 'overloaded-function' to 'PSYM_ENUMMODULES_CALLBACK64' None of the functions with this name in scope match the target type NMAKE : fatal error U1077: '"C:\Program Files\Microsoft Visual Studio 9.0\VC\BIN\cl.EXE"' : return code '0x2' Stop. NMAKE : fatal error U1077: '"C:\Program Files\Microsoft Visual Studio 9.0\VC\BIN\nmake.exe"' : return code '0x2' Stop. NMAKE : fatal error U1077: '"C:\Program Files\Microsoft Visual Studio 9.0\VC\BIN\nmake.exe"' : return code '0x2' Stop.
원인은 헤더 파일이 달라져서 그렇다고 합니다. 다음의 토픽에서 이를 위한 코드 수정 방법을 알려주고 있습니다. (저는 그냥 귀찮아서 ^^; Visual Studio 2005 명령어 창에서 빌드했습니다.)
Cannot make detours.lib.... ; http://social.msdn.microsoft.com/Forums/en-US/vcgeneral/thread/fcb5a809-5404-481f-82c0-40ffa6f58c9b/
출처 : http://www.sysnet.pe.kr/Default.aspx?mode=2&sub=0&pageno=0&detail=1&wid=631