首页
社区
课程
招聘
[分享][原创]异常自动报告模块,可用来辅助脱壳
发表于: 2011-9-24 06:11 3935

[分享][原创]异常自动报告模块,可用来辅助脱壳

2011-9-24 06:11
3935
这个工具代码并非我原创,只是看到代码了,提取一份然后修改代码,添加注释等等花了几小时,首先来份版权信息。
/*

    -------------------------------------------------
     异常自动报告工具   /////////我修改成中文了
    -------------------------------------------------
         by Piotr Bania <bania.piotr@gmail.com>
	      663K9s2c8@1M7q4)9K6b7g2)9J5c8W2)9J5c8Y4m8T1i4K6u0W2M7%4m8W2j5$3W2S2L8r3W2K6k6h3c8Q4x3X3g2A6L8X3k6G2
		 All rights reserved!


  Binary:
  - 98cK9s2c8@1M7q4)9K6b7g2)9J5c8W2)9J5c8Y4m8T1i4K6u0W2M7%4m8W2j5$3W2S2L8r3W2K6k6h3c8Q4x3X3g2A6L8X3k6G2i4K6u0r3j5h3I4D9i4K6u0r3k6h3k6A6L8s2c8W2M7W2)9J5c8X3g2X3K9h3I4@1k6i4u0Q4x3X3g2V1L8r3H3`.

  Source:
  - 52dK9s2c8@1M7q4)9K6b7g2)9J5c8W2)9J5c8Y4m8T1i4K6u0W2M7%4m8W2j5$3W2S2L8r3W2K6k6h3c8Q4x3X3g2A6L8X3k6G2i4K6u0r3j5h3I4D9i4K6u0r3k6h3k6A6L8s2c8W2M7W2)9J5c8X3g2X3K9h3I4@1k6i4u0Q4x3X3g2U0
*/

这个是挂钩ntdll.dll里面的KiUserExceptionDispatcher函数用来模拟处理异常,模拟的时候报告异常的地址,以及异常的方式,寄存器的值等等。
使用方法:拿一个有异常的软件或者壳,装入OD,然后点击菜单上的可执行文件模块,注入这个模块,然后直接运行程序,就会报告异常了,我已经拿ASrotect2.3SKE做了实验,成功报告异常的地址,以及异常方式等等,
编译环境:Pelloc C
编译选项:恢复Windows扩展
代码如下,附件在后:
/*

    -------------------------------------------------
     异常自动报告工具   /////////我修改成中文了
    -------------------------------------------------
         by Piotr Bania <bania.piotr@gmail.com>
	      342K9s2c8@1M7q4)9K6b7g2)9J5c8W2)9J5c8Y4m8T1i4K6u0W2M7%4m8W2j5$3W2S2L8r3W2K6k6h3c8Q4x3X3g2A6L8X3k6G2
		 All rights reserved!


  Binary:
  - 34aK9s2c8@1M7q4)9K6b7g2)9J5c8W2)9J5c8Y4m8T1i4K6u0W2M7%4m8W2j5$3W2S2L8r3W2K6k6h3c8Q4x3X3g2A6L8X3k6G2i4K6u0r3j5h3I4D9i4K6u0r3k6h3k6A6L8s2c8W2M7W2)9J5c8X3g2X3K9h3I4@1k6i4u0Q4x3X3g2V1L8r3H3`.

  Source:
  - c68K9s2c8@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);
			}
		}
	}
}
密码:ca9K9s2c8@1M7q4)9K6b7g2)9J5c8W2)9J5c8Y4N6%4N6#2)9J5k6i4m8W2k6r3W2&6i4K6u0W2j5$3!0E0

[培训]传播安全知识、拓宽行业人脉——看雪讲师团队等你加入!

上传的附件:
收藏
免费 0
支持
分享
最新回复 (3)
雪    币: 1689
活跃值: (379)
能力值: ( LV15,RANK:440 )
在线值:
发帖
回帖
粉丝
2
先Mark一下,备用!
2011-9-24 07:56
0
雪    币: 437
活跃值: (130)
能力值: ( LV5,RANK:70 )
在线值:
发帖
回帖
粉丝
3
不知道这个怎么用
2011-9-24 09:02
0
雪    币: 278
活跃值: (709)
能力值: ( LV15,RANK:520 )
在线值:
发帖
回帖
粉丝
4
打开附件,用OD的模块查看那个注入功能,注入这个模块,然后用ASProtect外壳测试就知道了,有异常的都可以测试。
2011-9-24 09:08
0
游客
登录 | 注册 方可回帖
返回