Conti ransomware source code investigation - part 2.
﷽
Hello, cybersecurity enthusiasts and white hackers!
This post is the second part of my own Conti ransomware source code investigation.
In the last part, I wrote about encryption/hashing methods and bypassing AV-engines. Today I will consider network connections and filesystem and some identified IoCs.
network connections
First of all, let’s go back a little to the logic of the encryptor:
As you can see when the encryption mode is ALL_ENCRYPT
or NETWORK_ENCRYPT
, the malware retrieves info about network.
Let’s go to definition of StartScan
:
Let’s go to deep into logic of network_connections.
GetCurrentIpAddress
is just get info about current IP address:
Function GetSubnets
uses GetIpNetTable
API which is called to restore the ARP table of the infected system. For earch entry the specified IPv4 addresses are checked against the following masks:
If the current ARP matches of this masks (172.*, 192.168.*, 10.*, 169.*
) the subnet is extracted and added to the subnet’s queue:
Function ScanHosts
tries a connection to IPv4 on the SMB port (445) using the TCP protocol:
If connection is successfull, saves the valid IP’s via AddHost
:
in a queue:
And what about HostHandler
:
and PortScanHandler
:
HostHandler
waits for some valid IP in the IP’s queue and for each IP enum the shares using the NetShareEnum
API:
And PortScanHandler
(1) repeat the scan via ScanHosts
(2) each 30
sec. (3):
So, what happens when calls network_scanner::StartScan
?
- Add
172.*, 192.168.*, 10.*, 169.*
subnet addresses to queue. - Create two threads.
- First thread via
HostHandler
enum the shares. - Second thread via
PortScanHandler
tries to connectSMB 445
port, for earh successfully connection, saves valid IPs and scan every30
sec:
Concluding the execution, the WaitForSingleObject
API is invoked on each thread to wait for the completion of operations before closing the main process and CloseHandle
for cleanup:
process killer
The logic of the prockiller.cpp
is simple. It enum through all processes and if it’s not equal to explorer.exe
then adds it’s PID to the queue:
filesystem
In the filesystem
module there is a function filesystem::EnumirateDrives
which, as the name implies, scan drives:
As you can see it uses GetLogicalDriveStringsW
API.
The logic of this function is used in the final enumeration during encryption. The malware uses a whitelist for both directories and files to avoid the encryption of unnecessary data. The following directories names and file names are avoided during the enumeration process:
yara rules
Let’s go to upload locker.exe
to VirusTotal:
57 of 69 AV engines detect this sample as malware
Yara rule for Conti:
rule Conti
{
meta:
author = "kevoreilly"
description = "Conti Ransomware"
cape_type = "Conti Payload"
strings:
$crypto1 = {8A 07 8D 7F 01 0F B6 C0 B9 ?? 00 00 00 2B C8 6B C1 ?? 99 F7 FE 8D [2] 99 F7 FE 88 ?? FF 83 EB 01 75 DD}
$website1 = "https://contirecovery.info" ascii wide
$website2 = "https://contirecovery.best" ascii wide
condition:
uint16(0) == 0x5A4D and any of them
}
I hope this post spreads awareness to the blue teamers of this interesting malware techniques, and adds a weapon to the red teamers arsenal.
first part
WSAStartup
WSAAdressToStringA
CreateToolhelp32Snapshot
CloseHandle
StrStrIW
CreateThread
WaitForSingleObject
NetShareEnum
GetLogicalDriveStringsW
This is a practical case for educational purposes only.
Thanks for your time happy hacking and good bye!
PS. All drawings and screenshots are mine