Conti Ransomware V2 Source Code Leak
Analysis of the leaked Conti Ransomware source code
Overview
Some backstory here, a twitter account @contileaks began posting leaked chat logs and source code from the Conti ransomware group. Initially they posted a password protected archive of the Conti v2 source code. Later posted an archive of the source code with the locker cpp files removed and no password. This was apparently an attempt to prevent others from compiling the source code and using it. The release of the second archive allowed a cryptographic attack on the password protected archive and the release of the full source code.
Builder
The ransomware project comes with a builder that can be used to customize the compiled ransowmare binary (and decryptor). It basically runs a string replace on the binary to insert custom data like the RSA key and the decryption note. Some examples of the replaced strings are below.
__publickey__
__privatekey__
__DECRYPT_NOTE__
Obfuscation
They are using a macro based on ADVObfuscator to obfuscate strings inline in the code.
#define OBFW(str)((const wchar_t*)MetaBuffer<std::get<MetaRandom2<__COUNTER__, 30>::value>(PrimeNumbers), \
MetaRandom2<__COUNTER__, 126>::value, \
std::make_index_sequence<sizeof(str)>>((const unsigned char*)str).decrypt())
API Hashing
Hashing: MurmurHash2A contant=0x5bd1e995
They pre-calculate the API hashes and define each API wrapper in api.cpp
then call the API definitions in the code. This doesn't seem like the most efficient way to do API hashing.
Example.
inline DWORD WINAPI pGetProcessId(
HANDLE Process
)
{
DWORD(WINAPI * pFunction)(HANDLE);
pFunction = (DWORD(WINAPI*)(HANDLE))api::GetProcAddressEx2(NULL, KERNEL32_MODULE_ID, 0x31d910df, 9);//GetProcAddress(hKernel32, OBFA("GetProcessId"));
return pFunction(Process);
}
Encryption
Encryption Modes (File To Encrypt)
enum EncryptModes {
ALL_ENCRYPT = 10,
LOCAL_ENCRYPT = 11,
NETWORK_ENCRYPT = 12,
BACKUPS_ENCRYPT = 13
};
Encrypt Modes (File Encryption)
Three modes of encryption based on file type and size.
enum ENCRYPT_MODES {
FULL_ENCRYPT = 0x24,
PARTLY_ENCRYPT = 0x25,
HEADER_ENCRYPT = 0x26
};
- DB files get full encrypt
- VM files get partial encrypt
- Under 1M is full encrypt
- Between 1M - 5M gets header encrypt
- Over 5M is partial encrypt
Partial Encrypt Mode
The partial encrypt mode can encrypt a file by percent, either 20% or 50%. This translates into a "step" size of data blocks that are encrypted in the file.
Delete Shadow Copies
Gain access to WMI via COM.
// Step 1: --------------------------------------------------
// Initialize COM. ------------------------------------------
// Step 2: --------------------------------------------------
// Set general COM security levels --------------------------
// Step 3: ---------------------------------------------------
// Obtain the initial locator to WMI -------------------------
// Step 4: -----------------------------------------------------
// Connect to WMI through the IWbemLocator::ConnectServer method
// Connect to the root\cimv2 namespace with
// the current user and obtain pointer pSvc
// to make IWbemServices calls.
// Step 5: --------------------------------------------------
// Set security levels on the proxy -------------------------
// Step 6: --------------------------------------------------
// Use the IWbemServices pointer to make requests of WMI ----
// For example, get the name of the operating system
// Step 7: -------------------------------------------------
// Get the data from the query in step 6 -------------------
// Get the value of the Name property
// Cleanup
// ========
Copy-paste from MSDN WMI
Then use WMI to delete shadows
"cmd.exe /c C:\\Windows\\System32\\wbem\\WMIC.exe shadowcopy where \"ID='%s'\" delete
KIll File Owner To Free File For Encryption
They use the RestartManager to enumerate processes with a handle to the file they are trying to encrypt. Then they can kill the process.
Crypto
Using the Windows crypto APIs to generate a chacha key CryptGenRandom
then they use statically linked chcha algorithm to encrypt files then RSA encrypt the generated key.
The chacha library is a copy-paste from this chacha-merged.c
Also ref wiki article on chacha.
/*
chacha-merged.c version 20080118
D. J. Bernstein
Public domain.
*/
Encrypted File Structure
The file is encrypted based on the encryption mode. The RSA encrypted chacha key is then appended to the encrypted file. Then a buffer containing the encryption mode constant and the data percent value is written to the file. This forms a footer that can be used by the decryptor to decrypt the file.
-------
encrypted data
-------
RSA encrypted chacha key
-------
byte encryption mode
-------
byte percent value
File Share Scanning
Scan local subnets for hosts, then scan hosts for shares.
Directory Blacklist
OBFW(L"tmp"),
OBFW(L"winnt"),
OBFW(L"temp"),
OBFW(L"thumb"),
OBFW(L"$Recycle.Bin"),
OBFW(L"$RECYCLE.BIN"),
OBFW(L"System Volume Information"),
OBFW(L"Boot"),
OBFW(L"Windows"),
OBFW(L"Trend Micro")
File Extension Blacklist
OBFW(L".exe"),
OBFW(L".dll"),
OBFW(L".lnk"),
OBFW(L".sys"),
OBFW(L".msi"),
OBFW(L"R3ADM3.txt"),
OBFW(L"CONTI_LOG.txt")
Readme File
The file name is hardcoded in the binary R3ADM3.txt
.
Log File
Logging is an option specified as a command parameter. The log file path is hard coded as C:\\CONTI_LOG.txt
.