When Data Mining Conti Leaks Leads to Actual Binaries and to a Hardcoded C2 With an Encryption Key on Tripod.com - Part Five
嗯,用户让我总结一下这篇文章的内容,控制在一百个字以内,而且不需要特定的开头。首先,我需要快速浏览文章,抓住主要信息。 文章看起来是关于一个恶意软件的分析。标题提到“当数据挖掘Conti泄露导致实际二进制文件和Tripod.com上的硬编码C2以及加密密钥”,所以这可能是一个网络后门或远程访问木马(RAT)。 接下来,文章详细分析了nowin.exe这个恶意软件的结构和功能。它有几个关键点:多线程C2信标、自定义协议、远程命令执行、交互式命令shell,还有SOCKS类似的控制交换。这些都是典型的RAT功能。 然后,作者讨论了它的运行机制,包括初始化过程、线程模型、C2基础设施和套接字操作。特别是它使用了非阻塞连接模式,并且有一个自定义的协议层,用“AssHole”作为标记进行轻量级混淆。 文章还详细描述了命令协议的具体令牌和行为,比如启动工作进程、执行命令并返回结果、下载有效载荷等。此外,它有两个反向shell模式:直接使用cmd.exe和基于SOCKS的中继通道。 最后,作者总结了防御者需要注意的关键点,包括网络指标和检测方法。 现在我要把这些信息浓缩到100字以内。重点应该是恶意软件的功能、通信机制以及防御要点。所以我会提到它是网络后门,多线程C2信标,自定义协议,“AssHole”混淆层,远程命令执行和交互式shell功能。同时还要提到它基于SOCKS的中继通道以及防御者需要注意的地方。 这样总结下来应该符合用户的要求。 </think> 该恶意软件nowin.exe是一个Windows网络后门程序,具备多线程C2信标功能、自定义协议(含"AssHole"混淆层)、远程命令执行及交互式cmd.exe shell功能。其通信机制采用长度前缀帧格式,并支持基于SOCKS协议的反向壳通道。防御者需关注其网络行为及固定令牌特征以进行检测与防御。 2026-3-25 12:41:0 Author: ddanchev.blogspot.com(查看原文) 阅读量:4 收藏

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

Worker thread redundancy (up to 3 concurrent)

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:

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

Framing

“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:

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)


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:

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

  1. Worker thread starts (backdoor_worker_thread), increases global thread count.
  2. Creates TCP socket → connects to 88.214.27.52:443 with timeout.
  3. Sends initial beacon string (contains NUDEew97834g and local config values separated by |) using the primary framed+obfuscated protocol.
  4. Enters command recv loop:
    • receive length-prefixed payload,
    • decode using "AssHole"-salted obfuscated-hex scheme,
    • compare decoded command token to known strings, execute handler.
  5. 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.

文章来源: https://ddanchev.blogspot.com/2026/03/when-data-mining-conti-leaks-leads-to_25.html
如有侵权请联系:admin#unsafe.sh