HOOKAPI之修改IAT法則


HOOK是一種WINDOWS下存在很久的技術了。
HOOK一般分兩種1。HOOK MESSAGE  2。HOOK API 本問討論的是HOOK API之修改IAT。(如果你是HOOK高手就不要看了)
在最初學HOOK-API的時候通常都是通過覆蓋地址和修改IAT的方法。
通過這兩種技術,我們基本都可以實現對本進程的API函數進行HOOK了。但是在高興之余會有點遺憾,
怎么才能HOOK其他進程的API函數呢?怎么才能對一個API函數進行全局的HOOK呢?
下面是我的一個簡單的“HOOK其他進程API函數”的實現。(對另一進程的MessageBoxA這個函數進行HOOK)

其實里面的應用了兩個技術
1。遠程線程注入
2。修改IAT,HOOK-API

好了貼出代碼如下:
一共是3個文件
install.c  注入程序
fundll.cpp  DLL程序
test.cpp  測試程序  

CODE:

//-------------------------install.c--------------------------
//
//install.c

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

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

const char *pkill="fundll.dll";                //DLL文件的路徑

//這個路徑很有意思,這個路徑是相對於目標進程的,而不是自身進程。
//所以要嘛寫成絕對路徑,要嘛寫成相對於目標進程的相對路徑。
//如果寫成相對於自身的路徑就要麻煩了,本程序就找不到DLL文件了。

char *prosess="test.exe";   //要注入的進程名(目標進程名)

int main()
{

       //變量聲明
        HANDLE hSnap;
        HANDLE hkernel32;        //被注入進程的句柄
        PROCESSENTRY32 pe;
        BOOL bNext;
        HANDLE hToken;
        TOKEN_PRIVILEGES tp;
        LUID Luid;
        LPVOID p;
        FARPROC pfn;
        //提升進程權限
        if (!OpenProcessToken(GetCurrentProcess(),TOKEN_ADJUST_PRIVILEGES|TOKEN_QUERY,&hToken))
        {
                return 1;
        }

        if (!LookupPrivilegeValue(NULL,SE_DEBUG_NAME,&Luid))
        {
                return 1;
        }

        tp.PrivilegeCount = 1;
        tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
        tp.Privileges[0].Luid = Luid;

        if (!AdjustTokenPrivileges(hToken,0,&tp,sizeof(TOKEN_PRIVILEGES),NULL,NULL))
        {
                return 1;
        }
        

        //枚舉進程
        pe.dwSize = sizeof(pe);
        hSnap=CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
        bNext=Process32First(hSnap, &pe);
        while(bNext)
        {
                if(!stricmp(pe.szExeFile,prosess))                //--->>
                {
                        hkernel32=OpenProcess(PROCESS_CREATE_THREAD|PROCESS_VM_WRITE|PROCESS_VM_OPERATION,1,pe.th32ProcessID);
                        break;
                }
                bNext=Process32Next(hSnap, &pe);
        }

        CloseHandle(hSnap);


          //注入,關鍵所在!

        //1,在目標進程分配線程函數的參數空間大小
        p=VirtualAllocEx(hkernel32,NULL,strlen(pkill),MEM_COMMIT,PAGE_READWRITE);

        //2,把參數寫到目標進程分配的空間中
        WriteProcessMemory(hkernel32,p,pkill,strlen(pkill),NULL);

        //3,獲取LoadLiabray函數的地址,作為新線程的線程函數調用
        pfn=GetProcAddress(GetModuleHandle("kernel32.dll"),"LoadLibraryA");

        //在目標空間創建新線程,線程函數地址是pfn,函數的參數地址是p
        CreateRemoteThread(hkernel32,NULL,0,pfn,p,NULL,0);

        return 0;
}


//----------------------fundll.cpp-----------------------------
//
//fundll.cpp

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

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

PIMAGE_DOS_HEADER  pDosHeader;
PIMAGE_NT_HEADERS  pNTHeaders;
PIMAGE_OPTIONAL_HEADER   pOptHeader;
PIMAGE_IMPORT_DESCRIPTOR  pImportDescriptor;
PIMAGE_THUNK_DATA         pThunkData;
PIMAGE_IMPORT_BY_NAME     pImportByName;
HMODULE hMod;


// 定義MessageBoxA函數原型
typedef int (WINAPI *PFNMESSAGEBOX)(HWND, LPCSTR, LPCSTR, UINT uType);
int WINAPI MessageBoxProxy(IN HWND hWnd, IN LPCSTR lpText, IN LPCSTR lpCaption, IN UINT uType);

int * addr = (int *)MessageBoxA;        //保存函數的入口地址
int * myaddr = (int *)MessageBoxProxy;


void ThreadProc(void *param);//線程函數

//-------------------------------------------------------主函數開始

BOOL WINAPI DllMain(HINSTANCE hinstDLL,DWORD fdwReason,LPVOID lpvReserved)
{
        if(fdwReason==DLL_PROCESS_ATTACH)        
                _beginthread(ThreadProc,0,NULL);        //創建線程,調用ThreadProc

        return TRUE;
}


//線程函數,修改IAT地址

void ThreadProc(void *param)
{
        //------------hook api----------------
        hMod = GetModuleHandle(NULL);

        pDosHeader = (PIMAGE_DOS_HEADER)hMod;
        pNTHeaders = (PIMAGE_NT_HEADERS)((BYTE *)hMod + pDosHeader->e_lfanew);
        pOptHeader = (PIMAGE_OPTIONAL_HEADER)&(pNTHeaders->OptionalHeader);

        pImportDescriptor = (PIMAGE_IMPORT_DESCRIPTOR)((BYTE *)hMod + pOptHeader->DataDirectory[1].VirtualAddress);

        while(pImportDescriptor->FirstThunk)
        {
                char * dllname = (char *)((BYTE *)hMod + pImportDescriptor->Name);

                pThunkData = (PIMAGE_THUNK_DATA)((BYTE *)hMod + pImportDescriptor->OriginalFirstThunk);

                int no = 1;
                while(pThunkData->u1.Function)
                {
                        char * funname = (char *)((BYTE *)hMod + (DWORD)pThunkData->u1.AddressOfData + 2);
                        PDWORD lpAddr = (DWORD *)((BYTE *)hMod + (DWORD)pImportDescriptor->FirstThunk) +(no-1);
               
                        //修改內存的部分
                        if((*lpAddr) == (int)addr)
                        {
                                //修改內存頁的屬性
                                DWORD dwOLD;
                                MEMORY_BASIC_INFORMATION  mbi;
                                VirtualQuery(lpAddr,&mbi,sizeof(mbi));
                                VirtualProtect(lpAddr,sizeof(DWORD),PAGE_READWRITE,&dwOLD);
                                
                                WriteProcessMemory(GetCurrentProcess(),
                                                lpAddr, &myaddr, sizeof(DWORD), NULL);    //此處,修改了IAT的地址為我們自己定義函數的地址
                                //恢復內存頁的屬性
                                VirtualProtect(lpAddr,sizeof(DWORD),dwOLD,0);
                        }
            //---------
                        no++;
                        pThunkData++;
                }

                pImportDescriptor++;
        }
        //-------------------HOOK END-----------------
}

//new messagebox function
int WINAPI MessageBoxProxy(IN HWND hWnd, IN LPCSTR lpText, IN LPCSTR lpCaption, IN UINT uType)
{
        return         ((PFNMESSAGEBOX)addr)(NULL, "gxter_test", "gxter_title", 0);
        //這個地方可以寫出對這個API函數的處理代碼
}


//----------------------------test.cpp------------------------------------
//test.cpp

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

int main()
{
        printf("test---/n");
        while(1)
        {
                getchar();
                MessageBoxA(NULL, "原函數", "09HookDemo", 0);
        }
        return 0;
}



測試過程:先運行TEST不要關閉(建立目標),再運行install(進行注入)。但要注意FUNDLL和TEST文件位置。

上面的代碼進本上就實現了對其他進程的API進行HOOK了。
但還有一個問題就是對“API函數進行全局的HOOK”。我的想法就是注入所有進程就可以實現了。
只要簡單的改一下上面的代碼就可以實現了。 這好象有點像SetWindowsHookEx這個函數的的實現過程。
以上就是我想法了,如果在什么地方有錯誤還請糾正。


參考資料:
《WINDOWS 程序設計》
《WINDOWS 核心編程》


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM