之前朋友有一个服务端程序,总是受到一些人的恶意漏洞攻击,没有源代码,只好反汇编修复了漏洞,并且使用WinLicense加保护授权.
漏洞总不是一次可以修复完的,恶意攻击并没有停止,然后加了WL保护程序在崩溃的时候在没有提示信息,服务器日志中也没有记录任何有用的信息了,这里所需要有用的信息即是崩溃时候汇编代码运行的内存地址.c++写的程序崩溃的时候我们经常可以看到这种包含了运行址,以及访问内存地址相关信息的对话框.
首先想到的办法是使用windbg的adplus -crash dump内存分析,cdb刚attach上目标进程就直接退出了,不错,WL检查到了调试器,自动触发了保护,程序退出进程了.所以通过windbg,od类似的调试器方案是行不通了.
还有一次,攻击影响了客户端,使部分客户端崩溃,通过日志看到的错误内存地址,经过分析发现是在SEH中,即我们平常代码__try{}__except{}的__except{}代码中,关键是这层SEH还被上一层SEH包着,找了很久还是没能有效的定位到崩溃的内存地址.
后来只好电话求助了小明哥,没说别的,就VEH向量化异常处理解决问题.
更多的知识可以看雪http://bbs.pediy.com/showthread.php?t=173853
通过看雪上的这篇文章我们可以了解到,在没有调试器的情况下,程序发生异常,如果有安装VEH,则VEH先处理异常,然后才是SEH,TopLevelEH.
我要的东西很简单,就是程序崩溃的内存地址,即当时发生崩溃的时候,cpu EIP寄存器的值.
代码就很简单了
#define DBG_PRINTEXCEPTION_C ((DWORD )0x40010006L) LONG WINAPI ExceptionHandler(EXCEPTION_POINTERS * pExceptionInfo) { char lpMsg[512]={0}; switch( pExceptionInfo->ExceptionRecord->ExceptionCode ) { case DBG_PRINTEXCEPTION_C: break; default: { memset(lpMsg,0,512); wsprintfA(lpMsg,"Exp EIP:%x ExpAddr:%x",pExceptionInfo->ContextRecord->Eip,pExceptionInfo->ExceptionRecord->ExceptionAddress); OutputDebugStringA(lpMsg); } } return EXCEPTION_CONTINUE_SEARCH; } BOOL APIENTRY DllMain( HMODULE hModule,DWORD ul_reason_for_call,LPVOID lpReserved) { switch (ul_reason_for_call) { case DLL_PROCESS_ATTACH: { AddVectoredExceptionHandler(1, (PVECTORED_EXCEPTION_HANDLER)ExceptionHandler); } case DLL_THREAD_ATTACH: case DLL_THREAD_DETACH: case DLL_PROCESS_DETACH: break; } return TRUE; }
不错,写一个dll,然后Exe程序启动进入Main函数后,直接反汇编写段代码,loadlibrary一下dll,即可.
打开DbgView,运行目标进程,崩溃一出现,dbgview中就输出了Eip地址,在反汇编定位到代码处理,具体问题具体分析即可!