Hook技术简单介绍

Hook技术简单介绍Hook主要就是通过一定手段在程序执行过程中进行干预。IATHook篡改MessageBox借用accills的例子#include<windows.h>#include<stdio.h>#include<imagehlp.h>#pragmacomment(lib,"imagehlp.lib")//以MessageBoxA的…

大家好,又见面了,我是你们的朋友全栈君。

Hook主要就是通过一定手段在程序执行过程中进行干预。

IAT Hook 篡改MessageBox

借用accills的例子

#include <windows.h>
#include <stdio.h>
#include <imagehlp.h>
#pragma comment(lib,"imagehlp.lib")


//以MessageBoxA的原型定义一个函数指针类型
typedef int 
(WINAPI *PFN_MessageBoxA)(
	HWND hWnd,          // handle of owner window
	LPCTSTR lpText,     // address of text in message box
	LPCTSTR lpCaption,  // address of title of message box
	UINT uType          // style of message box
	);

//以MessageBoxA的原型定义一个函数来替代原始的MessageBoxA
int WINAPI My_MessageBoxA(
	HWND hWnd,          // handle of owner window
	LPCTSTR lpText,     // address of text in message box
	LPCTSTR lpCaption,  // address of title of message box
	UINT uType          // style of message box
	);

//存在以下关系
//*(*pThunkPointer) == *pOriginalFuncAddr ;
BOOL InstallModuleIATHook(
	HMODULE hModToHook,
	char *szModuleName, 
	char *szFuncName,
	PVOID ProxyFunc,
	PULONG_PTR *pThunkPointer,
	ULONG_PTR *pOriginalFuncAddr
	);

VOID ShowMsgBox(char *szMsg);
BOOL IAT_InstallHook();
VOID IAT_UnInstallHook();
BOOL IsWow64();
//保存原始MessageBoxA的地址
PFN_MessageBoxA OldMessageBox=NULL;
//指向IAT中pThunk的地址
PULONG_PTR g_PointerToIATThunk = NULL;

int main(int argc, char *argv[ ])
{
	BOOL bIsWow64 = IsWow64();
	printf("IsWow64 = %d\n",bIsWow64);
	ShowMsgBox("Before IAT Hook");
	IAT_InstallHook();
	ShowMsgBox("After  IAT Hook");
	IAT_UnInstallHook();
	ShowMsgBox("After  IAT Hook UnHooked");
	return 0;
}

//之所以把这个调用单独放在一个函数中,是因为Release模式下对调用进行了优化,第二次调用时直接采用了寄存器寻址而不是导入表
//因此,单独放在一个函数中可以避免这个情况。

VOID ShowMsgBox(char *szMsg)
{
	MessageBoxA(NULL,szMsg,"Test",MB_OK);
}


int WINAPI My_MessageBoxA(
	HWND hWnd,          // handle of owner window
	LPCTSTR lpText,     // address of text in message box
	LPCTSTR lpCaption,  // address of title of message box
	UINT uType          // style of message box
	)
{	
	//在这里,你可以对原始参数进行任意操作
	int ret;
	char newText[1024]={0};
	char newCaption[256]="pediy.com";
	printf("有人调用MessageBox!\n");
	//在调用原函数之前,可以对IN(输入类)参数进行干涉
	lstrcpy(newText,lpText);//为防止原函数提供的缓冲区不够,这里复制到我们自己的一个缓冲区中再进行操作
	lstrcat(newText,"\n\tMessageBox Hacked by pediy.com!");//篡改消息框内容
	uType|=MB_ICONERROR;//增加一个错误图标
	ret = OldMessageBox(hWnd,newText,newCaption,uType);//调用原MessageBox,并保存返回值
	//调用原函数之后,可以继续对OUT(输出类)参数进行干涉,比如网络函数的recv,可以干涉返回的内容
	return ret;//这里你还可以干涉原始函数的返回值
	
}

BOOL IAT_InstallHook()
{
	BOOL bResult = FALSE ;
	HMODULE hCurExe = GetModuleHandle(NULL);
	PULONG_PTR pt ;
	ULONG_PTR OrginalAddr;
	bResult = InstallModuleIATHook(hCurExe,"user32.dll","MessageBoxA",(PVOID)My_MessageBoxA,&pt,&OrginalAddr);
	if (bResult)
	{
		printf("[*]Hook安装完毕! pThunk=0x%p  OriginalAddr = 0x%p\n",pt,OrginalAddr);
		g_PointerToIATThunk = pt ;
		OldMessageBox = (PFN_MessageBoxA)OrginalAddr ;
	}
	return bResult;
	
}

VOID IAT_UnInstallHook()
{
	
	DWORD dwOLD;
	MEMORY_BASIC_INFORMATION  mbi;
	if (g_PointerToIATThunk)
	{
		//查询并修改内存页的属性
		VirtualQuery((LPCVOID)g_PointerToIATThunk,&mbi,sizeof(mbi));
		VirtualProtect(mbi.BaseAddress,mbi.RegionSize,PAGE_EXECUTE_READWRITE,&dwOLD);
		//将原始的MessageBoxA地址填入IAT中
		*g_PointerToIATThunk = (ULONG)OldMessageBox;
		//恢复内存页的属性
		VirtualProtect(mbi.BaseAddress,mbi.RegionSize,dwOLD,0);
	}

}

//************************************
// FullName:    InstallModuleIATHook
// Description: 为指定模块安装IAT Hook
// Access:      public 
// Returns:     BOOL
// Parameter:   HMODULE hModToHook , 待Hook的模块基址
// Parameter:   char * szModuleName , 目标函数所在模块的名字
// Parameter:   char * szFuncName , 目标函数的名字
// Parameter:   PVOID DetourFunc , Detour函数地址
// Parameter:   PULONG * pThunkPointer , 用以接收指向修改的位置的指针
// Parameter:   ULONG * pOriginalFuncAddr , 用以接收原始函数地址
//************************************
BOOL InstallModuleIATHook(
	HMODULE hModToHook,// IN
	char *szModuleName,// IN
	char *szFuncName,// IN
	PVOID DetourFunc,// IN
	PULONG_PTR *pThunkPointer,//OUT
	ULONG_PTR *pOriginalFuncAddr//OUT
	)
{
	PIMAGE_IMPORT_DESCRIPTOR  pImportDescriptor;
	PIMAGE_THUNK_DATA         pThunkData;
	ULONG ulSize;
	HMODULE hModule=0;
	ULONG_PTR TargetFunAddr;
	PULONG_PTR lpAddr;
	char *szModName;
	BOOL result = FALSE ;
	BOOL bRetn = FALSE;

	hModule = LoadLibrary(szModuleName);
	TargetFunAddr = (ULONG_PTR)GetProcAddress(hModule,szFuncName);
	printf("[*]Address of %s:0x%p\n",szFuncName,TargetFunAddr);
	printf("[*]Module To Hook at Base:0x%p\n",hModToHook);
	pImportDescriptor = (PIMAGE_IMPORT_DESCRIPTOR)ImageDirectoryEntryToData(hModToHook, TRUE,IMAGE_DIRECTORY_ENTRY_IMPORT, &ulSize);;
	printf("[*]Find ImportTable,Address:0x%p\n",pImportDescriptor);
	while (pImportDescriptor->FirstThunk)
	{
		szModName = (char*)((PBYTE)hModToHook+pImportDescriptor->Name) ;
		printf("[*]Cur Module Name:%s\n",szModName);
		if (stricmp(szModName,szModuleName) != 0)
		{
			printf("[*]Module Name does not match, search next...\n");
			pImportDescriptor++;
			continue;
		}
		//程序的导入表处理完毕后OriginalFirstThunk可能是无效的,不能再根据名称来查找,而是遍历FirstThunk直接根据地址判断
		pThunkData = (PIMAGE_THUNK_DATA)((BYTE *)hModToHook + pImportDescriptor->FirstThunk);
		while(pThunkData->u1.Function)
		{
			lpAddr = (ULONG_PTR*)pThunkData;
			//找到了地址
			if((*lpAddr) == TargetFunAddr)
			{
				printf("[*]Find target address!\n");
				//通常情况下导入表所在内存页都是只读的,因此需要先修改内存页的属性为可写
				DWORD dwOldProtect;
				MEMORY_BASIC_INFORMATION  mbi;
				VirtualQuery(lpAddr,&mbi,sizeof(mbi));
				bRetn = VirtualProtect(mbi.BaseAddress,mbi.RegionSize,PAGE_EXECUTE_READWRITE,&dwOldProtect);
				if (bRetn)
				{
					//内存页属性修改成功,继续下一步操作,先保存原始数据
					if (pThunkPointer != NULL)
					{
						*pThunkPointer = lpAddr ;
					}
					if (pOriginalFuncAddr != NULL)
					{
						*pOriginalFuncAddr = *lpAddr ;
					}
					//修改地址
					*lpAddr = (ULONG_PTR)DetourFunc;
					result = TRUE ;
					//恢复内存页的属性
					VirtualProtect(mbi.BaseAddress,mbi.RegionSize,dwOldProtect,0);
					printf("[*]Hook ok.\n");
				}
				
				break;	
			}
			//---------
			pThunkData++;
		}
		pImportDescriptor++;
	}
	
	FreeLibrary(hModule);
	return result;
}
typedef BOOL (WINAPI *LPFN_ISWOW64PROCESS) (HANDLE, PBOOL);

LPFN_ISWOW64PROCESS fnIsWow64Process;

BOOL IsWow64()
{
	BOOL bIsWow64 = FALSE;

	fnIsWow64Process = (LPFN_ISWOW64PROCESS)GetProcAddress(
		GetModuleHandle(TEXT("kernel32")),"IsWow64Process");

	if (NULL != fnIsWow64Process)
	{
		if (!fnIsWow64Process(GetCurrentProcess(),&bIsWow64))
		{
			// handle error
		}
	}
	return bIsWow64;
}

 

00DA8845  |.  C745 A4 01000>||mov [local.23],0x1
00DA884C  |.  8BF4          ||mov esi,esp
00DA884E  |.  6A 00         ||push 0x0                                       ; /pOldProtect = NULL
00DA8850  |.  8B45 8C       ||mov eax,[local.29]                             ; |
00DA8853  |.  50            ||push eax                                       ; |NewProtect = PAGE_READWRITE|PAGE_WRITECOPY
00DA8854  |.  8B8D 74FFFFFF ||mov ecx,[local.35]                             ; |
00DA885A  |.  51            ||push ecx                                       ; |Size = 501EBA15 (1344190997.)
00DA885B  |.  8B95 68FFFFFF ||mov edx,[local.38]                             ; |IATHookM._IMPORT_DESCRIPTOR_KERNEL32:NativeDll::ProcessAttach)'0,64)'4)'64)'
00DA8861  |.  52            ||push edx                                       ; |Address = IATHookM.00E04038
00DA8862  |.  FF15 8882E000 ||call dword ptr ds:[<&KERNEL32.VirtualProtect>] ; \VirtualProtect
00DA8868  |.  3BF4          ||cmp esi,esp
00DA886A  |.  E8 80E3FFFF   ||call IATHookM.00DA6BEF
00DA886F  |.  68 7C4DDF00   ||push IATHookM.00DF4D7C                         ;  [*]Hook ok.\n
00DA8874  |.  E8 F5E6FFFF   ||call IATHookM.00DA6F6E
00DA8879  |.  83C4 04       ||add esp,0x4
00DA887C  |>  EB 0E         ||jmp short IATHookM.00DA888C
00DA887E  |>  8B45 EC       ||mov eax,[local.5]                              ;  <&USER32.MessageBoxA>
00DA8881  |.  83C0 04       ||add eax,0x4
00DA8884  |.  8945 EC       ||mov [local.5],eax
00DA8887  |.^ E9 1EFFFFFF   |\jmp IATHookM.00DA87AA
00DA888C  |>  8B45 F8       |mov eax,[local.2]                               ;  IATHookM._IMPORT_DESCRIPTOR_USER32t Hierarchy Descriptor'r',-1,0,64)'4)'64)'
00DA888F  |.  83C0 14       |add eax,0x14
00DA8892  |.  8945 F8       |mov [local.2],eax
00DA8895  |.^ E9 AEFEFFFF   \jmp IATHookM.00DA8748

跟踪到这一步已经实现了HOOK,在IAT——InstallHook函数执行后

Hook技术简单介绍

Hook技术简单介绍

 这个MessageBox的地址已经被修改

之前的是

00DA832C  |.  F3:AB         rep stos dword ptr es:[edi]
00DA832E  |.  8BF4          mov esi,esp
00DA8330  |.  6A 00         push 0x0                                         ; /Style = MB_OK|MB_APPLMODAL
00DA8332  |.  68 C44CDF00   push IATHookM.00DF4CC4                           ; |Test
00DA8337  |.  8B45 08       mov eax,[arg.1]                                  ; |
00DA833A  |.  50            push eax                                         ; |Text = B0ADE667 ???
00DA833B  |.  6A 00         push 0x0                                         ; |hOwner = NULL
00DA833D  |.  FF15 4884E000 call dword ptr ds:[<&USER32.MessageBoxA>]        ; \MessageBoxA
00DA8343  |.  3BF4          cmp esi,esp
00DA8345  |.  E8 A5E8FFFF   call IATHookM.00DA6BEF

   所以现在调用的是My——MessageBox函数

 

说明第二次条用ShowMsgBox之前执行的IAT_InstallHook函数。因为这个函数以修改IAT方式拦截了对API的调用。

第二个Inline Hook 篡改指定MessageBox消息

Hook技术简单介绍

esi值向User32.MessageBoxA 

而MessageBoxA 函数内部被篡改了(在开头直接通过一个跳转指令到了MY—— MessageBoxA函数里)

Hook技术简单介绍

00401050 > .  81EC 00050000 sub esp,0x500                                    ;  ?My_MessageBoxA@@YGHPAUHWND__@@PBD1I@Z
00401056   .  57            push edi                                         ;  InlineHo.<ModuleEntryPoint>
00401057   .  B9 FF000000   mov ecx,0xFF
0040105C   .  33C0          xor eax,eax
0040105E   .  8DBC24 050100>lea edi,dword ptr ss:[esp+0x105]
00401065   .  C68424 040100>mov byte ptr ss:[esp+0x104],0x0
0040106D   .  66:8B15 C0804>mov dx,word ptr ds:[0x4080C0]                    ;  m
00401074   .  F3:AB         rep stos dword ptr es:[edi]
00401076   .  8B0D BC804000 mov ecx,dword ptr ds:[0x4080BC]                  ;  y.com
0040107C   .  66:895424 0C  mov word ptr ss:[esp+0xC],dx
00401081   .  66:AB         stos word ptr es:[edi]
00401083   .  AA            stos byte ptr es:[edi]
00401084   .  A1 B8804000   mov eax,dword ptr ds:[<??_C@_09HIDC@pediy?4com?$>;  pediy.com
00401089   .  894C24 08     mov dword ptr ss:[esp+0x8],ecx
0040108D   .  894424 04     mov dword ptr ss:[esp+0x4],eax
00401091   .  B9 3D000000   mov ecx,0x3D
00401096   .  33C0          xor eax,eax
00401098   .  8D7C24 0E     lea edi,dword ptr ss:[esp+0xE]
0040109C   .  F3:AB         rep stos dword ptr es:[edi]
0040109E   .  68 A0804000   push offset <InlineHo.??_C@_0BF@ODOO@?S?P?H?K?$L>;  有人调用MessageBox!\n
004010A3   .  66:AB         stos word ptr es:[edi]
004010A5   .  E8 4C030000   call InlineHo.printfsbh_decommit_pagesem_page
004010AA   .  8B8424 100500>mov eax,dword ptr ss:[esp+0x510]
004010B1   .  83C4 04       add esp,0x4
004010B4   .  8D8C24 040100>lea ecx,dword ptr ss:[esp+0x104]
004010BB   .  50            push eax                                         ; /String2 = 00000001 ???
004010BC   .  51            push ecx                                         ; |String1 = 00000005
004010BD   .  FF15 04704000 call dword ptr ds:[<&KERNEL32.lstrcpyA>]         ; \lstrcpyA
004010C3   .  8D9424 040100>lea edx,dword ptr ss:[esp+0x104]
004010CA   .  68 7C804000   push offset <InlineHo.??_C@_0CC@ELLF@?6?7Message>; /\n\tMessageBox Hacked by pediy.com!
004010CF   .  52            push edx                                         ; |ConcatString = ""
004010D0   .  FF15 00704000 call dword ptr ds:[<&KERNEL32.lstrcatA>]         ; \lstrcatA
004010D6   .  8D4C24 04     lea ecx,dword ptr ss:[esp+0x4]

总结:通过在执行真正的目标函数之前执行事先插入的代码,获得了程序执行过程的决定权(Hook终极奥义)。

 

 

AddressHook 是指通过修改数据(指一些函数的地址也可能是偏移量)进行Hook方法。

 Hook的典型过程

不管是哪种Hook都需要自定义的函数来代替被Hook的函数。称之为Detour函数。其原型、调用约定、返回值都与原函数一模一样。

对函数调用的约定为_cdecl,WindowAPI通常是stdcall调用。

AddressHook 是指通过修改数据(指一些函数的地址也可能是偏移量)进行Hook方法。

以messageBox原型定义一个函数指针类型

实现IATHook的函数见上

虚函数Hook

(1)确定TargetFun在TargetClass虚函数表中的位置及函数原型

(2)定义DetourClass和TrampolineClass

(3)修改虚函数表,实现Hook

 

InlineHook的实施过程中要明确的3个概念

TargetFun : 要被Hook的目标函数;

DetourFun:用于代替TargetFun的自定义函数;

TargetpolineFun:该函数不是一个完成的函数,而是调用用原函数的入口。在该函数中要执行TargetFun中被替换的前几条指令,也就是说,TrampolinentFun和TargetFun中被Hook位置之后的部分构成了一个完成的函数。

 

 

实现Inline Hook 时需要解决两个问题:一是确定要采用的Hook方式。这样才能确定要写入何种机器码来完成执行的转移。

1、确定Hook方式及需要Trampoline中执行的指令

2、准备TrampolineFun函数

3、准备JMP指令并写入

4、call Hook

 

 

 

 

 

 

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/144951.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)
blank

相关推荐

  • 中文按字母排序_怎么按首字母顺序排

    中文按字母排序_怎么按首字母顺序排        项目中用到前端排序,自己写了一个实现,给大家分享一下。      存在的问题:很多时候是用汉字的首拼来比较,但汉字转拼音在前端实现是个问题,主要表现在两个地方1、字符库里的数据量没有覆盖所有汉字,2、多音字问题(注:这里都是说简体汉字)。      实现思路:1、从网上找了一个汉字转拼音的库,能转大部分汉字(多音字也没处理);2、写一个字符比较的函数;3、调用Array里的…

    2022年10月12日
  • 刚重装的win7系统不能上网(深度系统安装步骤)

    SDN网络系统之Mininet与API详解Mininet是轻量级的软件定义网络系统平台,同时提供了对OpenFlow协议的支持。本文主要介绍了Mininet的相关概念与特性,并列举的Mininet自定义网络及参数网络拓扑示例,以及相关重要执行文件的分析,帮助用户更好的理解与使用Mininet技术。现在就开始免费试用SDN与Minine

  • ghost备份系统有什么用_win备份和ghost备份的区别

    ghost备份系统有什么用_win备份和ghost备份的区别  Ghost(是GeneralHardwareOrientedSoftwareTransfer的缩写译为“面向通用型硬件系统传送器”)软件是美国赛门铁克公司推出的一款出色的硬盘备份还原工具,可以实现FAT16、FAT32、NTFS、OS2等多种硬盘分区格式的分区及硬盘的备份还原。俗称克隆软件。  1、特点:既然称之为克隆软件,说明其Ghost的备份还原是以硬盘的扇区为单位进行的

  • Hadoop体系_集团架构

    Hadoop体系_集团架构目录2.1Hadoop简介2.1.1Hadoop由来2.1.2Hadoop发展历程2.1.3Hadoop生态系统2.2Hadoop的体系架构2.2.1分布式文件系统HDFS2.2.2分布式计算框架MapReduce2.2.3分布式资源调度系统YARN2.2.4三大发行版本2.1Hadoop简介自从大数据的概念被提出后,出现了很多相关技术,其中对大数据发展最有影响力的就是开源分布式计算平台Hadoop,它就像软件发展史上的Win…

    2022年10月17日
  • pycharm如何搜索关键字_pycharm import变灰

    pycharm如何搜索关键字_pycharm import变灰1DCS调试方案按照以下内容做出一个完整的调试方案。2编制说明为高效优质完成调校工作,确保工艺试车进度,并实现长期、安全稳定生产的目标,特编制本DCS系统调试方案。3编制依据2.1工程合同2.2施工图及产品说明书2.3《工业自动化仪表工程施工及验收规范》GBJ93-864仪表系统调试程序图一为仪表系统调试程序方框图。本着分层隔离、平行作业的方法,本方案将系统调试分划为以下四个层次:4.1…

  • 基于jsp和基于web的区别_java发送短信

    基于jsp和基于web的区别_java发送短信最新web/java/jsp实现发送手机短信验证码和邮箱验证码的注册登录功能(详细)最近几天有人需要帮忙做一个关于发送验证码的功能,之前没有做过,于是我鼓捣一阵子,记录一下关于web项目中注册登录常用的手机验证码和邮箱验证码的发送。作为一个演示项目,我没有使用任何框架,用了一个简单的jsp+Servlet,当然用boostrap美化了一下。代码带有注释,非常简单易懂。一、手机验证码由于手机…

    2022年10月13日

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号