哎,刚开始确实难得看懂,不过耐心看下去就好了
首先很有必要知道几个结构
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);
//IDOK
return TRUE ;
case IDOK :
EndDialog (hwndDIG, 0) ;
return TRUE ;
case IDCANCEL :
EndDialog (hwndDIG, 0) ;
return TRUE ;
}
break ;
}
return FALSE ;
}
稍后给出详解...