API 후킹

컴퓨터 이야기/C++ 2010. 7. 19. 02:53
API 후킹이 뭐냐면, 말 그대로 다른 프로그램이 특정 API 를 호출할 때 낚아채는 기법을 말함

아래 void main() 에서 핸들값을 적절한 다른 값으로 바꾸세요.

아래 소스 방법은 Dll Injection 임. 메모리에 로드된 import table 을 바꿔치기 해서 내가 원하는 dll 을 호출하게 만듬.
#include <iostream>
#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");


        // 계산기의 주소공간에 메모리를 할당하고, 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, &amp;len);

        // 계산기에 새로운 스레드를 만든다.
        // CreateRemoteThread는 다른 프로세스에 스레드를 생성시킨다.
        HANDLE hThread = CreateRemoteThread(hProcess, // 계산기 핸들
                0, 0, 
                f, p, // 함수, 파리미터
                0, 0);


        CloseHandle(hThread);
        CloseHandle(hProcess);
}

void main()
{
        using namespace std;
        HWND hwnd = (HWND)0x0005115A;
        DWORD pid;
        DWORD tid = GetWindowThreadProcessId(hwnd, &amp;pid);
        DllInject(pid, "C:\\spy1.dll");
}
[DLL]
#include <urlmon.h>
#include <iostream>
#include <commctrl.h>
#include<windows.h>
#include<dbghelp.h>
#include<stdio.h>
#pragma comment(lib,"dbghelp.lib")



// Repalce 부분..

void Replace( char *dll_name,                          // dll 이름

                                         PROC proc,             // hooking 할 함수

                                         PROC new_proc,     // 새로운 함수

                                         HMODULE hMod)     // .idata 섹션을 조사할 모듈 핸들

                                                                         // (exe 주소)

{

             // hMod 주소에서 .idata의 위치를 찾는다.

             ULONG sz;

             PIMAGE_IMPORT_DESCRIPTOR pImport = (PIMAGE_IMPORT_DESCRIPTOR)

                        ImageDirectoryEntryToDatahMod, 

                        TRUE,IMAGE_DIRECTORY_ENTRY_IMPORT,       // IMPORT하고 있는 곳

                         &amp;sz);



             if(pImport==0)                // .idata section이 없는 경우.

                          return;



             //===================================================

             // .idata에서 원하는 dll의 위치를 찾는다.

             for(;pImport-&gt;Name;++pImport)

             {

                          char* p = (char*)hMod+pImport-&gt;Name;



                          if(strcmpi(p,dll_name)==0)                   // 찾은 경우

                                       break;

             }

             if(pImport-&gt;Name==0)             return; // .idata항목에 해당하는 DLL이 없다.

             //====================================================

             // thunktable에서 원하는 함수를 찾아서 바꾸어 쓴다.

             PIMAGE_THUNK_DATA pThunk=(PIMAGE_THUNK_DATA)

             ((char*)hMod+pImport-&gt;FirstThunk);



             

             for(;pThunk-&gt;u1.Function;++pThunk)

             {

                          PROC* pf=(PROC*)&amp;(pThunk-&gt;u1.Function);



                          if(*pf==proc)                // 찾은 경우.

                          {

                                       *pf=new_proc;              // 덮어쓴다.

                          }

             }

}



// MessageBoxW를 대신할 함수

UINT WINAPI foo(HWND hwnd,PCWSTR s,PCWSTR title,UINT btn)

{

             // Console 참을 생성해서 출력해준다.



             AllocConsole();



             freopen("CONOUT$","wt",stdout);



             printf("Messagebox 호출");



             return 0;

}



BOOL WINAPI DllMain(HANDLE h,DWORD r,void*p)

{

             if(r==DLL_PROCESS_ATTACH)

             {

                          Replace("User32.dll",

                                       (PROC)MessageBoxA,

                                       (PROC)foo,

                                       GetModuleHandle(0));

             }

             return TRUE;

}



: