输入表与HOOK

来源:互联网 发布:大华端口号 编辑:程序博客网 时间:2024/04/29 14:40

难过哎,刚开始确实难得看懂,不过耐心看下去就好了


首先很有必要知道几个结构 


IMAGE_DOS_HEADER *pidh;    //DOS头
MAGE_NT_HEADERS *pinh;   //NT头
IMAGE_DATA_DIRECTORY *pSymbolTable;  //数据目录
MAGE_IMPORT_DESCRIPTOR *piid;   //输入表

IMAGE_THUNK_DATA   //函数结构



IMAGE_DOS_HEADER 通过程序的模块句柄换转获得    (IMAGE_DOS_HEADER *)模块句柄;

 MAGE_NT_HEADERS  通过 基址 + DOS头结构中的 e_ifanew 标志   给出 .  机制就是将模块句柄强制转换 DWORD类型

IMAGE_DATA_DIRECTORY  通过 NT头的可选头 DataDirectory[1] 成员就是输入表数据目录

MAGE_IMPORT_DESCRIPTOR  通过 基址 + 输入表.VirtualAddress   给出输入表模块的第一个DLL

IMAGE_THUNK_DATA  基址 + 输入表.OriginalFirstThunk  等于 函数名 的 RVA

IMAGE_THUNK_DATA  基址 + 输入表.FirstThunk等于 IAT ,也就是函数呼叫地址




下面给出例子源码,c++程序


#include <windows.h>#include <iostream>typedef int (WINAPI *MsgBoxType)(HWND,LPCWSTR,LPCWSTR,UINT); MsgBoxType oldMsg;  /*API原入口地址*/int WINAPI  MyMessage(HWND hWnd ,LPCWSTR M1,LPCWSTR M2, UINT M3);DWORD APIAddress; /*存储API入口地址的地方的地址*/int WINAPI WinMain( __in HINSTANCE hInstance, __in_opt HINSTANCE hPrevInstance, __in LPSTR lpCmdLine, __in int nShowCmd ){/* 1 */HANDLE hCurrent = GetModuleHandle(NULL);/* 2 */IMAGE_DOS_HEADER *pidh;    //DOS头/* 3 */IMAGE_NT_HEADERS *pinh;   //NT头/* 4 */IMAGE_DATA_DIRECTORY *pSymbolTable;  //数据目录/* 5 */IMAGE_IMPORT_DESCRIPTOR *piid;   //输入表/* 6 */pidh = (IMAGE_DOS_HEADER *)hCurrent; /* 7 */pinh = (IMAGE_NT_HEADERS *)((DWORD)hCurrent + pidh->e_lfanew);  /* 8 */pSymbolTable = &pinh->OptionalHeader.DataDirectory[1]; //输入表/* 9 */piid =(IMAGE_IMPORT_DESCRIPTOR *)((DWORD)hCurrent +  pSymbolTable->VirtualAddress); //输入表的相对虚拟地址RVA,//0x00cb0000+/*10 */do {/*11 */    IMAGE_THUNK_DATA *pitd,*pitd2;/*12 */    pitd = (IMAGE_THUNK_DATA *)((DWORD)hCurrent + piid->OriginalFirstThunk);  //pitd 等于函数名的RVA/*13 */    pitd2 = (IMAGE_THUNK_DATA *)((DWORD)hCurrent + piid->FirstThunk);     //pitd2 等于函数的RVA/*14 */    do {/*15 */ IMAGE_IMPORT_BY_NAME *piibn;/*16 */ piibn = (IMAGE_IMPORT_BY_NAME *)((DWORD)hCurrent +  *((DWORD *)pitd));/*17 */ PROC *ppfn = (PROC *)(pitd2->u1.Function);/*18 */ if (!strcmp("MessageBoxW",(char *)piibn->Name)) {/*19 */     oldMsg = (MsgBoxType)(ppfn);/*20 */     DWORD addr = (DWORD)MyMessage;/*21 */     DWORD written = 0;/* 改变内存读写状态 *//*22 */     DWORD oldAccess;/*23 */     VirtualProtect(&pitd2->u1.Function,sizeof(DWORD),PAGE_WRITECOPY,&oldAccess);/*24 */     APIAddress = (DWORD)&pitd2->u1.Function;/* 向内存映像写入数据 *//*25 */     WriteProcessMemory(GetCurrentProcess(),&pitd2->u1.Function, &addr,sizeof(DWORD), &written);/*26 */ }/*27 */ pitd++;pitd2++;/*28 */    } while (pitd->u1.Function);/*29 */    piid++;/*30 */} while (piid->FirstThunk + piid->Characteristics + piid->ForwarderChain + piid->Name + piid->TimeDateStamp);MessageBoxW(NULL,L"呵呵",NULL,NULL);return 0;}int WINAPI  MyMessage(HWND hWnd ,LPCWSTR M1,LPCWSTR M2, UINT M3) {/* 这是用来替换的函数 */return oldMsg(hWnd,L"被修改啦",M2,MB_OK);}

大致过程就是获得指定函数的详细信息, 比较函数名,如果等于你想要HOOK的,就改写内存地址的属性,然后修改 函数的IAT为你自己的,


接下来就是 跨进程 API HOOK ,先给出源码


DLL源码

#include <windows.h>#include <iostream>/*DLL 入口函数*/HHOOK hook;HINSTANCE hIns;HWND wind;DWORD Treeid;LRESULT CALLBACK GetMsgProc(int,WPARAM, LPARAM);//void UnHookAPIHook();typedef int (WINAPI *MsgBoxType)(HWND,LPCWSTR,LPCWSTR,UINT); MsgBoxType oldMsg;  /*API原入口地址*/int WINAPI  MyMessage(HWND hWnd ,LPCWSTR M1,LPCWSTR M2, UINT M3);DWORD APIAddress; /*存储API入口地址的地方的地址*/int HookApi() ;BOOL WINAPI DllMain(HINSTANCE hInst, DWORD reason,LPVOID lpvReserved){switch (reason){case DLL_PROCESS_ATTACH://MessageBoxW(NULL,L"加载DLL",NULL,NULL);hIns = hInst;break;case DLL_PROCESS_DETACH://MessageBoxW(NULL,L"装卸DLL",NULL,NULL);break;}return true;}extern "C" __declspec(dllexport) BOOL SetAPIHook(HWND target) {wind = FindWindowW(NULL,L"Dialog");Treeid =  GetWindowThreadProcessId(wind,NULL);hook = SetWindowsHookEx(WH_GETMESSAGE,GetMsgProc,hIns,Treeid);     //PostThreadMessage(pg_data->idTarget,WM_ENABLEAPIHOOK,0,0);return TRUE;}LRESULT CALLBACK GetMsgProc(int nCode,WPARAM wParam, LPARAM lParam) {if (nCode == HC_ACTION) {MSG *msg = (MSG *)lParam;//MessageBoxW(wind,L"失去焦点",NULL,NULL);if (msg->message == WM_KEYDOWN){HookApi();MessageBoxW(wind,L"失去焦点",NULL,NULL);}}return CallNextHookEx(hook,nCode,wParam,lParam);}int HookApi() {/* 1 */HANDLE hCurrent = GetModuleHandle(NULL);/* 2 */IMAGE_DOS_HEADER *pidh;    //DOS头/* 3 */IMAGE_NT_HEADERS *pinh;   //NT头/* 4 */IMAGE_DATA_DIRECTORY *pSymbolTable;  //数据目录/* 5 */IMAGE_IMPORT_DESCRIPTOR *piid;   //输入表/* 6 */pidh = (IMAGE_DOS_HEADER *)hCurrent; /* 7 */pinh = (IMAGE_NT_HEADERS *)((DWORD)hCurrent + pidh->e_lfanew);  /* 8 */pSymbolTable = &pinh->OptionalHeader.DataDirectory[1]; //输入表/* 9 */piid =(IMAGE_IMPORT_DESCRIPTOR *)((DWORD)hCurrent +  pSymbolTable->VirtualAddress); //输入表的相对虚拟地址RVA,//0x00cb0000+/*10 */do {/*11 */    IMAGE_THUNK_DATA *pitd,*pitd2;/*12 */    pitd = (IMAGE_THUNK_DATA *)((DWORD)hCurrent + piid->OriginalFirstThunk);  //pitd 等于函数名的RVA/*13 */    pitd2 = (IMAGE_THUNK_DATA *)((DWORD)hCurrent + piid->FirstThunk);     //pitd2 等于函数的RVA/*14 */    do {/*15 */ IMAGE_IMPORT_BY_NAME *piibn;/*16 */ piibn = (IMAGE_IMPORT_BY_NAME *)((DWORD)hCurrent +  *((DWORD *)pitd));/*17 */ PROC *ppfn = (PROC *)(pitd2->u1.Function);/*18 */ if (!strcmp("MessageBoxW",(char *)piibn->Name)) {/*19 */     oldMsg = (MsgBoxType)(ppfn);/*20 */     DWORD addr = (DWORD)MyMessage;/*21 */     DWORD written = 0;/* 改变内存读写状态 *//*22 */     DWORD oldAccess;/*23 */     VirtualProtect(&pitd2->u1.Function,sizeof(DWORD),PAGE_WRITECOPY,&oldAccess);/*24 */     APIAddress = (DWORD)&pitd2->u1.Function;/* 向内存映像写入数据 *//*25 */     WriteProcessMemory(GetCurrentProcess(),&pitd2->u1.Function, &addr,sizeof(DWORD), &written);return 0;/*26 */ }/*27 */ pitd++;pitd2++;/*28 */    } while (pitd->u1.Function);/*29 */    piid++;/*30 */} while (piid->FirstThunk + piid->Characteristics + piid->ForwarderChain + piid->Name + piid->TimeDateStamp);}int WINAPI  MyMessage(HWND hWnd ,LPCWSTR M1,LPCWSTR M2, UINT M3) {/* 这是用来替换的函数 */MessageBoxW(hWnd,L"呵呵",NULL,NULL);return oldMsg(hWnd,L"被修改啦",M2,MB_OK);}extern "C" __declspec(dllexport) void UnHookAPIHook(){UnhookWindowsHookEx(hook);}


程序源码


#include <windows.h>#include <iostream>#include "resource.h"typedef BOOL (*PSetAPIHook)(HWND);typedef void (*PUnHookAPIHook)();BOOL CALLBACK DialogProc(HWND hwndDIG , UINT UMsg , WPARAM wParam, LPARAM lParam);HMODULE hDll = NULL;PSetAPIHook SetAPIHook;PUnHookAPIHook UnHookAPIHook;int WINAPI WinMain( __in HINSTANCE hInstance, __in_opt HINSTANCE hPrevInstance, __in LPSTR lpCmdLine, __in int nShowCmd ){DialogBoxW(hInstance,(wchar_t*)IDD_DIALOG1 ,NULL,DialogProc);return 0;}BOOL CALLBACK DialogProc(HWND hwndDIG , UINT UMsg , WPARAM wParam, LPARAM lParam){switch (UMsg){case   WM_INITDIALOG :return TRUE ;case   WM_COMMAND :switch (LOWORD (wParam)){case   IDC_BUTTON1 :hDll = LoadLibraryW(L"例子.dll");SetAPIHook = (PSetAPIHook)GetProcAddress(hDll,"SetAPIHook");SetAPIHook(NULL);//MessageBoxW(hwndDIG,L"这是按钮1",NULL,NULL);return TRUE ;case   IDC_BUTTON2 ://hDll = LoadLibraryW(L"例子.dll");UnHookAPIHook = (PUnHookAPIHook)GetProcAddress(hDll,"UnHookAPIHook");UnHookAPIHook();//MessageBoxW(hwndDIG,L"这是按钮2",NULL,NULL);//IDOKreturn TRUE ;case   IDOK :EndDialog (hwndDIG, 0) ;return TRUE ;case   IDCANCEL :EndDialog (hwndDIG, 0) ;return TRUE ;}break ;}return FALSE ;}

稍后给出详解...


原创粉丝点击