I've started this article with the idea to throw some light on the latest malware obfuscation trends.
Therefore, I'll try to be less technical about the malicious payload, and give more details about the used obfuscations instead.
When I started wandering through the exciting world of malware analysis, things were simple. There was only few AV vendors at the time, they were betting on fingerprinting, and of course, that was plenty enough to fight with the latest threads.
Because at that time, the malware niche was still small and the AV vendors were few, obfuscation techniques were rarely (if none at all) used.
Now days however, things are more complicated.
Instead on blindly fingerprinting the threads, AV vendors are using combination of fingerprinting, heuristic analysis, sandboxing, and more.
On the other hand, the malware authors are also up to date, so instead of recompiling the malicious payload and change the workhorse code, they are using obfuscations that can fool the AV detection schemes.
Usually, the payload is something developed long time ago, but wrapped by multiple type of "obfuscations" - encryption, code randomization, bundling with a well known clean application, and so on.
It's often when I spend a week to beat the obfuscations, and when I finally start working on the payload itself, it turns out to be a malware from 2-3 years ago...
And since the malware is mostly static through the time, the interesting part becomes the obfuscation wrapping it and not the actual malicious code.
In this article I was able to catch in the wild
this sample.
Some of the vendors detect it as "
Downloader", other as "
Ransom", third call it "
Kryptik" - and technically, they are all correct.
Because the obfuscation of the thread has many layers, I decided to split each of them in stages.
So, buckle up and enjoy the ride!
Stage 1: Raw sample
Filename:
societe_generale_sa.scr
Size:
53 248b
MD5:
2D0775DD7718EEDD1104BEE38633E58B
Timestamp:
05/08/2010 20:16:32 (probably forged)
There are small obfuscations of some code parts, like this one here, where HeapCreate parameters are calculated, instead of just being static:
Assembly.text:004010C9 mov edx, 28982F6Ch
.text:004010CE sub edx, 2898289Ch ; 0x28982F6C - 0x2898289C = 0x6D0
.text:004010D4 push edx ; dwMaximumSize = 0x6D0
.text:004010D5 mov edx, 28982F6Ch
.text:004010DA sub edx, 2898289Ch ; 0x28982F6C - 0x2898289C = 0x6D0
.text:004010E0 push edx ; dwInitialSize = 0x6D0
.text:004010E1 mov eax, 289C289Ch
.text:004010E6 sub eax, 2898289Ch ; 0x289C289C - 0x2898289C = 0x00040000
.text:004010EB push eax ; flOptions = HEAP_CREATE_ENABLE_EXECUTE
.text:004010EC lea eax, ds:663C1FAAh
.text:004010F2 sub eax, 65FC0F72h
.text:004010F7 call dword ptr [eax] ; kernel32.HeapCreate
Here, the first encryption is encountered, but it turns out it's rather simple one:
MinGW Cvoid decrypt(byte* data_buffer, int data_size) {
DWORD key = 0x6F7A34AD;
DWORD t;
int i;
for(i = 0; i < data_size; i += 4) {
t = ~((*(DWORD*)&data_buffer[i] & 0xFFFFFFFF) - 0x08) - key + 1;
key = rol((t & 0xFFFFFFFF), 0x08);
*(DWORD*)&data_buffer[i] = t;
}
}
The produced result is a shellcode that is executed at Stage 2.
Stage 2: The "loader" shellcode
The API function used here are obtained by a checksum calculated from the API name, instead of using the API name itself.
This technique is well known, and its goal is to hide the plaintext ASCII strings from the curious eyes of people like me.
Implementation of the checksum calculator in C, looks like this:
MinGW CDWORD encode(char* input_data) {
DWORD crc = 0;
DWORD t = 0;
int i;
for(i = 0; i < strlen(input_data)+1; i++) {
t = ror(t, 0x07);
crc = rol(crc, 0x0D) + t;
t = (t & 0xFFFFFF00) + *(char*)&input_data[i];
}
return crc;
}
Something interesting that catches my eye is this code:
Assembly0088002B 8B45 2C MOV EAX,DWORD PTR SS:[EBP+2C] ; kernel32.ReadFile
0088002E 8038 8B CMP BYTE PTR DS:[EAX],8B
00880031 75 01 JNZ SHORT 00880034
00880033 C3 RETN ; exit
00880034 E8 B0010000 CALL 008801E9
It basically check if the entry point of
kernel32.ReadFile starts with
MOV (opcode
0x8B).
Originally,
ReadFile starts with
PUSH, so this verification appears to be an
API hook protection or something, although I'm more of a
JMP guy and
MOV wouldn't be my weapon of choice if I was about to hook anything.
Another encryption is used here, to decrypt a payload data:
MinGW Cvoid decrypt(byte *data_buffer, int data_size) {
DWORD key = 0x173FDE3C;
DWORD t;
int i;
key ^= 0x7845EA91;
for(i = 0; i < data_size; i += 4) {
t = *(DWORD*)&data_buffer[i] ^ 0x01;
__asm__("bswap %0" : "+r" (t));
t ^= key;
key = *(DWORD*)&data_buffer[i];
*(DWORD*)&data_buffer[i] = t;
}
}
This algorithm is decrypting a fully functional
MZ-PE file. However, instead of dropping it on the disk, it gets self injected into the current process.
Again, a well known and widespread technique of keeping the code away from the antivirus.
Stage 3: The cake is a lie!
Since the decrypted by Stage 2 data is a
MZ-PE, I can fetch some interesting statistics information:
File size:
10 752b
MD5:
1AC0CB549C277F8825AB6B140BAFB90C
Timestamp:
22/04/2015 10:31:26 (matches the time of the catch)
This file has two goals:
- Drop a .rtf "decoy" file (stored as a .cab, inside the data section of the executable), that should mislead the user by showing him some boring text file.
- Download the sneaky payload from a set of attack/CnC websites and infect the machine.
But first things first.
In this executable, the important
ASCII strings are all encrypted, using a simple
dynamic key-XOR encryption:
MinGW Cvoid decrypt(char* data, int data_size) {
char key[] = "\x6A\x08\x2D\xB4\x69\xD7\x96\x31\x0B\xEA\xBD\xE6\xB3\xDF\x4E\x1C";
int i;
for(i = 0; i < data_size; i++) {
*(byte*)&data[i] = *(byte*)&data[i] ^ *(byte*)&key[i%0x10];
*(byte*)&key[i%0x10] ^= *(byte*)&data[i];
}
}
//* This encryption algorithm is used for both wide char and multibyte strings.
A sophisticated random file name generator is also used:
MinGW Cint genRandom(int strLengthLimit, int seed) {
DWORD t;
SystemFunction036(&t, 4);
return (t % ((strLengthLimit - seed) + 1)) + seed;
}
void genRndStr(char *result, int strLengthLimit, int fileExt) {
char charset1[] = "aeoiuy.";
char charset2[] = "qwrtpsdfghjklzxcvbnm";
char extList[] = "txtrtfdocchmhlpttfpdffb2xlscabmdbcdawavwmamp3avimpgmdvflvswfwmvvobbmpgifjpgpngisomdfmdsbindatnrg3gpoggvobexedll";
//all these charset1, charset2 and extList are decrypted using the previously mentioned key-XOR crypto.
int i, strLength;
strLength = genRandom(strLengthLimit, 3);
if (strLength > 0) {
for(i = 0; i < strLength; i++) {
if (i&0x80000001) {
result[i] = *(byte*)&charset1[genRandom(0x05, 0)];
} else {
result[i] = *(byte*)&charset2[genRandom(0x13, 0)];
}
}
}
result[i] = *(byte*)&charset1[6];
if (fileExt == 1) {
fileExt = 0x69; // points to "exe"
} else if (fileExt == 3) {
fileExt = 0x1B; // points to "cab"
} else {
fileExt = genRandom(0x22, 0) * 3; // get random extension
}
*(DWORD*)&result[i+1] = *(DWORD*)&extList[fileExt];
*(byte*)&result[i+4] = 0; // terminate the string
}
The file name for the
.cab archive, holding the decoy
.rtf file is generated by this function.
However, using this random string generator, the attacker can generate file names with many different extensions (see extList for reference).
Since I already mention this file is a downloader, it holds an URL list, where the actual malicious part is located:
lac-fessenheim.org/components/image.jpg
jacobohm.webatu.com/image.jpg
ndiprintmaking.ca/wp-admin/image.jpg
ndiprintmaking.ca/image.jpg
cambori.awardspace.biz/2/image.jpg
ogarape.com/images/image.jpg
Again, the URLs are encrypted by the
key-XOR encryption, and every time one of them is used, it gets encrypted back to its original state, to (probably) hide it from potential memory analysis.
The downloaded file "
image.jpg" is structured like a very simple file system:
C Structuretypedef struct malFS_raw {
DWORD crc32;
DWORD data_size;
byte* data_encrypted;
}
This "
data_encrypted" buffer is encrypted by the same string encryption used before, and the crc32 parameter is (obviously) the
CRC32 checksum of the decrypted data, that is used as verification after the decryption.
The produced data is again structured:
C Structuretypedef struct malFS_decrypted {
DWORD data_size_0;
byte* data_0;
//...
DWORD data_size_N;
byte* data_N;
}
According to the structure above, the decrypted data can contain many entries. However, in the current sample, the entries are two
MZ-PE files, that are executed in reverse order.
Because the execution process splits in two here, I will also split the article as
Stage 3.1 (second entry of the downloaded payload) and
Stage 4 (first entry).
The executable I will analyze next at stage 3.1 is
<SPOILER ALERT> only credential gatherer, and it doesn't make any HTTP requests.
All of the information that it gathers is sent to the
CnC server by the current code here in stage 3.
Speaking of the
CnC, the exact URL is not present as-is, but it is dynamically created on the run, from the payload URLs.
The algorithm is quite simple:
- Lets say we use "
ogarape.com/images/image.jpg" as a payload server.
- From that address, we take the file name - "
image.jpg", calculate its
CRC32 checksum, convert it from HEX to decimal number and we get
3447786819.
- Finally the
CnC URL is constructed back, to produce the URL "
ogarape.com/images/3447786819.php"
After sending the stolen data, depending on the server response, leads to either process termination (if the server doesn't response with "
Confirmed") or to execution of the first payload (see stage 4).
But first thing first, lets see the "credential stealer" payload first, at Stage 3.1
Stage 3.1: All of your _pass_ are belong to me
I already mentioned that this one is a stand-alone
MZ-PE, but it is actually a
DLL file.
File size:
91 648b
MD5:
C6F1A88592BE4C9BB2390E8ED57B8831
Timestamp:
20/05/2014 13:19:19 (probably legit compile time stamp)
The DLL has only one export function - "
Grab_Psw", that quite obviously shows what the code actually do - grabs passwords.
Stolen credentials can be put in five categories:
FTP,
E-Mail,
Web Browser,
e-currency and misc credentials, plus user certificates.
Follows a complete list of the affected programs.
FTP Clients and alike:
Far Manager,
Total Commander / Windows Commander,
ipswitch,
CuteFTP,
FlashFXP,
FileZilla,
FTP Navigator / FTP Commander,
Bullet Proof FTP,
SmartFTP,
TurboFTP,
FFFTP,
Direct FTP,
Core FTP,
FTP Explorer,
Frigate,
SecureFX,
UltraFXP,
FTP Rush,
Web Site Publisher,
BitKinex,
ExpanDrive,
Classic FTP,
Fling,
SoftX FTP Client,
Directory Opus,
LeapFTP,
WinSCP,
32bit FTP,
NetDrive,
WebDrive,
FTP Control,
WISE-FTP,
FTP Voyager,
FireFTP,
LeechFTP, Odin Secure FTP Expert,
WinFTP,
FTP Surfer,
FTPGetter,
ALFTP,
DeluxeFTP, Staff-FTP,
AceFTP,
Global Downloader,
FreshFTP,
BlazeFtp,
FTP++,
GoFTP,
3D-FTP,
EasyFTP,
NetSarang Xftp,
FTPNow,
Robo-FTP, LinasFTP,
Cyberduck, Notepad++ NppFTP plugin,
FTPShell,
FTPInfo,
NexusFile,
WinZip FTP plugin,
My FTP,
NovaFTP,
FastTrack FTP,
E-Mail clients:
Windows Live Mail, Windows Mail,
Becky! Internet Mail,
Pocomail,
IncrediMail,
BatMail/The Bat!, Outlook, Thunderbird
E-currency clients:
Bitcoin,
Electrum,
MultiBit,
FTP Disk,
Litecoin,
Namecoin,
Terracoin,
Armory,
PPCoin,
Primecoin,
Feathercoin,
NovaCoin,
Freicoin,
Devcoin,
Franko,
ProtoShares,
Megacoin,
Quarkcoin,
Worldcoin,
Infinitecoin,
Ixcoin,
Anoncoin,
BBQcoin,
Digitalcoin,
Mincoin,
GoldCoin,
Yacoin,
Zetacoin,
Fastcoin,
I0coin,
Tagcoin,
Bytecoin,
Florincoin,
Phoenixcoin,
Luckycoin,
Craftcoin,
Junkcoin
Web browsers:
FastStone 4in1 Browser,
ChromePlus,
Yandex Browser, Epic privacy browser,
K-Meleon,
RockMelt,
Comodo, Nichrome,
Bromium, Chrome,
Chromium,
Flock,
SeaMonkey,
Firefox,
Opera,
Misc:
PuTTY saved sessions, valid certificates, Remote Desktop, Internet Explorer proxy settings,
Dreamweaver stored passwords,
CoffeeCup shared accounts, Unknown GUID {74FF1730-B1F2-4D88-926B-1568FAE61DB7}
Most of the strings are plaintext but few are encrypted with XOR 0x01:
MinGW Cvoid decrypt(char *input_data) {
for(int i = 0; i < strlen(input_data); i++) {
*(char*)&input_data[i] = *(char*)&input_data[i]^0x01;
}
}
The stolen information is formatted as "
PKDFILE" package and compressed using
aPLib 1.01.
Then, the compressed data gets
RC4 encrypted twice, using "
Ukulele" as encryption key.
A slightly modified
CRC32 checksums are added between the
RC4 encryption stages, probably for future verification by the
CnC:
Assembly.text:10001580 push [ebp+var_8]
.text:10001583 push eax
.text:10001584 push 0
.text:10001586 call _CRC32
.text:1000158B mov [ebp+var_C], eax
;...
.text:1000159E mov eax, [ebp+var_C]
.text:100015A1 bswap eax ; < Modification 1
.text:100015A3 not eax ; < Modification 2
Stage 4: The drop
Again, I got a MZ-PE, so here are the details:
File size:
1 096 704b
MD5:
723E2B1B686A62BF564DD45E97E5F3EE
Timestamp:
23/04/2015 02:47:28 (probably legit compile time stamp)
Something that might be considered as a flaw is the fact that this payload is physically dropped on the victim's machine, then executed.
This makes the obfuscations and encryption used so far kind of useless, but never mind.
At first glance, this executable appears to be "Frankensteined" from many different legit programs, to hide its malicious core in between them.
Some of the artifacts I've found, lead to Calibre, others to a unknown Russian software.
Even though the encryption used here appeared to be a bit complicated, it turns out that the final algorithm is XOR-0x24:
MinGW Cvoid decrypt(byte *data_buffer, int data_size) {
for(int i = 0; i < data_size; i++) {
*(byte*)&data_buffer[i] ^= 0x24;
}
}
Obviously, the attackers intentionally obfuscated the encryption algorithm, by using bulk code and pointless calculations:
Assembly;* commented lines are just "filler" code.
00402210 |> 8B0D 148B4F00 MOV ECX,DWORD PTR DS:[4F8B14] ; key = 0x0817
00402216 |> 8B5424 10 MOV EDX,DWORD PTR SS:[ESP+10] ; encrypted_data
0040221A |. 8B4424 14 MOV EAX,DWORD PTR SS:[ESP+14] ; i
0040221E |. 8A1402 MOV DL,BYTE PTR DS:[EDX+EAX] ; encrypted_data[i]
;00402221 |. 884C24 3B MOV BYTE PTR SS:[ESP+3B],CL ; temp_key, but it's not used!
00402225 |. 885424 47 MOV BYTE PTR SS:[ESP+47],DL ; temp_encrypted_data[i]
;00402229 |. 85C9 TEST ECX,ECX ;/ probably will never jump
;0040222B |. 74 0E JE SHORT cepyg.0040223B ;\
0040222D |. 8BF7 MOV ESI,EDI ; EDI = 0xFA
0040222F |. 2B7424 3C SUB ESI,DWORD PTR SS:[ESP+3C] ; ESP+3C = var1 = 0, zeroed
;00402233 |. 0335 108B4F00 ADD ESI,DWORD PTR DS:[4F8B10] ; 004F8B10 = 0, we can ignore it
00402239 |. 03F6 ADD ESI,ESI
;0040223B |> 8B0D 088B4F00 MOV ECX,DWORD PTR DS:[4F8B08]
;00402241 |. 8B15 188B4F00 MOV EDX,DWORD PTR DS:[4F8B18] ; 004F8B18 = 0, we can ignore it
;00402247 |. 8D8424 2803000>LEA EAX,DWORD PTR SS:[ESP+328]
;0040224E |. 50 PUSH EAX ; /lParam
;0040224F |. 6A 02 PUSH 2 ; |wParam = 2
;00402251 |. 68 01040000 PUSH 401 ; |Message = WM_USER+1
;00402256 |. 51 PUSH ECX ; |ControlID => FFED0BD4
;00402257 |. 52 PUSH EDX ; |hWnd => NULL
;00402258 |. FF15 10124100 CALL DWORD PTR DS:[<&USER32.SendDlgItemM> ; \SendDlgItemMessageA
;0040225E |. 8B0D 188B4F00 MOV ECX,DWORD PTR DS:[4F8B18] ; 004F8B18 = 0, we can ignore it
Something that puzzled me is that little piece at the end, after the decryption routine:
Assembly0040235A |. 8B4424 10 MOV EAX,DWORD PTR SS:[ESP+10] ; decrypted shellcode
0040235E |. 8D5424 34 LEA EDX,DWORD PTR SS:[ESP+34] ; hInstance of the current process (00400000)
00402362 |. 8950 01 MOV DWORD PTR DS:[EAX+1],EDX ; places the hInstance pointer, one byte after the beginning of the shellcode
There are two potential problems I see here.
First is the shellcode itself:
Assembly;00B80688 24 B8 AF BE AD DE E9 76 14 00 00 CC CC CC CC CC
00B80688 24 B8 AND AL,0B8
00B8068A AF SCAS DWORD PTR ES:[EDI]
00B8068B BE ADDEE976 MOV ESI,76E9DEAD
00B80690 14 00 ADC AL,0
00B80692 00CC ADD AH,CL
00B80694 CC INT3
;...
That doesn't make sense, unless I replace the first byte (
0x24) with
NOP:
Assembly;00B80688 90 B8 AF BE AD DE E9 76 14 00 00 CC CC CC CC CC
00B80688 90 NOP
00B80689 B8 AFBEADDE MOV EAX,DEADBEAF
00B8068E E9 76140000 JMP 00B81B09
00B80693 CC INT3
;...
Now, that looks way better.
However, the hInstance will be set on the wrong place, so instead of:
Assembly00402362 8950 01 MOV DWORD PTR DS:[EAX+1],EDX
I've changed it to:
Assembly00402362 8950 02 MOV DWORD PTR DS:[EAX+2],EDX
I have no idea why the code starts with opcode 0x24. Bug? Maybe. RE protection? Could be...
Since now I know how the shellcode "should" look, I have another problem, this time with the code that sets the hInstance value.
Assembly0040235A 8B4424 10 MOV EAX,DWORD PTR SS:[ESP+10] ; decrypted shellcode
0040235E 8D5424 34 LEA EDX,DWORD PTR SS:[ESP+34] ; hInstance of the current process (00400000)
00402362 8950 02 MOV DWORD PTR DS:[EAX+2],EDX ; now pointing to the right place
For some reason, the hInstance is not taken by value, but it's stack pointer (
LEA).
This renders the code invalid, because every time that
hInstnce is needed, it will take the stack pointer, and not the value.
Fixing this is easy:
Assembly0040235A 8B4424 10 MOV EAX,DWORD PTR SS:[ESP+10] ; decrypted shellcode
0040235E 8B5424 34 MOV EDX,DWORD PTR SS:[ESP+34] ; LEA goes to MOV
00402362 8950 02 MOV DWORD PTR DS:[EAX+2],EDX ; now pointing to the right place
The shellcode is now fixed, so let's go to the next stage - the shellcode itself.
Stage 5: Just a simple shellcode. Really?
Even that Stage 5 has a simple job, yet it holds quite complicated code.
The shellcode egghunts for some data inside the executable. This egghunt is quite complicated actually.
It fetches small pieces of data and applies different decryption, decompression and decoding routines over them.
Basically, the egghunted data is split into small chunks inside the executable, and not only the size of these chunks vary, they may use different encryption, compression or encoding.
I was able to reverse engineer most of the algorithm for eggunting and building the shellcode, but since my code became one giant meatballs and spaghetti beast, it's also incomplete (yet it can drop the correct result) I'll not publish it in this article. Trust me, for the sake of humanity.
It's good to mention that the result shellcode get "patched", the same way it was with the current one, but this time, the value is not
hInstance, but forced to 0.
Assembly00B81BA2 8B55 FC MOV EDX,DWORD PTR SS:[EBP-4] ; decrypted shellcode
00B81BA5 C742 01 00000000 MOV DWORD PTR DS:[EDX+1],0 ; set the value to 0
;...
00B836BD B8 AFBEADDE MOV EAX,DEADBEAF ; this one is set by the MOV EAX,0 above
00B836C2 E9 26220000 JMP 00B858ED
00B836C7 CC INT3
Stage 6: Almost the last shellcode
This shellcode has two ways of execution, depending on the
hInstance parameter mentioned before.
If the first value assigned to
EAX was
hInstance for example, the current code continues by eghunting plain (not encrypted) payload from its memory and executes it.
In my case however, the
hInstance is set to
NULL, so it continues by eghunting for encrypted payload.
That encrypted payload is again built using the same decrypt/decompress/decode method as the one used in Stage 5.
So, here we can see classic "reusing" of the same code.
The obtained payload is executed directly as all shellcodes were so far (no physical dropping of the payload).
Stage 7: Simple obfuscation and another shellcode decrypt
File size:
669 696b
MD5:
45D3CBEEF8B792D4470355B5764BE88F
Timestamp:
NULL
Stage 7 is a short one. It uses a simple
JMP oriented obfuscation, that is easy to beat and hard to fingerprint:
Assembly.text:00401FA3 push ebp
.text:00401FA4 jmp loc_440E0C
;... bulk data ...
.text:00440E0C mov ebp, esp
.text:00440E0E jmp sub_456CF9
;... bulk data ...
.text:00456CF9 sub esp, 20h
.text:00456CFC jmp loc_40BE41
;... bulk data ...
The obfuscated code is a encryption routine, that decrypts the shellcode for the next stage:
MinGW Cbyte* decrypt(byte* data_buffer, DWORD* data_size) {
int i, j;
DWORD key;
byte t;
byte* data;
byte* result_data;
key = 0x0C78E5EC3;
data = data_buffer + 0x2B0;
result_data = (byte*)VirtualAlloc(NULL, *data_size, MEM_COMMIT|MEM_RESERVE, PAGE_READWRITE);
*data_size = 0;
while(1) {
t = *(byte*)&data[0] ^ LOBYTE(key);
data++;
if (t == 0) { break; }
key = rol(key, 3) * 0xDB0CCE3F;
if (t >= 0xE0) {
data = data + t - 0xE0;
} else {
for(j = 0; j < t; j++) {
*(byte*)&result_data[*data_size] = *(byte*)&data[0] ^ LOBYTE(key);
data++;
key = rol(key, 3) * 0x0DB0CCE3F;
*data_size+=1;
}
}
}
return result_data;
}
Stage 8: Final decryption
At stage 8 the final payload is decrypted by unknown (to me) encryption that I didn't even bother reverse engineering it.
The result payload is a headless
MZ-PE that is built in the memory during its decryption, and executed from there.
Stage 9: The twist
Stage 9 is the final payload.
It didn't take me too long to figure out that the payload is actually
CTB-Locker.
<screentext>%a1%%f3%%c3%Your personal files are encrypted by CTB-Locker.%f0%%c0%
Your documents, photos, databases and other important files have been encrypted with strongest encryption and unique key, generated for this computer.
Private decryption key is stored on a secret Internet server and nobody can decrypt your files until you pay and obtain the private key.
If you see the main locker window, follow the instructions on the locker. Overwise, it's seems that you or your antivirus deleted the locker program. Now you have the last chance to decrypt your files.
Open %c1%http://%gatea%%c0% or %c1%http://%gateb%%c0% in your browser. They are public gates to the secret server.
If you have problems with gates, use direct connection:
1. Download Tor Browser from %c1%http://torproject.org/%c0%
2. In the Tor Browser open the %c1%http://%onion%/%c0%
Note that this server is available via Tor Browser only. Retry in 1 hour if site is not reachable.
Write in the following public key in the input form on server. Avoid missprints.
%f1%%c1%%key%%f0%%c0%
Follow the instructions on the server.
These instructions are also saved to file named Decrypt-All-Files.txt in Documents folder. You can open it and use copy-paste for address and key.</screentext>
Overall, the whole thread can be represented as the following block diagram:
That concludes this article.
As you can see the malware of tomorrow is build as onion, and pealing the scales most of the time reveals something well known, like
CTB-Locker.
During the time of the analysis i was able to catch different versions of the same thread.
Currently the URLs of the
CnC are long gone, as expected, but the thread is probably still present in the wild.
So, watch out, and I hope I'll see you in the next article!
Comments
* You have an opinion? Let us all hear it!