在过去的两个月里,我一直在研究采用Go语言编写的恶意软件。
Go,又称Golang,是谷歌公司开发的一种编程语言,如今正在被越来越多的恶意软件开发者所使用的。
在这篇文章中,我就将针对一款采用GO语言编写的新型linux勒索软件进行分析。
这里分析的样本,是一个被剥离了编译和调试信息的ELF可执行文件,这使得逆向工程变得困难。值得庆幸的是,一款补救工具(REDRESS: https://go-re.tk/redress/)可以为我们提供帮助。
下面是使用参数“-src”分析此样本的输出:
图1.恶意软件的源代码
通过图1,我们可以看出该恶意软件由三个Go文件组成。
此外,我们还可以看到它所有的函数以及它们的代码行号。根据一些函数的名称,我们大致就能判定,它应该是一种勒索软件。
源代码仅有300多行,说明这款勒索软件并不复杂,可能还处于初始开发阶段。
接下来,就让我们在调试器中开始动态调试吧。
在这里,我使用的是Radare2(Radare2: https://rada.re/r/)。这是因为对于分析被剥离了的Go二进制文件而言,它比GDB更合适。
我在Radare2中发出命令“aaa”以执行自动分析,在图2中,我们可以看到Radare2很好地还原并识别了函数名和符号名。
图2.使用Radare2还原的函数名称和符号
如你所见,函数init()在主函数之前执行,函数check()在函数init()中调用。
在函数check()中,勒索软件首先会通过向hxxps://ipapi.co/json/发送一个http请求来获取受感染主机的位置信息,目的是避免感染一些特定国家的用户,如白俄罗斯(BY)、俄罗斯(RU)和乌克兰(UA)。
图3.过滤掉白俄罗斯(BY)、俄罗斯(RU)和乌克兰(UA)
在main()函数中,它将首先删除Go二进制文件,然后调用函数randSeq()生成一个随机AES密钥,其大小为0x20字节,如下图所示:
图4.生成随机AES密钥
接下来,它将调用函数makesecret(),目的是使用以二进制形式硬编码的RSA公钥来加密AES密钥。在这个函数中,它通过调用函数EncryptPKCS1v15以使用RSA加密和PKCS#1 v1.5中的填充方案对给定的AES密钥进行加密。
图5. Go二进制文件中的硬编码RSA公钥
使用RSA加密后的数据如下:
图6.使用RSA加密后的AES密钥
接下来,它将在Golang包编码/base64中调用函数EncodeToString,以使用base64算法对先前加密的数据进行编码。
图7.使用Base64编码的AES密钥
然后,它将为解密的README文件(赎金票据)形成一个缓冲区,如图8所示:
图8.解密的README文件的缓冲区
我们可以看到,加密的AES密钥以Base64编码的形式被写入了解密的README文件中。
在加密文件之前,它还会通过发出命令“service stop [pname]”或“systemctl stop [pname]”来杀死以下进程。
图9.目标服务
当它尝试停止Apache2.service时,会弹出一个标题为“Authentication Required(需要身份验证)”的对话框,提示用户输入系统密码以完成此操作。
图10. apache2.service身份验证对话框
最后,它将通过在Golang包“path/filepath”中调用函数Walk(根字符串,walkFn WalkFunc)来遍历根目录“/”,然后开始加密文件。
图11.遍历根目录并加密文件
值得一提的是,该勒索软件还包含一份加密目录黑名单,目的是避免加密这些目录下面的文件。
图12.加密目录黑名单
加密算法使用的是AES-256-CFB,被加密文件将被附加扩展名“.encrypted”,README文件如图13所示:
图13. README文件
用于执行加密的函数是EncFile(),它首先会获取目标文件的大小。如果文件小于0x986880(1,000,000)字节,它将使用AES-256-CFB算法加密所有文件数据。否则,它将读取数据的前0x986880(1,000,000)字节并将其加密,然后将原始文件的剩余数据复制到加密后文件的末尾。
图14.检查目标文件的大小
图15.大于0x989680字节的文件经过加密后的数据
通过上述分析,我们可以看到这种勒索软件并不复杂,可能还处于初始开发阶段。
但是,我们应该意识到,Go语言正在被用来开发越来越多的恶意软件,各大杀毒软件厂商更是有必要注意这一点。