ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [펌] Dll injection
    Programming 2009. 3. 25. 00:20
    출처 : http://yuik.tistory.com/83
    예전에 복사해 놓은 것인데..
    출처가 어디인지 정확히 기억이 안난다;;

    dll Injection은?
    이미 실행되어 있는 프로세스로 DLL 을 삽입하는 기법
      -특정 함수를 실행 하기 전에 프로세스를 실행 하는 지점에서 제어권을 가로 챈 뒤, 자신의 코드를 주입,   실행 하고 제어권을 다시 돌려주는 방법

    dll Injection에 필요한 함수와 코드의 흐름

    OpenProcess
            - 프로세스를 열어 핸들을 구한다
    LoadLibrary
             - .dll을 로드한다.
    GetProcAddres
        - 특정함수의 메모리 주소를 얻어온다.
    VirtualAllocEx
    - 타 프로세스의 새로운 힙영역을 확보한다.
    WriteProcessMemory
        - 타 프로세스의 공간에 데이터를 쓴다.
    CreateRemoteThread
          -타 프로세스에 스레드를 생성 시킨다. 


    간단한 dll injection 샘플

    계산기 프로그램의 주소공간에 DLL을 인젝션하여 숫자 입력시 1씩을 더하도록 하는 인젝션 예..

    #include <iostream.h>
    #include <windows.h> 
    // DLL Inject : 다른 프로세스의 주소 공간에 특정 DLL을 넣는다.
    void DllInject(DWORD pid, char* path)
    {
     HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, 0, pid);
     // 내 프로세스에 있는 KERNEL32.DLL의 주소와 LoadLibrary의 주소를 구한다.
     HMODULE hDll = GetModuleHandle("kernel32.dll"); // kernel32.dll 모듈의 핸들값을 GetModuleHandle로 구한다.
     PTHREAD_START_ROUTINE f = (PTHREAD_START_ROUTINE)GetProcAddress(hDll, "LoadLibraryA");
     // PTHREAD_START_ROUTINE은 미리 정의되어 있는 스레드 함수 모양의 함수 포인터 type
     // 계산기의 주소공간에 메모리를 할당하고, DLL의 경로를 복사해준다.
     // VirtualAlloc은 가상 메모리를 할당하는 API이지만, Ex가 붙으면 다른 프로세스의 주소공간을 할당할 수 있다.
     void* p = VirtualAllocEx(hProcess, 0, // 원하는 주소(0은 알아서 해달라)
           strlen(path)+1, // 크기
           MEM_RESERVE | MEM_COMMIT, // 예약과 동시 확정
           PAGE_READWRITE);
     
     // 이제 DLL의 경로를 담을 문자열 복사
     // WriteProcessMemory()는 다른 프로세스 주소 공간에 무언가를 쓸 수 있다.
     DWORD len;
     WriteProcessMemory(hProcess, p, path, strlen(path)+1, &len);
     // 계산기에 새로운 스레드를 만든다.
     // CreateRemoteThread는 다른 프로세스에 스레드를 생성시킨다.
     HANDLE hThread = CreateRemoteThread(hProcess, // 계산기 핸들
              0, 0,
              f, p, // 함수, 파리미터
              0, 0);

     CloseHandle(hThread);
     CloseHandle(hProcess);
    }
    void main()
    {
     HWND hwnd = FindWindow(0, "계산기");
     if(hwnd == 0)
     {
      cout << "계산기를 먼저 실행하시오" << endl;
      return;
     }
     DWORD pid;
     DWORD tid = GetWindowThreadProcessId(hwnd, &pid);
     DllInject(pid, "C:\\spy1.dll");
    }


    이제부터, DLL 로 작성한다.
    #include <windows.h> 
    WNDPROC old; // 원래 계산기의 메세지 함수의 주소를 담을 변수
    // 계산기의 메세지를 처리할 새로운 함수
    LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp)
    {
     switch(msg)
     {
     case WM_COMMAND: // 버튼 또는 메뉴를 선택할 경우
      {
       UINT id = LOWORD(wp);
       if(id >= 0x7c && id <= 0x85)
        return CallWindowProc(old, hwnd, msg, wp+1, lp+1);
       break;
      }
     }
     // 나머지 모든 메세지는 원래의 함수로 보내준다.
     return CallWindowProc(old, hwnd, msg, wp, lp);
    }
    // 모든 DLL은 Process에 Mapping 되거나 해제될 때 DllMain이 호출됨.
    BOOL WINAPI DllMain(HANDLE h, DWORD r, LPVOID p)
    {
     if(r == DLL_PROCESS_ATTACH)
     {
      HWND hwnd = FindWindow(0, "계산기");
      old = (WNDPROC)SetWindowLong(hwnd, GWL_WNDPROC, (LONG)WndProc);
     }
     return TRUE;
    }

Designed by Tistory.