// InlinkHook.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include "windows.h"
//抽丝剥茧Inline Hook 学习笔记
//网上有很多inline hook 的例子,但是都是嵌在大量代码中,而且基本没有对inline hook 代码进行详细解释
//我刚学的时候对很多东西都很陌生,忽然明白了,觉得应该写点东西给还不会的人
//写的不好的地方请别见笑
// 首先我们不hook 系统的函数,我们自己写个函数进行一下hook 这样才比较清晰
void add(int a,int b)
{
printf("加法的结果:%d",a+b);
}
void sub(int a,int b)
{
printf("减法的结果%d",a-b);
}
//我们把对自己函数的hook封装在这个函数里
void my_simple_hook()
{
//首先我们要对某个函数进行hook ,肯定要获取他的地址
DWORD addr_old = (DWORD)add;
//获取我们要进行hook 替换的函数
DWORD addr_new= (DWORD)sub;
//接下来,我想我们因该看一下汇编代码了,看看call add函数的时候干了什么事情
//首先进行函数参数压站 然后call add(4110Dh)
//***这里有2张图片不知道怎么传上来**//
//4110DCh 后 用了一个jmp 指令 跳转到add 处 ==》这里我不明白为什么不直接call 到函数 ,知道的告诉一下
//学过汇编因该知道 jmp 指令 占5 字节 就是说我们定位到这里 修改jmp 的地址就可以进行hook
//解释下:这里为什么用addr_new – addr_old -5
//jmp 取地址 其实不是真正的函数地址,而是他们某个地址的相对偏移
// 2个函数 地址想减就是他们之间的相对偏移
//-5 是干什么的:因为jmp 指令时5字节的
*(LPBYTE)addr_old = 0xE9; //0xE9是jmp的机器码
*(LPWORD)(addr_old +1) = (DWORD)(addr_new – addr_old - 5);
}
//下面进行一下测试
int _tmain(int argc, _TCHAR* argv[])
{
///hook();
//现在我们来调用一下系统的FindWindowA
//FindWindowA(NULL,"calc.exe");
my_simple_hook();
add(10,20);
return 0;
}
//呵呵报错了,为什么呢?
//大家知道我们操作系统运行在保护模式下,内存怎么能随意修改呢
//但是Microsoft 为我们提供了解决方案 :VirtualProtect函数可以修改指定内存的权限
//修改后的因该是这样
void my_simple_hook()
{
//首先我们要对某个函数进行hook ,肯定要获取他的地址
DWORD addr_old = (DWORD)add;
//获取我们要进行hook 替换的函数
DWORD addr_new= (DWORD)sub;
MEMORY_BASIC_INFORMATION mbi;
VirtualProtect((LPVOID)addr_old,5,PAGE_EXECUTE_READWRITE,&(mbi.Protect));
*(LPBYTE)addr_old = 0xE9;
*(LPDWORD)(addr_old+1) = (DWORD)(addr_new- addr_old -5);
}
//结果:我们执行的时加法,却运行了我们的加法
///////////////////////////////////////////////////////////////////////////
///如果上面你理解了,那下面你就可以进行hook 系统函数来完成某个功能了
//目标函数是 FindWindowA
//同样我们需要写 自己的FindWindowA 用来替换系统函数
HWND My_FindWindowA(LPCSTR clsName,LPCSTR winName)
{
//对我们的计算器程序进行保护
if(strcmp(winName,"无标题 – 记事本") == 0)
{
MessageBoxA(NULL,"被hook了","title",MB_OK);
}
//这里我直接全部返回NULL 其实是不正确的
//我们达到自己目的的同时一定要确保不破坏其他程序正常运行
//因该再次调用原FindWindow 但是这个函数被HOOK 了 ,所以因该先保存原函数地址 然后重新调用
return NULL;
}
void hook()
{
HMODULE hModule = LoadLibraryA("user32.dll");
//获取源FindWindowA的地址
DWORD addr_old = (DWORD)GetProcAddress(hModule,"FindWindowA");
//获取自己的FindWindowA的地址
DWORD addr_new = (DWORD)My_FindWindowA;
//修改系统那个函数的前五个字节的属性为可读写可执行
MEMORY_BASIC_INFORMATION mbi;
VirtualProtect((LPVOID)addr_old,5,PAGE_EXECUTE_READWRITE,&(mbi.Protect));
//使用间接寻址修改原函数前个字节
*(LPBYTE)addr_old= 0xE9; //0xE9 对应的汇编指令时JMP
*(LPDWORD)(addr_old+1) = (DWORD)(addr_new - addr_old - 5);
}
//进行下测试
int _tmain(int argc, _TCHAR* argv[])
{
//my_simple_hook();
//add(10,20);
hook();
FindWindowA(NULL,”无标题 – 记事本”);
return 0;
}
//运行结果
//不好意思,本来有几张截图,不知道怎么传上来
//教程到这里就结束了,自学点东西不容易,说的不对的地方请指教,希望对还不会的人有帮助
[课程]Android-CTF解题方法汇总!