样例0892792dc7783184451c6621b6e4a87c是一个MFC框架编写的恶意文件,上一篇文章《如何缩短人工分析样本的时间》提及了该文件在沙箱分析后是跑不出有效网络请求的,于是现在我们回归到手工分析的流程寻找一下原因,由于对MFC框架的文件静态分析会有些繁琐,需要一些技巧找到核心的代码位置,这篇文章需要对IDA的使用与C++相关知识和结构体有一定了解才可以比较好的理解与上手实践。
在沙箱记录的API信息中,我们可以很容易发现奇怪的痕迹(目的是省时间),例如一段由OutputDebugStringA函数调试打印输出的字符串。
根据这段字符串的线索,我们可以在IDA中通过字符串索引交叉引用功能找到对应的代码区域。
使用交叉引用后来到如下位置:
利用F5插件反编译功能后得到如下伪代码内容:
当我们继续对sub_401330函数进行交叉引用查询后发现位于如下位置,简单静态分析后发现这是在前期检查系统里是否存在对应的进程名的流程,符合上图中沙箱记录的API信息Process32Next被不断调用的内容。
不断地继续往前回溯发现已经结束了,到此可以确定这些代码属于该恶意文件的核心代码内容,被执行的原因是在其余位置被调用,但我们不用细究这里的细节,因为这不是我们需要关注的核心问题。
上面我们大致已经确认了核心代码区域,现在让我们回到最初的位置sub_401330,该函数调用完_CxxThrowException后就结束了,在IDA中切换到非图块模式也没有发现后续的代码执行流程。问题来了,此时静态分析看起来已经让人感觉模糊了,那么它是如何执行后续核心代码的呢?我们现在不关心该恶意文件的免杀能力、如何去检测它,如何去对抗它的恶意技术以及涉及的相关攻击事件,或者是比较恶意技术能力等这些与我们核心问题不相干的问题。
带着具体的问题,我们可以从上述沙箱截图里记录的API调用信息获取到的信息是后续还会存在其他的API调用,并不是在IDA截图中调用完_CxxThrowException直接就结束了,那么根据这种动静态分析结果存在不同的场景,短暂思考后我们可以断定这是一种阻碍静态分析的手段。既然这是一种很明显的阻碍静态分析的手段,我们首先要想到的是这个手法是不是已经公开了?或者说有没有比较好的解决这个问题的好方法?我们不要重复造轮子浪费时间解决重复的问题。
通过搜索“_CxxThrowException”我们可以找到与C++异常处理相关的内容,此时我们与接近最核心的问题更近了一步。为了后续能理解为什么恶意文件会采用C++异常处理,我们需要对C++异常处理的基本原理有一些了解。
C++异常处理的基本原理
C++标准规定了异常处理的语法,各编译器厂商需要遵循这些语法。然而,由于标准没有规定具体的实现过程,不同厂商的编译器产生的异常处理代码会有所不同。
异常处理的作用
异常处理是一种类型安全的处理方式,用于确保在函数结束的栈解退(stack unwinding)过程中,所有对象的析构函数都能被正确调用。栈解退的过程如下:
1. 当函数因异常而不是正常返回而终止时,程序会释放该函数的栈内存。
2. 程序不会立即结束,而是继续释放多级函数栈,直到找到一个在try块中的返回地址。
3. 然后控制权会转移到相应的异常处理程序。
4. 在这个过程中,所有相关对象的析构函数都会被调用。
关键字
try块用于监视异常,一个try块后可以跟随多个catch块,每个catch块用于捕获一种异常。
catch声明语句中的省略号(…)可以捕获所有未被捕获的异常,包括C类型异常和系统异常。
throw表达式用于抛出各种类型的异常。
在捕获异常时,通常会指定标准库中定义的 std::exception 类及其派生类作为异常类型,当然,C++也允许用户自定义异常类。
MSVC的异常处理机制
在MSVC(微软的编译器)中,异常处理机制建立在SEH(结构化异常处理)机制之上。处理C++异常时,编译器会在具有异常处理的函数入口处注册一个异常回调函数,该函数会将一种异常信息结构体(FuncInfo)压栈并调用库函数__CxxFrameHandler来处理异常。
抛出异常:使用库函数__CxxThrowException来完成,它接受两个参数:产生异常的对象指针和异常信息结构体(ThrowInfo)指针。
异常处理:异常回调函数在获得执行权后,会根据这两个参数和FuncInfo表结构地址,进行try块匹配操作。如果匹配失败,则析构异常对象并继续搜索;如果找到对应的try块,则通过ThrowInfo表结构的类型遍历找到匹配的catch块,之后进行栈解退和析构对象操作,最终执行catch块。
这种机制确保了在异常处理中,对象的析构函数能够被正确调用,确保资源的正确释放。
在了解了上述关于C++异常处理的基本原理后,我们现在需要找到是不是有类似的恶意文件也采用了这种手法,是不是有相关的分析文章可供我们参考?这是一种比较好的解决具体问题的思路与分析过程。人生短暂,总的核心是节省我们解决问题的时间,留有更多的时间享受生活。
经过搜索,我们在互联网上找到了一篇分析文章,里面提及了关于使用C++的异常处理来阻碍分析的手法,这正好可以作为我们解决具体问题的参考。
Earth Preta Spear-Phishing Governments Worldwide
https://www.trendmicro.com/en_us/research/22/k/earth-preta-spear-phishing-governments-worldwide.html
反分析:C++中的自定义异常处理程序
有趣的是,对手通过实现自定义异常处理程序来隐藏实际的代码流。根据进程名称检查的结果,不同的异常处理程序将被调用,通过调用_CxxThrowException触发异常来继续执行恶意程序。在触发异常后,C++运行时将从ThrowInfo结构开始,一直到_msRttiDscr结构中的CatchProc成员,找到相应的异常处理程序,该成员包含真正的恶意代码。在这个示例中,异常处理程序位于偏移量0x10005300处。这种技术不仅隐藏了执行流程,还能停止分析人员调试器的执行。
具体过程简单总结如下:
调用_CxxThrowException:
恶意软件通过调用_CxxThrowException函数来触发异常。这个函数是C++运行时库的一部分,用于抛出C++异常。
ThrowInfo结构:
ThrowInfo结构包含了异常的信息,包括如何处理异常。当异常被抛出时,C++运行时会根据这个结构来查找相应的异常处理程序。
_msRttiDscr结构中的CatchProc成员:
在这个结构中,有一个名为CatchProc的成员,包含实际的异常处理代码。在这种情况下,恶意代码被隐藏在这个成员中。
文章提到了如何找到由C++异常处理而“隐藏”的具体核心代码的方法,并给出了可供寻找的数据结构路线图,这可以作为我们解决这个问题的参考手册。
在本次样例的_CxxThrowException最后,这段代码会抛出一个异常。由于在sub_401330函数入口处注册了SEH(结构化异常处理),处理C++异常时,编译器会在具有异常处理的函数入口处注册一个异常回调函数,该函数会将一种异常信息结构体(FuncInfo)压栈并调用库函数__CxxFrameHandler来处理异常。要找到上述伪代码中真正的异常处理程序,我们需要了解C++异常处理机制中的几个关键结构和步骤。
上图的红框是SEH位置,接着来到SEH位置如下:
找到了FuncInfo异常信息结构体,如下:
经过上述的步骤找到了具体的异常信息结构体(FuncInfo)位置,该结构体具体分布如下,我们发现pTryBlockMap位于结构体第五个位置,于是根据IDA已经解析好的结构体分布,找到第五个位置为stru_4037C8(如上图)。
根据TryBlockMapEntry结构体分布与IDA解析后的位置对照,我们可以找到pHandlerArray位置,位于第五个位置,不过这里存在三个不同的位置,分别为stru_403808、stru_403818和stru_403828。
pHandlerArray位置找到后,继续寻找异常处理函数的具体位置,结合HandlerType结构体与IDA解析后的位置分布找到addressOfHandler的具体位置,分别为loc_401422、loc_401406和loc_4013EA。
我们可以找到其中一个异常处理程序所在的位置以及接下来会执行的核心代码逻辑,如下,按照下图红框中的执行流程,我们会发现在地址00401422处存在mov eax, offset loc_401428指令,接着执行了retn指令,初步看这里的话会觉得可疑,因为这两条指令执行后好像不会执行到最终的00401434处的核心代码?带着这个疑问,我们可以对其进行简单的动态调试,经过简单的动态调试会发现当执行retn指令后程序的执行流来到了msvcrt内存空间中,表明是MSVC运行时内部代码区域,在这里经过对eax的一些操作,最终将执行流指向了00401434处的核心代码,因此整个执行流程是合理的也符合沙箱记录的相关API调用序列信息。
该函数内部的截图确实是会在沙箱记录的API信息中出现过的API调用记录,如下。
至此,经过对相关问题解决思路的梳理与提炼,我们发现了在静态分析中会存在模糊的原因,原来恶意文件是利用了C++与MSVC编译环境下的异常处理技术导致恶意代码出现了“隐藏”行为,我们也成功地找到了被“隐藏”在静态分析过程中的恶意代码。
`黑客&网络安全如何学习
今天只要你给我的文章点赞,我私藏的网安学习资料一样免费共享给你们,来看看有哪些东西。
1.学习路线图
攻击和防守要学的东西也不少,具体要学的东西我都写在了上面的路线图,如果你能学完它们,你去就业和接私活完全没有问题。
2.视频教程
网上虽然也有很多的学习资源,但基本上都残缺不全的,这是我自己录的网安视频教程,上面路线图的每一个知识点,我都有配套的视频讲解。
内容涵盖了网络安全法学习、网络安全运营等保测评、渗透测试基础、漏洞详解、计算机基础知识等,都是网络安全入门必知必会的学习内容。
(都打包成一块的了,不能一一展开,总共300多集)
因篇幅有限,仅展示部分资料,需要点击下方链接即可前往获取
CSDN大礼包:《黑客&网络安全入门&进阶学习资源包》免费分享
3.技术文档和电子书
技术文档也是我自己整理的,包括我参加大型网安行动、CTF和挖SRC漏洞的经验和技术要点,电子书也有200多本,由于内容的敏感性,我就不一一展示了。
因篇幅有限,仅展示部分资料,需要点击下方链接即可前往获取
CSDN大礼包:《黑客&网络安全入门&进阶学习资源包》免费分享
4.工具包、面试题和源码
“工欲善其事必先利其器”我为大家总结出了最受欢迎的几十款款黑客工具。涉及范围主要集中在 信息收集、Android黑客工具、自动化工具、网络钓鱼等,感兴趣的同学不容错过。
还有我视频里讲的案例源码和对应的工具包,需要的话也可以拿走。
因篇幅有限,仅展示部分资料,需要点击下方链接即可前往获取
CSDN大礼包:《黑客&网络安全入门&进阶学习资源包》免费分享
最后就是我这几年整理的网安方面的面试题,如果你是要找网安方面的工作,它们绝对能帮你大忙。
这些题目都是大家在面试深信服、奇安信、腾讯或者其它大厂面试时经常遇到的,如果大家有好的题目或者好的见解欢迎分享。
参考解析:深信服官网、奇安信官网、Freebuf、csdn等
内容特点:条理清晰,含图像化表示更加易懂。
内容概要:包括 内网、操作系统、协议、渗透测试、安服、漏洞、注入、XSS、CSRF、SSRF、文件上传、文件下载、文件包含、XXE、逻辑漏洞、工具、SQLmap、NMAP、BP、MSF…
因篇幅有限,仅展示部分资料,需要点击下方链接即可前往获取