开始分析
用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]@1
char v5; // [sp+F0h] [bp-F0h]@1
memset(&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".Ni
puts("You are Right");
else
puts("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@5
char v3[32]; // [sp+10h] [bp-70h]@3
char v4[32]; // [sp+30h] [bp-50h]@3
char v5[40]; // [sp+50h] [bp-30h]@3
int v6; // [sp+78h] [bp-8h]@1
int i; // [sp+7Ch] [bp-4h]@1
i = 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)