姜鹏辉的个人博客 GreyNius

【精读】Linux下的恶意软件

2020-05-03

类型 内容
标题 Understanding Linux Malware
时间 2018
会议 2018 IEEE Symposium on Security and Privacy (S&P)
DOI 10.1109/SP.2018.00054

论文信息

作者共4位,3位来自Eurecom,一位来自思科公司

摘要

文章提出了为Linux下恶意软件定制的恶意软件分析管道收集的10548个恶意样本的研究结果

介绍

以往恶意软件主要在Windows系统上,且安全界都把精力放在Windows的恶意软件上。 目前由于Iot设备的推广,还有嵌入式设备,Linux下的恶意软件增多

文章贡献:

  • 记录了几种Linux恶意软件分析工具的设计和实现
  • 在一年时间里研究了10548个恶意软件样本
  • 发现了一些恶意软件使用的底层Linux技术,并统计了使用情况

挑战

分析Linux恶意软件有很多挑战

目标多样性

基于Linux的恶意软件可以针对不同的目标,如路由器、打印机、监控摄像头、智能电视或医疗设备。这使分析的过程非常复杂。实际上,如果没有关于目标的正确信息,很难正确配置正确的执行环境。

计算机体系结构:Linux支持数十种不同的体系结构,例如一篇关于Mirai僵尸网络的论文1,支持了MIPS32,ARM32,X86三种结构,但这三种结构只占总数据集的32%。且ARM有很多不同的CPU结构。

加载库:被分析的环境缺少一些动态链接库,如uClibc或musl

操作系统:要区分ELF程序是为Linux系统设计还是其他如FreeBSD或安卓设计的非常困难。

静态链接

一些恶意软件使用静态链接,将所需要的依赖项都编译进二进制文件中,使得其更具移植性(其实目标环境没有安装该依赖项,也将正确执行)。但是兼容性较差,如果内核ABI和它们期望的不同,将导致程序崩溃。

分析环境

一些恶意软件是假设以Root权限运行的(对于某些嵌入式目标)。而沙盒通常是以普通用户的身份执行恶意软件,如果给管理权限将会使程序行为的观察变得复杂,

缺少以前的研究

这是第一个对恶意软件进行全面分析的工作,并且缺乏全面的数据集。少数基于Linux恶意软件的研究只关注僵尸网络,因此使用蜜罐来构建一个具有代表性的数据集

分析结构

数据收集

使用VirusTotal Intelligence API来获取在2016年11月至2017年11月之间提交的ELF文件的报告。根据报告的内容,我们每天下载200个候选样本,为每天观察到的每个系列选择至少一个样本。 我们还将我们的选择分为两组:从具有超过五个AV阳性匹配项的样本中抽取140个样本,以及在AV分数介于1-5之间的60个样本。

文件和元数据分析

ELF文件格式中包含的某些字段在运行时是操作系统所必需的,因此需要提供有关应用程序应在其上运行的体系结构以及文件中包含的代码类型(例如,可执行或共享对象)的信息。我们实现了ELF格式的自定义解析器,因为现有的解析器常常无法处理格式错误的字段、意外值或丢失的信息。

两个目的:首先,筛选出与我们的分析无关的文件。例如共享库、核心转储、损坏的文件或为其他操作系统设计的可执行文件(例如,当样本导入Android库时)。其次,识别异常的文件结构,这些结构虽然不会阻止样本运行,但可以用作反分析例程,并阻止现有工具正确处理该文件。

从VirusTotal报告中提取每个样本的AV标签,输入到AVClass工具中,获取这个恶意软件家族的规范化名称。 AVClass2实现了一种最先进的技术,根据恶意软件的样本检测出一组AV标签中的别名。因此,每当它能够输出一个名称时,就意味着不同的杀毒软件对该恶意软件所属的类(族)有一个普遍的共识。

静态分析

我们的静态分析阶段包括两个任务:二进制代码分析和包检测。

动态分析

两种:在模拟器中执行五分钟和自定义打包分析和解包尝试。 对于仿真实现了两种类型的动态沙盒:1. 基于KVM的沙箱,支持X86和X86-64。2. 基于QEMU的沙箱,支持ARM 32位小字节序,MIPS 32位大字节序,和PowerPC 32位。 这五个沙箱在一个外部虚拟机中,根据结构分配不同的恶意软件样本,并设置了多个快照,每个快照对应着不同的配置(例如在普通用户或root下执行,使用glibc或uClibc)

使用SystemTap3来实现内核探测(kernel probes,kprobes)和用户探测(user probes,uprobes)。根据其文档,SystemTap应该在各种不同的体系结构(如x86、x86-64、ARM、aarch64、MIPS和PowerPC)上受支持,但实际上我们需要修补它的代码,以使用o32 ABI支持ARM和MIPS。我们的补丁包括对系统调用号、CPU寄存器命名和偏移量的修复,以及从堆栈中提取系统调用参数所需的例程。 我们使用了SystemTap来收集每个系统调用及其参数和返回值,以及从中调用syscall的指令指针。我们还将glibc重新编译以添加uprobes功能,以便在可能的情况下收集有关字符串和内存操作函数的附加信息。

在执行结束时,每个沙箱都会返回一个文本文件,其中包含系统调用和用户空间功能的完整跟踪。 然后立即对该跟踪进行解析,以识别沙箱的有用反馈信息。 例如,此初步分析可以标识缺少的组件(例如库和加载程序),或者检测样本是否测试了其用户权限或尝试执行由于权限不足而失败的操作。 在这种情况下,我们的系统将立即重复执行样本,但这次具有root特权。 如第V-D节所述,我们稍后将比较不同用户收集的两条跟踪作为差异分析的一部分,以识别特权如何影响样本行为。 最后,初步跟踪分析还可以向分析人员报告导致样本无法在我们的系统中运行的任何错误。 作为这些警告的样本,我们遇到了许多ARM样本,这些样本由于其LOAD段的物理地址和虚拟地址之间的四字节未对齐而崩溃。 这些样本可能旨在感染基于ARM的系统,该系统的内核将通过考虑其物理地址来存储映射段,而这在常见的桌面Linux发行版中是不会发生的。 我们扩展了系统,其组件旨在通过查看ELF标头来识别这些情况,并在将数据传递至动态分析阶段之前修复数据对齐方式。

为了避免妨碍执行和丢失重要的代码路径,我们提供了部分网络访问样本,同时监视通信量以查看是否有滥用的迹象。尽管不是一个理想的解决方案,但在其他行为分析实验中已经采用了类似的方法14,因为这是观察样本全部行为的唯一方法。

最后,为了动态地解压未知的UPX变体,我们开发了一个基于Unicorn的工具。系统在多个体系结构上模拟指令,其行为类似于一个小内核,在解包期间导出UPX使用的有限系统调用集(支持不同系统调用表和系统调用ABIs的组合)。正如我们在第V-E节中所解释的,这种方法允许我们在数据集中自动解包除三个恶意软件样本之外的所有样本。

数据集

最终数据集由10548个ELF可执行文件组成,涵盖了十多种不同的体系结构

基于Linux的恶意软件大小差别很大,从最小的134字节(一个简单的后门)到最大的14.8兆字节(一个用Go编码的僵尸网络)

有超过10%的样本使用malloc但从不使用free 大多数二进制文件的熵都在6左右,这是已编译但未打包的代码的常见值。

恶意软件家族

AVClass工具能够将我们数据集中83%的样本与恶意软件家族关联起来。运行DDoS攻击的僵尸网络在基于Linux的恶意软件领域占据主导地位,占总样本的69%,分布在25个以上的家庭中。这种流行的原因之一是,攻击者经常获取保护不力的物联网设备,加入大型远程控制僵尸网络。 通过在线服务Shodan或扫描工具ZMap可以快速定位目标,而且很多恶意软件的源代码是公开的,导致出现了大量的变体。 数据集还包含成千上万个属于其他类别的样本,包括后门,勒索软件,加密货币挖矿病毒,bankers,传统文件感染,提权工具,rootkit,邮件程序,蠕虫,用于APT活动的RAT程序,基于CGI的二进制webshel​​l

在HOOD下

ELF头操作

ELF(Executable and Linkable Format)是Linux可执行文件的标准格式,有复杂的结构。 数据显示,恶意软件开发人员经常篡改ELF头来愚弄分析人员或破坏常用的分析工具。

异常ELF:第一类中最常见的样本(数据集中样本的5%)是删除有关ELF部分的所有信息。另一个样本是包含错误的文件执行信息,例如一个Linux程序可以报告成另一个操作系统ABI(例如FreeBSD),并且仍可以被内核正确执行。

无效ELF:此类别包括具有错误的section信息或segment信息(样本占数据集中的2%)的样本,通常是无效e_shoff(节标题表的偏移),e_shnum(节标题表中的条目数)的结果 )或e_shentsize(节条目的大小),

对用户工具的影响: 在表三中,作者报告了流行用于处理ELF文件的工具对异常或格式错误的文件做出的反应。 其中包括readelf(GNU Binutils的一部分),pyelftools(用于分析和分析ELF文件的便捷Python库),GDB(Linux和许多类似UNIX的系统上的事实上的标准调试器)和IDA Pro 7

作者决定编写自定义ELF解析器,该解析器专门设计用于处理异常设置、不一致、无效值或格式错误的头信息。IDA Pro 7是作者在分析管道中使用的唯一工具,它能够正确处理任何损坏的section信息或其他不会影响程序执行的字段的存在。

持久化

恶意软件作者可以轻松在Microsoft Windows平台上实现持久性,这些技术中的绝大多数依赖于注册表项的修改,以便在引导时,用户登录时,某些事件发生时或计划特定服务时运行软件。 基于Linux的恶意软件需要依赖于不同的策略,到目前为止,无论在数量上还是在本质上,这些策略都受到限制。 我们将在数据集中观察到的技术分为四类,如下所述。

子系统初始化:这似乎是恶意软件作者最常用的方法,并利用了众所周知的Linux init system。 表IV显示了超过1000个样本试图修改系统的rc脚本(在每个运行级别的末尾执行)。 相反,有210个样本在/etc/init.d/下添加了自己,然后创建到包含运行级配置的目录的软链接。 总体而言,我们发现有212个二进制文件替换了/etc/rc1.d/etc.rc5.d中的链接,其中有16个使用了专门用于机器停止和重新引导操作的较不常见的运行级别。 请注意,恶意程序仍在很大程度上依赖System-V初始化系统,并且我们数据集中只有两个样本支持较新的初始化技术(例如systemd)。这种持久性仅在进程具有root权限时才有效,如果执行ELF的用户不是root用户,则通常无法修改service和初始化配置。

基于时间的执行:它依赖于cron,cron是Unix系统的基于时间的作业调度程序。 恶意ELF文件会尝试修改cron配置文件,并在固定的时间间隔内按计划执行。 对于子系统初始化,如果恶意软件是由非特权用户启动的,则基于时间的持久性将不起作用,除非该样本调用系统实用程序crontab(存储在/var/spool/cron/下的配置文件的SUID程序,专门设计用于修改配置成文件)。

文件感染和替换:恶意软件在系统中保持立足点的另一种方法是替换(或感染)目标中已存在的应用程序。 Gates家族完全替换了/bin/usr/bin中的系统工具,在/usr/bin/dpkgd备份了一份

用户文件更改:如表四中间部分所示,很少有样本修改用户主目录中的配置文件,如shell配置。采用这种方法的恶意软件编写器可以确保用户级的持久性,但是除了受感染的Linux用户之外,其他Linux用户不会受到这种持久性机制的影响。虽然最常见,但对shell配置的更改并不是每用户持久性的唯一形式。很少有针对桌面Linux安装的样本(如handofthief家族中的样本)修改了windows管理器使用的.desktop启动文件。

伪装

恶意软件会使自己的进程名看起来无害。

表V显示,超过50%的样本在内存中采用不同的名称,并且冒充良性应用程序。 带有请求PR_SET_NAME的系统调用prctl或仅修改程序的第一个命令行参数(程序名称)的样本总数超过了4K。 其中,有11%采用的名称来自公用事业公司。 例如,属于Gafgyt家族的样本通常会伪装成sshd和telnetd。 基于prctl的调用导致在/proc/<PID>/status中列出的不同进程名称,而第二种修改了/proc/<PID>/cmdline中的信息。 数据集中没有一个恶意软件将这两种技术结合在一起(因此可以通过查找名称不一致来轻松地检测出所有恶意软件)。

其余48%的样本要么使用一个空名称,一个虚构文件的名称,要么使用一个由当前时间和进程PID共同组成的随机名称。

特权

恶意样本在以root限执行时可以执行不同的操作并显示不同的行为。尤其是针对嵌入式系统或IoT设备时,恶意软件甚至设计为以root用户身份运行。

首先以普通用户权限执行每个样本。 如果在执行过程中,我们检测到任何尝试检索用户或组标识(程序可以用来确定恶意软件的下一步操作)或访问任何返回EPERM或EACCES错误的资源的尝试,重试以root特权运行样本。 2637个样本(数据集的25%)满足了这种情况,两次执行记录中提取的样本行为有89%存在差异。

表VII列出了在以root执行但在以普通用户身份运行时未观察到的行为列表。其中,对文件的特权shell命令和操作占主导地位,恶意软件使用root权限在受保护的文件夹中创建或删除文件。 例如,Flooder和IoTReaper系列的样本通过删除/var/log中的所有日志文件来隐藏其踪迹,而Gafgyt系列只删除最后登录和注销信息(var/log/wtmp)。
在少数情况下,以root运行的恶意软件能够篡改沙箱:在检测到模拟环境时,会杀死SSH守护进程,甚至删除整个文件系统。

特权提升: 沙箱的系统保持了最新,修补了漏洞。没有样本在沙箱中成功提升了权限。对于旧的提权攻击,开发了自定义的签名,可以识别10种常见的提权攻击。

CVE-2017-7308
CVE-2017-6074
CVE-2017-5123
CVE-2017-1000112
CVE-2016-9793
CVE-2016-8655
CVE-2016-5195
CVE-2016-0728
CVE-2015-1328
CVE-2014-4699 

识别到CVE-2016-5195是最常用的漏洞,共有52个ELF程序试图使用它。还检测到5次试图利用CVE-2015-1328

内核模块: 以root执行的2637个恶意软件样本中,只有15个成功加载了内核模块,并且没有一个执行卸载过程。 所有这些情况都涉及ip_tables.ko,这是设置IP数据包过滤器规则所必需的。 属于Gates或Elknot家族的119个样本试图加载自定义内核模块,但由于沙箱不存在相应的.ko文件而失败

包装与多态性

Runtime packing是最复杂的混淆技术之一,可以防止任何静态分析代码的尝试,并且减缓手动逆向工程
UPX是1998年推出的一个流行的开源压缩打包程序,用于减少可执行文件的大小,许多操作系统都可以免费使用它。

添加了一些自定义分析的程序,识别可能打包过的程序 Vanilla UPX及其变种是数据集中最流行的打包形式。如表8所示,在380个打包的二进制文件中,只有3个不属于此类别

自定义打包程序:有三个样本实现了自定义的打包

进程交互

多进程 25%的样本是单进程的,9%的生成一个新进程,43%的涉及三个进程,而其余23%创建了更多的进程(多达1684个)。
在产生多个进程的样本中,有许多流行的僵尸网络,如gafgyt、Tsunami、Mirai和XorDDos。例如,gafgyt为每次连接到其C&C服务器的尝试创建一个新进程。XorDDos会创建并行的DDos攻击进程。

Shell命令 我们在沙箱中分析的样本中,有13%执行了至少一个Shell命令。 总共有93个命令的执行
表IX中总结了其中最流行的命令行工具。 通常执行诸如sed,cp和chmod之类的命令以在目标系统上实现持久性,而rm则用于取消链接样本或删除bash历史记录。 几个恶意软件家族还试图删除以前对该相同恶意软件的感染。

进程注入 攻击者可能希望将新代码注入正在运行的进程中,以更改其行为,使样本更加难以调试或挂钩特定的功能以窃取信息

信息收集

信息收集是恶意软件执行的一个重要步骤,因为收集的信息可用于检测沙盒的存在,或控制样本的执行。存储在系统上的数据也可以被传输到远程位置。

Proc和Sysfs文件系统 proc和sysfs虚拟文件系统分别包含进程、系统和硬件配置的运行时系统信息,以及内核子系统、硬件设备和内核驱动程序的信息。我们将恶意软件样本收集到的信息分为三大类:系统配置、进程信息和网络配置。如表X所示,访问网络目录是最常见的,有3000多个样本,恶意软件通过访问/proc/net/route(系统路由表)以获得活动网络接口及其相关配置的列表。 附加信息从/proc/net/tcp(活动的tcp套接字)和/proc/net/dev(发送和重新接收的数据包)中提取。此外,数据集中有111个样本读取/proc/net/ARP以检索系统ARP表。对于表XI中报告的sysfs,DDoS攻击访问/sys/class/net/以获取传输队列长度。

系统配置类别是第二常见的,有数百个样本提取了内存大小、CPU内核数和其他CPU特性。用于沙盒检测和规避的文件也属于这一类,以及USB和PCI连接设备的列表。此类别访问/proc/cmdline检索内核镜像的名称

另一种常见的信息收集类型侧重于进程枚举。这用于防止同一恶意软件的多次执行(例如由mirai),或识别目标计算机上运行的其他相关程序。如表IX所示,我们发现131个样本执行ps命令获取正在运行的进程列表。 例如,67个BitCoinMiner调用ps命令,并尝试杀死可能干扰其活动的挖矿进程。

配置文件 系统配置文件包含在/etc/文件夹中。如表XII所示,实现持久性所需的配置文件是访问频率更高。与网络相关的配置文件/etc/resolv.conf(DNS解析器)或/etc/hosts(主机和IP地址之间的映射)。 Flooder使用/etc/passwd来检查系统上是否存在后门帐户。如果找不到,则直接修改/etc/passwd/etc/shadow来添加新用户。

规避

规避的目的是隐藏恶意行为,尽可能不被发现。样本会检测分析工具的存在或者区分是否运行在沙箱环境中还是在真实设备中。

沙箱检测:一些恶意软件尝试从系统中检测”VMware”或”QEMU“字符串

有10个样本在root权限下会查看sys_vendor文件来检测分析环境。一些样本在检测到是在虚拟环境中运行时,会选择退出,而有一些会更激进的尝试删除整个文件系统。

进程枚举:有259个样本对/proc/<PID>目录进行了完整扫描,但是没有证据证明是为了逃避检测,一般是为了测试机器是否已经被感染,或者是为了kill指定进程

反调试:最常见的反调试技术是附加一个调试器上去,而一个进程最多只能附加一个调试器。有63个样本采用了基于带有PTRACE_TRACEMEPTRACE_ATTACH标志的ptrace系统调用,来检测是否连接另一个调试器。还有一个样本检查LD_PRELOAD环境变量的存在,该变量通常用语覆盖动态加载库中的函数,最终目的是检测动态执行情况。

反执行:我们的实验检测到属于DnsAmp家族的样本,除了将自己的文件名与硬编码字符串进行比较之外,这些样本没有表现出任何行为。 仔细查看这些样本可以发现,恶意软件作者将此技巧用作逃避解决方案,因为许多恶意软件收集基础结构和分析沙箱通常在分析之前重命名文件。

Stalling Code:众所周知,Windows恶意软件经常使用Stalling Code,顾名思义,这是一种用于延迟恶意行为执行的技术-使分析沙盒只运行每个样本几分钟。64%的二进制文件使用了nanosleep系统调用,但没有用来延迟执行,只是用来协调进程或网络通信。

样本中有80%以上是静态连接的,这些样本中只有24%进行了混淆,剩下的样本通常甚至包括开发人员使用的函数和变量名。动态链接样本,只有33%的样本混淆过。

常用的动态库如下,总共有超过200个动态库,分布不均匀,第10受欢迎的库只有1%的样本使用。

恶意软件家族内的区别

属于同一个家族的样本可能具有不同的特征

Tsunami家族有743个样本,针对9中不同的体系结构进行编译,最常见的是X86-64,最少见的Hitachi SuperH。其中86%是静态连接,13%是动态的。

有15%的Tsunami样本出现了关于Root权限的问题,其余的没有。17个样本包含了规避沙箱的代码。

  1. Antonakakis et al., “Understanding the Mirai Botnet,” inProceedings of the USENIX Security Symposium, 2017.  2

  2. M. Sebasti ́an, R. Rivera, P. Kotzias, and J. Caballero, “AVclass: A Tool for Massive Malware Labeling,” inRAID, 2016. 

  3. SystemTap.” https://sourceware.org/systemtap/. 

  4. “Malware analysis sandbox aggregation: Welcome Tencent HABO.” http: //blog.virustotal.com/2017/11/ malware-analysis-sandbox-aggregation. html. 


Comments

Content