逆向攻防世界CTF系列60-The_Maya_Society
逆向攻防世界CTF系列60-The_Maya_Society
64位无壳,zip下的其它文件浏览一遍,没发现什么线索,先看IDA
__int64 __fastcall main(int a1, char **a2, char **a3){
size_t v3; // rbx
size_t v4; // rax
size_t v6; // rax
size_t v7; // rax
__int64 v8; // rdi
time_t timer; // [rsp+18h] [rbp-128h] BYREF
char v10[32]; // [rsp+20h] [rbp-120h] BYREF
char src[32]; // [rsp+40h] [rbp-100h] BYREF
char s[104]; // [rsp+60h] [rbp-E0h] BYREF
__int64 v13; // [rsp+C8h] [rbp-78h] BYREF
char v14[9]; // [rsp+D4h] [rbp-6Ch] BYREF
char v15[9]; // [rsp+DDh] [rbp-63h] BYREF
char v16[9]; // [rsp+E6h] [rbp-5Ah] BYREF
char v17[9]; // [rsp+EFh] [rbp-51h] BYREF
void (__fastcall *v18)(__int64); // [rsp+F8h] [rbp-48h]
__int64 v19; // [rsp+100h] [rbp-40h]
char *v20; // [rsp+108h] [rbp-38h]
char *dest; // [rsp+110h] [rbp-30h]
int *v22; // [rsp+118h] [rbp-28h]
size_t v23; // [rsp+120h] [rbp-20h]
struct tm *tp; // [rsp+128h] [rbp-18h]
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
void __fastcall sub_B5A(const void *a1, size_t a2)
{
int v2; // kr00_4
int v3[64]; // [rsp+20h] [rbp-240h]
int v4[65]; // [rsp+120h] [rbp-140h]
int v5; // [rsp+224h] [rbp-3Ch]
__int64 v6; // [rsp+228h] [rbp-38h]
void *dest; // [rsp+230h] [rbp-30h]
unsigned int v8; // [rsp+23Ch] [rbp-24h]
int v9; // [rsp+240h] [rbp-20h]
unsigned int k; // [rsp+244h] [rbp-1Ch]
int v11; // [rsp+248h] [rbp-18h]
int v12; // [rsp+24Ch] [rbp-14h]
int v13; // [rsp+250h] [rbp-10h]
int v14; // [rsp+254h] [rbp-Ch]
int j; // [rsp+258h] [rbp-8h]
int i; // [rsp+25Ch] [rbp-4h]
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
char *__fastcall sub_18A4(const char *a1){
char *v2; // rax
ns_rr v3; // [rsp+10h] [rbp-24A0h] BYREF
ns_msg v4; // [rsp+430h] [rbp-2080h] BYREF
char s[4096]; // [rsp+480h] [rbp-2030h] BYREF
u_char v6[4104]; // [rsp+1480h] [rbp-1030h] BYREF
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);
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应该是最重要的部分
char *__fastcall sub_15E0(__int64 a1, unsigned __int64 a2, _QWORD *a3)
{
char *v4; // rax
char *v5; // rax
char *v6; // rax
char v8; // [rsp+28h] [rbp-138h] BYREF
unsigned __int8 v9; // [rsp+29h] [rbp-137h]
unsigned __int8 v10; // [rsp+2Ah] [rbp-136h]
char v11; // [rsp+2Bh] [rbp-135h]
char v12[4]; // [rsp+2Ch] [rbp-134h]
char s[271]; // [rsp+30h] [rbp-130h] BYREF
char v14; // [rsp+13Fh] [rbp-21h]
char *v15; // [rsp+140h] [rbp-20h]
size_t size; // [rsp+148h] [rbp-18h]
unsigned __int64 i; // [rsp+150h] [rbp-10h]
char *v18; // [rsp+158h] [rbp-8h]
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解密
void encodeBase64(char* str,int len,char** in){
char base64[65] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
//读取3个字节zxc,转换为二进制01111010 01111000 01100011
//转换为4个6位字节,011110 100111 100001 100011
//不足8位在前补0,变成00011110 00100111 00100001 00100011
//若剩余的字节数不足以构成4个字节,补等号
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;
}
/**
* 解码既编码的逆过程,先找出编码后的字符在编码之前代表的数字
* 编码中将3位个字符变成4个字符,得到这4个字符的每个字符代表的原本数字
* 因为在编码中间每个字符用base64码表进行了替换,所以这里要先换回来
* 在对换回来的数字进行位运算使其还原成3个字符
*/
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
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}
- 感谢你赐予我前进的力量