Test file: https://adworld.xctf.org.cn/media/task/attachments/17574fc423474b93a0e6e6a6e583e003.zip
We will direct the current date to 2012-12-21 Linux, run the file can get flag, but still want to analyze.
1. Prepare
getting information
- 64 files
2.IDA Open
The main function main
signed __int64 __fastcall main(__int64 a1, char **a2, char **a3) { size_t v3; // rbx size_t v4; // rax unsigned __int64 v6; // rax unsigned __int64 v7; // rax unsigned __int64 v8; // rsi char *v9; // rdi time_t timer; // [rsp+18h] [rbp-128h] char v11[8]; // [rsp+20h] [rbp-120h] char src; // [rsp+40h] [rbp-100h] chars; // [Instructions] [+ 60H rbp-E0hF] unsigned __int64 v14; // [Instructions] [+ C8h rbp-78h] char v15; // [Instructions] [+ D4h rbp-6ch] char v16; // [Instructions] [+ DDH rbp-63h] char v17; // [Instructions] [+ E6 rbp-5Ah] char v18; // [Instructions] [+ EFH rbp-51As] char * v19; // [Instructions] [+ F8h rbp-48h] char * v20; // [Instructions + 100] [rbp-40h] char * v21; // [Instructions + 108] [rbp-38grieving] char *; // [Instructions + 110] [rbp-30h] intV23 *; // [RSP + 118h] [RBP-28H] size_t V24; // [RSP + 120h] [RBP-for 20 h] struct (TM) TP *; // [RSP + 128H] [RBP-for 18 h] strcpy (V11 , " .fluxfingers.net " ); Timer = Time (0LL); TP = localtime (& Timer); the strftime ( & S, 99uLL, " % Y-M-% D% " , TP); // the current date Add s V24 = strlen (& s); // V24 = 99 sub_B5A (& s, V24); // date for the MD5 s v23 = &dword_2030B8; // v23为加密后的日期的一部分 snprintf( &v18, 9uLL, "%02x%02x%02x%02x", (unsigned __int8)dword_2030B8, BYTE1(dword_2030B8), BYTE2(dword_2030B8), HIBYTE(dword_2030B8)); v23 = &dword_2030C0; snprintf( &v17, 9uLL, "%02x%02x%02x%02x", (unsigned __int8)dword_2030C0, BYTE1(dword_2030C0), BYTE2(dword_2030C0), HIBYTE(dword_2030C0)); v23 = &dword_2030B4; snprintf( &v16, 9uLL, "%02x%02x%02x%02x", (unsigned __int8)dword_2030B4, BYTE1(dword_2030B4), BYTE2(dword_2030B4), HIBYTE(dword_2030B4)); v23 = &dword_2030BC; snprintf( &v15, 9uLL, "%02x%02x%02x%02x", (unsigned __int8)dword_2030BC, BYTE1(dword_2030BC), BYTE2(dword_2030BC), HIBYTE(dword_2030BC)); snprintf(&src, 33uLL, "%s%s%s%s", &v18, &v17, &v16, &v15);// src为加密后的日期 v3 = strlen(&src); // v3=33 v4 = strlen(v11); // v4=16 dest = (char *)malloc(v3 + v4 + 1); if ( !dest ) return 1LL; *dest = 0; strcat(dest, &src); strcat(dest, v11); // dest为MD5(s)+".fluxfingers.net" v21 = sub_18A4(dest); if ( !v21 ) return 1LL; v6 = strlen(v21); v20 = sub_15E0((__int64)v21, v6, &v14); // base64解密 v7 = strlen(v21); v19 = sub_15E0((__int64)v21, v7, &v14); if ( !v20 ) return 1LL; v8 = v14; v9 = v20; sub_1858((__int64)v20, v14, (__int64)v19); // 异或0x25 ((void (__fastcall *)(char *, unsigned __int64))v19)(v9, v8); return 0LL; }
3. Code Analysis
3.1 MD5 Encryption
First, the program will get the time for the MD5 encryption code
for ( i = 8 * a2 + 1; i % 512 != 448; ++i ) ; v2 = i; i /= 8; dest = calloc(v2 / 8 + 64, 1uLL); memcpy(dest, a1, a2); // 将a1中的值存入dest中 *((_BYTE *)dest + a2) = -128; *(_DWORD *)((char *)dest + i) = 8 * a2; for ( j = 0; j < i; j += 64 ) { v132 = (char *)dest + j; v140 = dword_2030B8; v139 = dword_2030C0; v138 = dword_2030B4; v137 = dword_2030BC; for ( k = 0; k <= 0x3F; ++k ) // MD5码加密 { if ( k > 0xF ) { if ( k > 0x1F ) { if ( k > 0x2F ) { v135 = v138 ^ (v139 | ~v137); v134 = 7 * (_BYTE)k & 0xF; } else { v135 = v137 ^ v138 ^ v139; v134 = (3 * (_BYTE)k + 5) & 0xF; } } else { v135 = v139 & v137 | v138 & ~v137; v134 = (5 * (_BYTE)k + 1) & 0xF; } } else { v135 = v138 & v139 | v137 & ~v139; v134 = k; } v131 = v137; v137 = v138; v138 = v139; v139 += __ROL4__(*(_DWORD *)&v132[4 * v134] + *(&v3 + k) + v135 + v140, *(&v67 + k)); v140 = v131; } dword_2030B8 += v140; dword_2030C0 += v139; dword_2030B4 += v138; dword_2030BC +=v137; } Free (); }
3.2 Connection String
The time encrypted in conjunction with ".fluxfingers.net"
snprintf(&src, 33uLL, "%s%s%s%s", &v18, &v17, &v16, &v15);// src为加密后的日期 v3 = strlen(&src); // v3=33 v4 = strlen(v11); // v4=16 dest = (char *)malloc(v3 + v4 + 1); if ( !dest ) return 1LL; *dest = 0; strcat(dest, &src); strcat(dest, v11); // dest为MD5(s)+".fluxfingers.net"
3.3 transfer processing
The resulting string incoming v21 = sub_18A4 (dest); Processing
char *__fastcall sub_18A4(const char *a1) { char *v2; // rax ns_rr v3; // [rsp+10h] [rbp-24A0h] ns_msg v4; // [rsp+430h] [rbp-2080h] char s; // [rsp+480h] [rbp-2030h] u_char v6; // [rsp+1480h] [rbp-1030h] char *dest; // [rsp+2488h] [rbp-28h] size_t n; // [rsp+2490h] [rbp-20h] char *v9; // [rsp+2498h] [rbp-18h] char *src; // [rsp+24A0h] [rbp-10h] int V11; // [RSP + 24ACh] [RBP-4H] V11 = __res_query (A1, . 1 , 16 , & V6, 4096 ); // string as the incoming query the domain name, the length of a return message IF (V11 < 0 ) return 0LL; ns_initparse ( & V6, V11, & V4); // get the control handle V11 = v4._counts [ . 1 ]; ns_parserr ( & V4, ns_s_an, 0 , & V3); // parse specific region acquisition record type data ns_sprintrr (& v4, V3 &, 0LL, 0LL, & S, 0x1000uLL); // the field into a presentation format V2 = the strchr (& S, 34 is); src = v2 + 1; if ( v2 == (char *)-1LL ) return 0LL; v9 = strchr(src, 34); if ( !v9 ) return 0LL; n = v9 - src; dest = (char *)malloc(v9 - src + 1); strncpy(dest, src, n); dest[n] = 0; return dest; }
3.4 base64 decryption
And then the resulting string is decrypted base64
v6 = strlen(v21); v20 = sub_15E0((__int64)v21, v6, &v14); // base64解密 v7 = strlen(v21); v19 = sub_15E0((__int64)v21, v7, &v14);
char *__fastcall sub_15E0(__int64 a1, unsigned __int64 a2, _QWORD *a3) { char *v4; // rax char *v5; // rax char *v6; // rax _QWORD *v7; // [rsp+8h] [rbp-158h] char v8; // [rsp+28h] [rbp-138h] unsigned __int8 v9; // [rsp+29h] [rbp-137h] unsigned __int8 v10; // [rsp+2Ah] [rbp-136h] char v11; // [rsp+2Bh] [rbp-135h] char v12[2]; // [rsp+2Ch] [rbp-134h] char v13; // [rsp+2Eh] [rbp-132h] char v14; // [rsp+2Fh] [rbp-131h] char s[61]; // [rsp+30h] [rbp-130h] char v16; // [rsp+6Dh] [rbp-F3h] char v17; // [rsp+13Fh] [rbp-21h] char *v18; // [rsp+140h] [rbp-20h] size_t size; // [rsp+148h] [rbp-18h] unsigned __int64 i; // [rsp+150h] [rbp-10h] char *v21; // [rsp+158h] [rbp-8h] v7 = a3; memset(s, 128, 0x100uLL); for ( i = 0LL; i <= 0x3F; ++i ) s[(unsigned __int8)aAbcdefghijklmn[i]] = i; // base64解密 v16 = 0; size = 0LL; for ( i = 0LL; i < a2; ++i ) { if ( s[*(unsigned __int8 *)(a1 + i)] != -128 ) ++size; } if ( size & 3 ) return 0LL; v18 = (char *)malloc(size); v21 = v18; if ( !v18 ) return 0LL; size = 0LL; for ( i = 0LL; i < a2; ++i ) { v17 = s[*(unsigned __int8 *)(a1 + i)]; if ( v17 != -128 ) { v12[size] = *(_BYTE *)(a1 + i); *(&v8 + size++) = v17; if ( size == 4 ) { v4 = v21++; *v4 = (v9 >> 4) | 4 * v8; v5 = v21++; *v5 = (v10 >> 2) | 16 * v9; v6 = v21++; *v6 = v11 | (v10 << 6); size = 0LL; } } } if ( v21 > v18 ) { if ( v13 == 61 ) { v21 -= 2; } else if ( v14 == 61 ) { --v21; } } *v7 = v21 - v18; returnv18; }
.rodata:0000000000001E80 aAbcdefghijklmn db 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/%'
3.5 XOR operation
Finally, the decrypted string XOR 0x25
unsigned __int64 __fastcall sub_1858(__int64 a1, unsigned __int64 a2, __int64 a3) { unsigned __int64 result; // rax unsigned __int64 i; // [rsp+20h] [rbp-8h] for ( i = 0LL; ; ++i ) { result = i; if ( i >= a2 ) break; *(_BYTE *)(a3 + i) = *(_BYTE *)(a1 + i) ^ 0x25; } return result; }
3.6 summary
In fact, will be a date date
base64(sub_18A4(MD5(date)+".fluxfingers.net")).decode() ^ 0x25
So we can get to the correct time. Linked to the Mayan society, the most famous is the Mayan prophecy, so we can determine whether this time is 2012-12-21
4.get flag!
flag{e3a03c6f3fe91b40eaa8e71b41f0db12}