threat-analysis
Back in Black: FIN7’s Flagship Carbanak Malware Reappears After Long Hiatus
Background
DeepSeas has identified new samples of the Russian, financially motivated cyber criminal group FIN7’s former flagship backdoor malware, Carbanak. The malware, which has not been seen for several years, reemerged in the last few weeks as a new variant that is being uploaded to public malware repositories.
In the past, Carbanak has primarily been used by the APT group FIN7 for espionage and data exfiltration. FIN7 is known to target financial organizations, and it has used Carbanak in previous campaigns to conduct financial fraud and theft. In May 2019, the source code for Carbanak was reportedly leaked. However, based on threat hunting and retroactive analysis of submissions to public malware repositories, this leak did not lead to widespread adoption by low-skilled criminals.
Present Day
DeepSeas has not observed any detections in public malware repositories in the past three years. However, a recent surge in public submissions to public malware repositories is cause for concern. On VirusTotal alone, eight new examples of Carbanak have been uploaded, with the earliest being in late July 2023. Prior to this date, the earliest example of Carbanak available on VirusTotal was in March 2020.
DeepSeas cannot directly attribute the new malware samples to the FIN7 group. It is unclear whether this is the work of FIN7, another criminal group, or information security professionals testing the codebase. However, DeepSeas has observed several key changes in the malware code which make it likely that it is being used with malicious intent. DeepSeas has developed and deployed the following detection logic to properly identify, classify, and block this threat.
Detection Logic
Below is a Yara rule created by DeepSeas to detect the string decoding and function hashing algorithms.
rule Production_Categorization_Malware_Carbanak_Decoding_Functions
{
meta:
impact = "100"
author = "DeepSeas"
description = "Carbanak API Hashing and String Decoding"
hash = "460842d20206c6e7709d28b0bb5d31b326f9af0596e9f76e3cfd017e939c9aee"
reference = ""
malpedia = "https://malpedia.caad.fkie.fraunhofer.de/details/win.carbanak"
strings:
/*
uint CalcHash( const byte* ptr, int c_ptr )
{
uint hash = 0;
if( ptr && c_ptr > 0 )
{
for( int i = 0; i < c_ptr; i++, ptr++ )
{
hash = (hash << 4) + *ptr;
unsigned t;
if( (t = hash & 0xf0000000) != 0)
hash = ((hash ^ (t >> 24)) & (0x0fffffff));
}
}
return hash;
}
*/
/*
0x18000e06c 4533c0 xor r8d, r8d
0x18000e06f 4885c9 test rcx, rcx ; arg1
0x18000e072 7431 je 0x18000e0a5
0x18000e074 83fa01 cmp edx, 1 ; 1 ; arg2
0x18000e077 7c2c jl 0x18000e0a5
0x18000e079 448bca mov r9d, edx ; arg2
0x18000e07c 0fb601 movzx eax, byte [rcx] ; arg1
0x18000e07f 41c1e004 shl r8d, 4
0x18000e083 4403c0 add r8d, eax
0x18000e086 418bc0 mov eax, r8d
0x18000e089 25000000f0 and eax, 0xf0000000
0x18000e08e 740d je 0x18000e09d
0x18000e090 c1e818 shr eax, 0x18
0x18000e093 4433c0 xor r8d, eax
0x18000e096 4181e0ffffff0f and r8d, 0xfffffff
0x18000e09d 48ffc1 inc rcx ; arg1
0x18000e0a0 49ffc9 dec r9
*/
$CalcHash_64 = {4533c0 4885c9 7??? 83fa01 7??? 448bca 0fb601 41c1e004 4403c0 418bc0 25000000f0 7??? c1e818 4433c0 4181e0ffffff0f 48ffc1 49ffc9}
/*
0x0040f3a7 33c9 xor ecx, ecx
0x0040f3a9 85f6 test esi, esi
0x0040f3ab 7427 je 0x40f3d4
0x0040f3ad 8b550c mov edx, dword [arg_8h]
0x0040f3b0 85d2 test edx, edx
0x0040f3b2 7e20 jle 0x40f3d4
0x0040f3b4 0fb606 movzx eax, byte [esi]
0x0040f3b7 c1e104 shl ecx, 4
0x0040f3ba 03c8 add ecx, eax
0x0040f3bc 8bc1 mov eax, ecx
0x0040f3be 25000000f0 and eax, 0xf0000000
0x0040f3c3 740b je 0x40f3d0
0x0040f3c5 c1e818 shr eax, 0x18
0x0040f3c8 33c8 xor ecx, eax
0x0040f3ca 81e1ffffff0f and ecx, 0xfffffff
0x0040f3d0 46 inc esi
0x0040f3d1 4a dec edx
*/
$CalcHash_32 = {33c9 85f6 7??? 8b550c 85d2 7??? 0fb606 c1e104 03c8 8bc1 25000000f0 7??? c1e818 33c8 81e1ffffff0f 46 4a}
/*
StringDecoded DECODE_STRING( const char* codeStr )
{
int len = Str::Len(codeStr) - CountStringOpcode;
if( len < 0 ) len = 0;
char* s = Str::Alloc(len + 1);
int lenBlock = len / CountStringOpcode;
int nb = 0;
int rb = 0;
int delta = 0;
int n = 0;
int i = 0;
while( n < len )
{
if( rb == 0 )
{
nb++;
if( nb <= CountStringOpcode )
{
delta = codeStr[i] - 'a';
i++;
rb = lenBlock;
}
else
rb = len - n;
}
if( rb > 0 )
{
rb--;
int c = codeStr[i];
int min, max;
if( c < 32 )
min = 1, max = 31;
else if( c < 128 )
min = 32, max = 127;
else
min = 128, max = 255;
c = Config::TableDecodeString[c];
c -= delta;
if( c < min ) c = max - min + c;
s[n++] = c;
i++;
}
}
s[n] = 0;
return StringDecoded(s);
}
*/
/*
0x1800019f5 480fbe03 movsx rax, byte [rbx]
0x1800019f9 ffc9 dec ecx
0x1800019fb 83f820 cmp eax, 0x20 ; 32
0x1800019fe 7d0b jge 0x180001a0b
0x180001a00 ba1f000000 mov edx, 0x1f ; 31
0x180001a05 448d4ae2 lea r9d, [rdx - 0x1e]
0x180001a09 eb1b jmp 0x180001a26
0x180001a0b 3d80000000 cmp eax, 0x80 ; 128
0x180001a10 7d0b jge 0x180001a1d
0x180001a12 ba7f000000 mov edx, 0x7f ; 127
0x180001a17 448d4aa1 lea r9d, [rdx - 0x5f]
0x180001a1b eb09 jmp 0x180001a26
0x180001a1d baff000000 mov edx, 0xff ; 255
0x180001a22 448d4a81 lea r9d, [rdx - 0x7f]
0x180001a26 4c8d05b3e40100 lea r8, data.18001fee0 ; 0x18001fee0
0x180001a2d 460fbe0400 movsx r8d, byte [rax + r8]
0x180001a32 442bc5 sub r8d, ebp
*/
$DECODE_STRING_64 = {480fbe03 ffc9 83f820 7??? ba1f000000 448d4ae2 ???? 3d80000000 7??? ba7f000000 448d4aa1 ???? baff000000 448d4a81 4c8d ?????????? 460fbe0400 442bc5}
/*
0x004029cd 0fbe06 movsx eax, byte [esi]
0x004029d0 49 dec ecx
0x004029d1 83f820 cmp eax, 0x20 ; 32
0x004029d4 7d07 jge 0x4029dd
0x004029d6 33db xor ebx, ebx
0x004029d8 43 inc ebx
0x004029d9 6a1f push 0x1f ; 31
0x004029db eb0c jmp 0x4029e9
0x004029dd 8b55e8 mov edx, dword [var_1ch]
0x004029e0 3bc2 cmp eax, edx
0x004029e2 7d08 jge 0x4029ec
0x004029e4 6a20 push 0x20 ; 32
0x004029e6 5b pop ebx
0x004029e7 6a7f push 0x7f ; 127
0x004029e9 5a pop edx
0x004029ea eb07 jmp 0x4029f3
0x004029ec 8bda mov ebx, edx
0x004029ee baff000000 mov edx, 0xff ; 255
0x004029f3 0fbe80f8434200 movsx eax, byte [eax + 0x4243f8]
0x004029fa 2b45f8 sub eax, dword [var_ch]
*/
$DECODE_STRING_32 = {0fbe06 49 83f820 7??? 33db 43 6a1f ???? 8b55e8 3bc2 7??? 6a20 5b 6a7f 5a ???? 8bda baff000000 0fbe????????00 }
condition:
any of them
}
Indicators of Compromise (IOCs)
Hashes | File Name |
MD5: cbda24f8ac22d68c0c3bfad37d0c2ed8SHA-1: 07fff967d4b10ebf6b6c40584a5ddb27d8ce288a
SHA-256: 59b9f82fd8e6f5aefbdd1c93d9e1d3012bbe843ddb958b1ca50c026b2217e25a |
59b9f82fd8e6f5aefbdd1c93d9e1d3012bbe843ddb958b1ca50c026b2217e25a.dll |
MD5: 091688921520012e70d61125c0f7c269SHA-1: 94d6b21d1b347d6d83c875c71927a6906927ebaa
SHA-256: 1b0f24eb2149bc7ba10d98651488f651e12e00956adcdb90b9775e95168b2fdd |
decoded.dll |
MD5: aa9d7ce1d08ec1a4147846f91423f431SHA-1: 492d6cb1c6f30f628145a14180440dae9d8b2454
SHA-256: 91d4ae2f55f71f13fea98d23c99a6e7110d5bff0217ea195df90d6f96c46c84b |
payload.bin |
MD5: 8ae185afebe306e8f84fda01a37094d3SHA-1: 9275da21ea5255df3d22d5f8b516234088ea2703
SHA-256: e381d8d00e2d9686c5e0144bfafec980c806210e11331a0a9616c48c66667f7c |
N/A |
MD5: e18a9bb146ccb98e67c8cce6e69ac8b7SHA-1: 7d5df6177acfea5c572d26d0082e203719971b42
SHA-256: 460842d20206c6e7709d28b0bb5d31b326f9af0596e9f76e3cfd017e939c9aee |
460842d20206c6e7709d28b0bb5d31b326f9af0596e9f76e3cfd017e939c9aee.sample |
Sources
https://malpedia.caad.fkie.fraunhofer.de/details/win.carbanak
https://malpedia.caad.fkie.fraunhofer.de/actor/fin7