个人觉得学习分两种,
- 一种是当面请教和直接从书本网络中的资料学习.
- 其二就是看着令你惊叹的作品-顿悟.
- 什么?顿悟不了?那我们就一起来逆向学习吧!差点忘了,我并不打算提供Demo,这并不重要,难道你打算遇到一个同样的情景?
重在方法.
注意:
本文为了照应新手人群,对于某些内容可能会非常具体的推演.
名词解释:
- 一个实例:一个对象,这里指一个程序被创建后在内存中的数量.大白话就是:成功执行了几次.
事由:
今天闲来无事(忙里偷闲)执行了两次Dr_COM的宽带认证client.如咱所料,
如图:
我们知道,限制程序仅仅执行一个实例的方法非常多,例如以下主流的几种:
- 查找窗体.
- 使用相互排斥对象之类的.病毒经常也这么干.
- 使用共享区块.
- 使用暂时文件.
那我们的COM先生是否怎样实现的呢?
开弓or工
好的操起家伙(OllyDBG,IDA)開始一次内科手术.
假设你不是非常熟悉这两个工具能够在须要的时候參考这里:
首先,用OD加载我们Dr.COM
这里的入口点似乎是早期的VS版本号编译的Release版本号C/C++程序.用工具ExeInfoPE验证一下我们的经验并简单看下是否是伪装壳:
ExeInfoPe的使用方法及介绍能够看这里:
我们须要找到哪句提示语“程序xxx已经在执行”,在系统中的位置.在界面中央(反汇编窗体)右键,选择“中文字符串搜索->智能搜索”(这是一个插件,你能够从主流的OD版本号中同样位置找到相似的字符串查找功能).弹窗如图:
非常幸运,我们找到了它.我们并非每次都这么幸运,由于一些程序猿会将它们加密存储.对于处理种种加密情况我们有机会再谈.
双击这个字符串就可以来到这个字符串的地址.
我们看到一个红色箭头指向这里.而本字符串地址的上面是一个jmp,它指向了以下的某处,这表明指令执行的时候仅仅能从远处跳到本字符串地址而不可能是一行一行走下来的.
请牢记我们的目的,我们的目的是找到程序怎样进行”是否执行了多个实例”的推断.这个推断导致指令走向两条或者很多其它的路.当中一条就是这条提示信息.顺藤摸瓜就可以.
我们逆着跳到本字符串地址的箭头找到根源.
如上图,我们找到了jmp的根源它就在我们圈住的地方.这是一个动态的jmp.它依据eax的值进行运算,eax*4+0x401D98,运算结果是一个地址跳转表,指向结果.eax就是关键.是谁改动了eax呢?
这里有条mov 指令,原来eax的值来自于[esp+0x174],而esp是栈顶寄存器,仅仅有在执行到该条指令的时候才会有真正參与运算的值.好的.F2在该条指令下断点.然后执行起我们的程序,聪明的OD已经帮助我们计算出了地址,原来eax的值来自于ss:[0018FC64].ss是段选择寄存器,就是我们右下角的窗体显示的内容咯.
我们要监视这个地址是谁将’1’这个值写入当中的.这里提供三种方法:
- 紧盯住该地址的内容,我们通过栈回溯跟踪到改动者.
- 通过硬件断点,在左下角窗体-“数据窗体”找到该地址,右键”断点”->”写入断点”.长度依据具体情况,这里WORD就可以.
- 使用RUN跟踪.菜单条”调试”->”设置条件”,将中断条件设置为该地址为’1’则中断.至于关于强大的RUN跟踪的使用方法,假设你感兴趣,你须要找OD的资料学习.
下图描写叙述了观察栈回溯的两种方法:
皇天不负有心人,我终于找到了将’1’写入的操作,它的地址是:403992.如图:
检測到多个实例的情况已经找到.那么单个演示样例执行的情况怎样呢?我们关闭上面打开的两个Dr.COM程序.如今我们要实验一下仅仅执行一个该程序的时候eax是多少?
将程序拖入OD中一个client,找到我们上次的eax*4+0x401D98的地方.发现正常情况下eax的值为A.继续用上面的方法寻找是谁改动了这个eax,找到了一个新的地址403466.这真是非常醉,这个程序看来是在推断之后进行了不少其它任务才进行push操作的.VS2005…
既然我们有了两次操作的地址,仅仅要找到它们的共同调用者就可以.一般通过重复对照OD中的栈回溯能够帮助我们找到它们的祖先函数.可是这次我不打算用这样的毫无趣味的方法.
IDA上场!!!!
IDA作为一款擅长图形化程序流程的超棒静态分析工具非常适合此次任务.将程序拖入IDA.
小经验:注意:不要把快捷方式拖进去.OD是会将快捷方式指向的程序进行分析,**而**IDA连快捷方式本身都不放过!
如图:
假设你发现你的界面是汇编界面而不是像上图的流程图,这往往意味你刚刚不小心关闭了流程图.放心,你能够通过View->Opensubviews->Proximity browsers 又一次打开它.
在图形界面按”G”,写上push 0xA的地址”403466”如图:
OK,跳过去:
同样的办法按”G”,写上push 0x1的地址.找到push 0x1在流程图的显示.
在IDA中使用你的Ctrl+鼠标滚轮,能够放大or缩小流程图.让你感觉到更直观.
我的天两幅图居然没有在一幅”大图”里面!!!这意味这两个函数在调用上相隔非常远.
我们通过”大图”的顶端.点击函数名称,按住”X”键能够看到交叉引用的界面.这项功能非常有用,它能够将全部对目标函数或变量的调用列出来.我们看到对于push 0xA这一路的顶端函数仅仅有一个父函数调用过它.双击这个父函数.
这以下的图中,我们看到它们的关系:
让我们放大分道扬镳之地.如图:
从后往前看,假设cmp结果是0,就会跳到右边(loc_403A99),没有发现已经执行了本程序.cmp比較的是eax是否等于0FFFFFFFF(八个F).假设等于就是正常.OK,显然是call sub_40A4E0做了某种推断导致eax的值.
如今记住eax假设等于0FFFFFFFF就是没有检測到其它演示样例.
在OD中进入这个函数:
发现新大陆
我和我的小伙伴们都惊呆了.这全然超出了我的预期.本来以为这个程序会用传统的实例检測方法,可是我们看到了CreateFileMappimg之类的函数.初步推断此程序利用多次映射文件产生的冲突来做的文章.继续看:
我们发现一个新的分道扬镳的跳转,它位于40A529.
它用以下这句做了比較:
cmp ebp,0xB7
向上追溯:
mov ebp,eax
ebp来自eax.依照约定,函数的调用能够改动eax的值来达到传递结果的目的.而这里的eax正是GetLastError函数的执行结果.
地址40A529的代码的意思是假设执行GetLastError返回的不是0xB7,则跳走.跳走的结果是:
0040A54A mov eax,edi
而此时的edi为FFFFFFFF,回忆上面,这个值意味着我们没有检測到还有一个演示样例在执行.
有同学可能会问,’0xB7是嘛意思呀?
随机的一个值?’.当然不是,0xB7是错误码,它拥有明白的含义,你能够通过VisualStudio中菜单条中的工具->”错误查找”小工具,找到它的含义:
果然如此.
收工总结
到此我们已经达到了我们预期的目的-探明Dr. Com检測到自己是否仅仅执行了一个实例的方法.通过逆向分析了解到它是通过:
设置CreateFileMapping函数的最后一个參数MapName,该參数是一个共享值.假设该值被重复命名,会报错,该错误能够通过GetLastError函数得到,返回值为ERROR_ALREADY_EXISTS(0xB7).
知识拓展
很多其它关于该函数的情况能够阅读这里:
学到了什么?
估计一名纯新手读者通过阅读本文会学到:
- OD对程序的基本分析方法.
- 栈回溯概念
- 利用IDA流程图分析程序.
- 一种独特的进程相互排斥方法.(目的)
- ……
我从中学到了什么:
- 复习了以上全部知识
- 沿途看了数个感兴趣的WindowsAPI的实现.
- 直接下断经常使用相互排斥函数找捷径差点被坑.
- 了解了一些字符串函数和文件夹路径设置函数的使用方法.
- ……
尾声
在我幼稚园时,老师问我,”你从哪里懂得这么多”.”我的老师是书本.”我回答道.
有人说书本是不会说话的老师.假设你学到很多其它知识,请珍惜和程序在一起的时光吧.
有问题请留言评论以便讨论.
假设本文为你来到了新奇空气,请点(~ o ~)~