Hooking 후킹 – CreateRemoteThread

CreateRemoteThread

후킹을 위해 제일 많이 애용하는 방법이 바로 CreateRemoteThread일 것이다. CreateRemoteThread는 방법도 쉬울 뿐더러 Dll을 인젝션 오류 없이 진행할 수 있다. 그래서 실제 악성코드나 해킹도구에서도 많이 사용하는 방법이다.

그럼 이 CreateRemoteThread를 이용하는 로더 프로그램을 작성해 보자.

injectiondll.cpp
#include
<stdio.h>#include
<windows.h>#include
<tlhelp32.h>BOOL InjectDll(DWORD PID, char* DllName){

HANDLE h = OpenProcess(PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION | PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_VM_READ, FALSE, PID);

if (h)

{

// LoadLibrary 주소를 얻는다.

LPVOID LoadLibAddr = GetProcAddress(GetModuleHandle(“kernel32.dll”), “LoadLibraryA”);

// 대상 프로세스의 주소 공간안에 공간을 할당 한다.

LPVOID Alloc = VirtualAllocEx(h, NULL, strlen(DllName), MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);

// 할당된 메모리 공간에 기록한다.

WriteProcessMemory(h, Alloc, DllName, strlen(DllName), NULL);

// 대상 프로세스에서 스레드를 실행시킨다.

HANDLE x = CreateRemoteThread(h, NULL, 0, (LPTHREAD_START_ROUTINE)LoadLibAddr, Alloc, 0, NULL);

//지정한 Dll을 인젝션한다.

if( x == NULL )

{

printf(“[ERROR] [%d]!!!\n”, GetLastError());

return FALSE;

}

WaitForSingleObject(x, INFINITE);

printf(“%s Injection Success\n”, DllName);

CloseHandle(x);

CloseHandle(h);

return TRUE;

}

return FALSE;

}

BOOL UninjectDll(DWORD PID, char* DllName)

{

// 현재 실행중인 PID를 확인한다.

HANDLE s = ::CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, PID);

MODULEENTRY32 me32;

memset(&me32, 0, sizeof(MODULEENTRY32));

me32.dwSize = sizeof(MODULEENTRY32);

bool isFound = false;

do

{

isFound = (0 == strcmp(me32.szModule, DllName) || 0 == strcmp(me32.szExePath, DllName));

if (isFound)

{

break;

}

} while (TRUE == Module32Next(s, &me32));

HANDLE h = OpenProcess(PROCESS_ALL_ACCESS, FALSE, PID);

if (h)

{

LPVOID LoadLibAddr = GetProcAddress(GetModuleHandle(“kernel32.dll”), “FreeLibrary”);

//지정한 Dll을 제거한다.

HANDLE x = CreateRemoteThread(h, NULL, 0, (LPTHREAD_START_ROUTINE)LoadLibAddr, me32.modBaseAddr, 0, NULL);

if( x == NULL )

{

printf(“[ERROR] [%d]!!!\n”, GetLastError());

return FALSE;

}

printf(“%s Uninjection Success\n”, DllName);

CloseHandle(x);

CloseHandle(h);

CloseHandle(s);

return TRUE;

}

return FALSE;

}

int main(int argc, char *argv[])

{

if(argc != 4)

{

printf(“Usage : Injectiondll -i/-u <PID> <InjectionDll>\n”);

return 0;

}

if (!strcmp(argv[1],“-i”))

{

//Inject dll을 진행한다.

if(!InjectDll((DWORD)atoi(argv[2]), argv[3]) )

{

printf(“[ERROR] [%d]!!!\n”, GetLastError());

return 0;

}

return 1;

}

if (!strcmp(argv[1],“-u”))

{

//Uninject dll을 진행한다.

if(!UninjectDll((DWORD)atoi(argv[2]), argv[3]) )

{

printf(“[ERROR] [%d]!!!\n”, GetLastError());

return 0;

}

return 1;

}

//인자가 4개이지만 위 설정과 맞지 않는 경우 아래 내용을 출력한다.

printf(“press usage : Injectiondll -i/-u <PID> <InjectionDll>\n”);

return 0;

}

[예제] 인젝션 로더

이제 이 로더를 이용하여 Dll을 자유롭게 넣거나 뺄 수 있다. 이 로더는 24장 프로세스 보호에서 다시 사용할 것이다.

그럼 위 Dll 로더를 빌드하고 이제 인젝션할 Dll을 만들어 보자. 여기서는 네트워크 소켓 내용을 후킹해 해당 내용을 디버깅 메시지로 출력해보고자 한다. 이 후킹을 위해 Detours Library를 이용할 예정이다. Detours Library란 Hooking 방법의 일종으로, Dummy (Trampoline) 함수를 이용하여 다른 일을 시키고 난 후 원래의 리턴 코드를 그대로 수행해 후킹하는 방법입니다. 기존 코드의 후킹 도 복원도 쉽다는 장점이 있다. 그래서 런타임 후킹도 쉽게 가능해 후킹 용도로 많이 사용된다.

아래 사이트에 접근하면 Detours 관련 다양한 프로젝트를 접해 볼 수 있다.

http://research.microsoft.com/en-us/projects/detours/

그럼 Detours를 설치해 보자. nmake 명령을 이용하여 손쉽게 설치할 수 있다. 단 “Visual Studio 명령 프롬프트(2010)”상태에서 명령을 실행해야 한다.

[그림] Detours 기능을 설치하고 있다

생성된 Include 디렉토리와 Lib 디렉토리의 파일을 “C:\Program Files (x86)\Microsoft Visual Studio 9.0\VC” 하위 디렉토리에 복사하도록 하자.

hooksocket.cpp
#pragma
comment(lib, “detours.lib”)#pragma
comment(lib, “Ws2_32.lib”)// 이미 정이된 UNICODE를 사용하지 않도록 한다.
#undef
UNICODE
#include
<cstdio>

#include
<Winsock2.h>

#include
<ws2tcpip.h>

#include
<windows.h>

// 컴파일 오류시 detours.h 파일내의 경로에 문제가 있을수 있으니 문제 발생시 이를 확인하자

#include
<detours.h>

//프로토타입을 지정한다.

int (WINAPI *pSend)(SOCKET s, const
char* buf, int len, int flags) = send;

int WINAPI MySend(SOCKET s, const
char* buf, int len, int flags);

int (WINAPI *pRecv)(SOCKET s, char* buf, int len, int flags) = recv;

int WINAPI MyRecv(SOCKET s, char* buf, int len, int flags);

INT APIENTRY DllMain(HMODULE hDll, DWORD Reason, LPVOID Reserved)

{

switch(Reason)

{

// Detour를 이용하여 후킹 코드를 작성

case Dll_PROCESS_ATTACH:

DisableThreadLibraryCalls(hDll);

// Detour처리를 위해 동기화가 완료되기 전에 스레드를 일시정지하는데, 이를 위해 아래 두개의 함수를 이용한다. (Detour 라이브러리 이용시 이와 같이 사용한다.)

DetourTransactionBegin();

DetourUpdateThread(GetCurrentThread());

// pSend API을 후킹한다.

DetourAttach(&(PVOID&)pSend, MySend);

if(DetourTransactionCommit() == NO_ERROR)

OutputDebugString(“Send() detoured attach successfully”);

// 다시 동기화 한다.

DetourTransactionBegin();

DetourUpdateThread(GetCurrentThread());

// pRecv API을 후킹한다.

DetourAttach(&(PVOID&)pRecv, MyRecv);

if(DetourTransactionCommit() == NO_ERROR)

OutputDebugString(“Recv() detoured detach successfully “);

break;

case Dll_PROCESS_DETACH:

DetourTransactionBegin();    

DetourUpdateThread(GetCurrentThread());

// 후킹을 해제한다.

DetourDetach(&(PVOID&)pSend, MySend);

if(DetourTransactionCommit() == NO_ERROR)

OutputDebugString(“Recv() detoured detach successfully “);

DetourTransactionBegin();

DetourUpdateThread(GetCurrentThread());

DetourDetach(&(PVOID&)pRecv, MyRecv);

if(DetourTransactionCommit() == NO_ERROR)

OutputDebugString(“Recv() detoured detach successfully “);

DetourTransactionCommit();

break;

case Dll_THREAD_ATTACH:

case Dll_THREAD_DETACH:

break;

}

return TRUE;

}

// 디버그 메시지를 찍도록 한다. 이를 통해 전송 내용을 Dbgview로 확인할 수 있다.

int WINAPI MySend(SOCKET s, const
char* buf, int len, int flags)

{

OutputDebugString(buf);

return pSend(s, buf, len, flags);

}

int WINAPI MyRecv(SOCKET s, char* buf, int len, int flags)

{

OutputDebugString(buf);

return pRecv(s, buf, len, flags);

}

[예제 23-3] Send, Recv 후킹 예제

위 코드를 빌드하고, 인터넷 브라우저에 Dll을 인젝션 시켜보자.

injectiondll firefox hooksocket

필자는 파이어폭스에 진행하였지만 인터넷 익스플로러만 사용하는 경우 인터넷 익스플로러를 선택하여 진행해도 무방하다. 정상적으로 인젝션이 완료되면, Dbgview를 실행해서 동작 상황을 감시할 수 있다.

↓웹페이지를 보면 아래 디버깅뷰에 메시지를 표시한다.

[그림] Detour를 이용하여 파이어폭스의 소켓을 성공적으로 후킹하였다

이처럼 쉽게 CreateRemoteThread를 이용한 후킹 방법에 대해 알아보았다. CreateRemoteThread를 이용한 방법은 이외에도 여러 방식으로 사용할 수 있다.

Drew_Benton이 공개한 아래 내용을 참고하면 더 많은 도움을 받을 수 있을 것이다.

http://www.codeproject.com/Articles/20084/A-More-Complete-Dll-Injection-Solution-Using-Creat

Facebook Comments

Leave A Reply

이메일은 공개되지 않습니다. 필수 입력창은 * 로 표시되어 있습니다.