刚初步学习完毕seh,开始写些代码实践一下:
#include "windows.h"
#include "stdio.h"
int WinMain(__in HINSTANCE hInstance, __in_opt HINSTANCE hPrevInstance, __in_opt LPSTR lpCmdLine, __in int nShowCmd)
{
__try
{
//LARGE_INTEGER li_temp01,li_temp02;
//QueryPerformanceCounter(&li_temp01);
//QueryPerformanceCounter(&li_temp02);
//QueryPerformanceCounter(&li_temp02);
//QueryPerformanceCounter(&li_temp02);
char char_temp01[1024];
sprintf_s(char_temp01,sizeof(char_temp01),"%I64",
0);//li_temp02.QuadPart - li_temp01.QuadPart);
MessageBox(0,char_temp01,0,0);
//__asm jmp [li_temp01.LowPart];
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
MessageBox(0,0,0,0);
}
return 1;
}
多么简单的代码阿! -_-b
//__asm jmp [li_temp01.LowPart]; 专门触发seh的代码都屏蔽了……
因为sprintf或者wsprintf不是被vs2005说不安全嘛,我们用它推荐的sprintf_s函数,注意后面的format参数“"%I64"”,我特意少些一个“d”,理论上不是messagebox弹出一个乱码的对话框,就是seh被触发。
各位可以用vs2005编译一下,项目设置都是默认的,(/EHsc)开关也是默认的,能够正常触发__try的。
实际的结果是进程直接被卡擦:弹出标准windows异常窗口。
好的,我们OllDbg……
00401040 6A 00 push 0
00401042 68 60A14000 push SEH.0040A160 ; ASCII "%I64"
00401047 68 00040000 push 400
0040104C 8D85 E4FBFFFF lea eax,dword ptr ss:[ebp-41C]
00401052 50 push eax
00401053 E8 51000000 call SEH.004010A9;sprintf_s函数调用。
00401058 83C4 10 add esp,10
================= 悲惨的分割线 =================
进入call SEH.004010A9后多次call,来到了:
00404C51 8A13 mov dl,byte ptr ds:[ebx]; 开始检查格式化字符串。
00404C53 84D2 test dl,dl
.
.
.
.
.
.
.
00404DF0 8A03 mov al,byte ptr ds:[ebx]
00404DF2 3C 36 cmp al,36
00404DF4 75 17 jnz short SEH.00404E0D
00404DF6 807B 01 34 cmp byte ptr ds:[ebx+1],34
00404DFA 75 11 jnz short SEH.00404E0D
00404DFC 43 inc ebx ; 检查通过,已经是%I64字符串。
00404DFD 43 inc ebx ; SEH.0040A162
00404DFE 814D E8 00800000 or dword ptr ss:[ebp-18],8000
00404E05 895D B4 mov dword ptr ss:[ebp-4C],ebx ; SEH.0040A162
00404E08 E9 28060000 jmp SEH.00405435
%I64都已经检查完毕了,就差检查“d”了,如果有d的话都一切正常…… 悲剧阿~~~
00405435 8B5D B4 mov ebx,dword ptr ss:[ebp-4C] ; SEH.0040A164
00405438 8A03 mov al,byte ptr ds:[ebx]
0040543A 84C0 test al,al
0040543C 8845 E7 mov byte ptr ss:[ebp-19],al
0040543F 74 21 je short SEH.00405462
00405441 8B7D D4 mov edi,dword ptr ss:[ebp-2C]
00405444 8AD0 mov dl,al
00405446 ^ E9 1FF8FFFF jmp SEH.00404C6A
上面的代码就是检查“d”的,如果有d,红色的代码不会触发,会继续运行,然后jmp SEH.00404C6A,一切正常…… 悲剧阿~~~
我们通过je short SEH.00405462来到了下面的代码:
================= 悲惨的分割线 =================
00404B6B E8 9CCCFFFF call SEH.0040180C
00404B70 56 push esi
00404B71 56 push esi
00404B72 56 push esi
00404B73 56 push esi
00404B74 C700 16000000 mov dword ptr ds:[eax],16
00404B7A 56 push esi
00404B7B E8 2DCCFFFF call SEH.004017AD
00404B80 83C4 14 add esp,14
红色的代码call SEH.004017AD是关键,我们进入看看。
================= 悲惨的分割线 =================
004017AD 55 push ebp
004017AE 8BEC mov ebp,esp
004017B0 FF35 6CCF4000 push dword ptr ds:[40CF6C]
004017B6 E8 26130000 call SEH.00402AE1
004017BB 85C0 test eax,eax
004017BD 59 pop ecx ; SEH.00404B80
004017BE 74 03 je short SEH.004017C3
004017C0 5D pop ebp ; SEH.00404B80
004017C1 FFE0 jmp eax
004017C3 6A 02 push 2
004017C5 E8 1B320000 call SEH.004049E5
004017CA 59 pop ecx ; SEH.00404B80
004017CB 5D pop ebp ; SEH.00404B80
004017CC ^ E9 E0FEFFFF jmp SEH.004016B1
.
.
.
.
.
.
0040174E C745 80 0D0000C0 mov dword ptr ss:[ebp-80],C000000D
00401755 8975 8C mov dword ptr ss:[ebp-74],esi ; SEH.00404B80
00401758 8945 D4 mov dword ptr ss:[ebp-2C],eax
0040175B FF15 2CA04000 call dword ptr ds:[<&KERNEL32.IsDebuggerPres>; kernel32.IsDebuggerPresent
00401761 6A 00 push 0
00401763 8BF0 mov esi,eax
00401765 FF15 28A04000 call dword ptr ds:[<&KERNEL32.SetUnhandledEx>; kernel32.SetUnhandledExceptionFilter
0040176B 8D45 D0 lea eax,dword ptr ss:[ebp-30]
0040176E 50 push eax
0040176F FF15 24A04000 call dword ptr ds:[<&KERNEL32.UnhandledExcep>; kernel32.UnhandledExceptionFilter
00401775 85C0 test eax,eax
00401777 75 0C jnz short SEH.00401785
00401779 85F6 test esi,esi ; SEH.00404B80
0040177B 75 08 jnz short SEH.00401785
0040177D 6A 02 push 2
0040177F E8 61320000 call SEH.004049E5
00401784 59 pop ecx
00401785 68 0D0000C0 push C000000D
0040178A FF15 20A04000 call dword ptr ds:[<&KERNEL32.GetCurrentProc>; kernel32.GetCurrentProcess
00401790 50 push eax
00401791 FF15 1CA04000 call dword ptr ds:[<&KERNEL32.TerminateProce>; kernel32.TerminateProcess
00401797 8B8D A4020000 mov ecx,dword ptr ss:[ebp+2A4]
0040179D 33CD xor ecx,ebp
0040179F 5E pop esi ; SEH.00404B80
004017A0 E8 20F9FFFF call SEH.004010C5
004017A5 81C5 A8020000 add ebp,2A8
004017AB C9 leave
004017AC C3 retn
进入函数之后,call了2次,然后红色代码:直接jmp SEH.004016B1,接着就是一系列的函数调用:
kernel32.IsDebuggerPresent
kernel32.SetUnhandledExceptionFilter
kernel32.UnhandledExceptionFilter
kernel32.GetCurrentProcess
kernel32.TerminateProcess
我的心阿~ 拔凉拔凉的阿~~~
更换其他诸如:sprintf、wsprintf,或者只更换格式化字符串“%d”,“%s”,都正常,自己的seh能触发。
sprintf_s 内部bug?天杀的sprintf_s !!!该死的微软?
继续研究中……
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!