迷雾少年 发表于 2015-2-25 11:54:28

APIHOOK拦截MessageBox

本帖最后由 迷雾少年 于 2015-2-25 11:57 编辑

不久开学了!!!做个小例子送给大家~~~~
小小例子 ,高手勿喷!!!

#include<windows.h>

LRESULT CALLBACK WndProc(HWND,UINT,WPARAM,LPARAM);
/*
Windows 的窗口总是基于窗口类来创建的,窗口类同时确定了处理窗口消息的窗口过程(回调函数)。
回调函数需要到函数最后面几行找
*/

int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE hprevInstance,PSTR szCmdLine,int iCmdShow)

{
static TCHAR szAppName[] = TEXT("Windows");
HWND hwnd;
MSG msg;
WNDCLASS wndclass;
wndclass.style = CS_HREDRAW;
wndclass.lpfnWndProc = WndProc;
wndclass.cbClsExtra = 0;
wndclass.cbWndExtra = 0;
wndclass.hInstance = hInstance;
wndclass.hIcon = LoadIcon(NULL,IDI_APPLICATION);
wndclass.hCursor = LoadCursor(NULL,IDC_ARROW);
wndclass.hbrBackground = (HBRUSH)GetStockObject(COLOR_CAPTIONTEXT); //背景色
wndclass.lpszMenuName = NULL;
wndclass.lpszClassName = szAppName;


if(!RegisterClass(&wndclass))
{

MessageBox(NULL,TEXT("这个程序无法执行"),szAppName,MB_OK);
return 0;
}


hwnd =CreateWindow(szAppName,
TEXT("AAAAAAAAAA"),
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
NULL,
NULL,
hInstance,
NULL);

ShowWindow(hwnd,iCmdShow); //显示窗口
UpdateWindow(hwnd); //更新窗口

while(GetMessage(&msg,NULL,0,0))


{
TranslateMessage(&msg);


DispatchMessage(&msg);

}
return msg.wParam;


}

/*
WINUSERAPI int WINAPI MessageBoxA( HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType);
*/

/* 根据原型我们 自己定义一个函数*/
/* PS 不要修改返回值和参数类型或参数个数 否则栈不平衡 */
int_MessageBoxA( HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType)
{
/* 在这里我们可以做很多事 */
/* 比如直接返回 等于啥也没调用 */
/* 还可以在之前保存入口的5字节现在在这里修改回去 然后调用就可以 实现数据监控 */
return 0;
}



<FONT color=red>//内存对齐
#pragma pack(1)
struct _
{
BYTE type; //直接填233 也就是JMP
int *p; //地址 需要计算
};</FONT>


void _Created(HWND hWnd)
{
_ __={0};
__.type = 233; //233 = JMP

// USER32.DLL 为什么是这个DL 因为我们要拦截的函数在里面
char szUsee32[] = "User32.DLL";
//为什么是char 因为 GetProcAddress 函数第二个参数是char*
char szFunName[] = "MessageBoxA"; //拦截 ansi版的
//加载这个DLL返回事例句柄 也可以用 GetModuleHandle
HMODULE hModule = LoadLibraryA(szUsee32);
//得到 MessageBoxA 函数在内存的地址
<FONT color=red>void *p = GetProcAddress(hModule,szFunName); //</FONT>
// 关键 计算 最终地址 = 我们函数地址 - 目标地址 - 5
int* address =(int*)((int)_MessageBoxA - (int)p - 5);
// 把计算后的地址放上去
__.p = address;

//得到最终地址后还要做一件事

//我们要做的就是把 MessageBoxA 函数入口的 5 个字节改为 jmp address 这个address就是我们经过计算后的地址
//但是默认DLL加载到的那段地址空间不能写数据
//所以我们要修改他的内存属性
//需要用 VirtualProtectEx VirtualProtect VirtualProtectEx 是 VirtualProtect 扩展版 推荐用VirtualProtectEx
//http://baike.baidu.com/link?url=nH6bZ9peV5SPveHjtRNzG-bIsm7pNQJJTlomZjerGvYqr1aCY4FhGBtmWo_GRkHBwzThbB-kWAUov6BfvUSFz_
HANDLE hProcess = (HANDLE)-1; //-1代表我们自身进程句柄
DWORD lNewPro = PAGE_EXECUTE_READWRITE,lOldPro=0 ;//属性为可读可写
//如果成功,返回非零。失败返回零。

<FONT color=red>int ret = VirtualProtectEx(hProcess,(LPVOID)p,5,lNewPro,&lOldPro</FONT>);
if(!ret) MessageBoxA(NULL,"擦,属性修改失败",NULL,NULL);


/* 实际写入了多少字节 */
DWORD _Byte = 0;

//第一个参数是进程句柄
//第二个参数是写的地址
//第三个参数是要写的数据缓冲区
//第四个参数是要写多少字节
//第五个参数是函数实际写入多少字节了

// 一次性写入去
<FONT color=red>ret = WriteProcessMemory(hProcess,(LPVOID)p,(LPCVOID)&__,5,&_Byte);</FONT>


//然后调用 实际是到我们的函数了
MessageBoxA(NULL,NULL,NULL,NULL);




}



LRESULT CALLBACK WndProc(HWND hwnd,UINT message,WPARAM wParam,LPARAM lParam)
{


switch (message)
{
case WM_DESTROY:
PostQuitMessage(0);
break;
case WM_CREATE: //当接到窗口创建完的消息
_Created(hwnd);
break;
}

return DefWindowProc(hwnd, message, wParam, lParam);
}



图片

只能执行和READ 所以我们要修改属性

可以看到 函数入口变成JMPXXXX了

然后按F5


如果你按F5继续走

结果是这样

为什么??

MessageBoxA 这个函数是 _stacall 协定的
但是我们定义的       函数是 _cdecl协定的

这样就导致了栈不平衡

所以呢

在前面加个 __stdcall

然后运行
正常

没有消息框也没有错误 -> ->



打得很辛苦的 ~~~顶下吧














迷雾少年 发表于 2015-2-25 13:16:22

2楼自坐

漠水 发表于 2015-2-25 16:27:31

学习一下

air-C 发表于 2015-2-25 23:10:45

屌屌的

纯属宅男 发表于 2015-2-27 18:45:34

这是什么

迷雾少年 发表于 2015-2-27 19:37:43

纯属宅男 发表于 2015-2-27 18:45
这是什么

拦截 MessageBoxA

小小书童abc 发表于 2015-3-2 11:53:02

{:1_1:}好贴必回

pynliu 发表于 2015-3-3 09:01:45

求鱼币,看不懂
页: [1]
查看完整版本: APIHOOK拦截MessageBox