跟了一个晚上,终于解决了
大概要实现的是用这个函数替换ntdll中的KiUserExceptionDispatcher,实现方法如下:
VOID NTAPI KiUserExceptionDispatcher(PEXCEPTION_RECORD pExcptRec,PCONTEXT pContext) { DWORD retValue; if (RtlDispatchException(pExcptRec,pContext)) { retValue=::ZwContinue( pContext,0); }else{ retValue=::ZwRaiseException(pExcptRec,pContext,0); } /*略过.............*/ }
参考:http://www.longene.org/techdoc/0359381001224576966.html
这样看着只是通过KiUserExceptionDispatcher来调用ZwContinue与Zw...函数,看着很正常,几乎网上所有代码都是这个形式来写的(不知道他们是怎么通过的- -!)
运行时就出问题了,当有异常发生时 要么就是在RtlDispatchException里面不出来也没反应,要么就是一直循环的调用他,这个函数是R3异常处理的入口点,只要这里面发生异常还是调用他 - -!
在正常情况下,进入函数第一条指令时:
ESP=返回地址,ESP+X才是参数
..........................................................................
跟到刚刚才发现,跑到函数入口点时[ESP]=第一个参数,[ESP+4]=第二个参数,根本没有返回地址
而自己写的这个函数,永远是[ESP+4]=第一个参数,[ESP+8]=第二个参数.. - -! 这样不错才惨了...
----------------------------------------------------------------------------------------------------
----------------------------------------------------------------------------------------------------
这是KiUserExceptionDispatcher,异常无数,但从没见过执行到77C7014A, ZwContinue直接进入内核了,而进ZwRaiseException后,估计程序就崩了,RtlRaiseException这里也是没见执行过的,- - 都摆设..
-----------------------------------------------------------------------------------------------------
问题点找着了,翻遍了GG BING也没见有说无返回地址参数问题,最后为了省事把他当作跳板转到其它函数中处理(没有汇编基础的感觉这方法是最简单*_*-)
VOID NTAPI KiUserExceptionDispatcher_BT(PEXCEPTION_RECORD pExcptRec,PCONTEXT pContext) { DWORD retValue; if (RtlDispatchException(pExcptRec,pContext)) { ::AfxMessageBox("ZwContinue"); retValue=::ZwContinue( pContext,0); }else{ ::AfxMessageBox("ZwRaiseException"); retValue=::ZwRaiseException(pExcptRec,pContext,0); } } VOID NTAPI KiUserExceptionDispatcher(PEXCEPTION_RECORD pExcptRec,PCONTEXT pContext) { __asm { /* -_-! 这里入栈看着有些不顺似的-如果真不会执行到RETN貌似不用压栈也得 */ push [esp+4] push [esp+4] call KiUserExceptionDispatcher_BT /* 看着不顺眼,问题解决就成 - -! */ /*补充:需Release下,Debug栈是乱的*/ } }
哎,真走了不少弯路,当时以为是参数顺序错了..结果_估计_是该函数是由内核空间转入用户空间入口,则无返回地址入栈,网上文章也没细看,问题解决百岁!
---------------------------------------------------------------------------------------------------------------------
注:
RtlDispatchException在Ntdll中未导出,需按各个版本处理该函数地址
处理如下:
typedef NTSTATUS(NTAPI *pRtlDispatchException)(PEXCEPTION_RECORD pExcptRec,CONTEXT * pContext); pRtlDispatchException RtlDispatchException=NULL; /*这是WIN7 64位旗舰版下的地址,也就是在反汇编中看到的第一个Call地址*/ RtlDispatchException=(pRtlDispatchException)0x77CB865B;
经过上面的函数处理,能够捕捉到的异常貌似都能够通过了,然后就能在程序中制造出种种异常,一一奸杀,=_=