用于学习恶意软件分析的最佳编程语言

阅读量    25074 | 评论 1

分享到: QQ空间 新浪微博 微信 QQ facebook twitter

 

在过去,许多人会经常问我一个问题:“我想要入门恶意软件分析和逆向工程领域,应该学习什么编程语言?”为了回答这个问题,我将详细讲解我认为最适合的前三种语言,希望大家可以通过阅读本文找到自己认为最有用的语言。在本文中,我将重点讨论本地恶意软件(也就是不需要Java、Python或.NET等框架就能直接运行的恶意软件),因为这是最常用的类型,如果能够理解了这一类型,那么对其他类型的恶意软件也就变得轻车熟路。本文将不会涉及物联网或移动恶意软件的相关内容,因为我对这一领域并没有太多的经验。

 

第三名:Python

Python是一种具有多种用途的语言,当我需要快速完成某些工作时,我会选择使用Python语言。虽然其他几种语言的开发速度很快,但我发现Python具有可读性高、可快速开发、易于学习的优点。由于Python是一种解释型语言,所以解释器可以为我们完成不同操作系统之间的所有转换,因此我们仅需要编写一次代码就可以一劳永逸,而我们的代码可以在任何操作系统上运行。尽管我是一位Linux服务器的忠实粉丝,但我还是使用Windows作为日常主要使用的操作系统。因此,如果能在我的Windows上面编写并测试代码,然后在完成后将其上传到服务器上,这样就会特别方便,而不再需要尝试通过PuTTY终端开发和测试代码。

恶意软件分析

我最喜欢的一个Python的用途就是快速复制恶意软件的组件,以便更好地理解其工作方式,并获得恶意软件自身的接口,从而实现更快速的分析。我的TrickBot工具包就是一个很好的例子,它能有助于解决逆向模块化恶意软件时所遇到的一些问题。
我在研究TrickBot的过程中,遇到的一个主要问题就是它会使用被黑客入侵的服务器来控制恶意软件,当然,其中大部分服务器都会很快就关闭。在获得新样本后的几天之内,所有硬编码的控制服务器都会发生死机,并且样本开始失效。在对恶意软件所使用的加密和解密代码进行分析之后,我可以编写一个简单的Python脚本,该脚本可以允许我解密并修改任何TrickBot的配置文件,我通过这些文件来编辑主配置文件,并为其指定新的控制服务器,这些控制服务器是其他恶意软件分析者在网络上发布的。
我写的另一个脚本是用于命令与控制的基础结构接口,该脚本可以帮助我在不运行恶意二进制文件的前提下,就能获取到命令、有效载荷以及新的服务器地址。如果我们非常注重个人主机的风险防范,那么可能不希望在连接到互联网的系统上运行恶意软件。相反,通过Python来离线分析恶意软件并重新实现需要访问互联网的代码,这是非常有意义的。我们可以完全控制恶意软件的功能,使其不再发送真实数据,甚至是发送蜜罐凭据。

调试器扩展

通常,分析任务往往是枯燥、无聊的,并且需要耗费大量的时间,所以如果能识别这些任务并使其自动化完成,那么将会非常有帮助。我所使用的每个调试器和反汇编器都有自己的内置语言脚本,但如果我们使用多个调试器或反汇编器,那么恐怕就需要学习大量不同的脚本语言,这是没有意义的。但幸运的事,几乎所有的调试器或反汇编器都支持Python。
以前我写过一篇文章,主要讲解了如何使用Python实现任务的自动化,在文章中我是以IDA Pro为例的。在我的分析中,我使用了Python对Dridex系列进行自动解密、评论和转储加密字符串。此外,我还展示了如何使用它来处理只能在调用时才能解析的问题,这样使得静态分析更为简单。
在上面的示例中,脚本会遍历Dridex二进制文件中的每个加密字符串。然后进行解密,并转储每个字符串,在这过程中不需要运行恶意软件。

任务自动化

Python以其拥有大量可下载的库而闻名,它实现了各种不同的功能,可以让用户无需从头开始编写代码,就能够在计算机上高效地自动执行几乎任何任务。使用Python进行任务自动化,不仅仅适用于恶意软件的分析,对其他许多方面的工作都很有用。我编写过脚本来检查命令与控制域、在VirusTotal上传或查询文件、加载用于分析恶意软件的虚拟机等。Python是编程界的瑞士军刀,值得我们对其进行学习,并用于分析恶意软件。

 

第二名:C

对于作者而言,C语言是我在12岁开始学习相关技术之后,第一个熟练掌握的编程语言。由于我的梦想是成为一名程序员,因此我学习C的初衷并不是想研究逆向工程,也没有想到我学到的知识会在如今作为恶意软件分析工作的基础。尽管我并不会坚持让你掌握C语言,但我会在本文中提出如何阅读和理解的相关建议,这对于恶意软件分析来说是有所帮助的。

查看官方文档

即使对于一个经验丰富的逆向工程师,有时也会遇到不熟悉的某个恶意软件代码中的函数调用。如果想要了解该函数的功能、参数、如何对其初始化、返回什么结果,那么最好的方法就是调出文档并进行阅读。
例如,我们在Windows和Linux文档中查看“connect”函数。


在这两种环境下,函数的定义都是用C语言写成的(尽管左边的MSDN文档中说是C++,但实际上就是C语言)。在C中,传递给函数的每个参数都有一个“类型”,它只是指定其所包含的数据类型(数字/文本/二进制数据)。在示例中,第三个参数都是“sockaddr”类型,这是一个常见的C语言中的类型。如果能了解“sockaddr”是什么,我们就能够知道它需要什么数据、如何对其进行引用以及如何对其进行解释。由于“sockaddr”是一个结构,我们必须首先查找sockaddr的定义,找到它的数据类型,然后查找每个单独的数据类型,这实际上也是学习C语言的过程。MSDN中也经常提供示例C语言代码,来解释一个函数中的用法,阅读这些代码是了解函数之间关系的一种快速而有效的途径。

无官方文档的情况

对于像Microsoft Windows这样的闭源操作系统,就有很多没有记录的数据结构和功能,其原因通常是它们不应该被除微软之外的任何人使用。这些数据结构和功能通常被称为Windows内部机制。恶意软件开发者喜欢滥用内部机制来绕过安全控制,或者是为了迷惑恶意软件分析师。为了了解其内部结构,尽管我们可以对操作系统自身进行逆行工程,但该过程耗时过多且异常困难。然而,如果我们掌握了C,就有一个更快的方式。
(1) ReactOS源代码
ReactOS是一个用C语言编写的开源操作系统,旨在与Windows Server 2003可执行文件相兼容。为了保证与Windows二进制文件的兼容性,开发人员必须对NT 5.2(用于Windows 2000、Windows Server 2003和Windows XP的Windows操作系统核心版本)进行逆向工程并重新实现,因此许多Windows中的相关机制都可以通过ReactOS来了解。由于Windows XP仍然占有较大的市场份额,因此恶意软件开发者仍然会为了使他们的恶意软件兼容XP,而付出很多的努力,所以我们很难看到不支持5.2内核的恶意软件。就我个人而言,我借助ReactOS源代码来了解Windows内部知识,这样我就可以在真正的Windows操作系统上成功使用它了。
(2) Windows研究内核
Windows Research Kernel(WRK)是微软为研究人员提供的NTOS内核源代码的一个子集,其中包含大部分核心内核的源代码,但也有一部分内容被删除。尽管WRK仅包含Windows的内核部分,但它仍然可以用于帮助我们理解非内核的恶意软件,因为内核的某些部分经常被Rookie滥用的“Native API”暴露给用户级应用程序。最初,WRK很难获得,只作为各种计算机科学研究计划的一部分提供给经过认证的大学,但从那时开始,一些旧版本陆续被发布到GitHub,因此微软决定公开发布。尽管WRK不像ReactOS那样完整,但它还是具有一些优点,例如包含64位Windows内核的代码,并且它是由Microsoft编写的实际代码,并不是通过逆向工程而制作的副本。

泄露的恶意软件

要了解恶意软件工作模式并在逆向工程中读取实际恶意软件的源代码,最好的方法之一就是阅读真实恶意软件的源代码。显然,恶意软件开发者并不会轻易公开源代码,所以我们不可能获得大部分恶意软件的源代码。但是,一些庞大的恶意软件家族的源代码会在某个时间节点被披露(例如Zeus、Mirai、Carberp、ISFB、Rovnix)。大部分泄漏的恶意软件源代码都可以在GitHub找到,但我建议最好避免下载这些代码,因为其中可能会存在感染计算机的威胁。请注意,在某些国家,拥有恶意代码甚至可能违反法律。

IDA Pro伪代码

带有反编译器的完整版IDA Pro中有一个选项,可以将程序集显示为“伪代码”,这会导致它提供与程序集相匹配的代码。


虽然IDA伪代码在技术上并不是100%有效的C语言代码,其中有着细微的差别,但对于任何能阅读C语言的人来说,该伪代码都是清晰可读的。伪代码可以让我们快速了解代码的功能,可以有效节省时间。

 

第一名:汇编语言

汇编语言(ASM)是每一位逆向工程师的工具箱中最重要的一个工具,它是机器码的人类可读版本,是计算机CPU实际理解的唯一语言。任何在没有解释器的情况下在计算机上运行的代码,都必须被编译成机器代码,机器代码是一组0、1指令,该指令告诉CPU要做什么。像C、C++、GoLang、Pascal和Haskell这样的语言,都会被编译(翻译)成机器代码,因此大多数软件(包括恶意软件在内)都可以使用反编译器(将机器代码翻译成人类可读版本的汇编语言)。如果你能够很好地阅读汇编语言,那么就不需要使用高级语言,直接可以分析汇编语言的代码。同样,这一技能在恶意软件分析之外的很多地方都非常有用。
然而,因为汇编语言只是一个人类可读版本的机器代码,由于不仅仅有一种机器代码,所以也不仅仅存在一种汇编语言。不同类型的CPU会接受不同类型的指令,当你学习汇编语言时,其实只是在学习CPU所支持的指令内容(称为指令集)。在学习汇编语言之前,我们应该首先选择要学习的汇编语言指令集。目前,有两个在传统计算机上非常常见。

i386

英特尔Inter 80386,简称为i386,是x86指令集的32位版本,几乎用于所有的32位桌面计算机、服务器和笔记本电脑之中。运行Windows、Linux或Mac的计算机,如果是32位的,那么CPU就很可能是基于i386。由于这是最常见的指令集,因此如果有人在说到“汇编”时,可能就是在指i386。
当Microsoft开始设计64位操作系统时,他们遇到了很大的麻烦,因为他们需要确保32位(i386)应用程序仍然可以正常工作。目前,大多数Windows恶意软件开发者只编写32位恶意软件,因为它可以同时在32和64位操作系统上运行。即使在64位Windows上,大多数恶意软件仍然是基于i386,因此这也是我推荐的指令集

x86_64

这是x86的64位版本,也是现代计算机中较为常见的指令集。由于x86系列中的体系结构都保持了强大的向后兼容性,因此所有x86_64 CPU都可以执行i386指令,而大多数64位指令与i386指令非常相似,因此首先学习i386汇编,然后再学习x86_64是有意义的,因为x86_64指令集本质上包括i386。
虽然64位Windows可以运行i386应用程序,但其他操作系统并不支持,因此所有本地代码都必须是x86_64。更高级的Windows恶意软件系列通常会在64位Windows上部署64位版本的代码,并且所有内核模式函数都是64位的,因此x86_64汇编语言对于了解i386也是非常有价值的。

 

结论

如果此前没有程序设计经验,要转型成为恶意软件逆向工程师并不是很容易,但学习编程的这一过程能有非常多的收获。如果我们掌握编程语言(特别是汇编和C语言等),那么就可以更快地学习其他语言,并能更好地掌握计算机的工作原理。编程是市场化程度最高的一个计算机相关技能,即使最后没有成为恶意软件分析师,我们也可以借助该语言进行编程,所以希望大家不要觉得为了开始分析恶意软件而学习一种程序设计语言是非常麻烦的行为。

分享到: QQ空间 新浪微博 微信 QQ facebook twitter
|推荐阅读
|发表评论
|评论列表
加载更多