手记式的东西。自认为ASM还算没白学。。大概可以及格啦  至少应该不会被打PP咯~! 

引用:

;下面的代码其实就是为了找到360safebox的hook而已
nt!KiFastCallEntry+0x89:
804df77d mov     dword ptr [ebp+4],edi
804df780 sti
804df781 mov     edi,eax
804df783 shr     edi,8
804df786 
and     edi,30h
804df789 
mov     ecx,edi
804df78b add     edi,dword ptr [esi+0E0h]
804df791 mov     ebx,eax
804df793 and     eax,0FFFh
804df798 
cmp     eax,dword ptr [edi+8]
804df79b jae     nt!KiBBTUnexpectedRange (804df4e2)
804df7a1 cmp     ecx,10h
804df7a4 
jne     nt!KiFastCallEntry+0xcc (804df7c0)
804df7a6 mov     ecx,dword ptr ds:[0FFDFF018h]
804df7ac xor     ebx,ebx
804df7ae or      ebx,dword ptr [ecx+0F70h]
804df7b4 je      nt!KiFastCallEntry+0xcc (804df7c0)
804df7b6 push    edx
804df7b7 push    eax
804df7b8 call    dword ptr [nt!KeGdiFlushUserBatch (8055a6c4)]
804df7be pop     eax
804df7bf pop     edx
804df7c0 inc     dword ptr ds:[0FFDFF638h]
804df7c6 mov     esi,edx ;edx中是参数(堆栈顶的指针),如下:
;ntdll!ZwOpenProcess:
;7c92dd7b mov     eax,7Ah
;7c92dd80 mov     edx,offset SharedUserData!SystemCallStub (7ffe0300)
;7c92dd85 call    dword ptr [edx] edx中是7ffe0300
;7c92dd87 ret     10h
;lkd> dd 7ffe0300
;7ffe0300  7c92eb8b ;省略...
;lkd> u 7c92eb8b 
;ntdll!KiFastSystemCall:
;7c92eb8b mov     edx,esp ;把当前堆栈放到edx中
;7c92eb8d sysenter
804df7c8 mov     ebx,dword ptr [edi+0Ch]
804df7cb xor     ecx,ecx
804df7cd mov     cl,byte ptr [eax+ebx]
804df7d0 mov     edi,dword ptr [edi]
804df7d2 mov     ebx,dword ptr [edi+eax*4]
804df7d5 jmp     f71b767c ;诺。转跳到360safebox的处理函数
;360safebox的jmp语句覆盖掉的代码:
;sub     esp,ecx
;shr     ecx,2
804df7da mov     edi,esp ;把esp放到edi中
804df7dc cmp     esi,dword ptr [nt!MmUserProbeAddress (80560034)]
804df7e2 jae     nt!KiSystemCallExit2+0x9f (804df990)
804df7e8 rep movs dword ptr es:[edi],dword ptr [esi;把参数复制到内核态。
804df7ea call    ebx ;ebx就是相应的服务历程地址了。
804df7ec mov     esp,ebp ;恢复堆栈。(之前保存堆栈的代码自己用WinDBG找吧。。偶偷懒了。。)
804df7ee mov     ecx,dword ptr ds:[0FFDFF124h;0FFDFF124h中储存着当前线程的ETHREAD这就是另外一个故事了 :)
804df7f4 mov     edx,dword ptr [ebp+3Ch;似乎是在恢复现场吧。大概是KiServiceExit中的一些事情了。略。
804df7f7 mov     dword ptr [ecx+134h],edx
nt!KiServiceExit:
;...省略

;接下来是360safebox的过滤函数的分析。
;其中的push ret用的很邪恶。。
;行号    ;OpCode
f71b767c mov     edi,edi ;其实就是2字节版本的NOP,而且比NOP更节约CPU。应该是为了对齐吧?
f71b767e pushfd ;保存现场
f71b767f pushad ;保存现场
f71b7680 push    edi ;函数f71b6e40的参数5
f71b7681 push    ecx ;函数f71b6e40的参数4
f71b7682 push    esi ;函数f71b6e40的参数3
f71b7683 push    ebx ;函数f71b6e40的参数2
f71b7684 push    eax ;函数f71b6e40的参数1
;这些寄存器中的内容:
;Eax: 服务ID
;Ebx: 服务历程地址(你可以把这个改成原始地址,这样就绕过了SSDT HOOK :P)
;Esi: KiFastCall之前的堆栈栈顶(我没验证,不过也差不离,有兴趣自己看下)
;Ecx: 参数长度
;Edi: 服务表基址(比如KiServiceTable、W32pServiceTable)
f71b7685 call    f71b6e40 ;应该是个过滤函数吧。
f71b768a mov     dword ptr [esp+10h],eax ;把过滤函数的返回值保存起来 - 似乎放到了ebx中??? 我这么写的时候直接就bsod了。。难道过滤函数中还。。。?
f71b768e popad ;恢复现场
f71b768f popfd ;恢复现场
f71b7690 sub     esp,ecx ;应该是360safebox在自己实现覆盖掉的代码了。
f71b7692 shr     ecx,;同上
f71b7695 mov     edi,esp ;自己实现的不仅仅是覆盖掉的代码了。。(参考前文KiFastCallEntry代码)
f71b7697 cmp     esi,dword ptr ds:[0F71B9108h;在我的机器上,F71B9108h处的内容为80560034(MmUserProbeAddress)还是在自己实现。
;条件转移指令JB/JNAE
;格式: JB/JNAE 标号
;功能: 低于/不高于等于时转移
;也就是说如果参数比MmUserProbeAddress低就jmp(如果比MmUserProbeAddress高就是内核下的call,忽略之)
f71b769d jb      f71b76b1 ;----------------------------------------------+
;条件转移指令JE/JZ                                                       |
;格式: JE/JZ标号                                                         |
;功能: ZF=1,转至标号处执                                                |
;ZF(ZeroFlag) 零标志:当结果为负时,ZF=1否则为0。                        |
f71b769f test    byte ptr [ebp+6Ch],;if (*(PBYTE)[ebp+6Ch] && 1)       |  -------------没看懂
f71b76a3 je      f71b76b1 ;                { __asm jmp f71b76b1; } ------+  -------------没看懂,似乎是在检测高2G什么的。。也可能是判断之前过滤函数的返回值吧。。
f71b76a5 mov     eax,0C0000005h ;0xC0000005 = 内存分配访问无效。         |
;把0xC0000005放到eax的意思就是返回值为0xC0000005,看下来的东西:         |
f71b76aa push    dword ptr ds:[0F71C01B0h; 真淫荡啊。。。。            |
f71b76b0 ret ;ret了  其实是ret到了dword ptr ds:[0F71C01B0h]处这是|
;堆栈的一些事情,这是另外一个故事了 :D。[0F71C01B0h]=804df7ec(nt!KiFastCa|
;llEntry+0xf8)。在这儿直接越过了调用服务函数还有复制参数的一些事情, |
;返回了用户态。:D                                                        |
f71b76b1 rep movs dword ptr es:[edi],dword ptr [esi;<------------------+ 还是在自己实现KiFastCallEntry
;难道所有系统的KiFastCallEntry都一样么?不过这种ASM函数换谁也不愿意没事干就重写一次的,何况是M$那群BT :D
f71b76b3 push    dword ptr ds:[0F71C01B0h;精妙!! 之后的ret首先call到了服务函数(ebx中)
f71b76b9 push    ebx ;然后服务函数的ret就call到了[0F71C01B0h](=nt!KiFastCallEntry+0xf8(804df7ec))处
f71b76ba ret ;ret到了ebx
;几次push ret最后都有804df7ec处的一句 mov esp,ebp 来帮忙完成了所有的堆栈平衡 :D
;做的真的很漂亮,不愧是doskey的作品。