[HUBUCTF 2022 新生赛]simple_RE
[HUBUCTF 2022 新生赛]simple_RE
int __cdecl main(int argc, const char **argv, const char **envp) { int v4; // [rsp+24h] [rbp-44h] BYREF void *Buf1; // [rsp+28h] [rbp-40h] BYREF char v6[56]; // [rsp+30h] [rbp-38h] BYREF sub_401770(argc, argv, envp); printf("please input the flag:"); scanf("%s", v6); // v6是flag Buf1 = 0i64; // 初始化Buf1 sub_401570(v6, &Buf1, &v4); // v6进行base64编码,但是不是根据A-Z,...,而是根据这串字符编码qvEJAfHmUYjBac+u8Ph5n9Od17FrICL/X0gVtM4Qk6T2z3wNSsyoebilxWKGZpRD if ( !memcmp(Buf1, a5mc58bphliax7j, v4) ) // 对这串字符串"5Mc58bPHLiAx7J8ocJIlaVUxaJvMcoYMaoPMaOfg15c475tscHfM/8=="进行微改变的base64解码,即得flag printf("\nsuccess!"); else printf("\nfailed!"); if ( Buf1 ) free(Buf1); return 0; }
v6是flag,经过sub_401570函数加密,得到a5mc58bphliax7j对应的加密后的值,即加密后的flag值
这里的重点就是sub_401570函数,我们需要了解经过怎么样的加密,接下来我们点进去看看
__int64 __fastcall sub_401570(const char *a1, _QWORD *a2, int *a3) { int v6; // r15d int v7; // r12d int v8; // r13d __int64 v9; // r14 _BYTE *v10; // rax _BYTE *v11; // r9 __int64 v12; // r8 char v13; // cl char v14; // r11 char v15; // r10 __int64 result; // rax v6 = strlen(a1); v7 = v6 % 3; if ( v6 % 3 ) { v8 = 4 * (v6 / 3) + 4; v9 = v8; v10 = malloc(v8 + 1i64); v10[v8] = 0; if ( v6 <= 0 ) goto LABEL_5; } else { v8 = 4 * (v6 / 3); v9 = v8; v10 = malloc(v8 + 1i64); v10[v8] = 0; if ( v6 <= 0 ) goto LABEL_8; } v11 = v10; v12 = 0i64; do { v11 += 4; v13 = a1[v12]; *(v11 - 4) = aQvejafhmuyjbac[v13 >> 2]; v14 = a1[v12 + 1]; *(v11 - 3) = aQvejafhmuyjbac[(v14 >> 4) | (16 * v13) & 0x30]; v15 = a1[v12 + 2]; v12 += 3i64; *(v11 - 2) = aQvejafhmuyjbac[(v15 >> 6) | (4 * v14) & 0x3C]; *(v11 - 1) = aQvejafhmuyjbac[v15 & 0x3F]; } while ( v6 > (int)v12 ); LABEL_5: if ( v7 == 1 ) { v10[v9 - 2] = 61; v10[v9 - 1] = 61; } else if ( v7 == 2 ) { v10[v9 - 1] = 61; } LABEL_8: *a2 = v10; result = 0i64; *a3 = v8; return result; }
看不懂不要紧,为了这个,我专门用一天时间消化base64编码与解码的原理,链接如下:base64详解 - Zer0o - 博客园 (cnblogs.com)
这段代码一看移位运算,或运算,与运算,与base64编码一样,只不过base64是根据ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/编码,而这里修改为aQvejafhmuyjbac对应的字符串
双击进入,知道这个base64是根据这串字符串编码的qvEJAfHmUYjBac+u8Ph5n9Od17FrICL/X0gVtM4Qk6T2z3wNSsyoebilxWKGZpRD,而不是ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/
简单捋一下,就是将flag进行变异的base64编码,编码结果为a5mc58bphliax7j对应的数据,即5Mc58bPHLiAx7J8ocJIlaVUxaJvMcoYMaoPMaOfg15c475tscHfM/8==
#include <stdio.h> #include <string.h> #include <stdlib.h> char base64CharsArr[] = "qvEJAfHmUYjBac+u8Ph5n9Od17FrICL/X0gVtM4Qk6T2z3wNSsyoebilxWKGZpRD"; void base64decode(char str[]) { int length = strlen(str); int padding = 0; // 计算填充字符数量 if (str[length - 1] == '=') { padding++; if (str[length - 2] == '=') padding++; } // 计算解码后的字符数量 int decodedLength = (length * 3) / 4 - padding; // 分配存储解码结果的内存 char* decodedStr = (char*)malloc(decodedLength + 1); int outIndex = 0; for (int i = 0; i < length; i += 4) { char char1 = -1, char2 = -1, char3 = -1, char4 = -1; // 查找每个字符在Base64字符集中的索引 for (int j = 0; j < 64; j++) { if (base64CharsArr[j] == str[i]) { char1 = j; break; } } for (int j = 0; j < 64; j++) { if (base64CharsArr[j] == str[i + 1]) { char2 = j; break; } } for (int j = 0; j < 64; j++) { if (base64CharsArr[j] == str[i + 2]) { char3 = j; break; } } for (int j = 0; j < 64; j++) { if (base64CharsArr[j] == str[i + 3]) { char4 = j; break; } } // 解码并存储结果 decodedStr[outIndex++] = (char1 << 2) | ((char2 & 0x30) >> 4); if (char3 != -1) decodedStr[outIndex++] = ((char2 & 0xf) << 4) | ((char3 & 0x3c) >> 2); if (char4 != -1) decodedStr[outIndex++] = ((char3 & 0x3) << 6) | char4; } // 添加字符串结束符 decodedStr[decodedLength] = '\0'; printf("Decoded string: %s\n", decodedStr); // 释放内存 free(decodedStr); } int main() { char str[100]="5Mc58bPHLiAx7J8ocJIlaVUxaJvMcoYMaoPMaOfg15c475tscHfM/8=="; // Example base64 encoded string base64decode(str); return 0; }