开始分析
用64位ida打开
shift f12
搜索字符串
看到
.rodata:000000000000203D 0000001A C flag{This_1s_f4cker_flag}
提交下发现不是flag
双击跳转到调用该数据的函数
f12反编译
int __cdecl main(int argc, const char **argv, const char **envp)
{
char s; // [sp+0h] [bp-1E0h]@1char v5; // [sp+F0h] [bp-F0h]@1memset(&s, 0, 0x1EuLL);printf("Please Input Key: ", 0LL);scanf("%s", &v5);encode(&v5, (__int64)&s);if ( strlen(&v5) == key ){
if ( !strcmp(&s, enflag) ) // izwhroz""w"v.K".Niputs("You are Right");elseputs("flag{This_1s_f4cker_flag}");}return 0;
}
程序逻辑如下
首先需要你输入一个字符串
程序通过encode函数对其加密并把结果地址交给s变量
当输入字符串长度等于key(值为18)时
进行s与enflag(值为izwhroz"“w"v.K”.Ni)的比较
结果正确则现实You are Right
故输入的字符串就是flag
encode 加密函数如下
int __fastcall encode(const char *a1, __int64 a2)
{
int result; // eax@5char v3[32]; // [sp+10h] [bp-70h]@3char v4[32]; // [sp+30h] [bp-50h]@3char v5[40]; // [sp+50h] [bp-30h]@3int v6; // [sp+78h] [bp-8h]@1int i; // [sp+7Ch] [bp-4h]@1i = 0;v6 = 0;if ( strlen(a1) == key_18 ) // key=lenth=18{
for ( i = 0; i < key_18; i += 3 ) // 0 3 6 9 12 15 18{
v5[i] = key_18 ^ (a1[i] + 6);v4[i + 1] = (a1[i + 1] - 6) ^ key_18;v3[i + 2] = a1[i + 2] ^ 6 ^ key_18;*(_BYTE *)(a2 + i) = v5[i];*(_BYTE *)(a2 + i + 1LL) = v4[i + 1];*(_BYTE *)(a2 + i + 2LL) = v3[i + 2]; // string a2= izwhroz""w"v.K".Ni}result = a2;}else{
result = puts("Your Length is Wrong");}return result;
}
看到函数把字符串分为三个字符一组
分别进行异或运算加密
因为异或同一个数两次的值等于异或运算前的数
故而对encode函数逆向
代码如下
a2 = "izwhroz\"\"w\"v.K\".Ni"
s=""
for i in range(0,18,3):s+=chr((ord(a2[i])^18)-6)s+=chr((ord(a2[i+1])^18)+6)s+=chr(ord(a2[i+2])^18^6)print(s)