f5发现主函数逻辑很简单,直接找到关键函数进入:
void *__fastcall RxEncode(const char *a1, int a2) { void *result; // rax int v3; // [rsp+18h] [rbp-38h] signed int v4; // [rsp+1Ch] [rbp-34h] int v5; // [rsp+20h] [rbp-30h] signed int v6; // [rsp+24h] [rbp-2Ch] int v7; // [rsp+28h] [rbp-28h] int v8; // [rsp+28h] [rbp-28h] signed int i; // [rsp+2Ch] [rbp-24h] _BYTE *v10; // [rsp+30h] [rbp-20h] void *s; // [rsp+38h] [rbp-18h] v3 = 3 * (a2 / 4); v4 = 0; v5 = 0; if ( a1[a2 - 1] == '=' ) v4 = 1; if ( a1[a2 - 2] == '=' ) ++v4; if ( a1[a2 - 3] == '=' ) ++v4; if ( v4 == 3 ) { v3 += 2; } else if ( v4 <= 3 ) { if ( v4 == 2 ) { v3 += 3; } else if ( v4 <= 2 ) { if ( v4 ) { if ( v4 == 1 ) v3 += 4; } else { v3 += 4; } } } s = malloc(v3); if ( s ) { memset(s, 0, v3); v10 = s; while ( v5 < a2 - v4 ) { v6 = 0; v7 = 0; while ( v6 <= 3 && v5 < a2 - v4 ) { v7 = (v7 << 6) | (char)find_pos(a1[v5]); ++v6; ++v5; } v8 = v7 << 6 * (4 - v6); for ( i = 0; i <= 2 && i != v6; ++i ) *v10++ = v8 >> 8 * (2 - i); } *v10 = 0; result = s; } else { puts("No enough memory."); result = 0LL; } return result; }拿到之后乍一看感觉很像base64,输入32位转成24位,但其实仔细看下发现不同。
这里选择直接爆破:
table="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz01234{}789+/=" c="9E9B9C B5FE70 D30FB2 D14F9C 027FAB DE5965 63E740 9DCDFA" c=c.split() for i in range(len(c)): c[i]=eval("0x"+c[i]) print(c) for x in c: t=0 for i in range(len(table)): for j in range(len(table)): for k in range(len(table)): for l in range(len(table)): t=(0<<6)|i t=(t<<6)|j t=(t<<6)|k t=(t<<6)|l if(t==x): print(table[i]+table[j]+table[k]+table[l]) print(i) print(j) print(k) print(l) ''' npuctf{w0w+y0U+cAn+r3lllY+dAnc3} '''得到的结果把带有=的删掉,剩下的拼接起来就是flag~
通过三条加密:
直接上脚本吧:
AOX = [78, 78, 85, 59, 80, 64, 115, 46, 98, 96, 117, 53, 97, 108, 125] v = [2, 3, 4, 5] for i in range(len(AOX)): AOX[i] ^= v[i % 4] AOX[i] += v[i % 4] for i in range(len(AOX)): print(chr(AOX[i]), end="") ''' NPUCTF{0bfu5er} '''
