DLL Injection 구현 방법


몇 가지 구현 방법이 있습니다.

그 중에서 가장 유명한 방법이 CreateRemoteThread() API 를 이용하는 방법입니다.

이 방법은 윈도우즈 프로그래밍 서적의 바이블인 Jeffrey Richter Programming Applications for Microsoft Windows 에 소개된 내용입니다.

일단 소스 코드를 보겠습니다. (엔지니어에게는 백 마디 설명 보다는 역시 소스 코드를 한번 보는게 낫죠.)

먼저 Injection 시킬 myhack.dll 소스 코드입니다.

myhack.cpp


// myhack.cpp

#include "stdio.h"
#include "windows.h"

#pragma comment(lib, "urlmon.lib")

#define DEF_NAVER_ADDR ("http://www.naver.com/index.html")
#define DEF_INDEX_PATH ("c:\\index.html")

DWORD WINAPI ThreadProc(LPVOID lParam)
{
    URLDownloadToFile(NULL, DEF_NAVER_ADDR, DEF_INDEX_PATH, 0, NULL);
    return 0;
}

BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
    HANDLE hThread = NULL;

    switch( fdwReason )
    {
        case DLL_PROCESS_ATTACH :
            hThread = CreateThread(NULL, 0, ThreadProc, NULL, 0, NULL);
            CloseHandle(hThread);
            break;
    }
  
    return TRUE;
}

아주 간단한 코드입니다.

DllMain() 을 보시면 DLL 이 로딩(DLL_PROCESS_ATTACH)될 때 스레드(ThreadProc)를 실행합니다.

ThreadProc() 의 내용은 urlmon.dll 의 URLDownloadToFile() 함수를 실행시켜서 네이버 초기화면(index.html)을 다운받습니다.

프로세스에 DLL Injection 이 발생하면 해당 DLL 의 DllMain() 함수가 호출된다고 이전 포스트에서 설명드렸습니다. 따라서 notepad.exe 프로세스에 myhack.dll 이 Injection 되면 결국 URLDownloadToFile() 함수가 실행될 것입니다.

* DLLMain() 에서 직접 URLDownloadToFile() 을 호출하면 간혹 hang 이 걸리는 경우가 있어서, 별도의 스레드를 생성하여 호출하도록 프로그래밍 하였습니다.



이제 myhack.dll 을 notepad.exe 프로세스에 Injection 시켜줄 프로그램(InjectDll.exe)의 소스코드를 보시겠습니다.

InjectDll.cpp


// InjectDll.exe

#include "stdio.h"

#include "windows.h"
#include "tlhelp32.h"

#define DEF_PROC_NAME ("notepad.exe")
#define DEF_DLL_PATH ("c:\\myhack.dll")

DWORD FindProcessID(LPCTSTR szProcessName);
BOOL InjectDll(DWORD dwPID, LPCTSTR szDllName);

int main(int argc, char* argv[])
{
    DWORD dwPID = 0xFFFFFFFF;
 
    // find process
    dwPID = FindProcessID(DEF_PROC_NAME);
    if( dwPID == 0xFFFFFFFF )
    {
        printf("There is no <%s> process!\n", DEF_PROC_NAME);
        return 1;
    }

    // inject dll
    InjectDll(dwPID, DEF_DLL_PATH); 

    return 0;
}

DWORD FindProcessID(LPCTSTR szProcessName)
{
    DWORD dwPID = 0xFFFFFFFF;
    HANDLE hSnapShot = INVALID_HANDLE_VALUE;
    PROCESSENTRY32 pe;

    // Get the snapshot of the system
    pe.dwSize = sizeof( PROCESSENTRY32 );
    hSnapShot = CreateToolhelp32Snapshot( TH32CS_SNAPALL, NULL );

    // find process
    Process32First(hSnapShot, &pe);
    do
    {
        if(!_stricmp(szProcessName, pe.szExeFile))
        {
            dwPID = pe.th32ProcessID;
            break;
        }
    }
    while(Process32Next(hSnapShot, &pe));

    CloseHandle(hSnapShot);

    return dwPID;
}

BOOL InjectDll(DWORD dwPID, LPCTSTR szDllName)
{
    HANDLE hProcess, hThread;
    HMODULE hMod;
    LPVOID pRemoteBuf;
    DWORD dwBufSize = lstrlen(szDllName) + 1;
    LPTHREAD_START_ROUTINE pThreadProc;

    // #1. dwPID 를 이용하여 대상 프로세스(notepad.exe)의 HANDLE을 구함
    if ( !(hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPID)) )
        return FALSE;

    // #2. 대상 프로세스(notepad.exe) 메모리에 szDllName 크기만큼 메모리를 할당
    pRemoteBuf = VirtualAllocEx(hProcess, NULL, dwBufSize, MEM_COMMIT, PAGE_READWRITE);

    // #3. 할당 받은 메모리에 myhack.dll 경로("c:\\myhack.dll")를 씀
    WriteProcessMemory(hProcess, pRemoteBuf, (LPVOID)szDllName, dwBufSize, NULL);

    // #4. LoadLibraryA() API 주소를 구함
    hMod = GetModuleHandle("kernel32.dll");
    pThreadProc = (LPTHREAD_START_ROUTINE)GetProcAddress(hMod, "LoadLibraryA");

    // #5. notepad.exe 프로세스에 스레드를 실행
    hThread = CreateRemoteThread(hProcess, NULL, 0, pThreadProc, pRemoteBuf, 0, NULL);
    WaitForSingleObject(hThread, INFINITE); 

    CloseHandle(hThread);
    CloseHandle(hProcess);

    return TRUE;
}

역시 코드가 간결합니다. (편의상 예외처리, 리턴값 체크 등의 코드는 생략하였습니다.)

main() 함수에서는 2개의 서브 함수를 호출하고 있습니다.

FindProcessID(DEF_PROC_NAME) 함수는 프로세스 이름으로 PID(Process ID) 를 구해주는 함수입니다. (설명은 생략합니다.) 그리고 InjectDll(dwPID, DEF_DLL_PATH) 함수가 바로 DLL Injection 을 해주는 핵심 함수입니다.

InjectDll() 함수를 자세히 살펴보겠습니다.

InjectDll() 함수는 대상 프로세스(notepad.exe)로 하여금 스스로 LoadLibrary("myhack.dll") API 를 호출하도록 명령하는 기능을 가지고 있습니다.

#1. 대상 프로세스 핸들 구하기

hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPID))

OpenProcess() API 를 이용해서 notepad.exe 의 프로세스 핸들을 구합니다. (이때 미리 구해놓은 PID 를 사용함)
이 프로세스 핸들(hProcess)을 이용해서 해당 프로세스(notepad.exe)를 제어할 수 있습니다.

#2-3. 대상 프로세스 메모리에 Injection 시킬 DLL 경로를 써주기

pRemoteBuf = VirtualAllocEx(hProcess, NULL, dwBufSize, MEM_COMMIT, PAGE_READWRITE);

대상 프로세스(notepad.exe)에게 로딩할 DLL 파일의 경로(문자열)를 알려줘야 합니다.
아무 메모리 공간에 쓸 수 없으므로 VirtualAllocEx() API 를 이용하여 대상 프로세스(notepad.exe) 메모리 공간에 버퍼를 할당합니다. 버퍼 크기는 DLL 경로 문자열 길이(NULL 포함)입니다. 

* 주의! 
VirtualAllocEx() 함수의 리턴값(pRemoteBuf)은 할당된 버퍼 주소입니다. 이 주소는 내 프로세스(Inject.exe)의 메모리 주소가 아니라 hProcess 핸들이 가리키는 대상 프로세스(notepad.exe)의 메모리 주소라는것을 꼭 기억하시기 바랍니다.


WriteProcessMemory(hProcess, pRemoteBuf, (LPVOID)szDllName, dwBufSize, NULL);

할당 받은 버퍼 주소(pRemoteBuf)에 WriteProcessMemory() API 를 이용하여 DLL 경로 문자열("C:\\myhack.dll")을 써줍니다.

이로써 대상 프로세스(notepad.exe) 메모리 공간에 Injection 시킬 DLL 파일의 경로가 생겼습니다.

* 참고
Win32 프로그래밍을 처음 배울 때 분명 다른 프로세스의 메모리에 읽고 쓰는 일이 어렵다고(혹은 불가능하다고) 배웠습니다. 하지만 실제로는 다른 프로세스의 메모리 공간에 접근을 못하면 운영체제도 답답해 집니다. (예를 들어 다른 프로세스 메모리에 접근 할 수 없다면 디버거 제작이 불가능해지지요.) 그래서 Windows 운영체제는 Debug API 를 제공하여 다른 프로세스 메모리 공간에 접근 할 수 있도록 하였습니다. 대표적인 Debug API 가 바로 위에서 소개해 드린 VirtualAllocEx(), VirtualFreeEx(), WriteProcessMemory(), ReadProcessMemory() 등이 있습니다.

#4. LoadLibraryA() API 주소를 구하기

hMod = GetModuleHandle("kernel32.dll");
pThreadProc = (LPTHREAD_START_ROUTINE)GetProcAddress(hMod, "LoadLibraryA");


LoadLibrary() API 를 호출시키기 위해 그 주소가 필요합니다.
(LoadLibraryA() 는 LoadLibrary() 의 ASCII 문자열 버전입니다.)

위 코드의 의미를 잘 생각해봐야 합니다.
우리는 분명 notepad.exe 에 로딩된 kernel32.dll 의 LoadLibraryA() API 의 시작 주소를 알아내야 합니다.
하지만 위 코드는 InjectDll.exe 에 로딩된 kernel32.dll 의 LoadLibraryA() API 의 시작 주소를 얻어내고 있습니다.

notepad.exe 에 로딩된 kernel32.dll 과 InjectDll.exe 에 로딩된 kernel32.dll 의 메모리 시작 위치(ImageBase)가 동일 하다면 위 코드는 문제가 없습니다.

일반적인 DLL 파일의 ImageBase 는 0x10000000 으로 설정되기 때문에 a.dll 과 b.dll 을 차례대로 로딩하면 a.dll 은 정상적으로 0x1000000 주소에 로딩이 되겠지만 b.dll 은 자신이 원하는 0x10000000 주소에 로딩되지 못하고 다른 비어 있는 주소 공간에 로딩됩니다. 즉, DLL Relocation 이 발생하는 것입니다. (a.dll 이 같은 주소에 이미 로딩되어 있기 때문입니다.)

만약 kernel32.dll 이 프로세스마다 다른 주소에 로딩된다면 위 코드는 잘못된 것입니다.
하지만 실제 Winodows 운영체제에서 kernel32.dll 은 프로세스마다 같은 주소에 로딩됩니다.

어째서 그런걸까요?

PE View 를 통해서 Windows 운영체제의 핵심 DLL 파일들의 ImageBase 값을 조사해 봤습니다.
(Windows XP SP3 KOR 버전입니다. Windows 업데이트 상태에 따라서 아래 값들은 달라질 수 있습니다.)

DLL file        ImageBase       SizeOfImage
--------------------------------------------
msvcrt.dll      77BC0000        00058000
user32.dll      77CF0000        00090000
gdi32.dll       77E20000        00049000
advapi32.dll    77F50000        000A8000
kernel32.dll    7C7D0000        00130000
shell32.dll     7D5A0000        007FD000
...


Microsoft 에서 친절하게 OS 핵심 DLL 파일들의 ImageBase 값을 이쁘게 정리해놨습니다.
즉, 자신들끼리 절대로 겹치지 않고 따라서 DLL Relocation 이 발생하지 않습니다.

Dll Injection 기법은 위와같이 OS 핵심 DLL 들은 자신만의 고유한 주소에 로딩된는 것을 보장해주는 Windows 특성을 이용한 것입니다. (이 특성이 Windows 보안 취약점으로 이용되기도 합니다.)

따라서 InjectDll.exe 프로세스에 import 된 LoadLibraryA() 주소와 notepad.exe 프로세스에 import 된 LoadLibraryA() 주소는 동일합니다.

* 참고!
모든 Windows 프로세스는 kernel32.dll 을 로딩합니다.
PE Header 를 조작하여 IAT 에서 kernel32.dll 항목을 제거해버려도 loader 가 강제로 kernel32.dll 을 로딩시켜버립니다. (XP 부터 해당됨. 2000 에서는 실행불가.)


#5. 대상 프로세스에 스레드를 실행 시킴

모든 준비는 끝났고 마지막으로 notepad.exe 로 하여금 LoadLibraryA() API 를 호출하도록 명령만 내리면 됩니다. 하지만 Windows 에서는 그런 API 를 제공하지 않습니다.

그래서 편법(?)으로 CreateRemoteThread() API 를 사용합니다.
(편법이라기 보다는 DLL Injection 의 정석이라고 말 할 수 있지요.)

CreateRemoteThread() API 는 다른 프로세스에게 스레드를 실행시켜주는 함수입니다.

HANDLE WINAPI CreateRemoteThread(
  __in   HANDLE                   hProcess,             // 프로세스 핸들
  __in   LPSECURITY_ATTRIBUTES    lpThreadAttributes,
  __in   SIZE_T                   dwStackSize,
  __in   LPTHREAD_START_ROUTINE   lpStartAddress,       // 스레드 함수 주소
  __in   LPVOID                   lpParameter,          // 스레드 파라미터 주소

  __in   DWORD                    dwCreationFlags,
  __out  LPDWORD                  lpThreadId
);


첫번째 파라미터인 hProcess 만 빼면 일반적으로 사용되는 CreateThread() 함수와 다 똑같습니다.

hProcess 파라미터가 바로 스레드를 실행시킬 프로세스의 핸들입니다.
lpStartAddress 와 lpParameter 파라미터는 각각 스레드 함수 주소와 스레드 파라미터 주소입니다.
중요한건 이 주소들이 대상 프로세스의 가상 메모리 공간의 주소이어야 한다는 것입니다. (그래야 그 프로세스에서 인식을 할 수 있겠죠.)

좀 어리둥절 하시죠?
다른 프로세스에 DLL 을 injection 시키는데 스레드가 무슨 상관일까요?

스레드 함수 ThreadProc() 과 LoadLibrary() API 를 보시면 힌트를 얻을 수 있습니다.

DWORD WINAPI ThreadProc(
  __in  LPVOID           lpParameter
);

HMODULE WINAPI LoadLibrary(
  __in  LPCTSTR          lpFileName
);


두 함수 모두 4 byte 파라미터를 받고, 4 byte 값을 리턴하지요.
바로 여기서 아이디어를 얻은 것입니다.

CreateRemoteThread() 를 호출해서 4 번째 파라미터 lpStartAddress 에 "LoadLibrary() 주소"를 주고, 5 번째 파라미터 lpParameter 에 원하는 "DLL 의 경로" 문자열을 주면 됩니다. (반드시 대상 프로세스의 가상 메모리 공간에의 주소이여야 합니다.)

우린 이미 위에서 다 준비해놨지요. 편안하게 호출해주면 됩니다.

hThread = CreateRemoteThread(hProcess, NULL, 0, pThreadProc, pRemoteBuf, 0, NULL);

  pThreadProc = notepad.exe 의 LoadLibraryA() 주소
  pRemoteBuf = notepad.exe 의 "c:\\myhack.dll" 문자열 주소


CreateRemoteThread() 는 스레드를 생성하는 것이 아니라 실제로는 LoadLibraryA() 를 호출 시키는 것입니다.



+---+

CreateRemoteThread() 를 이용한 Dll Injection 기법에 대한 설명을 마치겠습니다.

처음에는 잘 이해가 되지 않을 수 있습니다. 설명을 다시 차근차근 읽어보시고 직접 실습해 보세요.

다음 번에는 다른 Dll Injection 기법들과 한번 Injection 된 Dll 을 꺼내는 (Ejection) 방법에 대해서 설명드리도록 하겠습니다.


Dll Injection - 다른 프로세스에 침투하기 (3)


ReverseCore

    이전 댓글 더보기
  1. 2011.09.09 21:47 댓글주소 | 수정 | 삭제 | 댓글

    비밀댓글입니다

    • reversecore 2011.09.19 20:17 신고 댓글주소 | 수정 | 삭제

      안녕하세요.

      혹시 Vista/7 계열의 OS 를 사용하시는지요?

      Vista/7 OS 의 특정 프로세스들에서는 다른 방법을 사용해야 합니다. 제 블로그에 관련 글이 있으니 참고하시기 바랍니다.

      혹은 64bit 환경에서도 그 환경에 맞는 DLL Injection 방법을 쓰셔야 합니다. (이건 블로그에 아직 없네요...)

      감사합니다.

  2. 2011.09.10 21:31 댓글주소 | 수정 | 삭제 | 댓글

    비밀댓글입니다

  3. 2011.10.14 23:24 댓글주소 | 수정 | 삭제 | 댓글

    비밀댓글입니다

  4. 고니파 2011.11.08 16:52 신고 댓글주소 | 수정 | 삭제 | 댓글

    책이 따로 없네요. 정말 잘 봤습니다. ^^

    그리고 혹시 Detours를 이용한 DLL injection에 관해 포스팅 하실 계획은 없으신지요... ^^

    Detours를 이용한 API hook 관련 글은 있지만 dll injection 부분을 Detours로 처리한 글은 찾을 수가 없네요..
    Detours API 매뉴얼도 없고 관련 정보를 찾기가 꽤 힘들군요..

    • reversecore 2011.11.18 20:42 신고 댓글주소 | 수정 | 삭제

      안녕하세요.

      Detour 후킹 라이브러리를 말씀하시는 것이지요?

      매뉴얼은 없구요. 그 내부에 있는 예제 샘플을 보시고 따라 만드시면 됩니다.

      Detour 를 이용한 API 후킹도 좋은 포스팅 주제가 되겠네요. 책이 완료되고 본격적인 블로그 활동이 재개되면 글을 써보도록 하겠습니다.

      감사합니다.

  5. 김정훈 2011.11.14 23:55 신고 댓글주소 | 수정 | 삭제 | 댓글


    혹시 VC++ 6 프로젝트 파일 2가지를 받을수 있을까요??

    phontest01@nate.com

    좋은 자료 감사합니다

  6. 탱그 2011.12.09 14:54 신고 댓글주소 | 수정 | 삭제 | 댓글

    CreateRemoteThread() 함수가 64bit컴퓨터에서는 안되네요 ㅜㅜ
    GetLastError()함수로 봤더니 5번 에러(ERROR_ACCESS_DENIED)
    가 나네요 ㅜㅜ

    • reversecore 2011.12.21 01:39 신고 댓글주소 | 수정 | 삭제

      안녕하세요.

      64bit 에서 무조건 안되지는 않습니다.
      세션이 다른 경우에 실패하지요.

      관련 설명은 http://www.reversecore.com/73 를 참고하시면 될 것 같습니다.

      문의하신 에러는 좀 다른 상황인데요...
      OpenProcess() API 호출에서 실패한 것 같은데요.
      적절한 권한이 없는 상태에서 타겟 프로세스를 Open 하려고 할때 그런 현상이 발생합니다.

      역시 알려드린 링크의 InjectDll.cpp 파일내의 SetPrivilege() 함수를 먼저 호출하시면 자신의 권한을 상승 시킬 수 있으며 그런 에러가 발생하지 않을 것입니다.

      감사합니다.

  7. 배우는중 2012.02.24 21:56 신고 댓글주소 | 수정 | 삭제 | 댓글

    맨날 버퍼오버플로우,포멧스트링 이런 리눅스에서 배운거 쓰다보면서 API만 보면 덜덜 떨었는데
    쉽게 잘 설명하셧네요

  8. 알려주세요 2012.06.05 02:48 신고 댓글주소 | 수정 | 삭제 | 댓글

    안녕하세요 Injectdll.exe 의 소스를 그대로 베껴서 해보니 몇가지 오류가 나서 고쳤더니 dll이 로딩되지 않는 것 같습니다. win7,winxp 전부 안되구여.. 왜 그럴까요?


    #include "stdio.h"
    #include "windows.h"
    #include "tlhelp32.h"

    #define DEF_PROC_NAME TEXT("notepad.exe")
    #define DEF_DLL_PATH TEXT("c:\\myhack.dll")

    DWORD FindProcessID(LPCTSTR szProcessName);
    BOOL InjectDll(DWORD dwPID, LPCTSTR szDllName);

    int main(int argc, char* argv[])
    {
    DWORD dwPID = 0xFFFFFFFF;

    // find process
    dwPID = FindProcessID(DEF_PROC_NAME);
    if( dwPID == 0xFFFFFFFF )
    {
    printf("There is no <%s> process!\n", DEF_PROC_NAME);
    return 1;
    }

    // inject dll
    InjectDll(dwPID, DEF_DLL_PATH);

    return 0;
    }

    DWORD FindProcessID(LPCTSTR szProcessName)
    {
    DWORD dwPID = 0xFFFFFFFF;
    HANDLE hSnapShot = INVALID_HANDLE_VALUE;
    PROCESSENTRY32 pe;

    // Get the snapshot of the system
    pe.dwSize = sizeof( PROCESSENTRY32 );
    hSnapShot = CreateToolhelp32Snapshot( TH32CS_SNAPALL, NULL );

    // find process
    Process32First(hSnapShot, &pe);
    do
    {
    if(!wcsicmp(szProcessName, pe.szExeFile))
    {
    dwPID = pe.th32ProcessID;
    break;
    }
    }
    while(Process32Next(hSnapShot, &pe));

    CloseHandle(hSnapShot);

    return dwPID;
    }

    BOOL InjectDll(DWORD dwPID, LPCTSTR szDllName)
    {
    HANDLE hProcess, hThread;
    HMODULE hMod;
    LPVOID pRemoteBuf;
    DWORD dwBufSize = lstrlen(szDllName) + 1;
    LPTHREAD_START_ROUTINE pThreadProc;

    // #1. dwPID 를 이용하여 대상 프로세스(notepad.exe)의 HANDLE을 구함
    if ( !(hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPID)) )
    return FALSE;

    // #2. 대상 프로세스(notepad.exe) 메모리에 szDllName 크기만큼 메모리를 할당
    pRemoteBuf = VirtualAllocEx(hProcess, NULL, dwBufSize, MEM_COMMIT, PAGE_READWRITE);

    // #3. 할당 받은 메모리에 myhack.dll 경로("c:\\myhack.dll")를 씀
    WriteProcessMemory(hProcess, pRemoteBuf, (LPVOID)szDllName, dwBufSize, NULL);

    // #4. LoadLibraryA() API 주소를 구함
    hMod = GetModuleHandle(TEXT("kernel32.dll"));
    pThreadProc = (LPTHREAD_START_ROUTINE)GetProcAddress(hMod, "LoadLibraryA");

    // #5. notepad.exe 프로세스에 스레드를 실행
    hThread = CreateRemoteThread(hProcess, NULL, 0, pThreadProc, pRemoteBuf, 0, NULL);
    WaitForSingleObject(hThread, INFINITE);

    CloseHandle(hThread);
    CloseHandle(hProcess);

    return TRUE;
    }

  9. 마리오 2012.06.18 23:53 신고 댓글주소 | 수정 | 삭제 | 댓글

    hMod = GetModuleHandle("kernel32.dll");
    pThreadProc = (LPTHREAD_START_ROUTINE)GetProcAddress(hMod,"LoadlibraryA");
    이부분 이해가 잘안가는대
    hMod = GetModuleHandle("kernel32.dll"); -> 이부분 Inject_DLL의 커널32.dll 핸들을 얻어서
    pThreadProc = (LPTHREAD_START_ROUTINE)GetProcAddress(hMod,"LoadlibraryA");
    └>이 부분은 커널32.dll의 LoadlibraryA 를 호출 한다고 보면될까요?

    그리고.. 이두 줄의 용도가 먼가요?
    이 2줄로 구해진 loadLibraryA 의 커널 핸들로 노트페드의 스레드를 실행시키는건가요?

    • reversecore 2012.06.23 01:28 신고 댓글주소 | 수정 | 삭제

      안녕하세요.

      아직 Win32 API 에 익숙치 않으셔서 그러실 겁니다.

      GetModuleHandle("kernel32.dll") API 는 프로세스에 로딩된 kernel32.dll 의 로딩 주소를 리턴합니다.

      GetProcAddress(hMod,"LoadlibraryA") API 는 kernel32.dll 에서 제공하는 LoadLibraryA 라는 API 코드 주소를 리턴합니다. 즉 pThreadProc 에는 LoadLibraryA API 주소가 저장되며, LoadLibraryA() 를 호출하는 것과 pThreadProc 을 호출하는 것은 같은 코드를 실행하게 됩니다. 이러한 pThreadProc 을 함수포인터라고 얘기합니다.

      MSDN 도움말에서 API 설명을 읽어보시면 더 자세히 설명되어 있습니다.

      감사합니다.

  10. gilyong 2012.06.26 16:16 신고 댓글주소 | 수정 | 삭제 | 댓글

    글을 읽고 실습을 하던 중 궁굼한점이 있어 글을 올립니다.
    혹시 notepad.exe의 IAT(Import Address Table)에 LoadLibraryA가 없으면, DLLinjection.exe에서
    LoadLibraryA의 주소를 가지고 오더라두 인젝션이 되는지 궁굼합니다.
    이렇게 생각한 이유는 위 코드를 유니코드로 작성했는데 인젝션이 안되서 자료를 찾던 중 유니코드로 작성되면 LoadLibraryW에 주소를 가지고 온다고 봤습니다. 그래서 notepad.exe에 해당"LoadLibraryW"가 있는지 확인 해봤는데 IAT에는 없었습니다.. 그런데 이건 추측으로 부터 시작해서 정확히 알고 싶습니다.....

  11. 익명 2012.07.27 08:46 신고 댓글주소 | 수정 | 삭제 | 댓글

    죄송하지만 ㅠㅠ visual 6.0에서 위의예제 BOOL InjectDll(DWORD dwPID, LPCTSTR szDllName)
    함수에서 이런 에러가 나는데 왜그런건가요 ㅠㅠ 도저히 해결을 못하겟네요

    injdectdll.obj : error LNK2001: unresolved external symbol "int __cdecl InjdectDll(unsigned long,char const *)" (?InjdectDll@@YAHKPBD@Z)

  12. 귀찮니즘 2012.07.29 15:51 신고 댓글주소 | 수정 | 삭제 | 댓글

    안녕하세요.
    제가 메일 보냈는데 확인좀 해주세요.

  13. 귀찮니즘 2012.07.30 22:17 신고 댓글주소 | 수정 | 삭제 | 댓글

    안녕하세요.
    여기 댓글들 보니까 UNICODE하면 실패하는것 같군요.
    저도 UNICODE로 해서 실패한것 같습니다.
    UNICODE로 할려면 어떻게 해야 되나요?

    • saeglo 2012.07.31 10:06 신고 댓글주소 | 수정 | 삭제

      // 귀찮니즘
      "string"의 형태는 유니코드에서는 char *로 인식하므로
      1. _T("string")
      2. _TEXT("string")
      3. L"string"
      의 세 가지 방법 중 하나로 하시면 됩니다.

  14. 2012.08.08 18:05 댓글주소 | 수정 | 삭제 | 댓글

    비밀댓글입니다

  15. 삼철 2012.12.05 11:42 신고 댓글주소 | 수정 | 삭제 | 댓글

    포스팅이 매우 간결하고 내용 이해가 너무 쉽워서 정말 많은 도움이 되었습니다.
    샘플코드를 수정해보면서 확인한 정보에 대해서, 본 포스트에 추가하면 좋을 것 같아 공유해봅니다.

    결론부터 말씀드리면 32bit, 64bit Windows의 차이점이 되겠네요.
    설명하신 내용 중에 DLL 파일의 Image Base 값이 Process 마다 거의 동일하다는 전제가 있었습니다.
    그런데 테스트 해본 결과 Windows 7 32bit 환경에서는 정상 동작하였으나,
    Windows 7 64bit 환경에서는 정상 동작하지 않았습니다.

    이유는, 64bit Windows가
    64bit Process에 대해서는 [ C:\\Windows\\System32\\kernel32.dll ] 을 사용하는 반면
    32bit Process에 대해서는 [ C:\\Windows\\SysWOW64\\kernel32.dll ] 을 사용하는 것에 있었습니다.
    이때, notepad.exe는 64bit Process이고
    예제코드로 만든 Process는 32bit 입니다.

    따라서 Injection 하려는 메모리 영역이 다른 곳에 존재하여 CreateRemoteThread를 호출 해봐야 별 의미가 없었습니다.

    • reversecore 2012.12.13 00:00 신고 댓글주소 | 수정 | 삭제

      안녕하세요.

      WOW64 에 대한 좋은 설명 감사합니다. ^^

      추가적으로 32bit DLL 은 64bit 프로세스에 인젝션 시킬 수 없습니다.
      그 반대도 마찬가지구요.

      참고하시기 바랍니다.

      감사합니다.

  16. 똥낀도너츠 2013.01.14 01:44 신고 댓글주소 | 수정 | 삭제 | 댓글

    안녕하세요.
    DLL 인젝터 프로그램을 만들어야하는데.
    아는 지식이 너무 없어 어찌하다보니 여기까지 들어오게됬네요 ^^;
    최근에 책도 구입해서 잘보고있답니다.

    개발환경이 Windows 7 / VC 2010 사용하신다고하셨는데요.
    2010이있긴한데 프로젝트 생성에서 DLL 파일을 만들때 사용하는 프로젝트가
    MFC DLL이 맞나요?
    VC 6에서는 Dynamic Linked Library를 사용하는 걸로 알고있는데.
    위의 코드를 그대로 입력해서 제대로 동작하려면
    어떤 프로젝트를 생성하고 c++ 소스파일을 생성해서 타이핑해야하나요?

    너무 기본적인것을 질문해서 죄송합니다. 구글링으로 알아보려했지만...
    제 검색실력에 한계가있는것같습니다 ㅠㅠ

    바쁘실텐데 이런 질문남겨 죄송합니다.

    • reversecore 2013.01.18 01:27 신고 댓글주소 | 수정 | 삭제

      안녕하세요.

      그냥 Win32 DLL 을 선택하시면 됩니다.

      제 책의 예제 소스 코드를 그대로 열어 보시면 참고가 되실 것입니다.

      질문은 좋은 것이니 부담갖지 말고 올려주세요~ ^^

      감사합니다.

  17. 라마르틴 2013.02.24 16:20 신고 댓글주소 | 수정 | 삭제 | 댓글

    깔끔합니다. 완벽한 소스네요. 감사합니다

  18. 낙군 2013.07.24 17:19 신고 댓글주소 | 수정 | 삭제 | 댓글

    안녕하세요.
    리버싱 핵심원리 책을 구매해서 공부 하던 중 궁금한 점이 있습니다.
    Windows 7 에서 실습을 하던 중 Dll Injection 보안정책 때문에 제대로 되지 않을 수 있다라고 책에 씌여져 있는데 이러한 경우 보안 정책을 우회하여 Dll Injection 가능하게 할 수 있는 기법이 있는가요?? ?

  19. 주영이ミ☆ 2013.09.09 18:29 신고 댓글주소 | 수정 | 삭제 | 댓글

    와.. 진짜 성인군자시네여..
    일일히 다 설명해주시네.. ㄷㄷ;;

  20. 김응두 2014.09.27 05:32 신고 댓글주소 | 수정 | 삭제 | 댓글

    하하 정말 감사합니다. 예전에 이 기법을 가지고 이런저런 해킹툴을 만들었던적이
    있었는데 해놓고도 의문이 가는게 한둘이 아니였거든요... 속 쉬원하게 해결이 되네요.
    사실 댓글은 잘 남가지 않는데 너무 제게 도움이 되어서... 남기게 되었어요 두번 감사합니다.





티스토리 툴바