## Tracking the entire iceberg ###### - long-term APT malware C2 protocol emulation and scanning ----- ## Who am I? ----- ## Motivation ----- ## Overview ----- ## Target Summary ###### Unique feature Server-mode Multiple protocol listening at a single port ----- # Winnti 4.0 ----- ## Winnti Malware ----- ## Winnti Malware 4.0 ###### Macnica Networks version 4.0 Version 3.0 Version 4.0 Initial component Dropper Loader and DAT file Initial encryption DES AES algorithm ###### Initial encryption key cracking ###### Easy Hard ###### Worker encryption 1-byte XOR and nibble swap DPAPI or AES with host ----- ## Winnti Malware 4.0 (Cont.) ###### struct struc_work_config { char campaignID[64]; char MAC_addr[6]; int c2_proto; // enum_proto ... } enum enum_proto { none = 0x0, TCP = 0x1, HTTP = 0x2, HTTPS = 0x3, TLS = 0x4, UDP = 0x5, ----- ## C2 Protocol ----- ## Packet Format ###### struct struc_custom_header { __int16 temp_key_seed; __int16 unk_word; // initial value is 2 __int16 signature; // 0x45DB int payload_len; }; ###### struct struc_custom_payload_init { int payload_type; // request:0xEE775BAA/0x4563CEFA/0x5633CBAD, response:0xFACEB007/0x5633CBAD int unk_dword; // request:0, response:0xC350/0xC352 GUID guid; char null_bytes[14]; __int16 seq_num; // starting from 1 __int16 null_word; }; ----- ## Encryption ----- ## HTTP Protocol ###### Customized packet size ----- ## HTTP: Size Calculation from Cookie Value ###### $ python validate_cookie.py 640ABEFB16D2CE36E7E83E1B8BEF31B2500ABEFB dw0=0xfbbe0a64, dw1=0x36ced216, dw2=0x1b3ee8e7, dw3=0xb231ef8b, dw4=0xfbbe0a50 The cookie value validated. dword key = 0x34 ----- ## HTTP: Dummy Data in GET Request ###### Size = 0 Size = 0 ----- ## Behavior After the Initial Handshake ###### // e.g., cmd_ID=5 & dispatch_ID=1 order to send victim info __int16 cmd_ID; __int16 dispatch_ID; ... int additional_data_len; struc_data_cmd1 additional_data; // flexible size }; ----- ### Scanner Implementation ###### • Internet-wide port scan • TCP 443 & 80 ZMap • UDP 443 & 53 (customized packet required) ###### Stand-alone Python Script ###### • HTTP(S): Decode and Validate Cookie value • Others: Get suspicious responses with the same size and different key • Decrypt response’s ##### IDAPython customized packet ###### • Validate signature ##### AppCall d l d i i ----- ## How to Differentiate Server-mode Infections and C2 Servers |Server-mode: the same GUID as client, sequence number incremented|Col2|Col3| |---|---|---| |||| |||| |C2: null GUID, sequence number reset|Col2|Col3| |---|---|---| |||| ###### [DEBUG] server header: unknown word = 0x2, header signature = 0x45db, payload length = 0x2a [*] server payload: payload type = 0xfaceb007 unknown dword = 0x0 GUID = 00000000-0000 ----- ## Result: Population by Protocol ###### UDP 5% TCP 11% TLS 35% HTTP 20% HTTPS 29% TLS HTTPS HTTP TCP UDP ###### HTTPS 29% ###### 11% HTTP 20% ###### UDP 5% TCP 11% HTTP ----- ### Result: Change in Number of Active C2s ###### 25 ###### 20 15 ###### 1st disclosure ###### 10 5 |2nd 1st disclosure disclosure|Col2|Col3|Col4| |---|---|---|---| ||||2nd disclosure| ||||| ||1st disclosure||| ||||| ###### 2nd disclosure ###### 0 ###### period ----- ## Public Reports Related to Winnti 4.0 C2s ----- # ShadowPad ----- ## ShadowPad Malware ----- ## C2 Protocol ###### TCP HTTP(S)/UDP Key size 4 2 Header size 0x14 8 ###### Payload size in the initial handshake packet ###### Up to 0x3F HTTP(S): Up to 0x1F, ###### UDP: 0x10 ----- ## C2 Protocol (Cont.) ###### Variant name C2 protocol Config size Attribution Variant1 TCP/UDP 0x896 APT41 Positive Technologies (aka ScatterBee) Variant2 HTTP(S) 0x85C Tonto Team ESET Variant3 HTTP(S) 0x85C unknown Positive ----- ## TCP Protocol ###### struct struc_common_header { int session_key; int plugin_and_cmd_id; // plugin_id (0x68) << 16 + cmd_id (0x51) by Variant1 int module_code; // 0 int payload_size_compressed; // QuickLZ int payload_size_original; } ----- ## TCP Protocol (Cont.) ###### Dr.WEB white paper ----- ## HTTP(S) and UDP Protocols ###### struct struc_proto_header { __int16 session_key; __int16 type; // 0 in HTTP, req=0x1001/res=(0x2002|0x5005) in UDP __int16 session_src_id; // random 2 bytes, generated by both client/server __int16 session_dst_id; // req=0, res=client's session_src_id }; ----- ## HTTP(S) and UDP Protocols (Cont.) ###### HTTP(S) packet encoding by Variant2 ###### HTTP(S) k di b V i 3 ----- ## HTTP(S) and UDP Protocols (Cont.) ###### struc_proto_header ----- ## Scanner Implementation ###### Scanning start period Target protocol/port/variant September 2021 HTTP/443 (Variant2 & Variant3) October 2021 TCP/443 & UDP/53 (Variant1) June 2022 UDP/443 (Variant1), HTTP/80 (Variant3) ----- ## Scanner Implementation (Cont.) #### ZMap • Internet-wide port scan ###### • Targets as mentioned previously #### Stand-alone Python Script ###### • Decode the response packet • Validate the decoded values • TCP: payload size fields • HTTP(S)/UDP: type and session_dst_id ----- ## Multiple Protocol Listening at a Single Port ----- ## Multiple Protocol Listening at a Single Port (Cont.) ###### $ ./c2fs.py -d -l corpus/query.txt -p 443 -f sp http Variant2 .. [*] malware options: family = ShadowPad; targeted protocol = http (version = Variant2) [*] ShadowPad specific options: version = Variant2; key size = 2; key endian = big; header size = 0x8; header type = 0x0; client session ID = 53978 [D] POST: http://137.220.185.203:443/ (proxy={}, stream=True, timeout=30) [+] 137.220.185.203,active,client session ID matched (type=0x0) .. $ ./c2fs.py -d -l corpus/query.txt -p 443 -f sp https Variant2 .. [*] malware options: family = ShadowPad; targeted protocol = https (version = Variant2) [*] ShadowPad specific options: version = Variant2; key size = 2; key endian = big; header size = 0x8; header type = 0x0; client session ID = 52256 [D] POST: https://137.220.185.203:443/ (proxy={}, stream=True, timeout=30) [+] 137 220 185 203 active client session ID matched (type=0x0) ----- ## Result: Population by Variant ###### Variant2 10% Variant1 Variant3 49% 41% Variant1 Variant3 Variant2 ###### Variant1 49% ###### Variant2 10% Variant3 41% ###### Variant2 10% ----- ### Result: Change in Number of Active C2s ###### System 25 ###### System issue ###### 20 15 ###### 10 5 |Col1|System|Col3| |---|---|---| |issue|issue|| |||| |||| |||| ###### 0 ###### period ----- ## Samples Communicating with C2 IPs ----- ## Incident Response Case Triggered by Discovered C2 ----- # Notes for Internet-wide C2 Scanning ----- ## How to Get Input (Port Scan) Data ###### ZMap Shodan CenSys TCP/10333 4,940,037 4 1,306 TCP/55555 3 199 856 86 486 497 ###### Note: The data was ll d 2021/11 ----- ## Anonymization ###### Tor Commercial VPN service Cost Free Non-free Supported protocols TCP TCP/UDP Risk of being blocked Hi h L ----- ## Anonymization (Cont.) ----- # Wrap-up ----- ## Wrap-up ----- ## Acknowledgement ----- ## Indicators of Compromise ###### Indicator Type Context 0a3279bb86ff0de24c2a4b646f24ffa196ee639cc23c64a SHA256 Winnti 4.0 dat file 044e20f50b93bda21 03b7b511716c074e9f6ef37318638337fd7449897be99 SHA256 ShadowPad Variant1 9505d4a3219572829b4 aef610b66b9efd1fa916a38f8ffea8b988c20c5deebf4db8 SHA256 ShadowPad Variant2 3b6be63f7ada2cc0 d011130defd8b988ab78043b30a9f7e0cada5751064b3 SHA256 ShadowPad Variant3 975a19f4de92d2c0025 1ded9878f8680e1d91354cbb5ad8a6960efd6ddca2da1 SHA256 Spyder communicating with the 57eb4c1ef0f0430fd5f ShadowPad C2 (156.240.104.149) 536def339fefa0c259cf34f809393322cdece06fc4f2b37f SHA256 ReverseWindow communicating 06136375b073dff3 with the ShadowPad C2 (43.129.188.223) 9447b75af497e5a7f99f1ded1c1d87c53b5b59fce224a3 SHA256 ShadowPad Variant1 25932ad55eef9e0e4a communicating with the |Indicator|Type|Context| |---|---|---| |0a3279bb86ff0de24c2a4b646f24ffa196ee639cc23c64a 044e20f50b93bda21|SHA256|Winnti 4.0 dat file| |03b7b511716c074e9f6ef37318638337fd7449897be99 9505d4a3219572829b4|SHA256|ShadowPad Variant1| |aef610b66b9efd1fa916a38f8ffea8b988c20c5deebf4db8 3b6be63f7ada2cc0|SHA256|ShadowPad Variant2| |d011130defd8b988ab78043b30a9f7e0cada5751064b3 975a19f4de92d2c0025|SHA256|ShadowPad Variant3| |1ded9878f8680e1d91354cbb5ad8a6960efd6ddca2da1 57eb4c1ef0f0430fd5f|SHA256|Spyder communicating with the ShadowPad C2 (156.240.104.149)| |536def339fefa0c259cf34f809393322cdece06fc4f2b37f 06136375b073dff3|SHA256|ReverseWindow communicating with the ShadowPad C2 (43.129.188.223)| ----- ## Questions? -----