网站建设联,家具设计软件下载,wordpress按标签筛选,雁塔区建设局网站InlineHook 是一种计算机安全编程技术#xff0c;其原理是在计算机程序执行期间进行拦截、修改、增强现有函数功能。它使用钩子函数#xff08;也可以称为回调函数#xff09;来截获程序执行的各种事件#xff0c;并在事件发生前或后进行自定义处理#xff0c;从而控制或增…InlineHook 是一种计算机安全编程技术其原理是在计算机程序执行期间进行拦截、修改、增强现有函数功能。它使用钩子函数也可以称为回调函数来截获程序执行的各种事件并在事件发生前或后进行自定义处理从而控制或增强程序行为。Hook技术常被用于系统加速、功能增强、等领域。本章将重点讲解Hook是如何实现的并手动封装实现自己的Hook挂钩模板。
首先我们来探索一下Hook技术是如何实现的如下图所示是一个简单的弹窗程序当读者点击测试弹窗按钮时则会弹出一个MessageBox提示窗口本次实现目标很简单通过向目标内注入一个DLL库实现Hook挂钩住MessageBox弹窗从而实现去除弹窗的目的 我们先来看看如何实现Hook思路
1.调用GetModuleHandle函数来获取到user32.dll模块的基址2.调用GetProcAddress函数获取到MessageBoxA弹窗的基址3.调用VirtualProtect来修改MessageBoxA前5个字节内存属性4.计算Dest - MsgBox - 5重定位跳转地址并写入JMP跳转指令5.计算Dest Offset 5 MsgBox 5得到需要跳转回RET的位置6.最后调用VirtualProtect来将内存属性修改为原始状态
我们载入带有MessageBoxA弹窗的程序,然后在x64dbg上按下CtrlG输入MessageBoxA找到我们需要Hook的位置或者说替换如下图所示为了完成弹窗转向功能只需要在函数开头写入jmp无条件跳转指令即可在32位系统中JMP指令默认占用5个字节前三条指令恰好5个字节为了能够保持堆栈平衡我们需要记下前三条指令并在自己的中转函数中对其进行补齐。 此外我们还需要计算出程序的返回地址使用0x76600BE5 - 0x76600BA0 0x45从而得出返回地址就是基址加上0x45这里的返回地址其实就是返回到原MessageBoxA弹窗的RET 0x10的位置76600BE6从这里可以看出屏蔽弹窗的原理就是通过中转函数跳过了原始弹窗函数的执行。
由于开头位置被替换为了我们自己的Transfer()函数当程序中弹窗被调用时默认会路由到我们自己的函数内首先执行补齐原函数的替换部分并执行自定义功能区中的增加内容当执行结束后则通过jmp ebx的方式跳转回原函数的ret 0x10的位置处从而实现增加功能的目的。这里读者需要注意__declspec(naked)的意思是不添加任何的汇编修饰当使用了此修饰符时则编译器会只编译我们自己的汇编指令并不会增加默认的函数开场或离场原语。
__declspec(naked) void Transfer()
{__asm{mov edi, edipush ebpmov ebp, esp// 自定义功能区mov ebx, jump // 取出跳转地址jmp ebx // 无条件转向}
}通过应用上述案例中的知识点我们能很容易的实现对弹窗的替换功能以下代码中实现了对MessageBoxA弹窗的屏蔽功能也就是通过跳过弹窗实现流程实现的一种劫持方法读者可自行编译这段DLL程序但需要注意一点读者在编译DLL时应该关闭DLL的DEP以及ASLR模式否则会出现无法定位的问题。
#include Windows.h
#include stdio.hDWORD jump 0;// 不添加任何的汇编修饰
__declspec(naked) void Transfer()
{__asm{mov edi, edipush ebpmov ebp, espmov ebx, jump // 取出跳转地址jmp ebx // 无条件转向}
}// DLL程序入口地址
bool APIENTRY DllMain(HANDLE handle, DWORD dword, LPVOID lpvoid)
{// 取进程内模块基址HMODULE hwnd GetModuleHandle(TEXT(user32.dll));DWORD base (DWORD)GetProcAddress(hwnd, MessageBoxA);DWORD oldProtect 0;// 将内存设置为可读可写可执行状态,并将原属性保存在oldProtect方便恢复if (VirtualProtect((LPVOID)base, 5, PAGE_EXECUTE_READWRITE, oldProtect)){DWORD value (DWORD)Transfer - base - 5; // 计算出需要Hook的地址jump base 0x45; // 计算出返回地址// 替换头部汇编代码__asm{mov eax, basemov byte ptr[eax], 0xe9 // e9 jmp 指令机器码inc eax // 递增指针mov ebx, value // 需要跳转到的地址mov dword ptr[eax], ebx}// 恢复内存的原始属性VirtualProtect((LPVOID)base, 5, oldProtect, oldProtect);}return true;
}读者可通过注入软件将hook.dll动态链接库注入到进程内此时我们可以再次观察0x76600BA0位置处的代码片段读者应该能看到已经被JMP替换如下图所示 继续跟进则读者能看到在跳转指令的下方则是我们自己补齐的汇编指令此处由于没有做任何事就被返回了这就导致当读者再次点击弹窗时弹窗失效 当我们需要替换程序标题时同样可是使用该方式实现一般来说程序设置标题会调用SetWindowTextA函数我们可以拦截这个函数并传入自定义的窗口名称从而实现修改指定窗口的标题的目的代码只是在上面代码的基础上稍微改一下就能实现效果只要程序使用了该函数设置标题则可以实现替换的目的
#include Windows.h
#include stdio.hDWORD jump 0;// 汇编中转函数
__declspec(naked) bool _stdcall Transfer(HWND hwnd, LPCSTR lpString)
{__asm{mov edi, edipush ebpmov ebp, espmov ebx, jumpjmp ebx}
}// 自己的设置窗体标题函数
bool __stdcall MySetWindowTextA(HWND hwnd, LPCSTR lpString)
{char * lpText LyShark 修改版;return Transfer(hwnd, lpText);
}// DLL程序入口地址
bool APIENTRY DllMain(HANDLE handle, DWORD dword, LPVOID lpvoid)
{HMODULE hwnd GetModuleHandle(TEXT(user32.dll));DWORD base (DWORD)GetProcAddress(hwnd, SetWindowTextA);DWORD oldProtect 0;if (VirtualProtect((LPVOID)base, 5, PAGE_EXECUTE_READWRITE, oldProtect)){DWORD value (DWORD)MySetWindowTextA - base - 5;jump base 5;__asm{mov eax, basemov byte ptr[eax], 0xe9inc eaxmov ebx, valuemov dword ptr[eax], ebx}VirtualProtect((LPVOID)base, 5, oldProtect, oldProtect);}return true;
}