逆向攻防世界CTF系列60-The_Maya_Society
64位无壳,zip下的其它文件浏览一遍,没发现什么线索,先看IDA
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
| __int64 __fastcall main(int a1, char **a2, char **a3){ size_t v3; size_t v4; size_t v6; size_t v7; __int64 v8; time_t timer; char v10[32]; char src[32]; char s[104]; __int64 v13; char v14[9]; char v15[9]; char v16[9]; char v17[9]; void (__fastcall *v18)(__int64); __int64 v19; char *v20; char *dest; int *v22; size_t v23; struct tm *tp;
strcpy(v10, ".fluxfingers.net"); timer = time(0LL); tp = localtime(&timer); strftime(s, 0x63uLL, "%Y-%m-%d", tp); v23 = strlen(s); sub_B5A(s, v23); v22 = &dword_2030B8; snprintf( v17, 9uLL, "%02x%02x%02x%02x", (unsigned __int8)dword_2030B8, BYTE1(dword_2030B8), BYTE2(dword_2030B8), HIBYTE(dword_2030B8)); v22 = &dword_2030C0; snprintf( v16, 9uLL, "%02x%02x%02x%02x", (unsigned __int8)dword_2030C0, BYTE1(dword_2030C0), BYTE2(dword_2030C0), HIBYTE(dword_2030C0)); v22 = &dword_2030B4; snprintf( v15, 9uLL, "%02x%02x%02x%02x", (unsigned __int8)dword_2030B4, BYTE1(dword_2030B4), BYTE2(dword_2030B4), HIBYTE(dword_2030B4)); v22 = &dword_2030BC; snprintf( v14, 9uLL, "%02x%02x%02x%02x", (unsigned __int8)dword_2030BC, BYTE1(dword_2030BC), BYTE2(dword_2030BC), HIBYTE(dword_2030BC)); snprintf(src, 0x21uLL, "%s%s%s%s", v17, v16, v15, v14); v3 = strlen(src); v4 = strlen(v10); dest = (char *)malloc(v3 + v4 + 1); if ( !dest ) return 1LL; *dest = 0; strcat(dest, src); strcat(dest, v10); v20 = (char *)sub_18A4(dest); if ( !v20 ) return 1LL; v6 = strlen(v20); v19 = sub_15E0(v20, v6, &v13); v7 = strlen(v20); v18 = (void (__fastcall *)(__int64))sub_15E0(v20, v7, &v13); if ( !v19 ) return 1LL; v8 = v19; sub_1858(v19, v13, v18); v18(v8); return 0LL; }
|
两眼一黑 T.T,硬着看
看到s和v10,time获取本机时间给s。
跟进sub_B5A
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
| void __fastcall sub_B5A(const void *a1, size_t a2) { int v2; int v3[64]; int v4[65]; int v5; __int64 v6; void *dest; unsigned int v8; int v9; unsigned int k; int v11; int v12; int v13; int v14; int j; int i;
dest = 0LL; v4[0] = 7; v4[1] = 12; v4[2] = 17; v4[3] = 22; v4[4] = 7; v4[5] = 12; v4[6] = 17; v4[7] = 22; v4[8] = 7; v4[9] = 12; v4[10] = 17; v4[11] = 22; v4[12] = 7; v4[13] = 12; v4[14] = 17; v4[15] = 22; v4[16] = 5; v4[17] = 9; v4[18] = 14; v4[19] = 20; v4[20] = 5; v4[21] = 9; v4[22] = 14; v4[23] = 20; v4[24] = 5; v4[25] = 9; v4[26] = 14; v4[27] = 20; v4[28] = 5; v4[29] = 9; v4[30] = 14; v4[31] = 20; v4[32] = 4; v4[33] = 11; v4[34] = 16; v4[35] = 23; v4[36] = 4; v4[37] = 11; v4[38] = 16; v4[39] = 23; v4[40] = 4; v4[41] = 11; v4[42] = 16; v4[43] = 23; v4[44] = 4; v4[45] = 11; v4[46] = 16; v4[47] = 23; v4[48] = 6; v4[49] = 10; v4[50] = 15; v4[51] = 21; v4[52] = 6; v4[53] = 10; v4[54] = 15; v4[55] = 21; v4[56] = 6; v4[57] = 10; v4[58] = 15; v4[59] = 21; v4[60] = 6; v4[61] = 10; v4[62] = 15; v4[63] = 21; v3[0] = -680876936; v3[1] = -389564586; v3[2] = 606105819; v3[3] = -1044525330; v3[4] = -176418897; v3[5] = 1200080426; v3[6] = -1473231341; v3[7] = -45705983; v3[8] = 1770035416; v3[9] = -1958414417; v3[10] = -42063; v3[11] = -1990404162; v3[12] = 1804603682; v3[13] = -40341101; v3[14] = -1502002290; v3[15] = 1236535329; v3[16] = -165796510; v3[17] = -1069501632; v3[18] = 643717713; v3[19] = -373897302; v3[20] = -701558691; v3[21] = 38016083; v3[22] = -660478335; v3[23] = -405537848; v3[24] = 568446438; v3[25] = -1019803690; v3[26] = -187363961; v3[27] = 1163531501; v3[28] = -1444681467; v3[29] = -51403784; v3[30] = 1735328473; v3[31] = -1926607734; v3[32] = -378558; v3[33] = -2022574463; v3[34] = 1839030562; v3[35] = -35309556; v3[36] = -1530992060; v3[37] = 1272893353; v3[38] = -155497632; v3[39] = -1094730640; v3[40] = 681279174; v3[41] = -358537222; v3[42] = -722521979; v3[43] = 76029189; v3[44] = -640364487; v3[45] = -421815835; v3[46] = 530742520; v3[47] = -995338651; v3[48] = -198630844; v3[49] = 1126891415; v3[50] = -1416354905; v3[51] = -57434055; v3[52] = 1700485571; v3[53] = -1894986606; v3[54] = -1051523; v3[55] = -2054922799; v3[56] = 1873313359; v3[57] = -30611744; v3[58] = -1560198380; v3[59] = 1309151649; v3[60] = -145523070; v3[61] = -1120210379; v3[62] = 718787259; v3[63] = -343485551; dword_2030B8 = 1732584193; dword_2030C0 = -271733879; dword_2030B4 = -1732584194; dword_2030BC = 271733878; for ( i = 8 * a2 + 1; i % 512 != 448; ++i ) ; v2 = i; i /= 8; dest = calloc(v2 / 8 + 64, 1uLL); memcpy(dest, a1, a2); *((_BYTE *)dest + a2) = 0x80; *(_DWORD *)((char *)dest + i) = 8 * a2; for ( j = 0; j < i; j += 64 ) { v6 = (__int64)dest + j; v14 = dword_2030B8; v13 = dword_2030C0; v12 = dword_2030B4; v11 = dword_2030BC; for ( k = 0; k <= 0x3F; ++k ) { if ( k > 0xF ) { if ( k > 0x1F ) { if ( k > 0x2F ) { v9 = v12 ^ (v13 | ~v11); v8 = (7 * (_BYTE)k) & 0xF; } else { v9 = v11 ^ v12 ^ v13; v8 = (3 * (_BYTE)k + 5) & 0xF; } } else { v9 = v13 & v11 | v12 & ~v11; v8 = (5 * (_BYTE)k + 1) & 0xF; } } else { v9 = v12 & v13 | v11 & ~v13; v8 = k; } v5 = v11; v11 = v12; v12 = v13; v13 += __ROL4__(*(_DWORD *)(4LL * v8 + v6) + v3[k] + v9 + v14, v4[k]); v14 = v5; } dword_2030B8 += v14; dword_2030C0 += v13; dword_2030B4 += v12; dword_2030BC += v11; } free(dest); }
|
这里其实是MD5算法,对它接触的不多,所以一开始没看出来,参考了攻防世界逆向高手题之The_Maya_Society_the maya society-CSDN博客
第一个64数组,和md5加密中的4大步骤16小步的移位S数字对应。
第二个64数组,符合md5的T[i]大小

下面是md5的实现,md5的448和ABCD是发现这个算法的关键,下次要注意
md5加密的结果存在了寄存器中,这里是把4四个寄存器以16进制显示出来,就是把md5加密结果输出为32位。
格式化输出:snprintf(src, 0x21uLL, “%s%s%s%s”, v17, v16, v15, v14);不用查也可以猜是v17,v16…给了src
v3,v4是长度,dest是v3+v4+1,然后是个strcat(dest, src);
C 库函数 char *strcat(char *dest, const char *src) 把 src 所指向的字符串追加到 dest 所指向的字符串的结尾。
sub_18A4进行处理,成了v20,后面没有用到dest,我们需要跟进看看sub_18A4
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
| char *__fastcall sub_18A4(const char *a1){ char *v2; ns_rr v3; ns_msg v4; char s[4096]; u_char v6[4104]; char *dest; size_t n; char *v9; char *src; int v11;
v11 = __res_query(a1, 1, 16, v6, 4096); if ( v11 < 0 ) return 0LL; ns_initparse(v6, v11, &v4); v11 = v4._counts[1]; ns_parserr(&v4, ns_s_an, 0, &v3); ns_sprintrr(&v4, &v3, 0LL, 0LL, s, 0x1000uLL); v2 = strchr(s, 34); 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; }
|


获取本地时间–>将时间MD5加密–>结果连接字符串.fluxfingers.net–>进入服务器后端函数sub_55E622E018A4(dest)
sub_15E0应该是最重要的部分
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
| char *__fastcall sub_15E0(__int64 a1, unsigned __int64 a2, _QWORD *a3) { char *v4; char *v5; char *v6; char v8; unsigned __int8 v9; unsigned __int8 v10; char v11; char v12[4]; char s[271]; char v14; char *v15; size_t size; unsigned __int64 i; char *v18;
memset(s, 128, 0x100uLL); for ( i = 0LL; i <= 0x3F; ++i ) s[(unsigned __int8)aAbcdefghijklmn[i]] = i; s[61] = 0; size = 0LL; for ( i = 0LL; i < a2; ++i ) { if ( s[*(unsigned __int8 *)(a1 + i)] != (char)0x80 ) ++size; } if ( (size & 3) != 0 ) return 0LL; v15 = (char *)malloc(size); v18 = v15; if ( !v15 ) return 0LL; size = 0LL; for ( i = 0LL; i < a2; ++i ) { v14 = s[*(unsigned __int8 *)(a1 + i)]; if ( v14 != (char)0x80 ) { v12[size] = *(_BYTE *)(a1 + i); *(&v8 + size) = v14; if ( ++size == 4 ) { v4 = v18++; *v4 = (v9 >> 4) | (4 * v8); v5 = v18++; *v5 = (v10 >> 2) | (16 * v9); v6 = v18++; *v6 = v11 | (v10 << 6); size = 0LL; } } } if ( v18 > v15 ) { if ( v12[2] == 61 ) { v18 -= 2; } else if ( v12[3] == 61 ) { --v18; } } *a3 = v18 - v15; return v15; }
|
aAbcdefghijklmn是ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/会不会是base编码?
下面是base64加解密代码,可以发现上面应该是base64解密
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
| void encodeBase64(char* str,int len,char** in){ char base64[65] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; int encodeStrLen = 1 + (len/3)*4 ,k=0; encodeStrLen += len%3 ? 4 : 0; char* encodeStr = (char*)(malloc(sizeof(char)*encodeStrLen)); for(int i=0;i<len;i++){ if(len - i >= 3){ encodeStr[k++] = base64[(unsigned char)str[i]>>2]; encodeStr[k++] = base64[((unsigned char)str[i]&0x03)<<4 | (unsigned char)str[++i]>>4]; encodeStr[k++] = base64[((unsigned char)str[i]&0x0f)<<2 | (unsigned char)str[++i]>>6]; encodeStr[k++] = base64[(unsigned char)str[i]&0x3f]; }else if(len-i == 2){ encodeStr[k++] = base64[(unsigned char)str[i] >> 2]; encodeStr[k++] = base64[((unsigned char)str[i]&0x03) << 4 | ((unsigned char)str[++i] >> 4)]; encodeStr[k++] = base64[((unsigned char)str[i]&0x0f) << 2]; encodeStr[k++] = '='; }else{ encodeStr[k++] = base64[(unsigned char)str[i] >> 2]; encodeStr[k++] = base64[((unsigned char)str[i] & 0x03) << 4]; encodeStr[k++] = '='; encodeStr[k++] = '='; } } encodeStr[k] = '\0'; *in = encodeStr; }
void decodeBase64(char* str,int len,char** in){ char base64[65] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; char ascill[129]; int k = 0; for(int i=0;i<64;i++){ ascill[base64[i]] = k++; } int decodeStrlen = len / 4 * 3 + 1; char* decodeStr = (char*)malloc(sizeof(char)*decodeStrlen); k = 0; for(int i=0;i<len;i++){ decodeStr[k++] = (ascill[str[i]] << 2) | (ascill[str[++i]] >> 4); if(str[i+1] == '='){ break; } decodeStr[k++] = (ascill[str[i]] << 4) | (ascill[str[++i]] >> 2); if(str[i+1] == '='){ break; } decodeStr[k++] = (ascill[str[i]] << 6) | (ascill[str[++i]]); } decodeStr[k] = '\0'; *in = decodeStr; }
|
最后sub_1858还要^0x25
1 2 3 4 5 6 7 8
| unsigned __int64 __fastcall sub_1858(__int64 a1, unsigned __int64 a2, __int64 a3){ for ( i = 0LL; ; ++i ){ result = i; if ( i >= a2 ) break; *(_BYTE *)(a3 + i) = *(_BYTE *)(a1 + i) ^ 0x25; } return result; }
|
获取到正确的日期———> md5加密后拼接.fluxfingers.net————>后端服务器域名解析sub_55E622E018A4(dest)并返回正确的响应内容————>传统base64解密———–>简单的逐位异或————–>得到flag
那么这个时间应该是多少呢,题目是玛雅社会
,图片下面有个2012!关于玛雅社会最著名的莫过于玛雅文明的2012年12月21日
的世界末日预言了
运行得flag即可。。
这题有点像misc+逆向,其实看懂那几个dns函数才是关键。
flag:flag{e3a03c6f3fe91b40eaa8e71b41f0db12}