DLL injection 은 어떻게 이루어지는가? - CreatRomoteThread ()

2009/07/31 12:37

CreatRomoteThread ()


DLL Injection의 마지막 세 번째 방법은 CreatRemoteThread() 함수를 이용하는 것입니다. 가장 많이 쓰이는 방법이라서 관련 문서도 쉽게 찾을 수 있죠.

사용자 삽입 이미지
[그림 1] CreatRemoteThread() 의 개요

CreatRemoteThread() 함수는 이름 그대로 쓰레드를 만드는 API 함수입니다. 원격은 다른 프로세스에서 쓰레드를 생성하기 때문에 붙은 것이죠. [그림 1]과 같은 구조로 구성되어 있고, 윈도우즈 NT 계열에서 지원합니다.

첫 번째 인자인 hProcess는 쓰레드를 생성할 프로세스를 가리킵니다. 윈도우즈에서 제공하는 OpenProcess()  API 함수를 이용해서 구할 수 있으며, PID(Process ID) 값을 이용합니다. OpenProcess()의 원형은 아래와 같습니다.

HANDLE WINAPI OpenProcess(
__in DWORD dwDesiredAccess,
__in BOOL bInheritHandle,
__in DWORD dwProcessId
);


네 번째 인자, lpStartAddress는 LoadLibrary() 함수를 가리킵니다. LoadLibray()를 이용하여 DLL을 삽입하기 때문이죠. 원래는 쓰레드를 생성할 프로세스에서의 LoadLibray()를 가리켜야 하지만, 윈도우즈는 각 프로세스의 kernel32.dll의 베이스주소를 일정하게 관리하기 때문에 DLL Loader에서 사용하는 kernel32.dll의 LoadLibray()를 가리키더라도 문제 없다고 합니다. LoadLibray()의 주소는 GetProcAddress()를 이용합니다. 원형은 아래와 같습니다.

FARPROC WINAPI GetProcAddress(
__in HMODULE hModule,
__in LPCSTR lpProcName
);


다섯 번째 인자인 lpParameter는 프로세스 안에서 쓰레드가 위치할 메모리 영역을 가리킵니다. CreateRemoteThread()는 프로세스 안에 쓰레드를 생성하는 것이므로 쓰레드를 위한 메모리를 별도로 생성해주어야 하지요. 이 때 사용하는 API 함수가 VirtualAllockEx()와 WriteProcessMemory()입니다. VirtualAllockEx()가 메모리를 할당하면, WriteProcessMemory()로 쓰는 것이죠. 각각의 원형은 아래와 같습니다.

LPVOID WINAPI VirtualAllocEx(
__in HANDLE hProcess,
__in_opt LPVOID lpAddress,
__in SIZE_T dwSize,
__in DWORD flAllocationType,
__in DWORD flProtect
);


BOOL WINAPI WriteProcessMemory(
__in HANDLE hProcess,
__in LPVOID lpBaseAddress,
__in LPCVOID lpBuffer,
__in SIZE_T nSize,
__out SIZE_T *lpNumberOfBytesWritten
);


나머지 인자들은 lp*는 NULL로, dw*는 0으로 넣습니다. 이 중에서 dwCreationFlags에 0을 넣는 것은 쓰레드가 생성되는 즉시 실행하라는 뜻입니다.

전체적으로 정리해보죠. OpenProcess()로 DLL을 집어넣을 프로세스를 구합니다. 그리고 GetProcAddress()로 DLL을 로드하는 LoadLibrary()의 주소를 구합니다. 마지막으로 VirtualAllockEx()로 DLL이 위치할 메모리를 할당하고 WriteProcessMemory()로 쓰게 됩니다. 이 모든 것들을 CreateRemoteThread()의 인자값으로 넣어서 DLL Loader에서 실행합니다. 이러면 DLL Injection이 된 것입니다. 간단하죠?

하지만 이 방법은 간단한 대신 쉽게 탐지되기도 합니다. CreateRemoteThread()를 호출하면 CreatThreat()가 호출되고, 그 안에서 다시 BaseThreadStartThunk()가 호출된다고 합니다. 이 BaseThreadStartThunk()를 후킹해서 lpStartAddress가 위에서 설명한 대로 LoadLibray()나 GetProcAddress()를 가리킨다면 DLL Injection이라고 간주하는 것이죠.

참고 문헌


루트킷 : 윈도우 커널 조작의 미학, Greg Hoglund, James Butler, 2007, 에이콘
CreateRemoteThread Function :: http://msdn.microsoft.com/en-us/library/ms682437(VS.85).aspx
OpenProcess Function :: http://msdn.microsoft.com/en-us/library/ms684320(VS.85).aspx
GetProcAddress Function :: http://msdn.microsoft.com/en-us/library/ms683212(VS.85).aspx
VirtualAllocEx Function :: http://msdn.microsoft.com/en-us/library/aa366890(VS.85).aspx
WriteProcessMemory Function :: http://msdn.microsoft.com/en-us/library/ms681674(VS.85).aspx
Shield from DLL-Injection :: http://nerd.egloos.com/2940078
크리에이티브 커먼즈 라이센스
Creative Commons License

6l4ck3y3 0x02 Windows RCE , , , ,

Trackback Address:http://hisjournal.net/blog/trackback/255
  1. 전 처음 CreatRemoteThread() API를 보았을 때 참 변태같은 API구나 라고 생각했습니다 +_+;;
    혹시 그런 생각 안하셨나요 ㅎ

  2. Blog Icon
    아리새의펜촉

    변태 같은 API요? 전 그냥 이게 꼭 있어야 하는 API인가 의문이었어요.

  3. 넹 .. 저도 비슷한 생각에서 였어요 ㅎ
    다른 프로세스에 세로운 쓰레드를 만든다니!
    머이런!! +_+ㅋ