这个工具代码并非我原创,只是看到代码了,提取一份然后修改代码,添加注释等等花了几小时,首先来份版权信息。
/*
-------------------------------------------------
异常自动报告工具 /////////我修改成中文了
-------------------------------------------------
by Piotr Bania <bania.piotr@gmail.com>
333K9s2c8@1M7q4)9K6b7g2)9J5c8W2)9J5c8Y4m8T1i4K6u0W2M7%4m8W2j5$3W2S2L8r3W2K6k6h3c8Q4x3X3g2A6L8X3k6G2
All rights reserved!
Binary:
- 1b9K9s2c8@1M7q4)9K6b7g2)9J5c8W2)9J5c8Y4m8T1i4K6u0W2M7%4m8W2j5$3W2S2L8r3W2K6k6h3c8Q4x3X3g2A6L8X3k6G2i4K6u0r3j5h3I4D9i4K6u0r3k6h3k6A6L8s2c8W2M7W2)9J5c8X3g2X3K9h3I4@1k6i4u0Q4x3X3g2V1L8r3H3`.
Source:
- f97K9s2c8@1M7q4)9K6b7g2)9J5c8W2)9J5c8Y4m8T1i4K6u0W2M7%4m8W2j5$3W2S2L8r3W2K6k6h3c8Q4x3X3g2A6L8X3k6G2i4K6u0r3j5h3I4D9i4K6u0r3k6h3k6A6L8s2c8W2M7W2)9J5c8X3g2X3K9h3I4@1k6i4u0Q4x3X3g2U0
*/
这个是挂钩ntdll.dll里面的KiUserExceptionDispatcher函数用来模拟处理异常,模拟的时候报告异常的地址,以及异常的方式,寄存器的值等等。
使用方法:拿一个有异常的软件或者壳,装入OD,然后点击菜单上的可执行文件模块,注入这个模块,然后直接运行程序,就会报告异常了,我已经拿ASrotect2.3SKE做了实验,成功报告异常的地址,以及异常方式等等,
编译环境:Pelloc C
编译选项:恢复Windows扩展
代码如下,附件在后:
/*
-------------------------------------------------
异常自动报告工具 /////////我修改成中文了
-------------------------------------------------
by Piotr Bania <bania.piotr@gmail.com>
0b6K9s2c8@1M7q4)9K6b7g2)9J5c8W2)9J5c8Y4m8T1i4K6u0W2M7%4m8W2j5$3W2S2L8r3W2K6k6h3c8Q4x3X3g2A6L8X3k6G2
All rights reserved!
Binary:
- 41cK9s2c8@1M7q4)9K6b7g2)9J5c8W2)9J5c8Y4m8T1i4K6u0W2M7%4m8W2j5$3W2S2L8r3W2K6k6h3c8Q4x3X3g2A6L8X3k6G2i4K6u0r3j5h3I4D9i4K6u0r3k6h3k6A6L8s2c8W2M7W2)9J5c8X3g2X3K9h3I4@1k6i4u0Q4x3X3g2V1L8r3H3`.
Source:
- 580K9s2c8@1M7q4)9K6b7g2)9J5c8W2)9J5c8Y4m8T1i4K6u0W2M7%4m8W2j5$3W2S2L8r3W2K6k6h3c8Q4x3X3g2A6L8X3k6G2i4K6u0r3j5h3I4D9i4K6u0r3k6h3k6A6L8s2c8W2M7W2)9J5c8X3g2X3K9h3I4@1k6i4u0Q4x3X3g2U0
*/
#include <stdio.h>
#include <windows.h>
#define SHOW_R_DUMP 1 // 显示当前上下寄存器环境
#define SIZE_OF_BUFF 2024 //////打印信息缓冲区大小
#define MY_API extern "C" __declspec(dllexport)
#define MY_NAKED extern "C" _declspec(naked)
#define MAX_BAD_SIZE 0x60
#define calc_jump(y,x) ((x-y)-5)
void MyLoadModule(void);
void MyUnLoadModule(void);
void StartFilter(void);
void FilterExceptions(EXCEPTION_RECORD *er,CONTEXT *con);
char* pname; ////进程名字
char fn[MAX_PATH+1];
char dbgmsg[SIZE_OF_BUFF]; ///////要打印的信息存放的缓冲区
DWORD cPid; /////进程PID
DWORD _KiUserExceptionDispatcher; ////保存获得的原函数地址
BOOL Done = FALSE;
void FilterExceptions(EXCEPTION_RECORD *er,CONTEXT *con)
{
DWORD aSEH;
DWORD req = (DWORD)er->ExceptionInformation+4;
DWORD method = (DWORD)er->ExceptionInformation; /*取出异常代码,这里指向第一个异常代码,内存访问无效(EXCEPTION_ACCESS_VIOLATION)
EXCEPTION_ACCESS_VIOLATION指明了内存访问的方式,0表示读取,1表示写入,其中RaiseException 指定这个异常信息中的异常代码*/
DWORD Flag=(DWORD)er->ExceptionFlags;///指明了异常的标志,这个值为0的时候,表明一直执行异常,不返回,当值为 1的时候表示不一直执行异常,异常执行完就返回
if (((DWORD)(er->ExceptionAddress) >= (DWORD)&IsBadReadPtr) && ((DWORD)(er->ExceptionAddress) <= (DWORD)(&IsBadReadPtr) + MAX_BAD_SIZE))
goto nono;
if (((DWORD)(er->ExceptionAddress) >= (DWORD)&IsBadWritePtr) && ((DWORD)(er->ExceptionAddress) <= (DWORD)(&IsBadWritePtr) + MAX_BAD_SIZE))
goto nono;
if (((DWORD)(er->ExceptionAddress) >= (DWORD)&IsBadStringPtr) && ((DWORD)(er->ExceptionAddress) <= (DWORD)(&IsBadStringPtr) + MAX_BAD_SIZE))
goto nono;
_asm {
mov eax,dword ptr fs:[0]
mov eax,[eax+4]
mov aSEH,eax
}
pname=strrchr(fn,'\\'); pname++;
sprintf(dbgmsg,"异常地址: 0x%X\r\n地址指向: 0x%X\r\nSEH处理地址:0x%X",er->ExceptionAddress,*(DWORD*)req,aSEH);
MessageBox(NULL,dbgmsg,"Information",MB_OK);
if(Flag==0)
{
sprintf(dbgmsg,"异常标志:%X==一直异常",er->ExceptionFlags);
MessageBox(NULL,dbgmsg,"Information",MB_OK);
}
if(Flag==1)
{
sprintf(dbgmsg,"异常标志:%X==不一直异常",er->ExceptionFlags);
MessageBox(NULL,dbgmsg,"Information",MB_OK);
}
switch(er->ExceptionCode) /////////////////异常代码,判断是哪个异常
{
case EXCEPTION_ACCESS_VIOLATION:
sprintf(dbgmsg,"内存访问无效:异常代码:%x==EXCEPTION_ACCESS_VIOLATION",er->ExceptionCode);
MessageBox(NULL,dbgmsg,"Information",MB_OK);
break;
case EXCEPTION_ARRAY_BOUNDS_EXCEEDED:
sprintf(dbgmsg,"线程试图访问数组元素,异常代码:%x==EXCEPTION_ARRAY_BOUNDS_EXCEEDED",er->ExceptionCode);
MessageBox(NULL,dbgmsg,"Information",MB_OK);
break;
case EXCEPTION_BREAKPOINT:
sprintf(dbgmsg,"一个断点发生:异常代码:%x==EXCEPTION_BREAKPOINT",er->ExceptionCode);
MessageBox(NULL,dbgmsg,"Information",MB_OK);
break;
case EXCEPTION_DATATYPE_MISALIGNMENT:
sprintf(dbgmsg,"线程试图读取或写入数据:异常代码:%x==EXCEPTION_DATATYPE_MISALIGNMENT",er->ExceptionCode);
MessageBox(NULL,dbgmsg,"Information",MB_OK);
break;
case EXCEPTION_FLT_DENORMAL_OPERAND:
sprintf(dbgmsg,"浮点运算不标准:异常代码:%x==EXCEPTION_FLT_DENORMAL_OPERAND",er->ExceptionCode);
MessageBox(NULL,dbgmsg,"Information",MB_OK);
break;
case EXCEPTION_FLT_DIVIDE_BY_ZERO:
sprintf(dbgmsg,"浮点值试图除以0:异常代码:%x==EXCEPTION_FLT_DIVIDE_BY_ZERO",er->ExceptionCode);
MessageBox(NULL,dbgmsg,"Information",MB_OK);
break;
case EXCEPTION_FLT_INEXACT_RESULT:
sprintf(dbgmsg,"浮点数不能精确的表示为小数,异常代码:%x==EXCEPTION_FLT_INEXACT_RESULT",er->ExceptionCode);
MessageBox(NULL,dbgmsg,"Information",MB_OK);
break;
case EXCEPTION_FLT_INVALID_OPERATION:
sprintf(dbgmsg,"浮点异常,异常代码:%x==EXCEPTION_FLT_INVALID_OPERATION",er->ExceptionCode);
MessageBox(NULL,dbgmsg,"Information",MB_OK);
break;
case EXCEPTION_FLT_OVERFLOW:
sprintf(dbgmsg,"浮点数溢出,异常代码:%x==EXCEPTION_FLT_OVERFLOW",er->ExceptionCode);
MessageBox(NULL,dbgmsg,"Information",MB_OK);
break;
case EXCEPTION_FLT_STACK_CHECK:
sprintf(dbgmsg,"堆栈溢出或下溢做为一个浮点运算结果,异常代码:%x==EXCEPTION_FLT_STACK_CHECK",er->ExceptionCode);
MessageBox(NULL,dbgmsg,"Information",MB_OK);
break;
case EXCEPTION_FLT_UNDERFLOW:
sprintf(dbgmsg,"一个浮点运算的指数小于相应类型的允许幅度,异常代码:%x==EXCEPTION_FLT_UNDERFLOW",er->ExceptionCode);
MessageBox(NULL,dbgmsg,"Information",MB_OK);
break;
case EXCEPTION_ILLEGAL_INSTRUCTION:
sprintf(dbgmsg,"线程试图执行无效指令,异常代码:%x==EXCEPTION_ILLEGAL_INSTRUCTION",er->ExceptionCode);
MessageBox(NULL,dbgmsg,"Information",MB_OK);
break;
case EXCEPTION_IN_PAGE_ERROR:
sprintf(dbgmsg,"线程试图访问的页面不存在系统无法加载的页面,异常代码:%x==EXCEPTION_IN_PAGE_ERROR",er->ExceptionCode);
MessageBox(NULL,dbgmsg,"Information",MB_OK);
break;
case EXCEPTION_INT_DIVIDE_BY_ZERO:
sprintf(dbgmsg,"线程试图除以零的整数除数的整数值,异常代码:%x==EXCEPTION_INT_DIVIDE_BY_ZERO",er->ExceptionCode);
MessageBox(NULL,dbgmsg,"Information",MB_OK);
break;
case EXCEPTION_INT_OVERFLOW:
sprintf(dbgmsg,"整数运算的结果造成了结果的最高的位,异常代码:%x==EXCEPTION_INT_OVERFLOW",er->ExceptionCode);
MessageBox(NULL,dbgmsg,"Information",MB_OK);
break;
case EXCEPTION_INVALID_DISPOSITION:
sprintf(dbgmsg,"异常处理程序返回一个无效的处置异常调度,异常代码:%x==EXCEPTION_INVALID_DISPOSITION",er->ExceptionCode);
MessageBox(NULL,dbgmsg,"Information",MB_OK);
break;
case EXCEPTION_NONCONTINUABLE_EXCEPTION:
sprintf(dbgmsg,"线程试图发生异常后不继续执行指定代码,异常代码:%x==EXCEPTION_NONCONTINUABLE_EXCEPTION",er->ExceptionCode);
MessageBox(NULL,dbgmsg,"Information",MB_OK);
break;
case EXCEPTION_PRIV_INSTRUCTION:
sprintf(dbgmsg,"线程试图执行一条指令,其操作是不会允许在当前的机器模式,异常代码:%x==EXCEPTION_PRIV_INSTRUCTION",er->ExceptionCode);
MessageBox(NULL,dbgmsg,"Information",MB_OK);
break;
case EXCEPTION_SINGLE_STEP:
sprintf(dbgmsg,"一个跟踪陷阱或其他单指令的机制标志着一个指令已被执行,异常代码:%x==EXCEPTION_SINGLE_STEP",er->ExceptionCode);
MessageBox(NULL,dbgmsg,"Information",MB_OK);
break;
case EXCEPTION_STACK_OVERFLOW:
sprintf(dbgmsg,"线程用完它的堆栈,异常代码:%x==EXCEPTION_STACK_OVERFLOW",er->ExceptionCode);
MessageBox(NULL,dbgmsg,"Information",MB_OK);
break;
}
///////////比较内存是访问还是读取
if (*(DWORD*)method == 0)
{
_snprintf(dbgmsg,sizeof(dbgmsg),"异常地址处尝试读取不可访问的数据。");
if (*(DWORD*)req == (DWORD)er->ExceptionAddress)
_snprintf(dbgmsg,sizeof(dbgmsg),"异常地址处准备执行一个地址的数据");
}
if (*(DWORD*)method == 1)
_snprintf(dbgmsg,sizeof(dbgmsg),"[+] 异常地址试图写入一个不可访问的地址");
MessageBox(NULL,dbgmsg,"Information",MB_OK);
#if SHOW_R_DUMP == 1
_snprintf(dbgmsg,sizeof(dbgmsg),"地址处寄存器的数据:\nEAX=%.08x\r\nECX=%.08x\nEDX=%.08x\nEBX=%.08x\nESI=%.08x\r\nEDI=%.08x\nEBP=%.08x\nESP=%.08x",con->Eax,con->Ecx,con->Edx,con->Ebx,con->Esi,con->Edi,con->Ebp,con->Esp);
MessageBox(NULL,dbgmsg,"Information",MB_OK);
#endif
Beep(0xFF,50);
nono:;
}
void _declspec(naked) FilterHandler(void)
{
__asm {
mov ecx,[esp+4]
mov ebx,[esp]
pushad
cmp dword ptr [ebx],0xc0000005
jne _leave_it
mov ebp,esp
push ecx
push ebx
call FilterExceptions
mov esp,ebp
_leave_it: popad
push _KiUserExceptionDispatcher
add [esp],7
ret
}
}
BOOL APIENTRY DllMain( HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
MyLoadModule();
break;
case DLL_PROCESS_DETACH:
MyUnLoadModule();
break;
}
return TRUE;
}
////////////////////////////////加载模块
void MyLoadModule(void)
{
cPid=GetCurrentProcessId();
if (GetModuleFileName(NULL,fn,MAX_PATH) != 0)
{
pname=strrchr(fn,'\\'); pname++;
_snprintf(dbgmsg, sizeof(dbgmsg),"加载模块 %s - pid: 0x%X \r\n",pname,cPid);
MessageBox(NULL,dbgmsg,"加载模块",MB_OK);
StartFilter();
}
}
////////////////////////////////卸载模块
void MyUnLoadModule(void)
{
if (Done == FALSE)
{
pname=strrchr(fn,'\\');
pname++;
_snprintf(dbgmsg, sizeof(dbgmsg),"卸载模块%s - Pid: 0x%X \r\n",pname,cPid);
MessageBox(NULL,dbgmsg,"卸载模块",MB_OK);
Done = TRUE;
}
}
//////////////////////////////挂钩ntdll.dll里面的KiUserExceptionDispatcher函数
void StartFilter(void)
{
DWORD oldp;
_KiUserExceptionDispatcher=(DWORD)GetProcAddress(LoadLibrary("ntdll.dll"),"KiUserExceptionDispatcher");
if (_KiUserExceptionDispatcher != 0)
{
if (*(BYTE *)_KiUserExceptionDispatcher != 0xE9)
{
if (VirtualProtect((LPVOID)_KiUserExceptionDispatcher,5,PAGE_READWRITE,&oldp))
{
*(BYTE *)_KiUserExceptionDispatcher = 0xE9;
*(DWORD *)(_KiUserExceptionDispatcher+1) = calc_jump(_KiUserExceptionDispatcher,(unsigned long)FilterHandler);
VirtualProtect((LPVOID)_KiUserExceptionDispatcher,5,oldp,&oldp);
Sleep(1000);
}
}
}
} 密码:
1d3K9s2c8@1M7q4)9K6b7g2)9J5c8W2)9J5c8Y4N6%4N6#2)9J5k6i4m8W2k6r3W2&6i4K6u0W2j5$3!0E0
[培训]传播安全知识、拓宽行业人脉——看雪讲师团队等你加入!
上传的附件: