安全厂商malwarebytes发布了Spartacus勒索软件的分析报告,Spartacus在2018年首次出现,使用C#编写,该勒索软件使用基于AES的Rijndael算法实现生成加密密钥。然后该密钥被静态RSA加密,这个勒索软件是离线操作,没有链接C2服务器,需要受害者向攻击者发送电子邮件才能获得解密工具。
Spartacus勒索软件是一个在2018年流传的新样本,用C#编写。原始样本被混淆,我们将其提取到可读状态。
Spartacus是一个相对直接的勒索软件样本,并使用了一些我们过去见过的类似的技术和代码,如ShiOne,Blackheart和Satyr。但是,这些样本和攻击者之间没有确定的关系。我提到它主要是为了表明它们具有相似的功能。
对于Satyr和Blackheart来说,代码几乎完全相同,Spartacus遵循几乎相同的代码流并做了一些修改。如果我要做一个假设,我会说他们要么是同一个执行者,要么他们的执行者使用相同的代码。但是,现在还没有证据证明这一点。
一般来说,我们注意到有一串.NET 勒索软件弹出,所有这些都或多或少的相同或相似。这只是犯罪分子制造的一种简单的勒索软件形式,因为它显然不需要太多时间或想法。
他们没有什么令人印象深刻的,实际上恰恰相反。我会说他们很无聊。那么我们为什么要写关于其中的一个呢?对Spartacus的分析可以用来分析将来可能会遇到的这些基本.NET勒索软件的变种,并作为基础知识和参考。
本文的两篇文章将详细了解代码,并了解如何将混淆的.NET示例转化为可读状态。
Spartacus加密方式
在开始之前,我想提一下Spartacus加密方法的一个特点。Spartacus首先生成用Rijndael算法完成加密的唯一密钥。 (Rijndael算法是AES的一个版本。)
该密钥被保存并用于加密每个单个文件,这意味着两个相同的文件将具有相同的密文。 AES密钥被嵌入在文件中的RSA密钥加密。密文被编码并在赎金记录中显示给用户。
RSA密钥静态嵌入勒索软件的事实意味着私钥存在于勒索软件作者系统的服务器端。 因此,如果这个私钥泄露出来,这个特定病毒的所有受害者的AES密钥都可以使用这个密钥进行解密。
由于这个勒索软件不是非常复杂,我们将直接进行深入的技术分析和代码演练。
Spartacus开箱
当我们首先在ILSpy中打开Spartacus样本时,我们看到这样的结果:
这些函数的代码是不可见的,正如你所看到的,所有的东西都是混淆的。 在这些场景中,我喜欢使用名为de4dot的工具。 它将处理文件并输出干净可读的版本。 -r标志是您设置目录的位置,其中包含混淆的.NET示例。
这给了我们清晰的版本,我们将在未来的分析中使用它。
Spartacus代码分析
让我们从下面显示的Main函数开始。
它首先确保系统上只运行该恶意软件的一个实例。 它通过CheckRunProgram函数来实现,除此之外,它还创建一个互斥锁并确保它是唯一的。
检查完成后,它会在一个线程中执行smethod_3。
smethod_3开始之前,此类的构造函数会自动调用,并设置所有私有成员(变量),其中包含要搜索和加密的所有特殊文件夹。 它还使用KeyGenerator.GetUniqueKey(133)函数生成对受害者唯一的AES密钥。 特殊文件夹可以在下面查看,并在整个勒索软件中被引用以开始文件夹遍历。
我提到的keygen函数是GetUniqueKey(),其细节如下。 本质上,它只是使用RNGCryptoServiceProvider.GetNonZeroBytes API函数创建一系列强加密的随机数。 然后它使用该系列的随机数作为字符集的索引
array =“abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890”来构建一个唯一的字符串。 这是AES密钥,它将加密所有前进的文件。
现在该类的构造函数已经启动了,让我们来看看被调用的smethod_3函数。
此函数迭代构造函数中生成的特殊文件夹列表,并使用smethod_6函数开始递送遍历文件夹中的每个文件。我要在这里注意的一点是,加密循环不会区分文件类型或特殊文件,它会加密它遇到的所有内容。另外,你可以看到smethod_1被调用。这可能是程序员遗留下来的一个错误,因为它的输出在程序中的任何地方都没有使用,并在稍后将该加密密钥显示给用户时被调用。
正如我所提到的,smethod_6函数是执行所有加密的函数,但smethod_5函数是递归函数,它将挖掘每个子文件夹的任何位置,在每次迭代时调用smethod_6来加密该子文件夹中的文件。
正如你所看到的,它会自行调用,以便它最终覆盖每个子文件夹。 然后它调用smethod_6来执行实际加密,循环访问该文件夹中的每个文件。
此方法迭代当前文件夹中的所有文件。 唯一的规定是该文件尚未加密。 以下是一部分代码,它只是确保扩展不是已经是.Spartacus了:
if (Path.GetExtension(text) == ".Spartacus") { return; }
如果此检查通过,它会调用smethod_7,它会使用加密版本重写文件内容。
该函数调用smethod_0加密原始文件数据,然后接下来的两行将加密数据写入文件并用.Spartacus扩展名重命名。快速提示:另一个表明每个文件都使用相同密钥加密的标志是,这个勒索软件不会将加密的AES密钥写入文件中,我们在其他勒索软件中看到它执行独特的文件加密。
正如你在这里看到的,它使用Rijndael方法 – 使用ECB模式的AES。在构造函数中生成的密钥是用MD5散列的,而这实际上是用作密钥本身的密钥。
现在我们已经完成了在主文件系统上进行文件加密的整个过程,通过在父函数smethod_3中调用的所有子函数。
现在让我们回到主函数到下一行,它调用smethod_4():
smethod_4基本上执行与smethod_3中所看到的完全相同的一组递归函数调用,但是,它不是循环访问特殊文件夹,而是遍历所有连接到系统的逻辑驱动器。因此,所有外部或映射的驱动器也将被加密。
我们现在不需要详细说明所有这些细节,因为我们已经介绍了它们的功能,因为它们与早期的函数调用相同。我只会提到smethod_6被称为两次。这最有可能通过在两个线程上运行来加速加密。
回到Main:下一个也是最后一个重要的函数调用是:
Application.Run(new Form1());
这将向用户显示赎金记录并在赎金记录中显示加密的AES密钥。
它首先调用smethod_1()。正如我上面提到的,这只需要AES密钥,它是在开始时生成的,并使用硬编码的公共RSA密钥进行加密。
public static string smethod_1() { return Convert.ToBase64String(Class1.smethod_2("<RSAKeyValue><Modulus>xA4fTMirLDPi4rnQUX1GNvHC41PZUR/fDIbHnNBtpY0w2Qc4H2HPaBsKepU33RPXN5EnwGqQ5lhFaNnLGnwYjo7w6OCkU+q0dRev14ndx44k1QACTEz4JmP9VGSia6SwHPbD2TdGJsqSulPkK7YHPGlvLKk4IYF59fUfhSPiWleURYiD50Ll2YxkGxwqEYVSrkrr7DMnNRId502NbxrLWlAVk/XE2KLvi0g9B1q2Uu/PVrUgcxX+4wu9815Ia8dSgYBmftxky427OUoeCC4jFQWjEJlUNE8rvQZO5kllCvPDREvHd42nXIBlULvZ8aiv4b7NabWH1zcd2buYHHyGLQ==</Modulus><Exponent>AQAB</Exponent></RSAKeyValue>", Encoding.UTF8.GetBytes(Class2.smethod_0()))); }
RSA密钥被硬编码并嵌入到勒索软件中,这意味着作者已经提前生成了私钥。
然后迭代所有驱动器并在那里写入赎金记录。最后,它打开显示消息的赎金记录和RSA加密的AES密钥,该密钥将由受害者用于解密。
完成所有这些之后,它所做的最后一件事就是调用smethod_0,它会删除shadow volumes以防止用户用作Windows还原点。
这个勒索软件纯属离线,因为没有网络通信回到作者或任何C2服务器。勒索软件作者不知道自己感染了谁,直到用他们的个人ID(AES密钥)向他发送电子邮件。这也意味着作者发送的解密工具可能会嵌入AES密钥,这对于特定的受害者来说是独一无二的。
Spartacus防护方案
这个样本没有特别的或创新的,但这并不意味着它不是危险的。它仍然会完成它的工作 – 目前没有解密器。如果你意识到自己正在遭受这种恶意软件的攻击,那么保护自己的唯一可能就是执行进程内存转储,在这种情况下,从内存中提取密钥的可能性很小。
一般来说,在杀死进程之前,尽可能在系统上执行任何恶意软件的内存转储是一个好主意,抱着有些密钥可能会被恢复的一线希望。