转载

威胁聚焦:CRYPTOWALL4

持续更新的恶意软件

原文: http://blog.talosintel.com/2015/12/cryptowall-4.html

0x00 摘要

在过去的一年里,Talos花费了大量的时间去研究ransomware的运作原理,它与其他恶意软件的管理,还有它的经济影响。这项研究对开发检测方法和破坏攻击者的攻击有很大的价值。CrytoWall是一款恶意软件,在过去的一年里,先是升级成了CryptoWall2,随后升级为CryptoWall3。尽管大家都在努力检测和破坏它的攻击行为,但是这款恶意软件开发者还是很厉害的,改进了一些技巧,然后现在放出了CryptoWall4这个版本。

为了保证我们能最有效地检测出来,Talos对CryptoWall4进行了逆向,去理解它的行为,还有升级之后的差异,并放在这里分享我们的研究成果。

读者可能不熟悉,ransomware是一款恶意软件,它锁定用户的文件(比如照片,文档,音频文件等等),然后对其进行加密。用户要给赎金才能解密这些文件,查看里面的内容。通常,用户会通过钓鱼邮件感染ransomware。CryptoWall4的核心功能仍然没变,加密用户文件然后要赎金解密。然而,Talos发现了一些新的特性。比如加密算法变了,而且CryptoWall4加入了一项新的技术来禁用并删除了Windows所有的自动备份机制,没有外部的备份想自行恢复文件基本不可能了。

我们还发现CryptoWall4用了一些没有公开的API来获得入侵主机的本地语言设置。在后面的文章里,会更详细地阐述Talos发现的CryptoWall的新特性。

对于有经验的读者,我们建议您继续读下午。我们强烈建议用户和企业遵循安全规范,而且采用多层次的检测手段来规避风险。我们对新版本CryptoWall的深入分析,给了我们保护用户和确定更好的检测方案的技术支持。最后,针对FBI声明说的:用户没办法了还是支付赎金吧。Talos强烈建议用户们不要支付赎金,因为这样会直接让这项恶意行动受益。

0x01 感染

CryptoWall的经营者用网络钓鱼和drive-by-download来将他们的恶意程序传播给用户。一旦CryptoWall4被成功运行,就会从C2服务去下载一个RSA公钥。然后所有的文件都被暂时地先被AES秘钥加密,之后就会被下载下来的RSA公钥加密。然后会用三种不同的方式告诉用户,你被加密了。第一种是一个文本文件,第二种是一张.png的图,第三种是一个HTML文档。所有的都会自动地从受害者的桌面打开。如下面所示。

威胁聚焦:CRYPTOWALL4 FigureA.1

威胁聚焦:CRYPTOWALL4 FigureA.2

威胁聚焦:CRYPTOWALL4 FigureA.3

威胁聚焦:CRYPTOWALL4 FigureA.4

威胁聚焦:CRYPTOWALL4 FigureA.5

一个有趣的发现是,一旦CryptoWall4不能从C2 server检索到RSA公钥,它就会不停地循环来下载公钥。只要公钥得不到,CryptoWall就不会破坏受害者的电脑。Talos同样观察到,这个样本也有一些另外的安全检查,比如如果受害者机器上的语言不受支持,就会自动终止感染进程。下面几种语言设置不会被感染:

Russian, Kazakh, Ukrainian, Uzbek, Belarusian, Azeri, Armenian, Kyrgyz, Georgian.

很明显,攻击者想要排除一些地区,使之免受感染。

感染进程就如下图描述的一样:

威胁聚焦:CRYPTOWALL4 Figure B

从上图所示的 ”Delete all shadow copies“开始,CrytoWall4已经注入到了svchost进程。注入到这个进程是为了在受害者机器上获得更高的权限,以此来绕过UAC。有权限了才能静默地删除所有的系统备份,不然会有UAC提示用户来处理。

下图C描述的是其网络通讯,用的是HTTP协议,但是对payload进行了加密。如图D和图E

威胁聚焦:CRYPTOWALL4 Figure C

威胁聚焦:CRYPTOWALL4 Figure D

威胁聚焦:CRYPTOWALL4 Figure E

CryptoWall4用了一个新的文件名生成算法来给加密后的文件命名:

  1. 扫描磁盘驱动器,排除在白名单里的磁盘驱动器
  2. 从目录下得到原始文件,然后跳过白名单里的文件名和扩展名
  3. 产生随机的文件名长度(5-10)
  4. 由随机的‘a-z’来构建文件名,长度是3得到的。(先得到0-1000的随机数,然后对26取模,再变成‘a-z’的字母)
  5. 文件名字符串以Null结尾
  6. size/2和size中间取一个随机数num1。(size为文件名长度)
  7. 在1个num1中去一个随机数num2(num2决定接下来往文件名字符串里插入随机数字的个数)
  8. 获得一个随机的 0-9(char类型),插入到文件名的随机位置
  9. 重复step8,num2次
  10. 用同样的算法来生成扩展名,不过长度是2-5
  11. 文件名后加上扩展名

CryptoWall4用的CRC32校验算法来排除一些目录,文件名和扩展名。下面是一些白名单:

Extensions:

exe, dll, pif, scr, sys, msi, msp, com, hta, cpl, msc, bat, cmd, scf

Directories:

windows, temp, cache, sample ,pictures, default pictures, Sample Music, program files, program files (x86), games, sample videos, user account pictures, packages

Files:

help_your_files.txt, help_your_files.html, help_your_files.png, thumbs.db

完整的白名单在文章末尾Appendix A.

这些在白名单里的目录,文件名以及扩展名都是为了保证操作系统的稳定性。这意味着受害者可以继续用他们的电脑来支付赎金。任何被感染的用户都应该记住,下次开机,加密又会自动运行,然后把新创建的任何文件都加密一次。

生成新文件的文件名后,它的加密算法如图F所示:这也清楚地告诉我们,在CryptoWall4将文件加密之后,如果没有RSA私钥来还原AES秘钥,要还原文件,基本不可能。然而私钥只存在于攻击者的电脑上,而且不会传给用户的电脑。换句话说,用户不支付赎金获得私钥,就没办法还原文件。用户应该备份好自己的重要文件,才能保证遭受这种攻击后,不用支付赎金就能将其恢复。

威胁聚焦:CRYPTOWALL4 Figure F

0x02 主体

病毒程序主体被压缩,且被不同的壳保护了,壳里面有很多垃圾代码,无用的API调用,还有代码混淆技巧,比如用调用随机的API,参数还很奇怪。

威胁聚焦:CRYPTOWALL4 Figure G

第二层保护用的一种交错跳转形式的代码:

INSTRUCTION 1 INSTRUCTION 2 JNO nextSteo 

0x03 解压缩代码

主要的代码和之前版本的CryptoWall是非常相似的:首先构造自己的IAT,获得需要的系统调用并且创建自己的主事件对象来管理进程同步(名字是workstation的MD5)。这个事件有两个目标:在执行期间,阻止其余的CryptoWall4进程运行而且为感染有关的不同的进程实现同步。这写代码注入到一个新命名为“explorer.exe”进程里。注入到目标进程里的实际代码,用了这两种技术中的一种:

  1. ZwCreateSection和ZwMapViewOfSection
  2. ZwAllocateVirtualMemory , ZwWriteVirtualMemory 和 ZwProtectVirtualMemory

最后,代码被重新安置。用了两种不同的技术来进行注入:

  1. 用ZwQueueApcThread这个内部API来将APC队列注入到目标进程
  2. 经典的CreateRemoteThread方法

最终注入到新的 宿主“explorer.exr”进程里的代码,会被执行然后用CryptoWall4感染系统并且实现持续感染。程序主体被复制进%APPDATA%目录,然后在用户根目录的"Run"键值后添加进去,实现开机自启。

病毒程序会用一种现在还没被发现方法来禁止所有的系统还原点,和windows备份。首先调用SRRemoveRestorePoint,然后参数是0-1000,直到方法返回 ERROR_INVALID_DATA 。它将注册表 HKLM/Software/Microsoft/Windows Nt/SystemRestore 路径下的“DisableSR”键值设置为1,这样就完全禁止了系统还原。最后它开始执行删除存储备份的标准命令:

#!bash vssadmin.exe Delete Shadows /All /Quiet 

接下来的流程在 “svchost.exe”进程里面。代码会重建IAT表,创建另一个事件(只在“svchost.ext”里使用),然后去形成并且打开自己的配置文件。这一步经常会失败,因为配置文件这时候还没有存在。dropper打开并解压位于自己内部的C&C URL列表(用的LZ压缩算法)。最后它尝试发广播去连接其中的某个 C&C server。

可以在IOC段找到恶意程序使用的C&C server的列表。

CryptoWall4的网络包比较特别,是下面这样的:

| request Id | crypt7 | workstation MD5 [|subRequest Id 1|subRequest 1 Data| … ]

在写这篇文章的时候,我们成功地了分出了五种不同的类型的包(request ID不同)。

1,3  --- Announcement packet --用来告诉C&C server有新的机器被感染了 7 --- Multi purpose packets。第一个sub-request ID用来区分不同类型的包:    1 - Public key request  -用来向 C&C server请求一个新的公钥,为之后的加密做准备    2 -  End announcement packet 用来告诉服务器感染结束了。另一个sub-request ID代表感染如何结束的详细信息:    1  - Success   2, 3 - Unsupported OS language packet - Exit  

这些包用标准的HTTPS协议送到网络上,但是在这之前就被加密了。加密算法很普通,用一个随机的字符串作为key,然后形成这样格式的数据流:

| Letter |=| encryption Key in Hex | encrypted stream |

例如:s=6975376e7a9b0fd24886fbd0c0de32d3ab4dd97174462ca3b06af16a1c840ae893eddacafbd93e56847c23a41352d4f45fc75468e4408

在广播进程成功连接到 C&C server后,就会请求获得公钥。这里有一个CryptoWall4的做的不足的地方:如果防火墙或者IPS足够好,能够拦截CryptoWall4的包,感染就进行不下去了。RSA-2048公钥请求包的request ID是7。C&C server返回的包这样子构成:

  1. 付款URL的列表
  2. base64加密的RSA-2048公钥
  3. base64加密的PNG图片(图片由系统的语言设置决定)

威胁聚焦:CRYPTOWALL4 Figure H.1

威胁聚焦:CRYPTOWALL4 Figure H.2

威胁聚焦:CRYPTOWALL4 Figure H.3

公钥用CryptStringToBinary API来解密。解密后的数据被存在一个全局变量中。HTML和text文件(用LZ 压缩算法压缩)由dropper释放出来,最终创建好配置文件并被加密,存储在 C:/Users/[Username]/AppData/Roaming/[Random 8 digits] 中。

CryptoWall4会确认配置文件的完整性,包含执行恶意代码所需要的全部信息。还会保证就算被中断了,恶意程序还是能继续加密文件。这个文件有很多连续的区段,开头是一个DWORD的值,来指定该区段的大小。

CryptoWall4在配置文件里,存储如下的信息:

  • 收到的公钥的二进制流数据
  • 与用户使用语言相符的HTML页面
  • 与用户使用语言相符的text文件
  • 与用户使用语言相符的PNG图片 (就是要让受害者看得懂)

文件加密进程完成后,最后三个文件会被写到感染者机器的所有目录下。

配置文件最终被压缩(LZ压缩算法,RtlCompressBuffer API,参数是2 COMPRESSION_FORMAT_LZNT1),然后为写入磁盘中。

一切顺利的话,主线程会被创建,之前的线程被终止(RtlExitUserThread)

0x04 主线程

主线程从导入公钥开始,这会把加密的公钥的二进制的数据解析成能被Windows Crypto APIs识别的数据结构。CryptoWall4用的CryptDecodeObjectEx API来解析加密的公钥。这之后,二进制数据被转化为一个 CERT_PUBLIC_KEY_INFO 结构体。最后,新的数据结构被导入到Crypto APIs中,用的函数是CryptImportPublicKeyInfo,会返回一个xx句柄。然后会计算公钥的MD5,这一步非常重要,因为它会被用来检查受害者的文件是否已经被加密。

这之后,真正的加密进程启动。对每个逻辑分区,会有下面的检查:

#!cpp LPWSTR pngFilePath = new TCHAR[MAX_PATH]; // This produces something like "C:/HELP_YOUR_FILES.PNG" ComposePngPath(driveName, "HELP_YOUR_FILES.PNG", pngFilePath, MAX_PATH); if (!FileExists(pngFilePath) == TRUE) {  // Proceed with the encryption  // … … … } 

一般来说,如果磁盘的根目录下含有 HELP_YOUR_FILES.PNG 文件,这块磁盘会被跳过。我们不知道这是一个bug还是它故意这么做的。对每个过滤掉的磁盘,一个新的加密线程会被启动(线程主函数的参数是一个小的结构体,一部分是公钥,一部分是磁盘名字符串的指针)

主线程会等待所有的加密进程完成。然后把那三个含有解密指示的文件放在两个位置:一是开始菜单的启动目录,而是桌面。

最后,一个end announcement包会被创建并发给C&C server。配置文件被删除,进程被终止(用的ZwTerminateProc)

威胁聚焦:CRYPTOWALL4 Figure I

0x05 加密线程

加密线程有两个主要任务:首先它调用“DoFilesEncryption”将所有白名单之外的文件加密,最后它将 HELP_YOUR_FILES.PNG 写到根目录里。

DoFileEncryption会遍历目标磁盘目录下所有的文件夹和文件。

遇到子目录,会检查目录名字,进行CRC32检验,看是否在白名单里(这样,“windows”,“system32”,“temp”这样的文件夹被过滤掉)。而且检查 HELP_YOUR_FILES.PNG 是否存在,如果不存在,就继续调用DoFileEncryption,参数是当前的目录。

对文件的检查做了两次:扩展名和文件名。没有在白名单里面的,会调用EncryptFile来进行加密。

“EncryptFile”函数,是用来将目标文件加密的。“IsFileAlreadyEncrypted"函数会检查目标文件是否已经被加密:读取最开始的16字节,然后和公钥的MD5值作比较。

这个时候,恶意程序会生成随机的文件名和扩展名。下面是算法:(用的RtlRandomEx API获得每一个可打印字符)

#!cpp // Generate a random value DWORD GenerateRandValue(int min, int max) {     if (min == max) return max;     // Get the random value     DWORD dwRandValue = RtlRandomEx(&g_qwStartTime.LowPart);     DWORD dwDelta = max - min + 1;     dwRandValue = (dwRandValue % dwDelta) + min;     return dwRandValue; } // Generate a Random unicode string LPWSTR GenerateRandomUString(int minSize, int maxSize) {     DWORD dwStringSize = 0;             // Generated string size     DWORD dwNumOfDigits = 0;            // Number of number letters inside the string     LPWSTR lpRandString = NULL;         // Random unicode string     // Generate the string size, and alloc buffer     dwStringSize = GenerateRandValue(minSize, maxSize);     lpRandString = new TCHAR[dwStringSize+1];     for (int i = 0; i < (int)dwStringSize; i++) {           DWORD dwLetter = 0;                       // Generated letter           dwLetter = GenerateRandValue(0, 1000);           dwLetter = (dwLetter % 26) + (DWORD)'a';           lpRandString[i] = (TCHAR)dwLetter;     }     // NULL-terminate the string     lpRandString[dwStringSize] = 0;     // Now insert the digits inside the string     DWORD dwUpperHalf = GenerateRandValue(dwStringSize / 2, dwStringSize);     dwNumOfDigits = GenerateRandValue(1, dwUpperHalf);     for (int i = 0; i < (int)dwNumOfDigits; i++) {           DWORD dwValue = 0, dwPos = 0;       // Generated value and position           dwValue = GenerateRandValue(0, 9) + (DWORD)'0';           dwPos = GenerateRandValue(0, dwStringSize-1);           lpRandString[dwPos] = (TCHAR)dwValue;     }     return lpRandString; } // Generate a random file name starting from a file full path BOOLEAN GenerateRandomFileName(LPWSTR lpFileFullPath, LPWSTR * lppNewFileFullPath,  LPWSTR * lppOrgFileName) {     LPWSTR lpRandFileName = NULL;         // New random file name (without extension)     LPWSTR lpRandExt = NULL;              // New random file extension     LPWSTR lpNewFileName = NULL;          // The new file full name     DWORD dwSize = 0;                     // size of the new filename     // Check the arguments     if (!lpFileFullPath || !lppNewFileFullPath || !lppOrgFileName)           return FALSE;     // Generate the new file name (without extension)     lpRandFileName = GenerateRandomUString(5, 10);     // Generate the random file extension     lpRandExt = GenerateRandomUString(2,5);     // Combine the new file name and extension and generate the final new file path     // ....     dwSize = wcslen(lpRandFileName) + wcslen(lpRandExt) + 1;     lpNewFileName = new TCHAR[dwSize+1];     swprintf_s(lpNewFileName, dwSize+1, L"%s.%s", lpRandFileName, lpRandExt);     // .... } 

新的文件被创建,一个新的AES-CBC 256 key也通过调用CryptGenKey和CryptExportKey生成。这个32位的key会用来加密整个文件。

这时CryptoWall4采取了一个技巧:讲生成的AES key用从C&C server得到的RSA-2048公钥加密,这样就生成了一个256位的key,而且只能被攻击者解密。

RSA公钥的MD5值会写到被加密的文件头部16字节。然后CryptoWall4写入256位的加密字串。原始文件的属性和大小被写入接下来的8字节。原始文件名被得到的AES密钥加密,然后和文件大小一起,被写入到新的加密文件中。

这之后,开始真正的文件内容加密。原始文件每次被读512kb,存到一个大的数据块里。每个数据库会被加密密钥进行AES-CBC 256加密。然后直接写入到新文件里(开头四字节是块的大小)

完成后,CryptoWall4占用的所有资源被释放。原始文件被删除,这个过程比较有趣,见下面代码:

#!cpp // Move the new encrypted file name in the old original position, replacing the old one  bRetVal = MoveFileEx(newEncFileName, lpOrgFileName, MOVEFILE_WRITE_THROUGH | MOVEFILE_REPLACE_EXISTING); if (!bRetVal) // Delete the old file in the standard manner:     DeleteFile(lpOrgFileName); else {     // Rename the original replaced file in the new random file name     bRetVal = MoveFileEx(lpOrgFileName, newEncFileName, MOVEFILE_REPLACE_EXISTING); } 

从伪代码看得出来,存储原始文件的磁盘区被特殊地重写了,这样能保证数据恢复起来非常困难。这是恶意程序的作者来保证高付款率的新奇有趣的方法。减少数据恢复的可能,这样他们更好赚钱。下图是加密后的文件的结构:

威胁聚焦:CRYPTOWALL4 Figure J

0x06 总结

这篇分析里,我们细致分析了CryptoWall4。恶意程序没有任何创新性的技术,但是还是有几个技术亮点。缺陷是感染进程需要和C2 server进行交互。如果防火墙或者IPS能捕获它用来交互的数据包,感染进程就进行不下去了,因为它需要得到公钥才能加密受害者的文件。然而,一旦CryptoWall4加密了受害者的文件,不给攻击者支付赎金,就没有办法恢复私钥或者是解密文件。因为受害者的机器上得不到RSA私钥。私钥只存在于攻击者手里。

正如我们的分析展示的,CryptoWall的开发者不断在更新这款恶意软件,保证它对用户仍然是有效的。在威胁之上,企业需要认识到,攻击者会不断地改进这款恶意软件。用多层次的自我保护方法,能帮助企业监测到CryptoWall,阻止其威胁。Talos也会继续跟进CryptoWall的研究,找到更好的监测方法,然后为用户建立更好的防护体系。沃恩强烈建议用户和企业遵循安全规范,比如及时安装系统补丁,收到未知的三方信息的时候要谨慎,还要保证有一个给力的备份。这些措施能减少这些恶意程序的威胁,而且被攻击了也能有应急措施。

0x07 防护

威胁聚焦:CRYPTOWALL4

  • 高等级防护(AMP)能很好地阻止这类恶意程序的执行。
  • CWS或者WSA网络扫描能排除攻击者用来进行钓鱼等攻击的恶意网站。
  • IPS和NGFW保持最新来提供网络安全保护,并且 能检测恶意软件的行为。
  • ESA能截获带有恶意行为的email

0x08 others

IOC DETAILS

这里可以下载IOCs http://blogs.cisco.com/wp-content/uploads/cryptowall-4-iocs.txt

样本:

3a73bb154506d8a9a3f4f658bac9a8b38d7590d296496e843503323d5f9b7801 

相似样本:

2d04d2a43e1d5a6920a806d8086da9c47f90e1cd25aa99b95af182ee9e1960b3 bf352825a70685039401abde5daf1712fd968d6eee233ea72393cbc6faffe5a2 299b298b433d1cc130f699e2b5c2d1cb3c7e5eb6dd8a5c494a8c5022eafa9223 

威胁报告:

https://panacea.threatgrid.com/samples/d25f94dc4f2ac59e0428f54d685ead38

C2 URL 列表

abelindia.com/1LaXd8.php purposenowacademy.com/5_YQDI.php mycampusjuice.com/z9r0qh.php theGinGod.com/HS0ILJ.php yahoosupportaustralia.com/8gX7hN.php successafter60.com/iCqjno.php alltimefacts.com/EiFSId.php csscott.com/YuF59b.php smfinternational.com/eRs70a.php lexscheep.com/OIsSCj.php successafter60.com/r_kfhH.php posrednik-china.com/etdhIk.php ks0407.com/VoZQ_j.php stwholesaleinc.com/yL54uH.php ainahanaudoula.com/GH09Dp.php httthanglong.com/yzoLR7.php myshop.lk/6872VF.php parsimaj.com/60wEBT.php kingalter.com/uVRfPv.php shrisaisales.in/ZUQce4.php cjforudesigns.com/E8B2gt.php mabawamathare.org/WEAbCT.php manisidhu.in/zJE0fD.php adcconsulting.net/XEGeuI.php frc-pr.com/dA91lI.php localburialinsuranceinfo.com/zDJRc8.phpsmfinternational.com/AYNILr.php 

附录A

Excluded files CRC32 Checksums 8E87F076h = help_your_files.txt 0A73B295Ch = help_your_files.html 11A8ACA3h = help_your_files.png 88068F93h 775DBED4h 60479578h  7BD40679h = iconcache.db 48F43013h = thumbs.db 95ED794Ah 884F3F52h 7DAC63A1h 4208466h 0BA069E4Ch 0EC619E8Dh 9B0FD8B3h  Excluded extensions CRC32 Checksums  6B63B6F0h = exe 3DD3B336h = dll 0BB5EA5C1h = pif 592D276Fh = scr 9E07ED22h = sys 8F3272A8h = msi 0A45BDDC1h = no three letter ext 0B65F578Ah = no three letter ext 0EB59DA68h = msp 64B6C6E6h = com 0C863AEB6h = hta 0DEEBF8EEh = cpl 6FE79BB6h = msc 9F9C299Fh = bat 2F5C1CC0h = cmd 43F7F312h = scf  Excluded directories CRC32 Checksums 0E3E7859Bh = windows 0B5385CAh = temp 0ED4E242h 9608161Ch 41476BE7h = cache 0F5832EB4h 0D8601609h 1DF021B7h 0B91A5F78h = sample pictures 0A622138Ah = default pictures 3FF79651h = sample Music 62288CBBh = program files 224CD3A8h = program files (x86) 72D480B3h 0FF232B31h = games 0A33D086Ah = sample videos 78B7E09h = user account pictures 9BB5C0A7h = packages 24FA8EBDh 
正文到此结束
Loading...