(Win32 : WindowsProgramming-28) DLL_INJECTION

Posted by : at

Category : win32   WindowsProgramming


  • 내가 만든 DLL을 실행중인 다른 프로세스에 넣어보자
    • 사용자가 만든 DLL을 다른 프로세스에 로드
  • DLL Injection 방법
    • Remote Thread (우리가 사용할 방법)
    • Windows Message Hook
    • Debugging API Injection
    • Registry Injection
    • Trojan horse

Remote Thread

  • 대략 이런 방향으로 구현된다.
    • 윈도우에서 실행되는 모든 프로세스는 Kernel32.dll을 로드하게 된다.
    • Kernel32.dll안에는 LoadLibrary()함수가 있다.
    • CreateRemoteThread를 이용하면 다른 프로세스의 스레드를 생성할 수 있다
    • 다른 프로세스에 생성된 스레드를 이용해 LoadLibrary()를 호출해보자.
// Spy.cpp
// 대략 dll은 다음과 같이 구성하고..
#include <Windows.h>
#include <stdio.h>

BOOL _stdcall DllMain(HINSTANCE hinstDll, DWORD fwdReason, LPVOID lpvReserved)
{
    switch(fwdReason)
    {
    case DLL_PROCESS_ATTACH:
        MessageBoxA(0, "Inject Spy.dll", "SPY" MB_OK);
        break;
    case DLL_PROCESS_DETACH:
        MessageBoxA(0, "Eject Spy.dll", "SPY" MB_OK);
        break;
    }

    return TRUE;
}
#include <Windows.h>
#include <stdio.h>

int main()
{
    const char* dllname = "D:\\Spy.dll";

    // 1. Inject시킬 프로세스(메모장)의 핸들 얻기
    // 메모장의 윈도우 핸들 얻음
    HWND hwnd = FindWindowA("Notepad", 0);
    DWORD pid;
    // 윈도우 핸들을 기반으로 프로세스id 얻음
    DWORD tid = GetWindowThreadProcessId(hwnd, &pid);

    // 프로세스 id기반으로 메모장의 프로세스 핸들을 얻음
    HANDLE hProcess = OpenProcess(PRICESS_ALL_ACCESS, FALSE, pid);

    printf("%x, %x, %x\n" hwnd, pid, hProcess);

    // 2. LoadLibrary 주소 구하기
    // kernel32.dll내에 LoadLibrary가 있을 것이다.
    HMODULE hDll = GetModuleHandleA("kernel32.dll");
    PTHREAD_START_ROUTINE f = (PTHREAD_START_ROUTINE)GetProcAddress(hDll, "LoadLibraryA");

    // 여기서 구한 LoadLibrary주소가 내가 사용중인 Process의 LoadLibrary주소이지
    // Injection 시킬 Process의 LoadLibrary일 것이라는 보장이 없음
    // 이 부분에 대해선 이후에 설명, 우선은 Kernel32.dll 내에서 같은 주소를 쓸꺼라 가정하자

    printf("%p, %p\n", hDll, f);

    // 3. Inject 시킬 프로세스 내에서 스래드 생성 후 LoadLibraryA 실행하기
    // HANDLE hThread = CreateRemoteThread(hProcess, 0, 0, f, (void*)dllname, 0, 0);
    // (void*)dllname -> dll이름을 주소값으로 넘기는데 Inject 시킬 프로세스는 이 주소공간에 메모리가 할당되어 있지 않음 -> 메모리 복사 필요

    char* p = (char*)VirtualAllocEx(hProcess, 0, strlen(dllname)+1, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
    SIZE_T sz;
    WriteProcessMemory(hProcess, p, dllname ,strl(dllname)+1, &sz);

    HANDLE hThread = CreateRemoteThread(hProcess,         // 메모장의 프로세스 핸들
                                        0, 0, 
                                        f,                // LoadLibraryA 주소
                                        (void*)dllname,   // LoadLibraryA에 넘길 파라미터
                                        0, 0);

    // 4. 빌드
    // cl DLL_inject.cpp /link user32.lib kernel32.lib
}

이렇게 하면 될까? -> 메모장이 그냥 죽어버린다.

HANDLE hThread = CreateRemoteThread(hProcess,
                                    0, 0, 
                                    f,
                                    (void*)dllname,   
                                    // dllname은 메모장에 할당된 변수가 아니라
                                    // 내 프로세스만 알고있는 변수이다.
                                    // 메모장도 알고있게 해야한다
                                    0, 0);
// ...
// dllname을 복사한다

char* p = (char*)VirtualAllocEx(hProcess, 0, strlen(dllname)+1, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
SIZE_T sz;
WriteProcessMemory(hProcess, p, dllname ,strl(dllname)+1, &sz);

HANDLE hThread = CreateRemoteThread(hProcess,         // 메모장의 프로세스 핸들
                                0, 0, 
                                f,          // LoadLibraryA 주소
                                (void*)p,   // p에 dllname의 값이 복사되어 있음
                                0, 0);

// ...

About Taehyung Kim

안녕하세요? 8년차 현업 C++ 개발자 김태형이라고 합니다. 😁 C/C++을 사랑하며 다양한 사람과의 협업을 즐깁니다. ☕ 꾸준한 자기개발을 미덕이라 생각하며 노력중이며, 제가 얻은 지식을 홈페이지에 정리 중입니다. 좀 더 상세한 제 이력서 혹은 Private 프로젝트 접근 권한을 원하신다면 메일주세요. 😎

Star
Useful Links