静态逆向工程Shellcode技术(上) - 嘶吼 RoarTalk – 网络安全行业综合服务平台,4hou.com

静态逆向工程Shellcode技术(上)

lucywang 恶意软件 2020-09-28 10:45:00
720876
收藏

导语:本文介绍的是分析恶意软件的逆向技术,而不是介绍恶意软件的“工作原理”类型的帖子,因此在本文中,我决定专注于研究与恶意软件紧密相关的概念,例如shellcode、加密算法等。

本文介绍的是分析恶意软件的逆向技术,而不是介绍恶意软件的“工作原理”类型的帖子,因此在本文中,我决定专注于研究与恶意软件紧密相关的概念,例如shellcode、加密算法等。而不是恶意软件本身,例如Dridex。本文我使用的是Metasploit,使用它来生成了一些shellcode。

Metasploit是一款开源的安全漏洞检测工具,可以帮助安全和IT专业人士识别安全性问题,验证漏洞的缓解措施,并管理专家驱动的安全性进行评估,提供真正的安全风险情报。这些功能包括智能开发,代码审计,Web应用程序扫描,社会工程。团队合作,在Metasploit和综合报告提出了他们的发现。

本文研究的恶意样本的MD5哈希:9d7e34250477acf632c6c32fc2c50d3b。

Shllcode分析第1阶段:静态分析

首先,你要在你选择的反汇编程序中打开shellcode ,我个人更喜欢IDA Pro,但是我不会使用伪代码功能,而是将重点放在反汇编视图上,因此这应该适用于你选择的任何工具。通过IDA Pro,你可以选择如何加载二进制数据(16位、32位或64位),因此,我将首先选择32位,如果反汇编有任何错误,我们可以对其进行简单地更改。加载二进制文件后,选择第一个字节并按“ C”,这将尝试将第一个字节转换为代码。因此,重新分析该文件,然后尝试将其余字节反汇编为部件。如下所示,入口点从位置0x00开始,shellcode一直向上到达位置0x2A,此时IDA无法将剩余的字节转换为程序集。

01.png

仅基于这个事实,我们就可以假定这部分数据是以某种方式加密的,并且上面的shellcode解密并执行它。因此,让我们来看看第一个要运行的函数sub_0()。此函数仅负责跳转到偏移量0x25,它将执行sub_2(),我将其命名为main_func(),因为它包含了大部分代码,因此,让我们继续研究该函数。

02.png

因此,这个函数内部的解密相当简单,只是一个基本的XOR循环,它将[edi]指向的XOR数据与[esi]指向的数据结合起来。在每一次XOR操作之后,edi(存储器地址)都会增加,并且程序会将[esi:esi + 1]与0x550D进行比较。在本例中,IDA以Little-Endian显示该值,,因此它被显示为0x0D55。如果值匹配,它将跳到ecx指向的地址,否则它将增加esi,将它现在指向的数据与0x73进行比较,如果匹配,它将恢复原始地址(存储在ebx中)。如果不匹配,它将循环回到XOR代码并继续。

03.png

基于以上分析,我们知道esi用作密钥,而edi被用作加密的shellcode。我们还知道密钥长度可以是任何长度,并且ebx将包含指向密钥首字节的地址。

利用所有这些信息,让我们首先尝试找出加密数据的开始和停止位置。从XOR循环(loc_F)开始并向上移动。我们可以首先看到存储在edi中的地址被移动到ecx中,这是有意义的,因为一旦解密完成,程序就会跳转到ecx中的地址。

现在,我们找到edi从ebx处获取加密代码地址,在函数的最顶部,弹出堆栈顶部的值,并将其存储在ebx中,然后将该值移到edi中,然后将0x73移动到eax的较低位,调用cld,然后输入a scasb循环。问题是,当它弹出ebx时,堆栈的顶部是什么?

好了,简单地看一下调试器中的堆栈,可以发现,当调用一个函数时,堆栈顶部的值是要返回的地址,这是调用指令之后的指令地址。在下图中,返回地址为0x013B1CAB,调用该函数的地址为0x013B1CA6(此处的调用指令占用5个字节)。那么,这如何适用于我们的shellcode?

04.png

上面我们说过,main_func是从位置0x25调用的。无法识别的数据从0x2A开始。位置0x25之后的5个字节可为调用指令腾出空间。因此,main_func()中位于堆栈顶部的数据为值0x2A。现在,我们终于知道了加密数据的起始位置!

05.png

不过不要高兴得太早,还记得0x73移入al后如何调用cld吗? cld指令负责删除(设置为0)EFLAGS寄存器中的DF(direction)标志。当此标志为0时,任何字符串操作都会根据操作中使用的寄存器来递增索引寄存器,尤其是esi或edi。调用cld后,将进入一个循环,该循环不断执行scasb,直到ZF(0)标志被设置(设置为1)。 scasb会做什么?它所做的只是将al中的字节与[edi]进行比较,并根据结果设置状态标志。如果不匹配,则ZF将保持删除状态,否则将被设置,并且程序会跳出循环。此外,由于scasb是字符串操作,因此它将在每个循环后增加edi中的地址,这意味着直到[edi]等于0x73为止,程序将永远不会执行解密功能。现在我们知道,加密的数据从0x73开始,密钥是从地址0x2A一直到[address] = 0x73的数据。如上图所示,0x73是ebx指向的数据中的第二个字节。因此,XOR密钥为0x06,加密的数据从0x2B开始!向下滚动到函数的最后,我们可以找到字节0x550D,这意味着加密的数据长401个字节!

了解了所有内容之后,让我们进入解密阶段!

Shllcode分析第2阶段:解密

06.png

因此,我们现在有了XOR密钥:0x06,以及加密数据开始的位置:0x2B。有了这些知识,我们就可以轻松地用Python编写一个基本的XOR解密函数,该函数带有2个参数:密钥和加密的数据。向函数添加一个简单的检查,以查看数据是否与0x550D匹配并且脚本是否已完成!

07..png

但是,为了实际使用它,我们需要手动或使用YARA或Regex从IDA提取数据来定位它。然后我们必须在新的IDA会话中将其打开,并且在某些情况下第二个“阶段”从第一阶段开始调用函数,可能是对另一部分数据进行XOR。幸运的是,我们可以将此基本脚本转换为IDAPython格式,并用解密的Shellcode覆盖加密的Shellcode!

不用担心,迁移到IDAPython的过程非常简单。首先,我们需要导入所需的库idaapi,然后将for循环更改为while循环,然后才能对传入的数据调用len(),但是在这种情况下,我们不知道数据的长度如何,因为我们现在正在传递加密数据的地址。

除此之外,只要在address + i中仍有数据,就可以使while循环连续循环。这可以通过使用Byte()函数来实现,该函数从给定地址获取一个字节的数据。在本文的示例中,该地址就是我们的加密blob。现在,我们就可以将该数据字节分配给一个变量字节,然后将其与0x55进行比较。我们还将address+(i+1)与0x0D进行比较,以确保这两个标记都存在。

如果这些标记不存在,则使用给定的输入执行XOR字节操作,然后调用PatchByte(),它将用我们的变量byte在address+i处覆盖字节。最后,将i增加1,循环继续!

08.png

将它导入IDA,并在命令行中输入ida_xor_crypt(0x06, 0x2B),将执行我们的函数,覆盖数据,如下图所示!它不再以0x73开头,因为现在是0x75。

09.png

将它导入IDA,并在命令行中输入ida_xor_crypt(0x06, 0x2B),将执行我们的函数,覆盖数据,如下图所示我们可以在选择0x75的情况下再次按“ C”,然后将其完全分解。

10.png

本文翻译自:https://0ffset.net/reverse-engineering/malware-analysis/common-shellcode-techniques/如若转载,请注明原文地址
  • 分享至
取消

感谢您的支持,我会继续努力的!

扫码支持

打开微信扫一扫后点击右上角即可分享哟

发表评论

 
本站4hou.com,所使用的字体和图片文字等素材部分来源于原作者或互联网共享平台。如使用任何字体和图片文字有侵犯其版权所有方的,嘶吼将配合联系原作者核实,并做出删除处理。
©2022 北京嘶吼文化传媒有限公司 京ICP备16063439号-1 本站由 提供云计算服务