User breakpoint called from code at 0x7c92120e

分配内存时用到了new[ ],而在释放内存时却用的是delete,虽然程序执行没有什么大问题,只是在调试的时候总是跳出一些断点(这些个断点我没有设置),显示的内容都是:User breakpoint called from code at 0x7c92120e,这个地址可能根据每次调试的不一样,在call stack窗口中显示NTDLL!7c92120e,当我每次点击断点跳出的对话框上的确定按钮时,Debug窗口中就会显示 HEAP[AdamR.exe]: .........,表面上程序执行是没有什么,其实正真的问题是内存根本没有释放,之后发现是我的new[]配上了delete,而不是delete[ ],改后就执行正常了。之后在网上搜到一篇文章“C++中new和delete导致的内存分配问题详解”,当你用delete去释放new[] 时,delete只会删除第一个new的对象,剩下的就没有释放,而操作系统就会认为你申请的堆空间破碎了,就会出现上面的问题了。所以一定要new[ ]配上delete[ ],否则你以为释放了new[ ]的内存,其实只是释放了第一个地址空间的内容。

  今天调试程序时在Debug版跳出这个错误..我根本程序没设置断点.而其好像说是我的堆有问题,而编译了个Release版本运行正常..后来google下,查到如下解释:

      说是调试状态下,操作系统用DebugWin32Heap来替代正常的heap分配内存空间。在这个堆上的任何操作debug的堆管理器会检查堆的数据完整性,如果它发现了一个错误,就会报告一个消息上来。当一个应用程序PageHeap机制被激活时,该应用程序的所有的堆分配被放到内存中,这样堆的边界就与虚拟内存的边界排在一起了。与堆相邻的虚拟内存页面被设置为NO_ACCESS。在该应用程序中对堆后面的空间的访问就会立刻引起错误,这就可以在一个调试工具中被捕获。在释放堆时,过程与之类似。PageHeap修改释放的应用程序虚拟页面为NO_ACCESS,这样,如果应用程序试图读写该内存时就会发生访问错误.

      既然是Heap的问题我就查遍了所有源代码的new和delete操作的代码,看来下感觉没有任何问题..改分配的都分配了该释放的也都释放了..而且没有错误情况.后来没办法弄个极端的,我把程序的中所有delete 的语句全部注释.再运行程序.果然没问题了...- -..我又继续查了下程序.感觉还是没问题....后来定位了一个一条delete 只要有它程序就报错.没有就正常.发现这个delete位于一个移除服务的函数中.这里有必要说下我的程序结构

      我将服务全部存入dll中 主要函数一个四个(其他的就不说了)

            createSrv 建立服务 removeSrv 移除服务 runSrv 运行服务 stopSrv 停止服务

 而这个delete正好位于removeSrv中...但是我的delete没有任何问题.后来没办法有 google下.找到了一个和我遇到同样问题的人..http://hi.baidu.com/yanerxh/blog/item /88d58455ace78cc2b645ae8e.html....

      "重复释放导致的问题,User breakpoint called from code at 0x77f9193c ,以上原因是由于释放了一个类的员,最后在作该类的析构时由于它的成员已经被释放导致出错(该成员被释放但是没有设 NULL)"

看完这句话后我立刻去看我的类的析构函数(由于我的dll为了通用并不是导出类而是导出函数,而我调用方编写了调用类来调用dll导出函数,达到统一管理和封装的目的),果然 - -||...我怕万一我的调用没有 " stopSrv 停止服务 "和"removeSrv 移除服务 " 我在析构函数中又调用了这个两个函数....郁闷我从9点陆陆续续调试到现在 - -.....写此文章警示后人......


今天在调试QQ医生时,突然蹦出来了这么个错误,使上了浑身解数,也没有定位到问题所在,只知道在 delete 一个堆上的对象时,程序就崩溃了,弹出了下面的对话框:


挺奇怪的吧,而且往往之前还弹出一个对话框:
 

提示说堆内存被破坏,有时候这样的错误在比较小的程序里面也许不会对整个程序造成破坏,依然能够继续运行,但是千万不要放过,像这种破坏堆内存的隐藏BUG,说不准哪天就会造成整个软件的crash。另外我要提醒的是,release版本也许什么提示都没有,直接放过了,这是因为在debug下,操作系统用DebugWin32Heap来代替正常的heap分配内存空间。在这个堆上的任何操作,debug的堆管理器会检查堆的数据完整性,如果它发现了一个错误,就会报告一个消息上来。

我们可以对这种情况作一个猜测,既然是delete的时候出了问题,那就是这个程序很可能去访问了“非法”的内存,这里的非法内存是指不是由你的程序分配的内存块,但是被你的程序在某种情况下访问到了,当然这是堆上的情况,所以在release下可能一时不会出问题,如果是栈上,程序也许早就是crase或者出现莫名其妙的错误了。

现在问题比较集中了,但是整个程序在堆上分配了那么多对象,到底哪次分配出了问题?这还是很难定位到错误,用 BoundsChecker完整跑一遍是一个好办法,但是比较麻烦,其实微软已经给我们想到了办法,试想如果在每次分配的内存块边界做限制,设置为虚拟内存,也就是NO_ACCESS(不可访问),那程序试图读写这个地方的时候,就会出错,程序会马上断下来,也就是所谓的PageHeap机制。

要让我们的程序启用Full Page Heap机制,需在注册表中
HKEY_LOCAL_MACHINE/SOFTWARE/Microsoft/Windows NT/CurrentVersion/Image File Execution Options/appName.exe下增加如下设置,

属性名:GlobalFlag,字符串类型,值:x02200000

属性名:PageHeapFlags,字符串类型,值:0x3

属性名:VerifierFlags,DWORD类型,值:1

另外替换appName.exe为你正在调试的真正的程序文件名,如果你安装了Debugging Tools for Windows,这一切会更加简单,在安装目录下有个gflags工具,直接用命令行运行 gflags –p /enable appName.exe /full 即可自动帮你添加上述注册表值,如果你没有该工具,你可以去 http://www.microsoft.com/whdc/devtools/debugging/installx86.mspx 下载。

DLL也是可以用这个机制的,注册表的设置有点区别,如下:

GlobalFlag,字符串类型,值是0x02000000

PageHeapTargetDlls,字符串类型,值是调试的dll名称,不带路径

VerifierFlags,DWORD类型,值是00000001

PageHeapFlags,字符串类型,0x403

 

或者使用命令行 gflags –p /enable appName.exe /full /dlls dllName.dll 这里要注意的是,注册表的子健值应该是dll依附的exe程序名。

好,使用该机制后再次调试,果然断下来了,在一个对象里面的结构体里面出错了,这个结构体是该类的最后一个成员,该结构体的最后四个DWORD的值显示是无效的,把这个结构体放在前面后,这个类的最后四个DWORD大小的空间还是无效的,现在可以知道,分配内存的时候,根本没有给该对象分配足够的内存,而delete的时候却按该对象的大小来释放,自然就被d堆管理器捕获了这个错误,为什么会少分配4个dword的大小?后来发现是滥用内联函数造成的,构造和析构函数使用了内联,其实内联这个东东,编译器完全可以无视,也就是说不给你内联,但是也许又给你内联,怎么理解?也就是说内联不内联完全由编译器决定,而程序员无法控制,这在win32里面有个词叫什么 - 不可预测,呵呵,既然是强大的不可预测,就不要为了那么一点点效率来使用内联了,后来把构造析构函数搬到CPP文件里面之后,分配马上就正常了。

 

重现上面的bug其实很容易,如下:

// 演示一个BUG

char* pHeap = new char[2];

::lstrcpy(pHeap, "tonglei");

delete pHeap;

 

转自:http://blog.youkuaiyun.com/charles_3081523/archive/2010/11/09/5998014.aspx

#include <stdio.h> // 添加printf支持 #include <windows.h> BOOL SetBreakPoint(PVOID pFuncAddr); BOOL ClearBreakPoint(PVOID pFuncAddr); BOOL InstallVEHHook(PVECTORED_EXCEPTION_HANDLER Handler); VOID UnInstallVEHHook(); typedef int (WINAPI* PFN_MessageBox)( 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 WINAPI My_MessageBox( 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 ); LONG WINAPI VectoredHandler1(struct _EXCEPTION_POINTERS* ExceptionInfo); LONG WINAPI VectoredHandler2(struct _EXCEPTION_POINTERS* ExceptionInfo); LONG WINAPI VectoredHandler3(struct _EXCEPTION_POINTERS* ExceptionInfo); VOID ShowMsgBox(LPCTSTR lpMsg); ULONG_PTR InitTrampolineFun(); PFN_MessageBox g_OriginalMessageBoxA; PVOID g_AddrofMessageBoxA = 0; PVOID g_hVector; BYTE g_OldCode[16] = { 0 }; int main(int argc, char* argv[]) { HMODULE hUser32 = LoadLibrary("user32.dll"); g_AddrofMessageBoxA = (PVOID)GetProcAddress(hUser32, "MessageBoxA"); printf("Address of MessageBoxA = 0x%p\n", g_AddrofMessageBoxA); g_OriginalMessageBoxA = (PFN_MessageBox)InitTrampolineFun(); //跳过开头的Hook printf("Addr of VectoredHandler1 = 0x%p\n", VectoredHandler1); printf("Addr of VectoredHandler2 = 0x%p\n", VectoredHandler2); printf("Addr of VectoredHandler3 = 0x%p\n", VectoredHandler3); //选择安装一个进行测试 InstallVEHHook(VectoredHandler1); //设置断点 SetBreakPoint(g_AddrofMessageBoxA); //call ShowMsgBox("VEH Hook Test."); printf("All Finished!\n"); ClearBreakPoint(g_AddrofMessageBoxA); UnInstallVEHHook(); ShowMsgBox("Hook Cleared"); return 0; } VOID ShowMsgBox(LPCTSTR lpMsg) { MessageBoxA(NULL, lpMsg, "Test", MB_OK); } ULONG_PTR InitTrampolineFun() { ULONG_PTR uResult = 0; PBYTE pFun = NULL; #ifdef _WIN64 //x64需要申请shellcode /* USER32!MessageBoxA: 00000000`779412b8 4883ec38 sub rsp,38h 00000000`779412bc 4533db xor r11d,r11d 00000000`779412bf 44391d760e0200 cmp dword ptr [USER32!gapfnScSendMessage+0x927c (00000000`7796213c)],r11d */ pFun = (PBYTE)VirtualAlloc(NULL, 128, MEM_COMMIT, PAGE_EXECUTE_READWRITE); uResult = (ULONG_PTR)pFun; memset(pFun, 0, 128); memcpy(pFun, (PVOID)g_AddrofMessageBoxA, 4); //拷贝第一条指令,4字节,推荐使用反汇编引擎来实际计算 pFun += 4; //下一条指令构造为jmp [xxxxxx] pFun[0] = 0xFF; pFun[1] = 0x25; *(ULONG_PTR*)(pFun + 6) = (ULONG_PTR)g_AddrofMessageBoxA + 4; //跳回到原函数加4的地方 #else //x86,第一条指令是mov edi,edi,直接跳过即可 uResult = (ULONG_PTR)g_AddrofMessageBoxA + 2; #endif return uResult; } //处理方式,修改参数并返回原函数继续执行 LONG WINAPI VectoredHandler1( struct _EXCEPTION_POINTERS* ExceptionInfo ) { const char* szNewMsg = "[VectoredHandler1] Hacked by pediy.com"; LONG lResult = EXCEPTION_CONTINUE_SEARCH; PEXCEPTION_RECORD pExceptionRecord; PCONTEXT pContextRecord; int ret = 0; pExceptionRecord = ExceptionInfo->ExceptionRecord; pContextRecord = ExceptionInfo->ContextRecord; ULONG_PTR* uESP = 0; printf("Exception Address = %p\n", pExceptionRecord->ExceptionAddress); if (pExceptionRecord->ExceptionCode == EXCEPTION_BREAKPOINT && pExceptionRecord->ExceptionAddress == g_AddrofMessageBoxA) { #ifdef _WIN64 //x64上前四个参数依次为RCX,RDX,R8,R9 //修改第二个参数,即LpMsg printf("lpText = 0x%p %s\n", pContextRecord->Rdx, (char*)pContextRecord->Rdx); pContextRecord->Rdx = (ULONG_PTR)szNewMsg; pContextRecord->Rip = (ULONG_PTR)g_OriginalMessageBoxA; //跳到Trampoline继续执行 #else /* 0012FF70 0040105A /CALL 到 MessageBoxA 来自 VEHHook.00401054 0012FF74 00000000 |hOwner = NULL 0012FF78 00407030 |Text = "VEH Hook" 0012FF7C 0040703C |Title = "Test" 0012FF80 00000000 \Style = MB_OK|MB_APPLMODAL 0012FF84 00401225 返回到 VEHHook.<ModuleEntryPoint>+0B4 来自 VEHHook.00401000 */ printf("ESP = 0x%p\n", pContextRecord->Esp); uESP = (ULONG_PTR*)pContextRecord->Esp; //取中断时的ESP uESP[2] = (ULONG_PTR)szNewMsg; //修改栈中的参数 pContextRecord->Eip = (ULONG_PTR)g_OriginalMessageBoxA; //跳过函数开头 #endif lResult = EXCEPTION_CONTINUE_EXECUTION; } return lResult; } //处理方式:直接调用原函数并替原函数返回 LONG WINAPI VectoredHandler2( struct _EXCEPTION_POINTERS* ExceptionInfo ) { const char* szNewMsg = "[VectoredHandler2] Hacked by pediy.com"; LONG lResult = EXCEPTION_CONTINUE_SEARCH; PEXCEPTION_RECORD pExceptionRecord; PCONTEXT pContextRecord; int ret = 0; pExceptionRecord = ExceptionInfo->ExceptionRecord; pContextRecord = ExceptionInfo->ContextRecord; ULONG_PTR* uESP = 0; if (pExceptionRecord->ExceptionCode == EXCEPTION_BREAKPOINT && pExceptionRecord->ExceptionAddress == g_AddrofMessageBoxA) { #ifdef _WIN64 //x64上前四个参数依次为RCX,RDX,R8,R9 printf("RSP = 0x%p\n", pContextRecord->Rsp); uESP = (ULONG_PTR*)pContextRecord->Rsp; printf("Return Address = 0x%p\n", uESP[0]); ret = g_OriginalMessageBoxA((HWND)pContextRecord->Rcx, szNewMsg, (LPCTSTR)pContextRecord->R8, (int)pContextRecord->R9); printf("ret = %d\n", ret); //修正RSP pContextRecord->Rsp += sizeof(ULONG_PTR);//参数在寄存器中,栈中无参数,仅需跳过返回地址 //直接返回到调用者处 pContextRecord->Rip = uESP[0];//设置EIP为返回地址 #else /* 0012FF70 0040105A /CALL 到 MessageBoxA 来自 VEHHook.00401054 0012FF74 00000000 |hOwner = NULL 0012FF78 00407030 |Text = "VEH Hook" 0012FF7C 0040703C |Title = "Test" 0012FF80 00000000 \Style = MB_OK|MB_APPLMODAL 0012FF84 00401225 返回到 VEHHook.<ModuleEntryPoint>+0B4 来自 VEHHook.00401000 */ printf("ESP = 0x%p\n", pContextRecord->Esp); uESP = (ULONG_PTR*)pContextRecord->Esp; ret = g_OriginalMessageBoxA((HWND)uESP[1], szNewMsg, (LPCTSTR)uESP[3], (int)uESP[4]); printf("ret = %d\n", ret); //直接返回到调用者处 pContextRecord->Eip = uESP[0];//设置EIP为返回地址 pContextRecord->Esp += (4 + 1) * sizeof(ULONG_PTR); //4为参数个数,1为返回地址 #endif lResult = EXCEPTION_CONTINUE_EXECUTION; } return lResult; } //处理方式:直接返回,相当于过滤掉 LONG WINAPI VectoredHandler3( struct _EXCEPTION_POINTERS* ExceptionInfo ) { LONG lResult = EXCEPTION_CONTINUE_SEARCH; PEXCEPTION_RECORD pExceptionRecord = ExceptionInfo->ExceptionRecord; PCONTEXT pContextRecord = ExceptionInfo->ContextRecord; ULONG_PTR* uESP = 0; if (pExceptionRecord->ExceptionCode == EXCEPTION_BREAKPOINT && pExceptionRecord->ExceptionAddress == g_AddrofMessageBoxA) { /* 0012FF70 0040105A /CALL 到 MessageBoxA 来自 VEHHook.00401054 0012FF74 00000000 |hOwner = NULL 0012FF78 00407030 |Text = "VEH Hook" 0012FF7C 0040703C |Title = "Test" 0012FF80 00000000 \Style = MB_OK|MB_APPLMODAL 0012FF84 00401225 返回到 VEHHook.<ModuleEntryPoint>+0B4 来自 VEHHook.00401000 */ //直接返回到调用者处 #ifdef _WIN64 printf("RSP = 0x%p\n", pContextRecord->Rsp); uESP = (ULONG_PTR*)pContextRecord->Rsp; pContextRecord->Rip = uESP[0];//设置EIP为返回地址 pContextRecord->Rsp += sizeof(ULONG_PTR); //将压入栈内的参数和返回地址清理掉,4为参数个数,1为返回地址 #else printf("ESP = 0x%X\n", pContextRecord->Esp); uESP = (ULONG_PTR*)pContextRecord->Esp; pContextRecord->Eip = uESP[0];//设置EIP为返回地址 pContextRecord->Esp += (4 + 1) * sizeof(ULONG_PTR); //将压入栈内的参数和返回地址清理掉,4为参数个数,1为返回地址 #endif lResult = EXCEPTION_CONTINUE_EXECUTION; } return lResult; } BOOL InstallVEHHook(PVECTORED_EXCEPTION_HANDLER Handler) { printf("Current Handler Address = 0x%p\n", Handler); g_hVector = AddVectoredExceptionHandler(1, Handler); return g_hVector != NULL; } VOID UnInstallVEHHook() { RemoveVectoredExceptionHandler(g_hVector); } /* 0:000> u user32!messageboxA USER32!MessageBoxA: 77d507ea 8bff mov edi,edi 77d507ec 55 push ebp 77d507ed 8bec mov ebp,esp */ BOOL SetBreakPoint(PVOID pFuncAddr) { DWORD dwCnt = 0; BYTE* pTarget = (BYTE*)pFuncAddr; g_OldCode[0] = *pTarget; printf("Original Fun Head Code = 0x%02X\n", g_OldCode[0]); //修改内存页的属性 DWORD dwOLD; MEMORY_BASIC_INFORMATION mbi; VirtualQuery(pTarget, &mbi, sizeof(mbi)); VirtualProtect(mbi.BaseAddress, mbi.RegionSize, PAGE_EXECUTE_READWRITE, &dwOLD); //写入int3 *pTarget = 0xCC; //恢复内存页的属性 VirtualProtect(mbi.BaseAddress, mbi.RegionSize, dwOLD, 0); return TRUE; } BOOL ClearBreakPoint(PVOID pFuncAddr) { BYTE* pTarget = (BYTE*)pFuncAddr; //修改内存页的属性 DWORD dwOLD; MEMORY_BASIC_INFORMATION mbi; VirtualQuery(pTarget, &mbi, sizeof(mbi)); VirtualProtect(mbi.BaseAddress, mbi.RegionSize, PAGE_EXECUTE_READWRITE, &dwOLD); *pTarget = g_OldCode[0]; //恢复内存页的属性 VirtualProtect(mbi.BaseAddress, mbi.RegionSize, dwOLD, 0); return TRUE; } int WINAPI My_MessageBox( 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 ) { char newMsg[400]; char newCation[] = "标题被我改了!"; int result; if (lpText) { ZeroMemory(newMsg, 400); lstrcpy(newMsg, lpText); lstrcat(newMsg, "\n\tMessage Box hacked by pediy.com"); } printf("有人调用MessageBox...\n"); result = g_OriginalMessageBoxA(hWnd, newMsg, newCation, uType); return result; }系统版本是win10 10240
07-25
#include "stdafx.h" #include <windows.h> BOOL SetBreakPoint(PVOID pFuncAddr); BOOL ClearBreakPoint(PVOID pFuncAddr); BOOL InstallVEHHook(PVECTORED_EXCEPTION_HANDLER Handler); VOID UnInstallVEHHook(); typedef int (WINAPI* PFN_MessageBox)( 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 WINAPI My_MessageBox( 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 ); LONG WINAPI VectoredHandler1(struct _EXCEPTION_POINTERS* ExceptionInfo); LONG WINAPI VectoredHandler2(struct _EXCEPTION_POINTERS* ExceptionInfo); LONG WINAPI VectoredHandler3(struct _EXCEPTION_POINTERS* ExceptionInfo); VOID ShowMsgBox(LPCTSTR lpMsg); ULONG_PTR InitTrampolineFun(); PFN_MessageBox g_OriginalMessageBoxA; PVOID g_AddrofMessageBoxA = 0; PVOID g_hVector; BYTE g_OldCode[16] = { 0 }; int main(int argc, char* argv[]) { HMODULE hUser32 = LoadLibrary("user32.dll"); g_AddrofMessageBoxA = (PVOID)GetProcAddress(hUser32, "MessageBoxA"); printf("Address of MessageBoxA = 0x%p\n", g_AddrofMessageBoxA); g_OriginalMessageBoxA = (PFN_MessageBox)InitTrampolineFun(); //跳过开头的Hook printf("Addr of VectoredHandler1 = 0x%p\n", VectoredHandler1); printf("Addr of VectoredHandler2 = 0x%p\n", VectoredHandler2); printf("Addr of VectoredHandler3 = 0x%p\n", VectoredHandler3); //选择安装一个进行测试 InstallVEHHook(VectoredHandler1); //设置断点 SetBreakPoint(g_AddrofMessageBoxA); //call ShowMsgBox("VEH Hook Test."); printf("All Finished!\n"); ClearBreakPoint(g_AddrofMessageBoxA); UnInstallVEHHook(); ShowMsgBox("Hook Cleared"); return 0; } VOID ShowMsgBox(LPCTSTR lpMsg) { MessageBoxA(NULL, lpMsg, "Test", MB_OK); } ULONG_PTR InitTrampolineFun() { ULONG_PTR uResult = 0; PBYTE pFun = NULL; #ifdef _WIN64 //x64需要申请shellcode /* USER32!MessageBoxA: 00000000`779412b8 4883ec38 sub rsp,38h 00000000`779412bc 4533db xor r11d,r11d 00000000`779412bf 44391d760e0200 cmp dword ptr [USER32!gapfnScSendMessage+0x927c (00000000`7796213c)],r11d */ pFun = (PBYTE)VirtualAlloc(NULL, 128, MEM_COMMIT, PAGE_EXECUTE_READWRITE); uResult = (ULONG_PTR)pFun; memset(pFun, 0, 128); memcpy(pFun, (PVOID)g_AddrofMessageBoxA, 4); //拷贝第一条指令,4字节,推荐使用反汇编引擎来实际计算 pFun += 4; //下一条指令构造为jmp [xxxxxx] pFun[0] = 0xFF; pFun[1] = 0x25; *(ULONG_PTR*)(pFun + 6) = (ULONG_PTR)g_AddrofMessageBoxA + 4; //跳回到原函数加4的地方 #else //x86,第一条指令是mov edi,edi,直接跳过即可 uResult = (ULONG_PTR)g_AddrofMessageBoxA + 2; #endif return uResult; } //处理方式,修改参数并返回原函数继续执行 LONG WINAPI VectoredHandler1( struct _EXCEPTION_POINTERS* ExceptionInfo ) { char* szNewMsg = "[VectoredHandler1] Hacked by pediy.com"; LONG lResult = EXCEPTION_CONTINUE_SEARCH; PEXCEPTION_RECORD pExceptionRecord; PCONTEXT pContextRecord; int ret = 0; pExceptionRecord = ExceptionInfo->ExceptionRecord; pContextRecord = ExceptionInfo->ContextRecord; ULONG_PTR* uESP = 0; printf("Exception Address = %p\n", pExceptionRecord->ExceptionAddress); if (pExceptionRecord->ExceptionCode == EXCEPTION_BREAKPOINT && pExceptionRecord->ExceptionAddress == g_AddrofMessageBoxA) { #ifdef _WIN64 //x64上前四个参数依次为RCX,RDX,R8,R9 //修改第二个参数,即LpMsg printf("lpText = 0x%p %s\n", pContextRecord->Rdx, (char*)pContextRecord->Rdx); pContextRecord->Rdx = (ULONG_PTR)szNewMsg; pContextRecord->Rip = (ULONG_PTR)g_OriginalMessageBoxA; //跳到Trampoline继续执行 #else /* 0012FF70 0040105A /CALL 到 MessageBoxA 来自 VEHHook.00401054 0012FF74 00000000 |hOwner = NULL 0012FF78 00407030 |Text = "VEH Hook" 0012FF7C 0040703C |Title = "Test" 0012FF80 00000000 \Style = MB_OK|MB_APPLMODAL 0012FF84 00401225 返回到 VEHHook.<ModuleEntryPoint>+0B4 来自 VEHHook.00401000 */ printf("ESP = 0x%p\n", pContextRecord->Esp); uESP = (ULONG_PTR*)pContextRecord->Esp; //取中断时的ESP uESP[2] = (ULONG_PTR)szNewMsg; //修改栈中的参数 pContextRecord->Eip = (ULONG_PTR)g_OriginalMessageBoxA; //跳过函数开头 #endif lResult = EXCEPTION_CONTINUE_EXECUTION; } return lResult; } //处理方式:直接调用原函数并替原函数返回 LONG WINAPI VectoredHandler2( struct _EXCEPTION_POINTERS* ExceptionInfo ) { char* szNewMsg = "[VectoredHandler2] Hacked by pediy.com"; LONG lResult = EXCEPTION_CONTINUE_SEARCH; PEXCEPTION_RECORD pExceptionRecord; PCONTEXT pContextRecord; int ret = 0; pExceptionRecord = ExceptionInfo->ExceptionRecord; pContextRecord = ExceptionInfo->ContextRecord; ULONG_PTR* uESP = 0; if (pExceptionRecord->ExceptionCode == EXCEPTION_BREAKPOINT && pExceptionRecord->ExceptionAddress == g_AddrofMessageBoxA) { #ifdef _WIN64 //x64上前四个参数依次为RCX,RDX,R8,R9 printf("RSP = 0x%p\n", pContextRecord->Rsp); uESP = (ULONG_PTR*)pContextRecord->Rsp; printf("Return Address = 0x%p\n", uESP[0]); ret = g_OriginalMessageBoxA((HWND)pContextRecord->Rcx, szNewMsg, (LPCTSTR)pContextRecord->R8, (int)pContextRecord->R9); printf("ret = %d\n", ret); //修正RSP pContextRecord->Rsp += sizeof(ULONG_PTR);//参数在寄存器中,栈中无参数,仅需跳过返回地址 //直接返回到调用者处 pContextRecord->Rip = uESP[0];//设置EIP为返回地址 #else /* 0012FF70 0040105A /CALL 到 MessageBoxA 来自 VEHHook.00401054 0012FF74 00000000 |hOwner = NULL 0012FF78 00407030 |Text = "VEH Hook" 0012FF7C 0040703C |Title = "Test" 0012FF80 00000000 \Style = MB_OK|MB_APPLMODAL 0012FF84 00401225 返回到 VEHHook.<ModuleEntryPoint>+0B4 来自 VEHHook.00401000 */ printf("ESP = 0x%p\n", pContextRecord->Esp); uESP = (ULONG_PTR*)pContextRecord->Esp; ret = g_OriginalMessageBoxA((HWND)uESP[1], szNewMsg, (LPCTSTR)uESP[3], (int)uESP[4]); printf("ret = %d\n", ret); //直接返回到调用者处 pContextRecord->Eip = uESP[0];//设置EIP为返回地址 pContextRecord->Esp += (4 + 1) * sizeof(ULONG_PTR); //4为参数个数,1为返回地址 #endif lResult = EXCEPTION_CONTINUE_EXECUTION; } return lResult; } //处理方式:直接返回,相当于过滤掉 LONG WINAPI VectoredHandler3( struct _EXCEPTION_POINTERS* ExceptionInfo ) { LONG lResult = EXCEPTION_CONTINUE_SEARCH; PEXCEPTION_RECORD pExceptionRecord = ExceptionInfo->ExceptionRecord; PCONTEXT pContextRecord = ExceptionInfo->ContextRecord; ULONG_PTR* uESP = 0; if (pExceptionRecord->ExceptionCode == EXCEPTION_BREAKPOINT && pExceptionRecord->ExceptionAddress == g_AddrofMessageBoxA) { /* 0012FF70 0040105A /CALL 到 MessageBoxA 来自 VEHHook.00401054 0012FF74 00000000 |hOwner = NULL 0012FF78 00407030 |Text = "VEH Hook" 0012FF7C 0040703C |Title = "Test" 0012FF80 00000000 \Style = MB_OK|MB_APPLMODAL 0012FF84 00401225 返回到 VEHHook.<ModuleEntryPoint>+0B4 来自 VEHHook.00401000 */ //直接返回到调用者处 #ifdef _WIN64 printf("RSP = 0x%p\n", pContextRecord->Rsp); uESP = (ULONG_PTR*)pContextRecord->Rsp; pContextRecord->Rip = uESP[0];//设置EIP为返回地址 pContextRecord->Rsp += sizeof(ULONG_PTR); //将压入栈内的参数和返回地址清理掉,4为参数个数,1为返回地址 #else printf("ESP = 0x%X\n", pContextRecord->Esp); uESP = (ULONG_PTR*)pContextRecord->Esp; pContextRecord->Eip = uESP[0];//设置EIP为返回地址 pContextRecord->Esp += (4 + 1) * sizeof(ULONG_PTR); //将压入栈内的参数和返回地址清理掉,4为参数个数,1为返回地址 #endif lResult = EXCEPTION_CONTINUE_EXECUTION; } return lResult; } BOOL InstallVEHHook(PVECTORED_EXCEPTION_HANDLER Handler) { printf("Current Handler Address = 0x%p\n", Handler); g_hVector = AddVectoredExceptionHandler(1, Handler); return g_hVector != NULL; } VOID UnInstallVEHHook() { RemoveVectoredExceptionHandler(g_hVector); } /* 0:000> u user32!messageboxA USER32!MessageBoxA: 77d507ea 8bff mov edi,edi 77d507ec 55 push ebp 77d507ed 8bec mov ebp,esp */ BOOL SetBreakPoint(PVOID pFuncAddr) { DWORD dwCnt = 0; BYTE* pTarget = (BYTE*)pFuncAddr; g_OldCode[0] = *pTarget; printf("Original Fun Head Code = 0x%02X\n", g_OldCode[0]); //修改内存页的属性 DWORD dwOLD; MEMORY_BASIC_INFORMATION mbi; VirtualQuery(pTarget, &mbi, sizeof(mbi)); VirtualProtect(mbi.BaseAddress, mbi.RegionSize, PAGE_EXECUTE_READWRITE, &dwOLD); //写入int3 *pTarget = 0xCC; //恢复内存页的属性 VirtualProtect(mbi.BaseAddress, mbi.RegionSize, dwOLD, 0); return TRUE; } BOOL ClearBreakPoint(PVOID pFuncAddr) { BYTE* pTarget = (BYTE*)pFuncAddr; //修改内存页的属性 DWORD dwOLD; MEMORY_BASIC_INFORMATION mbi; VirtualQuery(pTarget, &mbi, sizeof(mbi)); VirtualProtect(mbi.BaseAddress, mbi.RegionSize, PAGE_EXECUTE_READWRITE, &dwOLD); *pTarget = g_OldCode[0]; //恢复内存页的属性 VirtualProtect(mbi.BaseAddress, mbi.RegionSize, dwOLD, 0); return TRUE; } int WINAPI My_MessageBox( 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 ) { char newMsg[400]; char newCation[] = "标题被我改了!"; int result; if (lpText) { ZeroMemory(newMsg, 400); lstrcpy(newMsg, lpText); lstrcat(newMsg, "\n\tMessage Box hacked by pediy.com"); } printf("有人调用MessageBox...\n"); result = g_OriginalMessageBoxA(hWnd, newMsg, newCation, uType); return result; }严重性 代码 说明 项目 文件 行 禁止显示状态 详细信息 错误(活动) E0020 未定义标识符 "printf" veh hook C:\Users\17116\source\repos\veh hook\veh hook\源.cpp 41 错误(活动) E0020 未定义标识符 "printf" veh hook C:\Users\17116\source\repos\veh hook\veh hook\源.cpp 116 错误(活动) E0020 未定义标识符 "printf" veh hook C:\Users\17116\source\repos\veh hook\veh hook\源.cpp 166 错误(活动) E0020 未定义标识符 "printf" veh hook C:\Users\17116\source\repos\veh hook\veh hook\源.cpp 225 错误(活动) E0020 未定义标识符 "printf" veh hook C:\Users\17116\source\repos\veh hook\veh hook\源.cpp 243 错误(活动) E0020 未定义标识符 "printf" veh hook C:\Users\17116\source\repos\veh hook\veh hook\源.cpp 267 错误(活动) E0020 未定义标识符 "printf" veh hook C:\Users\17116\source\repos\veh hook\veh hook\源.cpp 314 错误 C1083 无法打开包括文件: “stdafx.h”: No such file or directory veh hook C:\Users\17116\source\repos\veh hook\veh hook\源.cpp 3 错误(活动) E1696 无法打开 源 文件 "stdafx.h" veh hook C:\Users\17116\source\repos\veh hook\veh hook\源.cpp 3 错误(活动) E0167 "LPCTSTR" (aka "const WCHAR *") 类型的实参与 "LPCSTR" (aka "const CHAR *") 类型的形参不兼容 veh hook C:\Users\17116\source\repos\veh hook\veh hook\源.cpp 68 错误(活动) E0167 "const char *" 类型的实参与 "LPCWSTR" (aka "const WCHAR *") 类型的形参不兼容 veh hook C:\Users\17116\source\repos\veh hook\veh hook\源.cpp 39 错误(活动) E0167 "const char *" 类型的实参与 "LPCWSTR" (aka "const WCHAR *") 类型的形参不兼容 veh hook C:\Users\17116\source\repos\veh hook\veh hook\源.cpp 312 错误(活动) E0167 "const char *" 类型的实参与 "LPCTSTR" (aka "const WCHAR *") 类型的形参不兼容 veh hook C:\Users\17116\source\repos\veh hook\veh hook\源.cpp 55 错误(活动) E0167 "const char *" 类型的实参与 "LPCTSTR" (aka "const WCHAR *") 类型的形参不兼容 veh hook C:\Users\17116\source\repos\veh hook\veh hook\源.cpp 62 错误(活动) E0144 "const char *" 类型的值不能用于初始化 "char *" 类型的实体 veh hook C:\Users\17116\source\repos\veh hook\veh hook\源.cpp 108 错误(活动) E0144 "const char *" 类型的值不能用于初始化 "char *" 类型的实体 veh hook C:\Users\17116\source\repos\veh hook\veh hook\源.cpp 152 错误(活动) E0167 "char *" 类型的实参与 "LPWSTR" (aka "wchar_t *") 类型的形参不兼容 veh hook C:\Users\17116\source\repos\veh hook\veh hook\源.cpp 311 错误(活动) E0167 "char *" 类型的实参与 "LPWSTR" (aka "wchar_t *") 类型的形参不兼容 veh hook C:\Users\17116\source\repos\veh hook\veh hook\源.cpp 312 错误(活动) E0167 "char *" 类型的实参与 "LPCTSTR" (aka "const WCHAR *") 类型的形参不兼容 veh hook C:\Users\17116\source\repos\veh hook\veh hook\源.cpp 169 错误(活动) E0167 "char *" 类型的实参与 "LPCTSTR" (aka "const WCHAR *") 类型的形参不兼容 veh hook C:\Users\17116\source\repos\veh hook\veh hook\源.cpp 315 错误(活动) E0167 "char *" 类型的实参与 "LPCTSTR" (aka "const WCHAR *") 类型的形参不兼容 veh hook C:\Users\17116\source\repos\veh hook\veh hook\源.cpp 315
07-25
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值