摘要
摘要:CONTI是去年最活跃的勒索软件家族之一。其中一个臭名昭著的攻击发生在HSE医疗(https://threatpost.com/conti-ransomware-fail-costly/166263/),攻击者要求2000万美元的赎金。正如Cybereason在https://www.cybereason.com/blog/cybereason-vs.-conti-ransomware上提到的,Conti在地下论坛上被作为RaaS(勒索软件作为服务)出售,它已经被TrickBot团伙部署。其中一个主要的担忧是,勒索软件集团采用了双重勒索的方法:他们还从受害者那里窃取敏感数据,并要求赎金。
该恶意软件可以运行不同的参数,如“-p”,“-m”,“-size”,“-log”和“-nomutex”,并创建一个互斥锁“YUIOGHJKCVVBNMFGHJKTYQUWIETASKDHGZBDGSKL237782321344”,以确保在同一时间只有一个实例的勒索软件运行。该恶意软件使用wmic和COM对象删除计算机上的所有卷影副本。勒索软件的目标是系统上所有有效的驱动器和可以访问的SMB共享。使用自定义ChaCha8实现对文件进行加密,该实现使用随机生成的密钥(32字节)和nonces(8字节),这些密钥由硬编码的公共RSA密钥加密。加密非常快,因为示例使用多个线程加密文件,并避免完全加密较大的文件(>5MB)。
火绒剑监控行为
可以看到是一些注册表的操作,最后带参数执行了一个WerFault.exe以及自身的删除操作。但是明显不太对,猜测是不是有反检测技术,去微步沙箱看,发现确实是这样。我们IDA分析看看能不能把反检测部分给nop掉。(WerFault.exe是Windows自带的主要用于错误报告的程序。但是网上没找到这个参数是什么意思,沙箱分析该进程行为主要是枚举进程和提权)
IDA静态分析
先看导入函数,有一个IsDebuggerPresent
(但是我在OD下了断点并没有触发)。
OD动态
我们根据IDA静态地址推出函数入口地址00358470,下断点,直接运行到这里。(进程有很多这样的混淆字符串的操作)
该进程通过调用GetCommandLineW
函数来获取命令行字符串
CommandLineToArgvW
(00357E20中被调用)被用来获取一个指向命令行参数的指针数组(类似于C中的argv和argc值)
调试可以发现依次会有”-p”,”-m”,”-log”,”-size”,”-nomutex”,它解析程序使用的参数,并将它们与列表进行比较
-p directory:使用单个线程加密目录
-m local:使用多个线程加密可用驱动器
-m net:使用多个线程加密网络共享
-m all:用多个线程加密可用驱动器和网络共享
-m backups:未实现(可能加密备份目录?)
-size chunk:加密大文件的块模式
-log logfile:日志记录模式(在日志文件中记录不同的活动)
-nomutex:没有创建互斥对象
下图是恶意软件混淆大多数堆栈字符串方面的部分,用于解密它们的解密算法每次都在改变(操作和常量有一些变化)。
这里创建了一个互斥锁,保证只有一个实例在运行(如果它使用“-nomutex”参数运行,则不会创建互斥锁)。使用上面的算法解密互斥对象的名称。重要的API是在运行时导入的,而不是将它们全部包含在IAT(导入地址表)中。有一个哈希算法003447C0
用于确定应该导入哪些函数(第一个参数是哈希值,第二个参数表示偏移量)
GetNativeSystemInfo
用于获取当前系统的信息,如下图所示
恶意进程会创建2个(处理器的数量)处理加密的新线程(执行了两次,后面细说)。
CreateToolhelp32Snapshot
用于检索所有进程的快照(0x2 = TH32CS_SNAPPROCESS),紧接着该二进制文件通过调用Process32FirstW
和Process32NextW
例程枚举系统上的进程。
恶意软件还在寻找“explorer.exe”进程,并将其进程ID保存在缓冲区(检索进程以及寻找explorer.exe都是在0035BE90实现的)
紧接着下一个函数中,CoInitializeEx例程用于在当前线程上初始化COM库。
CoInitializeSecurity用于注册和设置进程的默认安全值(0x3 = RPC_C_IMP_LEVEL_IMPERSONATE):
该恶意软件使用COM对象和wmic删除所有卷的影子副本。它调用CoCreateInstance
用CLSID {dc12a687-737f-11cf-884d-00aa004b2e24}(COM对象的类标识符)创建IWbemLocator
对象:
使用相同的函数,用CLSID {44aca674-e8fc-11d0-a07c-00c04fb68820}创建一个新的IWbemContext
接口
使用ConnectServer
函数连接到本地的” ROOT\CIMV2 “命名空间,并获取一个指向IWbemServices
对象的指针
CoSetProxyBlanket
设置用于在代理上调用的认证信息(0xA = RPC_C_AUTHN_WINNT - NTLMSSP, 0x3 = RPC_C_AUTHN_LEVEL_CALL和0x3 = RPC_C_IMP_LEVEL_IMPERSONATE)
勒索软件通过执行以下查询SELECT * FROM Win32_ShadowCopy
获得所有影子副本的枚举数
下面使用自定义算法解密的字符串将用于删除系统上的所有影子副本
Wow64DisableWow64FsRedirection
用于禁用当前线程的文件系统重定向
该恶意软件会创建一个新进程来删除指定ID对应的影子副本,如下所示
当前线程的文件系统重定向通过调用Wow64RevertWow64FsRedirection
来恢复
系统上的所有有效驱动器都是恶意软件的目标,它使用GetLogicalDriveStringsW
来检索它们,这里就两个,分别是C:\和D:\
WSAStartup
例程启动当前进程对Winsock DLL的使用,如下图.
通过调用WSASocketW
(0x2 = AF_INET, 0x1 = SOCK_STREAM, 0x6 = IPPROTO_TCP)创建一个新的套接字
WSAIoctl
被用来检索一个指向相关服务提供商支持的扩展函数的指针(0xc8000006 = SIO_GET_EXTENSION_FUNCTION_POINTER)
通过调用gethostname
函数来提取本地计算机的标准主机名
本地机器的本地IP地址是通过调用gethostbyname例程来获取的
CreateIoCompletionPort
被用来创建一个I/O(输入/输出)完成端口,它没有与文件句柄相关联(0xffffffff = INVALID_HANDLE_VALUE)
从本地机器提取ARP表项,并以MIB_IPNETTABLE结构返回信息
十六进制格式的IP地址从每个条目转换成ASCII字符串(点分十进制格式的IP地址)
将IP地址与以下字符串进行比较:” 172.”、“192.168.”、“10.”和“169”。下面是一个这样的两个比较(就不一一放图了)
通过调用CreateThread
创建了2个新的线程
恶意软件将I/O完成包发送到前面创建的I/O完成端口
线程1 sub_0035AF90
这一部分线程主要完成网络连接等操作。
发送完数据包后会执行waitForSingalObject
函数,此时先到线程sub_0035AF90。CreateTimerQueue
函数用于为计时器(指定在特定时间调用回调函数的对象)创建队列。
线程通信是使用由主线程创建的I/O完成端口完成的。GetQueuedCompletionStatus函数用于接收由主线程发送的缓冲区(对应前面那个函数)。
线程通过调用WSASocketW
例程(0x2 = AF_INET, 0x1 = SOCK_STREAM, 0x6 = IPPROTO_TCP和0x1 = WSA_FLAG_OVERLAPPED)创建一个新的套接字。
bind
将本地地址与新创建的套接字关联起来
CreateIoCompletionPort
函数将之前创建的TCP套接字与现有的I/O完成端口关联起来(它允许进程接收涉及到套接字句柄的I/O操作完成的通知)。
使用ntohs
例程将0x1bd(445)从网络字节顺序(大端序)转换为主机字节顺序(小端序)
该进程试图连接端口445(192.168.10.x和192.168.164.x),通过LPFN_CONNECTEX
回调函数(这里我没有看出来)
CreateTimerQueueTimer
用于创建一个计时器队列计时器。基本上,当计时器过期时(在我们的例子中0x7530 = 30秒),就会调用回调函数(0x010BAF60)
Process Monitor抓取到的网络行为
setsockopt
用于设置socket的SO_UPDATE_CONNECT_CONTEXT选项(0xffff = SOL_SOCKET, 0x7010 = SO_UPDATE_CONNECT_CONTEXT)(调快了一步…没截到)
为了检查连接是否成功,恶意软件调用getsockopt
函数,参数为0x700c = SO_CONNECT_TIME
线程2 sub_0035C7D0
这个线程主要实现加密
使用CryptAcquireContextA
获取Microsoft RSA和AES加密提供程序的句柄,如下所示
CryptImportKey
用于导入RSA公钥
该进程在它加密的每个目录中创建勒索通知
以下4字节常量表明加密算法是ChaCha8(主要还是看网上有介绍,这里有一篇论文)
WriteFile
写进去
该恶意软件使用FindFirstFileW
和FindNextFileW
枚举目标目录中的文件
调用PathIsDirectoryW
来检查文件路径是否为有效目录
下面的扩展名/文件被恶意软件跳过(“.LSNWX”是加密文件的扩展)
CryptGenRandom
生成32(0x20)个随机字节,将用作ChaCha8密钥
CryptGenRandom
生成8(0x8)个随机字节,将用作ChaCha8 nonce(只能被使用一次的随机数)
使用RSA公钥对ChaCha8密钥和nonce进行加密,如图所示
CreateFileW
函数用于打开将要加密的文件
将文件扩展名与多个目标扩展名的列表进行比较(整个列表很长就不一一贴了)
需要指出的是,如果文件扩展名不属于这些列表,这并不意味着该文件不会被加密。例如,作为例子的txt文件将被勒索软件加密,然而,它遵循不同的执行流程,将在几段中详细介绍。加密后的ChaCha8密钥和nonce是加密文件的一部分,如下所示
文件扩展名为”.LSNWX”,此时加密活动完成
网上博客分析说文件大小不同,加密的结果也不一样,主要分为小于1MB的,1MB到5MB的,大于5MB的。
线程2 sub_0035A880
恶意进程检索有关成功访问的IP上的SMB共享的信息,如下图所示(在这里是虚拟机本地IP地址进行调试),后面直接没有调用了,猜测估计是因为IP没访问成功(因为我后面把SMB打开了也没成功。
这个线程就是执行前面提到的参数命令。