URL has been copied successfully!
When Data Mining Conti Leaks Leads to Actual Binaries and to a Hardcoded C2 With an Encryption Key on Tripod.com Part Five
URL has been copied successfully!

Collecting Cyber-News from over 60 sources

When Data Mining Conti Leaks Leads to Actual Binaries and to a Hardcoded C2 With an Encryption Key on Tripod.com Part Five

Dear blog readers,  Continuing the “When Data Mining Conti Leaks Leads to Actual Binaries and to a Hardcoded C2 With an Encryption Key on Tripod.com – Part Four” blog post series in this post I’ll continue analyzing the next malicious software binary which I obtained by data mining Conti Leaks with a lot of success.  The actual malicious software binary location URL: hxxp://www.delwarren.com/backup/nowin.exe MD5: 320dd151aed6a181d84e63f78cf801f0
SHA-1: 573e93bb5075ec74ec3c45eaf4190af8e315a429
SHA-256: c366c4e26ec3d2698a94dc04afb58dad429d6c28dff1820d53e277e108103f8f Here’s the analysis. High-confidence classification nowin.exe is a Windows x86 network backdoor whose primary behaviors are: persistent/repairable multi-threaded C2 beacons (keeps up to 3 concurrent worker threads), a custom C2 application protocol (length-framed + lightweight obfuscation using a constant marker), remote command execution (via system() with captured output), interactive command shell (cmd.exe) over the network, a secondary, more complex relay-based shell channel negotiated using a SOCKS-like control exchange. The overall design is typical of a small bespoke RAT/backdoor: connect to a hardcoded controller, identify/beacon, then loop receiving commands which dispatch into a few core capabilities.


Runtime / threading model

Process start and initialization

entry_point (0x40383c) and runtime_init (0x40357c) implement standard CRT initialization and single-init locking. Initialization uses: InterlockedCompareExchange guarding a global init lock (g_init_lock at 0x407504), g_init_state (0x407500) to track initialization progress.

Worker thread redundancy (up to 3 concurrent)

backdoor_worker_thread (0x4019a0) is the main C2 loop. It increments/decrements g_active_thread_count (0x4074c0) under g_thread_count_lock (0x40749c). On certain failures or after certain commands, it respawns itself via _beginthread(backdoor_worker_thread, 0, 0) until g_active_thread_count < 3 no longer holds. This provides resilience: if a connection drops or a thread exits, the malware will try to maintain a small pool of active connections.


C2 infrastructure and basic socket operations

Hardcoded controller address

C2 IP: 88.214.27.52, constructed at 0x401adc (sprintf(“%d.%d.%d.%d”, 0x58, 0xd6, 0x1b, 0x34)). Port: 443 (htons(0x1bb)), set in connect_to_c2 (0x402aa0).

Connection procedure (connect_to_c2, 0x402aa0)

Creates TCP socket (via WSASocketA(AF_INET, SOCK_STREAM, IPPROTO_TCP)). Uses a non-blocking connect pattern: ioctlsocket(FIONBIO, 1) → nonblocking, connect, select(… writefds …, timeout=10s) to detect connection completion, ioctlsocket(FIONBIO, 0) restore blocking. Returns boolean-style success. This is a common technique for implementing a connect timeout on Windows.


Primary C2 protocol (framing + “AssHole” obfuscation layer)

The malware’s main message channel uses:

    4-byte length prefix encoded payload (obfuscated, not encrypted)

Framing

Receive path: recv_command_from_c2 (0x4027a0) Reads exactly 4 bytes (the length) via repeated recv. Allocates/resizes a std::string to that length. Reads exactly len bytes via recv_exact (0x402a60). Send path: send_data_to_c2 (0x4028d0) Builds a string, then sends 4-byte length followed by payload (body send uses send_exact at 0x402a20 for full transmission).

“AssHole” wrapper purpose and mechanics

Literal marker: “AssHole” at 0x405558. Alphabet used by transform: “0123456789abcdef” at 0x405544. Both send_data_to_c2 and recv_command_from_c2 incorporate “AssHole” directly into the transform pipeline: On send: the outgoing buffer is combined with “AssHole” and passed through encode_obfuscated_hex_string (0x4024a0). On receive: the received blob is combined with “AssHole” and passed through decode_obfuscated_hex_string (0x402620). What this achieves It is a lightweight obfuscation/encoding layer that: makes on-the-wire command tokens/results non-plaintext, provides a trivial shared constant that must match between sides (a weak “key”/salt), reduces accidental decoding of arbitrary traffic into meaningful commands. This is not cryptography; it behaves like reversible per-character nibble transformations over hex-like text.


Command protocol: exact tokens and behaviors

After initial beaconing, backdoor_worker_thread continually: recv_command_from_c2 → decodes into a command string compares equality against several hardcoded tokens dispatches behavior per match

Exact command tokens (as used in comparisons)

The decoded command string is compared against these literal tokens:

Role (renamed)

Token string

Address

kCmd_ShellIO Csdnma91fggw7 0x405234 (0x407100)
kResp_ShellIO_Ack Zcvznw8i739 0x405228 (0x407104)
kCmd_StartWorkersAndShell Fdh9873 0x405220 (0x407108)
kCmd_DropPayload VCNde92756 0x405214 (0x40710c)
kCmd_ExecAndReturn NMFVd8w7663 0x405208 (0x407110)
kCmd_SpawnCmdExe COMM500 0x405200 (0x407114)
kCmd_SelfMoveTrash JWEdj898 0x4051f4 (0x407118)

Also present in the initial beacon string: NUDEew97834g at 0x405244 (0x4070fc) (used as part of the initial identification string, not a compare token in the dispatch shown).

Command behaviors (as implemented)

Shell/relay initiation Matching kCmd_StartWorkersAndShell (“Fdh9873”) triggers: spawning additional workers (up to 3 total), entering handle_shell_io(s) (0x403360) which negotiates and runs the relay-based shell path. Matching kCmd_ShellIO (“Csdnma91fggw7”) results in sending kResp_ShellIO_Ack (“Zcvznw8i739”) back. Remote exec with output capture Matching kCmd_ExecAndReturn (“NMFVd8w7663”) triggers execute_system_and_capture_output (0x401720): constructs a temporary file path, runs system() redirecting output to file, reads file contents into a std::string, deletes the file, sends the output back (with token appended/used as delimiter/prefixing behavior). Direct interactive cmd.exe Matching kCmd_SpawnCmdExe (“COMM500”) triggers spawn_reverse_shell(&s) (0x402ba0). Drop/write payload to disk Matching kCmd_DropPayload (“VCNde92756”) triggers write_received_payload_to_file() (0x4011e0): parses content around a ‘-‘ delimiter and writes the trailing data to a file. then responds to C2 with the same token via send_data_to_c2. Self-move and exit Matching kCmd_SelfMoveTrash (“JWEdj898”) acks then calls self_move_and_exit() (0x401310), which renames/moves itself to a path with a .trash suffix and exits.


Reverse shell subsystem: two distinct modes

Mode A: inherited-handle cmd.exe over the connected socket

spawn_reverse_shell (0x402ba0) does the classic redirected-shell pattern: Builds command line “cmd.exe”, Creates process with bInheritHandles=1, Sets STARTUPINFOA.hStdInput/hStdOutput/hStdError to the socket handle, Waits for process termination. This provides a direct interactive shell if the controller can speak to the socket as a console stream.

Mode B: relay-based “secondary shell channel” with control handshake

handle_shell_io (0x403360) implements a more complex path that looks like it supports dynamic connection/relay behavior rather than only reusing the initial C2 socket.

Step 1, control header handshake (recv_shell_control_header, 0x403280)

On-wire control header:

#pragma pack(push, 1)
typedef struct {
 uint8_t magic; // must be 0x05
 uint8_t len; // number of payload bytes
 uint8_t payload[len]; // expected to include a NUL terminator
} ShellCtrlHeader;
#pragma pack(pop)

Behavior: reads 2 bytes + len payload bytes, validates magic==0x05 and len!=0, validates payload “looks like a C-string” by searching for ‘\0’ from the end, sends 2-byte ack: [0x05][0x00] if NUL found else [0x05][0xff]. This is a synchronization trigger for the next-stage negotiation.

Step 2, SOCKS-like relay parameter request (parse_shell_relay_params, 0x402f70)

Immediately after step 1, it reads and validates a structure that is strongly SOCKS5-inspired:

#pragma pack(push, 1)
typedef struct {
 uint8_t ver; // must be 0x05
 uint8_t cmd; // saved as `useRelay`
 uint8_t rsv; // must be 0x00
 uint8_t atyp; // 0x01 IPv4, 0x03 DOMAIN, 0x04 IPv6(16B)
 // dstaddr follows (size depends on atyp)
 // dstport follows (2 bytes)
} ShellRelayReqHdr;
#pragma pack(pop)

If atyp==0x01: reads 4 bytes IPv4 into controllerIp. If atyp==0x03: reads 1 byte domainLen, reads domainLen bytes, resolves via gethostbyname(), stores first IPv4 into controllerIp. If atyp==0x04: reads 16 bytes (IPv6-like); downstream connect-back code still appears IPv4-specific. Reads 2 bytes port into controllerPort. This function also performs response sends (including a distinct error response sequence when domain resolution fails), consistent with a mini-proxy/SOCKS-style negotiation.

Step 3, connect-back and relay loop

If useRelay == 1, handle_shell_io: calls connect_back_to_controller (0x402e80) to create a new socket and connect to the controller-provided endpoint. Notable detail: it uses *0xffff0000 as the IP source (a global/shared location used as a scratch/parameter channel) and controllerPort for the port. on success, sends a 10-byte “event packet” via send_shell_event (0x402e20), flips both sockets to non-blocking, and enters socket_relay_loop (0x402cf0) to relay data bidirectionally. Relay implementation details: socket_relay_loop uses select() + __WSAFDIsSet to detect readable sockets. relay_one_direction (0x402c70) transfers up to 0x80e8 bytes and then retries on WSAEWOULDBLOCK/WSAEINPROGRESS with sleeps.

Shell event packet (10 bytes)

send_shell_event (0x402e20) sends exactly 10 bytes:

#pragma pack(push, 1)
typedef struct {
 uint32_t magic_and_type; // (arg3 << 8) - 0x01000005 => low byte 
0x05, next byte = type
 uint32_t ip_be; // 32-bit IPv4 value
 uint16_t port_be; // 16-bit port
} ShellEventPacket;
#pragma pack(pop)

Used types observed in handle_shell_io: type 0 on successful connect-back path, type 7 on the failure/alternate path.


Operational picture: full C2 communication process

    Worker thread starts (backdoor_worker_thread), increases global thread count. Creates TCP socket → connects to 88.214.27.52:443 with timeout. Sends initial beacon string (contains NUDEew97834g and local config values separated by ) using the primary framed+obfuscated protocol. Enters command recv loop: receive length-prefixed payload, decode using “AssHole”-salted obfuscated-hex scheme, compare decoded command token to known strings, execute handler. Depending on command: run cmd.exe over the C2 socket, run a relay-negotiated shell channel using a secondary SOCKS-like control exchange, execute arbitrary commands via system() and return output, drop data to file, self-move and exit, or spawn additional workers to maintain 3 connections.

Key takeaways for defenders / responders (from a RE standpoint)

Primary network indicators: 88.214.27.52:443 TCP. Length-prefixed binary messages (4-byte length) containing obfuscated hex-like content salted with “AssHole”. Secondary shell negotiation begins with a 2-byte control header starting with 0x05 and then a SOCKS5-like request (ver=0x05, rsv=0, atyp in {1,3,4}). The command channel is token-driven; tokens are not human-readable but are fixed literals and can be used for detection after decoding. The reverse shell path is strong evidence: CreateProcessA(“cmd.exe”) with stdio set to the socket and inheritable handles.

First seen on securityboulevard.com

Jump to article: securityboulevard.com/2026/03/when-data-mining-conti-leaks-leads-to-actual-binaries-and-to-a-hardcoded-c2-with-an-encryption-key-on-tripod-com-part-five/

Loading

Share via Email
Share on Facebook
Tweet on X (Twitter)
Share on Whatsapp
Share on LinkedIn
Share on Xing
Copy link