分享
 
 
 

APIHOOK实例剖析

王朝vc·作者佚名  2006-01-08
窄屏简体版  字體: |||超大  

一、APIHOOK之dll部分

//////////////////////////////// APIHook_Dll.cpp ////////////////////////////////////////

// rivershan写于2002.9.23 //

/////////////////////////////////////////////////////////////////////////////////////////

#include "stdafx.h"

#include "APIHook_Dll.h"

#include <ImageHlp.h>

#include <tlhelp32.h>

#pragma comment(lib,"ImageHlp") //定义全局共享数据段

#pragma data_seg("Shared")

HMODULE hmodDll=NULL;

HHOOK hHook=NULL;

#pragma data_seg()

#pragma comment(linker,"/Section:Shared,rws") //设置全局共享数据段的属性

///////////////////////////////////// DllMain 函数 /////////////////////////////////////////

//dll的入口点

BOOL APIENTRY DllMain( HMODULE hModule,

DWORD ul_reason_for_call,

LPVOID lpReserved

)

{

switch(ul_reason_for_call)

{

case DLL_PROCESS_ATTACH:

//if(sHook)

case DLL_PROCESS_DETACH:

UnInstallHook();

break;

}

hmodDll=hModule;

return TRUE;

}

///////////////////////////////////// HookOneAPI 函数 /////////////////////////////////////////

//进行IAT转换的关键函数,其参数含义:

//pszCalleeModuleName:需要hook的模块名

//pfnOriginApiAddress:要替换的自己API函数的地址

//pfnDummyFuncAddress:需要hook的模块名的地址

//hModCallerModule:我们要查找的模块名称,如果没有被赋值,

// 将会被赋值为枚举的程序所有调用的模块

void WINAPI HookOneAPI(LPCTSTR pszCalleeModuleName,PROC pfnOriginApiAddress,

PROC pfnDummyFuncAddress,HMODULE hModCallerModule)

{

ULONG size;

//获取指向PE文件中的Import中IMAGE_DIRECTORY_DESCRIPTOR数组的指针

PIMAGE_IMPORT_DESCRIPTOR pImportDesc = (PIMAGE_IMPORT_DESCRIPTOR)

ImageDirectoryEntryToData(hModCallerModule,TRUE,IMAGE_DIRECTORY_ENTRY_IMPORT,&size);

if (pImportDesc == NULL)

return;

//查找记录,看看有没有我们想要的DLL

for (;pImportDesc->Name;pImportDesc++)

{

LPSTR pszDllName = (LPSTR)((PBYTE)hModCallerModule+pImportDesc->Name);

if (lstrcmpiA(pszDllName,pszCalleeModuleName) == 0)

break;

}

if (pImportDesc->Name == NULL)

{

return;

}

//寻找我们想要的函数

PIMAGE_THUNK_DATA pThunk =

(PIMAGE_THUNK_DATA)((PBYTE)hModCallerModule+pImportDesc->FirstThunk);//IAT

for (;pThunk->u1.Function;pThunk++)

{

//ppfn记录了与IAT表项相应的函数的地址

PROC * ppfn= (PROC *)&pThunk->u1.Function;

if (*ppfn == pfnOriginApiAddress)

{

//如果地址相同,也就是找到了我们想要的函数,进行改写,将其指向我们所定义的函数

WriteProcessMemory(GetCurrentProcess(),ppfn,&(pfnDummyFuncAddress),

sizeof(pfnDummyFuncAddress),NULL);

return;

}

}

}

//查找所挂钩的进程所应用的dll模块的

BOOL WINAPI HookAllAPI(LPCTSTR pszCalleeModuleName,PROC pfnOriginApiAddress,

PROC pfnDummyFuncAddress,HMODULE hModCallerModule)

{

if (pszCalleeModuleName == NULL)

{

return FALSE;

}

if (pfnOriginApiAddress == NULL)

{

return FALSE;

}

//如果没传进来要挂钩的模块名称,枚举被挂钩进程的所有引用的模块,

//并对这些模块进行传进来的相应函数名称的查找

if (hModCallerModule == NULL)

{

MEMORY_BASIC_INFORMATION mInfo;

HMODULE hModHookDLL;

HANDLE hSnapshot;

MODULEENTRY32 me = {sizeof(MODULEENTRY32)};

//MODULEENTRY32:描述了一个被指定进程所应用的模块的struct

VirtualQuery(HookOneAPI,&mInfo,sizeof(mInfo));

hModHookDLL=(HMODULE)mInfo.AllocationBase;

hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE,0);

BOOL bOk = Module32First(hSnapshot,&me);

while (bOk)

{

if (me.hModule != hModHookDLL)

{

hModCallerModule = me.hModule;//赋值

//me.hModule:指向当前被挂钩进程的每一个模块

HookOneAPI(pszCalleeModuleName,pfnOriginApiAddress,

pfnDummyFuncAddress,hModCallerModule);

}

bOk = Module32Next(hSnapshot,&me);

}

return TRUE;

}

//如果传进来了,进行查找

else

{

HookOneAPI(pszCalleeModuleName,pfnOriginApiAddress,

pfnDummyFuncAddress,hModCallerModule);

return TRUE;

}

return FALSE;

}

//////////////////////////////////// UnhookAllAPIHooks 函数 /////////////////////////////////////

//通过使pfnDummyFuncAddress与pfnOriginApiAddress相等的方法,取消对IAT的修改

BOOL WINAPI UnhookAllAPIHooks(LPCTSTR pszCalleeModuleName,PROC pfnOriginApiAddress,

PROC pfnDummyFuncAddress,HMODULE hModCallerModule)

{

PROC temp;

temp = pfnOriginApiAddress;

pfnOriginApiAddress = pfnDummyFuncAddress;

pfnDummyFuncAddress = temp;

return HookAllAPI(pszCalleeModuleName,pfnOriginApiAddress,

pfnDummyFuncAddress,hModCallerModule);

}

////////////////////////////////// GetMsgProc 函数 ////////////////////////////////////////

//钩子子程。与其它钩子子程不大相同,没做什么有意义的事情,继续调用下一个钩子子程,形成循环

LRESULT CALLBACK GetMsgProc(int code,WPARAM wParam,LPARAM lParam)

{

return CallNextHookEx(hHook,code,wParam,lParam);

}

//////////////////////////////////// InstallHook 函数 /////////////////////////////////////

//安装或卸载钩子,BOOL IsHook参数是标志位

//对要钩哪个API函数进行初始化

//我们这里装的钩子类型是WH_GETMESSAGE

void __declspec(dllexport) WINAPI InstallHook(BOOL IsHook,DWORD dwThreadId)

{

if(IsHook)

{

hHook=SetWindowsHookEx(WH_GETMESSAGE,(HOOKPROC)GetMsgProc,hmodDll,dwThreadId);

//GetProcAddress(GetModuleHandle("GDI32.dll"),"ExtTextOutA"):取得要钩的函数在所在dll中的地址

HookAllAPI("GDI32.dll",GetProcAddress(GetModuleHandle("GDI32.dll"),

"TextOutW"),(PROC)&H_TextOutW,NULL);

HookAllAPI("GDI32.dll",GetProcAddress(GetModuleHandle("GDI32.dll"),

"TextOutA"),(PROC)&H_TextOutA,NULL);

}

else

{

UnInstallHook();

UnhookAllAPIHooks("GDI32.dll",GetProcAddress(GetModuleHandle("GDI32.dll"),

"TextOutW"),(PROC)&H_TextOutW,NULL);

UnhookAllAPIHooks("GDI32.dll",GetProcAddress(GetModuleHandle("GDI32.dll"),

"TextOutA"),(PROC)&H_TextOutA,NULL);

}

}

///////////////////////////////////// UnInstallHook 函数 ////////////////////////////////////

//卸载钩子

BOOL WINAPI UnInstallHook()

{

UnhookWindowsHookEx(hHook);

return TRUE;

}

///////////////////////////////////// H_TextOutA 函数 /////////////////////////////////////////

//我们的替换函数,可以在里面实现我们所要做的功能

//这里我做的是显示一个对话框,指明是替换了哪个函数

BOOL WINAPI H_TextOutA(HDC hdc,int nXStart,int nYStart,LPCSTR lpString,int cbString)

{

MessageBox(NULL,"TextOutA","APIHook_Dll ---rivershan",MB_OK);

TextOutA(hdc,nXStart,nYStart,lpString,cbString);//返回原来的函数,以显示字符

return TRUE;

}

///////////////////////////////////// H_TextOutW 函数 /////////////////////////////////////////

//同上

BOOL WINAPI H_TextOutW(HDC hdc,int nXStart,int nYStart,LPCWSTR lpString,int cbString)

{

MessageBox(NULL,"TextOutW","APIHook_Dll ---rivershan",MB_OK);

TextOutW(hdc,nXStart,nYStart,lpString,cbString);//返回原来的函数,以显示字符

return TRUE;

}

**********************************************************************************************

**********************************************************************************************

//////////////////////////////// APIHook_Dll.h ////////////////////////////////////////

// rivershan写于2002.9.23 //

/////////////////////////////////////////////////////////////////////////////////////////

//dll头文件,用于声明函数

void __declspec(dllexport) WINAPI InstallHook(BOOL,DWORD);

BOOL WINAPI UnInstallHook();

LRESULT CALLBACK GetMsgProC(int code,WPARAM wParam,LPARAM lParam);

void WINAPI HookOneAPI(LPCTSTR pszCalleeModuleName,PROC pfnOriginApiAddress,

PROC pfnDummyFuncAddress,HMODULE hModCallerModule);

BOOL WINAPI HookAllAPI(LPCTSTR pszCalleeModuleName,PROC pfnOriginApiAddress,

PROC pfnDummyFuncAddress,HMODULE hModCallerModule);

BOOL WINAPI UnhookAllAPIHooks(LPCTSTR pszCalleeModuleName,PROC pfnOriginApiAddress,

PROC pfnDummyFuncAddress,HMODULE hModCallerModule);

BOOL WINAPI H_TextOutA(HDC, int, int, LPCSTR, int);

BOOL WINAPI H_TextOutW(HDC, int, int, LPCWSTR, int);

BOOL WINAPI H_ExtTextOutA(HDC, int, int, UINT, CONST RECT *,LPCSTR, UINT, CONST INT *);

BOOL WINAPI H_ExtTextOutW(HDC, int, int, UINT, CONST RECT *,LPCWSTR, UINT, CONST INT *);

**********************************************************************************************

**********************************************************************************************

;APIHook_Dll之def文件

LIBRARY APIHook_Dll.dll

EXPORT

InstallHook

二、APIHOOK之exe部分

//////////////////////////// APIHook_EXEDlg.cpp /////////////////////////////////////////

// rivershan写于2002.9.23 //

/////////////////////////////////////////////////////////////////////////////////////////

#include "stdafx.h"

#include "APIHook_EXE.h"

#include "APIHook_EXEDlg.h"

#include "APIHook_Dll.h"

#ifdef _DEBUG

#define new DEBUG_NEW

#undef THIS_FILE

static char THIS_FILE[] = __FILE__;

#endif

/////////////////////////////////////////////////////////////////////////////

// CAPIHook_EXEDlg dialog

CAPIHook_EXEDlg::CAPIHook_EXEDlg(CWnd* pParent /*=NULL*/)

: CDialog(CAPIHook_EXEDlg::IDD, pParent)

{

//{{AFX_DATA_INIT(CAPIHook_EXEDlg)

// NOTE: the ClassWizard will add member initialization here

//}}AFX_DATA_INIT

// Note that LoadIcon does not require a subsequent DestroyIcon in Win32

m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);

}

void CAPIHook_EXEDlg::DoDataExchange(CDataExchange* pDX)

{

CDialog::DoDataExchange(pDX);

//{{AFX_DATA_MAP(CAPIHook_EXEDlg)

// DDX_Control(pDX, IDC_EDIT1, m_Edit);

//}}AFX_DATA_MAP

}

BEGIN_MESSAGE_MAP(CAPIHook_EXEDlg, CDialog)

//{{AFX_MSG_MAP(CAPIHook_EXEDlg)

ON_WM_PAINT()

ON_WM_QUERYDRAGICON()

ON_BN_CLICKED(IDC_BUTTON_OUT, OnButtonOut)

ON_BN_CLICKED(IDC_BUTTON_BEGIN, OnButtonBegin)

ON_BN_CLICKED(IDC_BUTTON_STOP, OnButtonStop)

//}}AFX_MSG_MAP

END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////

// CAPIHook_EXEDlg message handlers

BOOL CAPIHook_EXEDlg::OnInitDialog()

{

CDialog::OnInitDialog();

// Set the icon for this dialog. The framework does this automatically

// when the application's main window is not a dialog

SetIcon(m_hIcon, TRUE); // Set big icon

SetIcon(m_hIcon, FALSE); // Set small icon

// TODO: Add extra initialization here

return TRUE; // return TRUE unless you set the focus to a control

}

// If you add a minimize button to your dialog, you will need the code below

// to draw the icon. For MFC applications using the document/view model,

// this is automatically done for you by the framework.

void CAPIHook_EXEDlg::OnPaint()

{

if (IsIconic())

{

CPaintDC dc(this); // device context for painting

SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);

// Center icon in client rectangle

int cxIcon = GetSystemMetrics(SM_CXICON);

int cyIcon = GetSystemMetrics(SM_CYICON);

CRect rect;

GetClientRect(&rect);

int x = (rect.Width() - cxIcon + 1) / 2;

int y = (rect.Height() - cyIcon + 1) / 2;

// Draw the icon

dc.DrawIcon(x, y, m_hIcon);

}

else

{

CDialog::OnPaint();

}

}

// The system calls this to obtain the cursor to display while the user drags

// the minimized window.

HCURSOR CAPIHook_EXEDlg::OnQueryDragIcon()

{

return (HCURSOR) m_hIcon;

}

///////////////////////////////////// OnButtonOut 函数 //////////////////////////////////////

//使用TextOut函数

void CAPIHook_EXEDlg::OnButtonOut()

{

// TODO: Add your control notification handler code here

HDC hdc = ::GetDC(GetSafeHwnd());

::TextOutA(hdc,0,0,"APIHOOK_EXE ---rivershan",30);

UpdateWindow();

}

///////////////////////////////////// OnButtonBegin 函数 ////////////////////////////////////

//开始挂钩,这里我们挂的是自身这个APIHook_EXE这个程序

void CAPIHook_EXEDlg::OnButtonBegin()

{

DWORD dwThreadId = GetWindowThreadProcessId(m_hWnd,NULL);//获得自身进程ID

InstallHook(TRUE,dwThreadId);

}

///////////////////////////////////// OnButtonStop 函数 ////////////////////////////////////

//取消挂钩

void CAPIHook_EXEDlg::OnButtonStop()

{

InstallHook(FALSE,0);

}

三、APIHOOK之集成

1. 用 VC++新建一个 Win32 Dynamic-Link Library 程序,命名为 APIHook_Dll。接下来选择第二项 A Simple DLL Project;

2. 新建一头文件,命名为 APIHook_Dll.h。删除工程中 APIHook_Dll.cpp文件中原来的内容,然后把上面的 APIHook_Dll.cpp 和 APIHook_Dll.h文件的内容全部复制到新建的这个工程的 .cpp及 .h文件中来;

3. 新建一 Text文件,命名为 APIHook_Dll.def。复制上面的def文件内容。

4. 编译;

5. 新建一 MFC APPWizard(exe)程序,命名为 APIHook_EXE。接着选择第三项,基于对话框的程序,其它默认;

6. 删除原来对话框上的控件,然后新建三个按钮ID分别为:IDC_BUTTON_BEGIN、IDC_BUTTON_STOP、IDC_BUTTON_OUT,Caption分别为:Bigin Hook、Stop Hook、Text Out。不要让这三个按钮出于对话框客户区的最上面就行;

7. 拷贝 APIHook_Dll.h文件到 APIHook_EXE程序目录下,然后加到 APIHook_EXE的头文件夹中。

8. 删除工程中 APIHook_EXEDlg.cpp文件中原来的内容,然后把上面的 APIHook_EXEDlg.cpp文件的内容全部复制到新建的这个工程的 .cpp文件中来;

9. 打开 Project->Setting菜单,选择第四项link,在 Object/library moduls里添加我们的dll的lib文件的路径:..\APIHook_Dll\Debug\APIHook_Dll.lib;

10. 编译;

11. 把 APIHook_Dll.dll文件放在 APIHook_Dll.exe程序的同一个文件夹内;

12. 运行程序,点击 Bigin Hook按钮,开始挂钩。再点击 Text Out按钮会跳出对话框并且会在程序中显示所要显示的字。点击 Stop Hook然后在点击 Text Out按钮就没有对话框出现了。

四、一些说明

1、我这个 HookAPI是使用了 Jeffrey Richter的改写程序的 IAT来实现的,也可以用跳转函数入口点的方法来实现,这个我没做研究。:)

2、我的一些心得:

所谓 HookAPI,就是改写程序的 IAT,再调用我自己写的用于替换原API函数的函数。在我们自己写的API函数中,我们可以进行我们想要的工作。之后呢,可以把原来的函数传回去,也可以不传回去,只要你设计好了就行。

而所谓调用自己的函数,就是把原函数参数都传给我的替换函数。我们就可以利用这些参数去干我们想做的事。而系统呢,我想由于微软设置的这个钩子的目的(我这么认为的),所以不会去检查替换函数是否就是原函数,只要参数、返回值符合条件就行,要不会出错。替换函数的返回值最好是原函数,否则有可能会出错

HookAPI时,exe程序起到的作用就是进行Hook,把dll注入到要Hook的程序,并且传回要挂接的进程的ID或者全局钩子,以便查询所要挂接的模块的IAT。如果不注入进去,系统不会让你去查询IAT的。DLL做的事情是确定要挂接哪个函数和这个函数在哪个DLL中等。

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有