코드 후킹을 위한 DLL Injector 만들기 (CUI)
#REVERSING#C-FamilyC++ CUI 환경에서 DLL Injection을 구현해 보기
코드 후킹
은 출현한 지 오래되었지만 여전히 지금도 강력한 기법이다. 코드 후킹은 DLL Injection
작업이 선행돼야 가능하다.
인터넷에 DLL 인젝션 툴이 많이 있지만 대부분 게임해킹에 사용되어 백신과 안티치트에 검거되는 편이므로 직접 개인 DLL 인젝터를 만들 수 있어야 된다고 한다. 옛날에 온라인 게임 핵에서 사용하는 주사기가 이 DLL 인젝션에 해당한다.
전체 소스코드는 깃허브에 있으므로 핵심 코드만 정리
Process32First, Process32Next
우선 DLL 인젝션을 할 프로세스의 PID
가 필요한데 CreateToolhelp32Snapshot()
와 Process32First()
그리고 Process32Next()
를 이용하여 프로세스의 PID를 구하는 코드가 위 코드이다.
프로세스의 이름과 확장자 예를 들어 Notepad.exe를 인자로 넘겨주면 해당 프로세스의 PID 값을 반환 시켜주는 함수이다.
CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0) 을 통해서 모든 프로세스에 대한 스냅샷을 생성하고 Process32First() 와 Process32Next() 를 통해서 스냅샷을 기반으로 프로세스를 순회하면서 타켓 프로세스의 PID를 찾는다.
OpenProcess
다음은 인젝션할 프로세스의 제어권을 가져와야 한다. 여기서 사용되는 함수가 OpenProcess
이다. 이 함수는 타켓 프로세스의 PID가 필요한데 위에서 구한 PID를 이용하면 된다.
VirtualAllocEx, WriteProcessMemory
프로세스의 제어권을 가져왔다면 프로세스가 사용하는 메모리 내부에 접근이 가능하다. VirtualAllocEx
는 타 프로세스에 메모리를 할당하는 API이다.
메모리를 할당할 사이즈는 DLL 경로 문자열 길이 정도면 충분하다.
그리고 할당된 공간에 WriteProcessMemory
를 이용하여 DLL 경로를 작성한다.
LoadLibraryW
이제 쓰여진 DLL을 프로세스에 로드하는 작업이 필요하다. Kernel32.dll 속의 LoadLibraryW
함수를 이때 사용한다. 그러나 우리는 LoadLibraryW함수의 주소를 모르기 때문에 GetModuleHandle 를 통해 Kernel32.dll 의 핸들을 얻은 후 GetProcAddress 함수를 이용해서 LoadLibraryW
함수의 주소를 찾는다.
★CreateRemoteThread★
그리고 마지막으로 가장 핵심이라고 생각되는 CreateRemoteThread
를 이용한다. 이 API는 타 프로세스의 메모리에 스레드를 생성할 수 있게 해준다.
타켓 프로세스에 스레드를 생성한 후 위에서 찾은 LoadLibraryW 의 주소를 이용하여 우리의 DLL을 인젝션한다.
실제 작동
실제로 DLL 인젝션이 되는지 확인을 해보자. DLL_Injector.exe의 인자로 NotePad(타켓 프로세스)와 TestDll.dll(주입할 dll)을 인자로 주고 실행하면
우선 NotePad가 실행될 때까지 대기하다가 NotePad가 실행되면 바로 DLL 주입을 한다.
그리고 프로세스 탐색기로 확인해보면 NotePad.exe에 TestDll.dll이 잘 주입된 것을 확인할 수 있었다.