MFC 逆向实例

2018 年 12 月 28 日 计算机与网络安全

一次性进群,长期免费索取教程,没有付费教程。

教程列表见微信公众号底部菜单

进微信群回复公众号:微信群;QQ群:460500587



微信公众号:计算机与网络安全

ID:Computer-network

为了进一步地理解逆向的意义,安排了一个例子。这个例子要分析的是一个由MFC编写的名为BypassUAC的演示程序,这个程序可以通杀目前所有Windows 7下默认设置的UAC提示,这个程序能以管理员权限运行CMD,但却不会触发任何UAC的提示,如图1所示。

图1  BypassUAC的执行结果

一、MFC逆向初探


我们到目前并没有接触过MFC的程序。那么逆向MFC的程序困难吗?是不是意味着要跟踪分析一大堆的框架代码?


这要看我们逆向的目的。如果我们逆向的内容是与MFC框架本身有关的,那么就必须要接触MFC框架,否则我们只需要关心其对应的消息响应函数即可。拿本例中的BypassUAC来说,其功能是因我们单击的那个名为BypassUAC的按钮而触发的,因此我们感兴趣的仅仅是当那个名为BypassUAC的按钮被单击后都做了些什么。


但是我们要怎样才能绕过庞杂的MFC框架代码,从而直达我们感兴趣的地方呢?


当我们遇到必须分析MFC的这种情况时,需要先对MFC框架有一个基础的了解,由于MFC是开源的,因此这为我们理解其内容打开了方便之门。然后我们就要试图在其中提炼出关键点,进而提炼出我们所需要的特征。其实整个过程与原理大致与找main()函数的内容一样。


在这里已经为您找到了特征,如下表所示。

以上特征是做什么用的?又是怎样被总结出来的?


先回答后一个问题。关于总结的问题,如果展开讲其实就是运用MFC的相关知识并结合频繁的猜测与测试。


关于是做什么用的,其实很简单,如果我们在对应的MFC版本中找到了以上特征,那么就代表我们已经找到了进入关键函数的“快车道”了。整个过程分为以下几步。


(1)判断目标程序是不是MFC程序,如果是,判断其MFC版本。


以BypassUAC为例,我们先用OllyDbg打开BypassUAC.exe,然后按快捷键Ctrl+E打开模块窗口,并在模块窗口中寻找是否存在类似于mfc*.dll这样的模块,如果找到了即可根据DLL的名称判定程序所用的MFC版本;如果找不到则证明这是一个在静态库中使用MFC的程序,或者这根本就不是MFC的程序。


(2)根据目标程序调用MFC方式的不同而采取不同的方式搜索特征。


如果目标程序是在动态库中使用的MFC,则双击对应的动态库,转到动态库的代码段起始位置,然后按Ctrl+F搜索指定特征。


如果目标程序是在静态库中调用MFC,则在目标程序的代码段起始位置搜索特征。


以BypassUAC.exe为例,它是在静态库中使用MFC,因此我们转到代码段起始位置,并按快捷键Ctrl+F搜索特征call[ebp+0x14],得到的结果如下所示:

由于我们搜索的特征位于消息分发函数里,因此特征指令所在的位置应该是一个非常大的switch-case。通过学习的逆向知识可以推断,指令JMP DWORD PTR DS:[EAX*4+0F8C62]便是一个典型的处理复杂switch-case的特征。


因此我们需要记住,只有找到的特征有类似于JMP DWORD PTR DS:[EAX*4+????]的指令,才证明我们找对了地方,否则要按快捷键Ctrl+L查找下一个。


(3)在合适的位置下断点,并跟进到相应消息的函数中。


搜索到指定特征后,在相关地方下断点,然后跟进即可到达相应消息的函数中。这就是我们最终的目标了。


以BypassUAC.exe为例,由于其要设断点的消息是单击按钮,因此按照经验应该是在0x39的分支里,可以发现我们找到的特征恰好就在这个分支内,因此直接在0x000F8B9C下断点即可。


那么如果要中断其他的消息呢?那就只有在JMP DWORD PTR DS:[EAX*4+0F8C62]这里下条件断点了,有关于目标程序窗口的一些消息响应都要经过这里,因此只需要通过条件断点逐个过滤排查,最终就会找到响应指定消息的分支。

二、分析BypassUAC.exe


我们在0x000F8B9C处下断点后,单击程序的BypassUAC按钮,即可触发断点,跟进后即可找到我们想要的相应按钮按下消息的函数:

通过分析以上反汇编代码可知,这里仅仅是调用了RemoteLoadDLL.dll中的导出函数RemoteLoadDLLByResource而已,而通过函数名我们可以猜测一下,这个函数的作用应该是在本程序的资源中读出一个DLL文件,并使其在远程加载。


而通过explorer.exe与SHELL_CODE的名称我们可以推断,这两个参数应该是远程加载DLL的宿主进程名以及DLL在本文件中的资源名。


我们先用LoadPE打开BypassUAC.exe,单击“目录”按钮后在弹出的新窗口中单击“资源”条目后的"……"按钮,弹出如图2所示的对话框。

通过资源目录我们发现,SHELL_CODE确实是BypassUAC.exe的资源。此时我们选中SHELL_CODE下的子节点后单击“另存数据”按钮,将此资源保存为Stub.dll。


通过对Stub.dll的简单检查发现,它确实是一个有效的DLL文件,这个文件究竟做了些什么呢?这就要我们通过逆向工作来挖掘它了。我们用IDA打开Stub.dll后直接停到了dllmain函数里,其反汇编代码如代码清单1所示。

代码清单1  Stub.dll中dllmain函数的反汇编代码

以上这段代码的意思简单明了,首先将本DLL资源中的数据保存在临时目录FileName里,接着获取cmd.exe的全路径,然后将FileName作为参数传进函数sub_10001200中(除此之外我们还应该怀疑cmd.exe的全路径也通过ecx寄存器传递了进去),最后程序在执行完sub_10001200后便删除了临时目录中的文件。


有的朋友到此或许有很多疑问,下面让我一一为大家解答。


(1)为什么不将代码完全还原出来?


这个要依逆向目的、代码复杂程度等因素而定。上面的操作都是一些很常规的API调用及操作,代码实现的目的也很简单,因此我们就没有必要再每个参数、每个变量地去分析它了,有这个时间、这个精力的话,我们完全可以自己实现一个完全同样功能的代码。


(2)为什么还原了一部分代码,而后面的仅作逻辑推理?


这是逆向的一个基本步骤,对于代码清单1所示的这段反汇编代码来说,在绝大多数情况下根本无需将其还原成源代码。


之所以这样做,目的是演示一下通常状况下的逆向步骤。因为在新接触一个程序时,我们暂时还无法确定其准确的意图究竟是什么,因此就需要先仔细地做一部分分析。在实际操作中,需要仔细分析的部分可能仅包括几十行反汇编代码,也可能包括十几个函数,视具体情况而定。


(3)如果我们不需要准确地还原源代码,那么逆向对于我们来说又有什么用呢?


在实际的逆向工作中,不需要我们准确还原源代码的情况虽然占大多数,但是整个工作最核心的部分是以我们准确还原源代码为基础的。


拿最常见的软件破解来说,可能在整个破解过程中你看到的95%的反汇编代码都不需要还原出源代码,但是它们却是为你找到那5%反汇编代码做准备的,而往往最关键的部分(例如注册码算法等)恰恰是你需要准确还原源代码的部分。


通过以上分析我们知道,dllmain()函数中的操作似乎都是为函数sub_10001200而准备的,因此我们有必要跟进这个函数一探究竟。在分析sub_10001200这个函数时,可以使用IDA插件Hex-Rays Decompiler提供的功能来辅助我们更加快速地理解反汇编代码的意思。


插件Hex-Rays Decompiler的使用非常简单,只需要我们转到需要分析的函数中,按F5键后Hex-Rays Decompiler便直接帮我们自动根据反汇编代码生成C代码。虽然这种转换并不总是可信的,且分析结果晦涩难懂,但是与大量的反汇编代码相比已经好很多了,如代码清单2所示。

代码清单2  Hex-Rays Decompiler对函数sub_10001200的分析结果

通过以上例子为大家演示了一次逆向工作的实战全过程,目的是让您明白真正的逆向都是怎么做的。


其实在很多时候,我们应该尽可能地利用最简单的方法达到我们的目的。就拿本例来讲,并不是所有的代码都能通过静态分析得出结果的,因此在遇到不明不白的函数指针时,并没有试图通过逆向来理解它,而是通过上下文进行了大胆的猜测,并用调试的方式验证自己的猜测。


虽然在这个例子中制造了很多在实际逆向工作中肯能会出现的状况,但这个例子并不能真实地重现实际的逆向工作。因此在我们学习逆向前期,要有意识地少做些猜测,多去动手实践,这样才能得到真正的提高。

微信公众号:计算机与网络安全

ID:Computer-network

【推荐书籍】
登录查看更多
0

相关内容

Microsoft Foundation Class Library 微软基础类库
深度学习目标检测方法及其主流框架综述
专知会员服务
143+阅读 · 2020年6月26日
【实用书】Python爬虫Web抓取数据,第二版,306页pdf
专知会员服务
115+阅读 · 2020年5月10日
【CVPR2020】多模态社会媒体中危机事件分类
专知会员服务
53+阅读 · 2020年4月18日
【干货书】流畅Python,766页pdf,中英文版
专知会员服务
223+阅读 · 2020年3月22日
【综述】基于图的对抗式攻击和防御,附22页论文下载
专知会员服务
68+阅读 · 2020年3月5日
PC微信逆向:两种姿势教你解密数据库文件
黑客技术与网络安全
16+阅读 · 2019年8月30日
Kali Linux 渗透测试:密码攻击
计算机与网络安全
15+阅读 · 2019年5月13日
逆向 | C++ 加壳程序的编写思路
计算机与网络安全
9+阅读 · 2019年1月1日
Python | Jupyter导出PDF,自定义脚本告别G安装包
程序人生
7+阅读 · 2018年7月17日
快乐的迁移到 Python3
Python程序员
5+阅读 · 2018年3月25日
今日头条推荐算法原理全文详解
架构文摘
7+阅读 · 2018年1月30日
用 Scikit-Learn 和 Pandas 学习线性回归
Python开发者
9+阅读 · 2017年9月26日
码农日常工具推荐
架构文摘
4+阅读 · 2017年9月26日
从前馈到反馈:解析循环神经网络(RNN)及其tricks
夕小瑶的卖萌屋
3+阅读 · 2017年8月20日
iOS高级调试&逆向技术
CocoaChina
3+阅读 · 2017年7月30日
Learning to See Through Obstructions
Arxiv
7+阅读 · 2020年4月2日
Interpretable CNNs for Object Classification
Arxiv
20+阅读 · 2020年3月12日
Learning by Abstraction: The Neural State Machine
Arxiv
6+阅读 · 2019年7月11日
Arxiv
21+阅读 · 2018年2月14日
VIP会员
相关VIP内容
深度学习目标检测方法及其主流框架综述
专知会员服务
143+阅读 · 2020年6月26日
【实用书】Python爬虫Web抓取数据,第二版,306页pdf
专知会员服务
115+阅读 · 2020年5月10日
【CVPR2020】多模态社会媒体中危机事件分类
专知会员服务
53+阅读 · 2020年4月18日
【干货书】流畅Python,766页pdf,中英文版
专知会员服务
223+阅读 · 2020年3月22日
【综述】基于图的对抗式攻击和防御,附22页论文下载
专知会员服务
68+阅读 · 2020年3月5日
相关资讯
PC微信逆向:两种姿势教你解密数据库文件
黑客技术与网络安全
16+阅读 · 2019年8月30日
Kali Linux 渗透测试:密码攻击
计算机与网络安全
15+阅读 · 2019年5月13日
逆向 | C++ 加壳程序的编写思路
计算机与网络安全
9+阅读 · 2019年1月1日
Python | Jupyter导出PDF,自定义脚本告别G安装包
程序人生
7+阅读 · 2018年7月17日
快乐的迁移到 Python3
Python程序员
5+阅读 · 2018年3月25日
今日头条推荐算法原理全文详解
架构文摘
7+阅读 · 2018年1月30日
用 Scikit-Learn 和 Pandas 学习线性回归
Python开发者
9+阅读 · 2017年9月26日
码农日常工具推荐
架构文摘
4+阅读 · 2017年9月26日
从前馈到反馈:解析循环神经网络(RNN)及其tricks
夕小瑶的卖萌屋
3+阅读 · 2017年8月20日
iOS高级调试&逆向技术
CocoaChina
3+阅读 · 2017年7月30日
Top
微信扫码咨询专知VIP会员