|
马上注册,结交更多好友,享用更多功能^_^
您需要 登录 才可以下载或查看,没有账号?立即注册
x
本帖最后由 迷雾少年 于 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 所以我们要修改属性
可以看到 函数入口变成JMP XXXX了
然后按F5
如果你按F5继续走
结果是这样
为什么??
MessageBoxA 这个函数是 _stacall 协定的
但是我们定义的 函数是 _cdecl协定的
这样就导致了栈不平衡
所以呢
在前面加个 __stdcall
然后运行
正常
没有消息框也没有错误 -> ->
打得很辛苦的 ~~~顶下吧
|
评分
-
查看全部评分
|