聊聊Go恶意软件的现状和趋势

Change 观察 2019年7月8日发布
Favorite收藏

导语:最近几个月,我对Go语言编写的恶意软件产生了浓厚的兴趣。Go,有时也被称为GoLang,由Google于2009年创建,近年来在恶意软件开发群体中越来越受欢迎。

概述

最近几个月,我对Go语言编写的恶意软件产生了浓厚的兴趣。Go,有时也被称为GoLang,由Google于2009年创建,近年来在恶意软件开发群体中越来越受欢迎。

虽然近年来讨论Go恶意软件系列的文章越来越多,但Go恶意软件在数量上是否真的呈现上升势头?当前普遍认为Go主要是由渗透测试人员和红队在使用,所以我很好奇哪种Go恶意软件家族将会最为流行。于是我开始收集尽可能多的Go恶意软件,并将其按恶意软件家族进行分类。本篇文章主要描述收集数据的方法和结果。

我总共获得了大约10,700个用Go编写的恶意软件样本。根据样本的时间戳,可以得出结论,Go编译的恶意软件在数量上已经稳定增长了数月。此外,已标识样本中有92%的是针对Windows操作系统编译的,表明Windows是Go恶意软件开发人员最具针对性的系统。

在这些样本中,能够确定其恶意软件家族的占到了75%。最出名的恶意软件家族包括Veil,GoBot2和HERCULES。此外还有一些流行的恶意软件组合,包括pentest、远程访问木马(rat)和后门。

需要说明的是,RAT病毒和后门之间的区别在于恶意软件家族的特性。那些只提供最小功能并提供远程访问的被标记为后门,而功能齐全的远程访问木马被标记为RAT。

为什么要用Go呢?

Go有许多吸引人的特性,最大的吸引力之一是可以为所有主要操作系统平台(包括Windows,OSX和Linux)编译单个代码库。这能让攻击者将注意力集中在一个代码库上,而其他编程语言可能需要三个不同的代码存储库。

也有替代的方法,比如使用通用脚本语言(如Python)来编写代码库,这种方法以前在Chafer 威胁组织的案例中看到过,他们用Python编写了其中一个payload;Seaduke恶意软件家族用的也是这种方法。然而,由于Windows并没有在原生环境中提供Python,为了让这些代码库在环境中正确执行,它们必须依赖于PyInstaller之类的实用程序进行封装。这类工具在完成这项工作时,会在植入文件运行过程中留下许多痕迹,而Go就没有留下任何这些构件,这可能也是吸引攻击者的一个因素。

另一个优点(或缺点,取决于你如何看待)是,所有必需的库都与编译后的二进制文件静态链接。这会导致二进制文件的大小高于平均大小,在10700个用Go编写的恶意软件样本中,这些样本的平均大小为4.65MB,比恶意软件通常要大得多,使得它在被木马程序包中更难以使用。此外,由于电子邮件服务器可能不允许附件太大,所以在钓鱼邮件中也不太好使。

不过这种大尺寸也有意想不到的好处。在某些情况下,反病毒产品可能会忽略文件,或无法扫描。这种情况在过去涉及Comnie恶意软件家族的定向攻击中也曾出现过,恶意软件的作者在文件中添加了64MB的垃圾数据以试图绕过反病毒产品。

方法

为了开始这项研究,我必须尽可能多地收集在Go中编译的恶意软件样本。然而事实证明,仅这项任务就相当困难。用于此研究的存储库包括我们自己的以及第三方的VirusTotal服务。首要步骤是简单地收集所有可以识别的Go样本,无论它们是否是恶意的。

· 为了收集这些样本,我采取了多种方法,包括但不限于以下方法:

· 带有引用“Go.org”的嵌入链接的OSX或Linux样本

· 使用'Go-http-client / 1.1'用户代理的样本

· 使用'GRequests'用户代理的样本

· 包含'.symtab'部分名称的PE样本

· 使用一系列已识别的导入哈希的PE样本

· 引用了Google的gopacket github存储库的OSX样本

· 引用gopkg.in的OSX样本

· 符合YARA规则的样本

关于YARA规则,这里是创建了三个单独的规则来识别每个主要平台的Go样本。例如,以下规则用于标识为OSX编译的Go样本:

rule osx_GoLang
 
{
 
meta:
 
     author = “Josh Grunzweig”
 
     description = “Attempts to identify samples written in Go     
 
     compiled for OSX.”
 
     strings:
 
          $Go = “go.buildid”
 
     condition:
 
          (
 
               uint32(0) == 0xfeedface or
 
               uint32(0) == 0xcefaedfe or
 
               uint32(0) == 0xfeedfacf or
 
               uint32(0) == 0xcffaedfe or
 
               uint32(0) == 0xcafebabe or
 
               uint32(0) == 0xbebafeca
 
          ) and
 
          $Go
 
}

使用以上方法,我收集了大约61.1万个独立的样本。

在获得所有样本哈希之后,我查询了Unit42的系统和VirusTotal,以确定哪些样本是恶意的。在VirusTotal里,我只是检查了具有“malware”标识或5个以上恶意软件特征的选项,然后下载了这些剩余的样本,并运行了之前创建的YARA规则,最后留下了大约13,000个独立的样本。

之后我开始将这些样本聚类到它们各自的恶意软件家族中去。为此我主要采用人工的方法,分析给定的文件,并基于已识别的恶意软件家族创建YARA规则,我还编写了一些辅助脚本用来从已标识的二进制文件中提取有用的信息。下面的辅助脚本能从二进制文件中提取用户定义的函数名,以及所有可能存在的用户定义路径:

import sys
 
import re
 
inputfile = sys.argv[1]
 
fh = open(inputfile, ‘rb’)
 
fd = fh.read()
 
fh.close()
 
minimum = 5
 
char = r”[\t\n\x20-\x7f]” + “{{{},}}”.format(minimum)
 
wchar = r”(([\t\n\x20-\x7f]\x00)” + “{{{},}}”.format(minimum) + r”\x00)”
 
allStrings = []
 
for s in re.findall(char, fd):
 
     allStrings.append(s)
 
for s in re.findall(wchar, fd):
 
     allStrings.append(s[0].replace(“\x00″,”))
 
 
 
blacklist = []
 
allStr = []
 
for s in allStrings:
 
     if s[-3:] == “.go” and “main.go” in s:
 
          allStr.append(s)
 
     elif s[0:5] == “main.”:
 
          if “statictmp” not in s:
 
               if “.init.” not in s:
 
                    if “.(*” not in s:
 
                         allStr.append(s)
 
for x in list(set(allStr)):
 
     print(repr(x))

该脚本对其中一个样本的运行结果如下:

$ python find_interesting_strings.py fc684bbf9428a4e33c390e3963c9bfa24e81cb040ccd601c6e7f5b6c193e2808.bin
 
‘main.encryptFile’
 
‘main.writeLog.func1’
 
‘main.writeLog’
 
‘main.init’
 
‘main.scanDir’
 
‘main.ignoreUsersFolders’
 
‘main.ignoreRootFolders’
 
‘main.encryptFile.func1’
 
‘main.logFilePath’
 
‘main.ignoreProgramFilesFolders’
 
‘C:/Users/pc/go/src/scaner/main.go’
 
‘main.ignoreProgramDataFolders’
 
‘main.initdone’
 
‘main.makeReadmeFile.func1’
 
‘main.ignoreFiles’
 
‘main.ignoreFileExtensions’
 
‘main.main’
 
‘main.makeReadmeFile’
 
‘main.DEBUG’

这样能够很容易确定哪些函数名和代码路径是最常见的,并且在某些情况下能让我仅根据这些信息对样本进行聚类。其中一个恶意软件家族的YARA规则如下:

rule trojan_golang_hercules: Pentesting
 
{
 
     meta:
 
          author = “jgrunzweig – PaloAltoNetworks”
 
          date = “2019-06-15”
 
          description = “the HERCULES malware family written in     
 
          Go.”
 
          hash1 = “2a7da0a0acadb61fb79fa4a33130d09ecff5a904b0999d264d8c1edffeffea95”
 
          hash2 = “6e68dafbb717daf6a505d8a95c41e5114d91c4fde703343356352c1ca5cd24ea”
 
          hash3 = “645ed38f2d55b2f7731d5c9223329428592497eb95c96bcd7c01a4eaeb38e137”
 
          reference = “https://github.com/EgeBalci/HERCULES”
 
     strings:
 
          $buildid = “go.buildid”
 
          $uniq1 = “cGFja2FnZSBtYWluCgppbXBvcnQgIm5ldCIKaW1wb3J0ICJvcy9leGVjIgppbXBvcnQgImJ1ZmlvIgppbXBvcnQgInN0cmluZ3MiCmltcG9ydCAic3lzY2FsbCIKaW1wb3J0ICJ0aW1lIgppbXBvcnQgIkVHRVNQTE9JVCIKCgoKY29uc3QgSVAgc3RyaW5nID0gIjEwLjEwLjEwLjg0Igpjb25zdCBQT1JUIHN0cmluZyA9ICI1NTU1IgoKY29uc3QgQkFDS0RPT1IgYm9vbCA9IGZhbHNlOw”
 
          $uniq2 = “cGFja2FnZSBtYWluCgoKaW1wb3J0ICJlbmNvZGluZy9iaW5hcnkiCmltcG9ydCAic3lzY2FsbCIKaW1wb3J0ICJ1bnNhZmUiCi8vaW1wb3J0ICJFR0VTUExPSVQvUlNFIgoKY29uc3QgTUVNX0NPTU1JVCAgPSAweDEwMDAKY29uc3QgTUVNX1JFU0VSVkUgPSAweDIwMDAKY29uc3QgUEFHRV9BbGxvY2F0ZVVURV9SRUFEV1JJVEUgID0gMHg0MAoKCnZhciBLMzIgPSBzeXNjYWxsLk5ld0”
 
          $uniq3 = “cGFja2FnZSBtYWluCgppbXBvcnQgIm5ldC9odHRwIgppbXBvcnQgInN5c2NhbGwiCmltcG9ydCAidW5zYWZlIgppbXBvcnQgImlvL2lvdXRpbCIKLy9pbXBvcnQgIkVHRVNQTE9JVC9SU0UiCgoKCmNvbnN0IE1FTV9DT01NSVQgID0gMHgxMDAwCmNvbnN0IE1FTV9SRVNFUlZFID0gMHgyMDAwCmNvbnN0IFBBR0VfQWxsb2NhdGVVVEVfUkVBRFdSSVRFICA9IDB4NDAKCnZhciBLMzIgPS”
 
         $path = “/HERCULES/”
 
 
 
         $banner = “HERCULES REVERSE SHELL”
 
         $help1 = “~DOS -A \”www.targetsite.com\””
 
         $help2 = “~WIFI-LIST “
 
         $help3 = “~KEYLOGGER-DUMP “
 
         $help4 = “Creates a reverse http meterpreter session at given pid (EXPERIMENTAL)”
 
 
 
     condition:
 
          (
 
                // Windows binary
 
               (uint16(0) == 0x5a4d) or
 
               // OSX binary
 
               (
 
                    (
 
                         uint32(0) == 0xfeedface or
 
                         uint32(0) == 0xcefaedfe or
 
                         uint32(0) == 0xfeedfacf or
 
                         uint32(0) == 0xcffaedfe or
 
                         uint32(0) == 0xcafebabe or
 
                         uint32(0) == 0xbebafeca)
 
                    ) or
 
                    // Linux binary
 
                    (uint32(0) == 0x464C457F)
 
               ) and
 
               filesize > 500KB and
 
               $buildid and
 
               (
 
                    any of ($uniq*) or
 
                    $banner or
 
                    any of ($help*) or
 
                    $path
 
               )
 
}

这种手动方法还能识别误报。当我终于完成时,发现了大约2,000个误报。这样恶意软件样本总数就是10,700,其中75%被确定为恶意软件。

我在此研究中共识别出53个恶意软件家族,并为每个家族创建了YARA规则。

结果

也许这项研究得出的最明确的结论之一是,在Go中编译的恶意软件文件数量还相对较少。虽然这有可能是基于我的方法的才得出的结论,但我相信这是一个相当准确的结论。Go作为一种恶意软件开发语言还处于起步阶段,还没有真正在恶意软件群体中获得很高的人气。话虽如此,根据收集的恶意软件样本的时间轴,我们可以看到它似乎越来越受欢迎。

1.png

图1所示.基于首次发现的Go恶意软件样本的时间轴。

这项研究的另一个结论是确定了Go恶意软件主要针对的操作系统——大多数是为Windows编写的,对许多人来说这个结果可能并不意外。

2.png

图2.编译了Go恶意软件样本的操作系统。

总共有92%的Go恶意软件样本是针对Windows操作系统编译的,4.5%是针对Linux编译的,其余的是针对OSX编译的。由于Windows仍然是攻击者最具针对性的平台,这数据并不令人惊讶。但是我个人认为,在这项研究中,Windows操作系统不会识别出这么大比例的恶意软件。

如前所述,在本研究过程中共识别出53个恶意软件家族。结果如下:

1.png

表1.确定的恶意软件家族。

根据恶意软件的属性和用途,将每个恶意软件家族归入不同的类别,结果如下:

3.png

图3.恶意软件类别。

可见,大多数识别的文件都与渗透测试活动相关联,虽然它们也可以被恶意使用,但渗透测试才是主要用途。除此之外,我们看到许多被识别的恶意软件样本都没有合法目的,比如RAT、后门、挖矿程序和信息窃取软件在剩下的类别中名列前茅。

结论

总的来说,这项研究工作对我个人的启发是多方面的。“Go恶意软件的普遍存在与渗透测试相关”的这种先入为主的观念虽然得到了证实,但我们也看到,有大量真实的各类恶意软件,从后门到僵尸网络再到银行木马无所不包。而另外一个有趣的地方在,识别出的恶意软件样本数量较低,这表明Go恶意软件仍然没有得到开发者的明显关注。不过根据恶意软件样本第一次出现的时间戳也可看出,Go恶意软件正变得越来越受欢迎,比如从2017年1月到2019年3月的这段时间来看,Go恶意软件的数量增长显著,增长了近20倍(+1944%)。

Go恶意软件的发展还处于起步阶段,不过随着新恶意软件家族的不断涌现,它将由于它的特性——针对所有主要操作系统仅需编译单个代码库——而越来越受到恶意软件开发者和整个安全社区的关注,所以我相信在未来的几年里,Go将在已开发的恶意软件中占据更大的比重。

本文翻译自: https://unit42.paloaltonetworks.com/the-gopher-in-the-room-analysis-of-golang-malware-in-the-wild/如若转载,请注明原文地址: https://www.4hou.com/info/observation/18958.html
点赞 0
  • 分享至
取消

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

扫码支持

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

发表评论