WS2_32.dll: It is the Windows library responsible for the network API based on the Windows Sockets (Winsock) standard. It provides all the TCP/IP communication, UDP, and socket handling functions used by practically any Windows application that communicates over the network. Probably for communication with the C2.
KERNEL32.dll:It is one of the core DLLs of Windows, responsible for providing most of the essential functions for managing processes, memory, threads, files, I/O, synchronization, and other fundamental services of the operating system.
IsDebuggerPresent This function allows an application to determine whether it is being debugged or not, so that it can modify its behavior.
2.1.3 Strings
1 2 3 4 5 6 7 8 9 10 11 12 13
C:\\Users\\Huynh Quoc Ky\\Downloads\\Ransomware\\libgen.dll gen_from_file anonymous get_result_bytes Socket creation failed 192.168.134.132 Connection to server failed Sent %s (%ld bytes) to server\n C:\\ProgramData\\Important\\user.html C:\\ProgramData\\Important\\user.html.enc hackingisnotacrime C:\\Users\\Huynh Quoc Ky\\Downloads\\Ransomware\\hacker What are you doing ?
libgen.dll and hacker in the same directory indicates that it was probably compiled.
user.html encrypted to user.html.enc
IP 192.168.134.132 with connection messagess.
2.1.4 File PCAP
The malware used wget to download the file “anonymous” from the C2 server..
I analyzed that it also contains false records; I think they may have been added to match the style of the challenge since it involves a ransomware.
3.1 Static Analysis IDA
Now we will start reverse engineering to understand its behavior.
3.1.1 Main Function
By obtaining the C pseudocode, we get the following execution flow:
The program’s entry point coordinates the entire execution through a simple yet critical pipeline. After the initial call to _main() — a typical setup routine used for internal initializations — the program attempts to obtain a crucial data block via sub_001860(). This block serves as a working structure for the subsequent steps; if its creation fails, the process is immediately aborted with a return of -1.
With the valid block, the program proceeds to two main operations:
sub_001DE1(Block), which uses the newly created buffer and probably implements the main functional logic (processing, transformation, or validation of the data contained in the block).
sub_001FB3(), an auxiliary routine independent of the block, possibly responsible for environmental checks, external communication, or final steps of the flow.
The function sub_001860() implements an initialization routine that tries to obtain a 32-byte block from different mechanisms exposed by an external DLL (libgen.dll). It follows a fallback chain, using three possible functions exported by the DLL:
gen_from_file
get_result_bytes
gen
If any of these strategies produce a valid result, the function copies the 32 bytes to a dynamically allocated buffer and returns it to the caller.
The function sub_001DE1() implements a file processing routine based on an external key buffer (the a1 argument). It operates on a fixed file located in ProgramData, carrying out three main steps: complete file reading, content transformation via sub_001668(), and writing the result to a new file with a modified extension. After that, it executes two auxiliary functions that are likely related to the handling or finalization of the original file and its replacement.
The function sub_001AEB() implements a data extraction and sending routine. It fully reads a file specified by a1, stores its content in memory, and establishes a TCP connection to a pre-configured address and port, first sending the file size in four bytes and then the entire content. The entire process is strictly validated: read failures, allocation issues, or socket creation and connection errors result in an error return after proper resource cleanup.
The function sub_00148C() implements exactly the RC4 key-scheduling algorithm (KSA), responsible for initializing and scrambling the state vector S[256] using the provided key.
This scrambled vector is then used by the PRGA (pseudo-random generator), which is probably inside sub_001558.
4.1 Resolution
4.1.1 Encrypted PCAP files
Let’s recall what we saw above in the code:
user.html is encrypted to user.html.enc
libgen.dll encrypted as hacker.
In the analysis of network traffic captured in the PCAP file, it is possible to identify that the malware exfiltrated these two encrypted files to the C2.
Going back to Wireshark:
TCP STREAM 1 the first 4 bytes in hexadecimal: 00 00 0A 1C, 0x00000A1C = 2,588 bytes in decimal.
TCP STREAM 2 upload done this time with a larger amount of data, first 4 bytes: 00 00 42 14, 0x00004214 = 16,916 in decimal.
// AES-ECB works in 16-byte blocks if (enc_size % AES_BLOCK_SIZE != 0) { printf("Erro: tamanho não alinhado ao bloco AES\n"); return1; }
uint8_t *decrypted = malloc(enc_size);
// --- Decrypt ECB --- for (long i = 0; i < enc_size; i += AES_BLOCK_SIZE) { AES_ecb_encrypt(encrypted + i, decrypted + i, &aes_dec_key, AES_DECRYPT); }
This code functions as a dynamic loader designed to extract a 32-byte key from the gen_from_file function exported by the libgen.dll library. Initially, it loads the DLL at runtime using LoadLibraryA and then resolves the address of the target function via GetProcAddress. After obtaining a valid pointer, the program calls gen_from_file, passing the filename “anonymous” as an argument. The function returns a pointer to a buffer containing the key, which is copied to a local array using memcpy. The code then prints the key in hexadecimal format and saves the raw content to the file rc4_key.bin, completing the extraction process.
We implemented a full RC4 decryption routine applied to the file user.html.enc. It starts by loading the 32-byte key directly from the file rc4_key.bin and prints its value in hexadecimal format for verification. Next, the program reads the entire encrypted content into memory, determines the total size, and interprets the first 4 bytes as a header representing the expected size of the actual data; if this information is consistent, the header is removed and the size is adjusted. Decryption is carried out by a full RC4 implementation, consisting of the Key Scheduling Algorithm (KSA), responsible for initializing and permuting the 256-position S array, and the Pseudo-Random Generation Algorithm (PRGA), which generates the keystream and applies XOR byte by byte over the encrypted content. At the end of the process, the resulting buffer is written to disk as user.html, restoring the original file, and the program finishes by releasing the resources used.
By opening the user.html file in the browser, we get the challenge flag!