本次分析的重点是,用实例来展示异常的机制的原理以及IDA的一些用法,借用此crack来演示。刚好,这个程序使用的技术和windows异常机制有关,也许程序的作者也是想表达出这样的意思。在这里对windows异常机制做一些补充,在我前面的文章中提到了CPU异常以及用户异常,这里补充一下VEH→SEH→UEH以及VCH,网络上有这类的资料有很多,在这就不在细讲,只做简单的总结。
VEH向量化异常处理器、SEH结构化异常处理器,UEH(UEF)顶层异常处理器。VEH:保存在全局的一个链表中,所有的线程共享一个VEH链表,VEH活动于用户层。SEH:保存在栈空间上是一个局部的链表,每个线程都有自己的SEH,线程之间的SEH互相不影响(既活动于内核层又活动于用户层)。UEH:保存在一个全局变量上,由于全局变量是所有线程能够共享的,所以所有的线程共享一个UEH,它是属于处理异常的最后一道关卡,如果没记错的话,它存在于两个地方,程序的开始位置和最后各存在一个,但是一般不做异常处理(也可以做异常处理),更多的被用于内存转储并上传服务器。最重要的是当程序处于被调试状态时,不会调用UEH。所以可以用于反调试。VCH:位置是跟随SEH的,就存储在SEH的旁边的一个链表中,可以设置多个,线程共享。可以看成是SEH的一部分,因为存在于SEH后面。也不会做异常处理,前面异常处理成功了,才会调用此VCH。KiUserExceptionDispatcher 函数1) 调用RtlDispatchException 查找并执行异常处理函数2) 如果RtlDispatchException返回真,调用ZwContinue再次进入0环重新把寄存器的值赋值给Trap_Frame,但线程再次返回3环时,会从修正后的位置开始行。3) 如果RtlDispatchException返回假,调用ZwRaiseException进行第二轮异常分发图为做小实验而找到的KiUserExceptionDispatcher:RtlDispatchException函数:1) 查找VEH链表(全局链表),如果有则调用2) 查找SEH链表(局部链表,在堆栈中),如果有则调用3) 最后一道防线UEH(UEF),住在SEH隔壁简单理清一下UEH流程(程序用到UEH机制):只有程序被调试时,才会存在未处理异常UnhandledExceptionFilter的执行流程:1) 通过NtQueryInformationProcess查询当前进程是否正在被调试,如果是,返回EXCEPTION_CONTINUE_SEARCH,此时会进入第二轮分发2) 如果没有被调试: 查询是否通过SetUnhandledExceptionFilter注册处理函数如果有就调用 如果没有通过SetUnhandledExceptionFilter注册处理函数弹出窗口让用户选择终止程序还是启动即时调试器 如果用户没有启用即时调试器,那么该函数返回EXCEPTION_EXECUTE_HANDLE用一张图表示执行顺序:
程序使用的是UEH的机制,安装一个顶层异常处理函数(SetUnhandledExceptionFilter),来处理异常,使用基于UEH机制的反调试技术。发现无壳,并且是用汇编编辑器编写的。使用IDA pro打开发现基本都是使用的库函数。除了DialogFunc回调函数的功能还不知道,那么接下来分析主要功能,就在这个回调函数里面。点击DialogFunc就得到这么一个流程图y设置变量类型,修改之前修改之后一目了然,并且在0040102B的地址处,可以发现正是消息回调函数,然后和10h进行比较,那么就可以确定10h其实是个枚举值,可以看到还有两个也是这枚举值,一并修改了,当然了如果想改回去也可以使用u 取消目标(局部变量\全局变量\函数)的定义。m选择枚举值可以确定这是一个窗口消息,那么就可以搜索WM_就能搜索出来了。如果不确定是否是不是一个窗口消息,那么可以通过此链接搜索对应的16进制,一般常用的消息都能搜到。https://www.cnblogs.com/lihuali/p/7566989.html可以看到返回的消息不是关闭程序的宏之后,就会执行右侧的指令,那么在40103E处和WM_COMMAND值相等时,就会执行左侧的代码,发现又在处和0BBBh比较,目前还不知道,wParam参数表示什么,我们使用OD查看一下
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!