使用IDA打开程序分析。
Str1 = '9';
v29 = 'n';
v30 = '?';
v31 = '<';
v32 = '>';
v33 = '<';
v34 = '@';
v35 = 'm';
v36 = '=';
v37 = '8';
v38 = 'i';
v39 = '>';
v40 = 'i';
v41 = '>';
v42 = '?';
v43 = '8';
v44 = '@';
v45 = 'm';
v46 = 'k';
v47 = '=';
v48 = '<';
v49 = 'i';
v50 = 'j';
v51 = ';';
v52 = ':';
v53 = '?';
v54 = 'i';
v55 = '9';
v56 = '>';
v57 = ';';
v58 = 'l';
v59 = '=';
v60 = '=';
v61 = ';';
v62 = '>';
v63 = 'j';
v64 = '?';
v65 = 'k';
v66 = 'm';
v67 = 'l';
v68 = 0;
v71encode = 0;
j_memset(&Dst, 0, 0xFFu);
v23 = 0;
j_memset(&v24, 0, 0xFFu);
v20 = 0;
v21 = 0;
v22 = 0;
v16 = 0x1CD6202D;
v17 = 830024388;
v15 = 0;
j_memset(&input, 0, 0x14u);
j_memset(&v27, 0, 9u);
j_memset(&v18, 0, 8u);
j_memcpy(&Src, "yeyeyess", 8u);
j_memcpy(&v13, &Src, 8u);
sub_411488(std::cout, "Please input your key:");
sub_411109(std::cin, &input);
if ( j_strlen(&input) == 15 && SBYTE1(v70) == 95 )// 输入长度要求为15
{
v19 = strstr_0(&input, "_"); // 判断_是否是其子字符串,如果是返回首次出现的地址
j_memcpy(&v27, v19 + 1, 8u); // 拷贝字符串输入_后面8个字符串
j_memcpy(&v18, &v27, 8u);
v8 = 6;
BYTE1(v70) = 0;
for ( i = 0; i < 6; ++i )
{
if ( *(&input + i) < '0' || *(&input + i) > '9' )// 输入字符要在0-9之间
{
sub_41157D("Wrong\n", v7);
goto LABEL_24;
}
}
sub_411546((int)&v71); // 给v71赋值
for ( j = 0; j < j_strlen(&input); ++j )
sub_41155A((int)&v71, *(&input + j));
sub_411550((int)&v71, (int)&v23); // v71进行一系列操作后给v23
for ( k = 0; k < 20; ++k )
wsprintfA(&v71encode + 2 * k, "%02x", (unsigned __int8)*(&v23 + k));// 格式化字符串数据不足2位是再前加0进行不足,并传递给encode
sub_4111F9((int)&Str1); // 将每个字符减去8
if ( !j_strcmp(&Str1, &v71encode) )
{
sub_411555((int)&v18, (int)&v13);
for ( l = 0; l < 2; ++l )
{
if ( *(&v16 + l) != *(&v18 + l) )
{
v3 = sub_411488(std::cout, "Wrong");
std::basic_ostream<char,std::char_traits<char>>::operator<<(v3, sub_4110A5);
goto LABEL_24;
}
}
v4 = sub_411488(std::cout, "Good flag is your input");
std::basic_ostream<char,std::char_traits<char>>::operator<<(v4, sub_4110A5);
}
else
{
v2 = sub_411488(std::cout, "Wrong");
std::basic_ostream<char,std::char_traits<char>>::operator<<(v2, sub_4110A5);
}
}
else
{
v0 = sub_411488(std::cout, "Wrong!");
std::basic_ostream<char,std::char_traits<char>>::operator<<(v0, sub_4110A5);
}
首先输入长度为要求为15,之后拷贝字符串_后面的8个字符前6个字符为数字0-9,由此可以判断,输入的为6个数字_8个字符。
之后查看411546函数
signed int __cdecl sub_414290(_DWORD *a1)
{
signed int result; // eax
signed int i; // [esp+D0h] [ebp-8h]
for ( i = 0; i < 80; ++i )
a1[i + 10] = 0;
a1[1] = 0;
*a1 = 0;
a1[2] = 0x67452301;
a1[3] = 0xEFCDAB89;
a1[4] = 0x98BADCFE;
a1[5] = 0x10325476;
result = 16;
a1[6] = 0xC3D2E1F0;
return result;
}
发现了类似MD5的数据特征,使用peid的插件进行查阅。发现为SHA1加密和黄金比例
由此可知数据经过了SHA-1加密之后与str1进行比较然而函数414390处对str1进行了处理,
将其没个字符减去8.
void __cdecl sub_414390(int str1)
{
unsigned int v1; // eax
char v2; // cl
signed int i; // [esp+D0h] [ebp-8h]
for ( i = 0; i < 40; ++i )
{
v1 = i & 0x80000000; // v1始终为0
if ( (i & 0x80000000 & 0x80000000) != 0 )
v1 = 0;
if ( v1 )
v2 = *(_BYTE *)(i + str1) + 3;
else
v2 = *(_BYTE *)(i + str1) - 8;
*(_BYTE *)(i + str1) = v2;
}
}
将字符用脚本处理一下得到新字符
1f74648e50a6a6708ec54ab327a163d5536b7ced
拿去SHA-1解密得到字符串122333正好对应着前面的6个字符,正好后面还差一个算法没有得到解决,必然对应着后面的8个字符 。
比较完sha-1之后就是函数411555进入这个函数
signed int __cdecl sub_419580(unsigned int *input_8, _DWORD *a2)
{
signed int v2; // ST10_4
signed int result; // eax
signed int v4; // [esp+D8h] [ebp-38h]
int delata; // [esp+F0h] [ebp-20h]
unsigned int v6; // [esp+FCh] [ebp-14h]
unsigned int v7; // [esp+108h] [ebp-8h]
v7 = *input_8;
v6 = input_8[1];
delata = 0;
v4 = 32;
while ( 1 )
{
v2 = v4--; // 循环32次
if ( v2 == 0 )
break;
delata -= 0x61C88647; // 为黄金分割点
v7 += (a2[1] + (v6 >> 5)) ^ (delata + v6) ^ (*a2 + 16 * v6);// a2为yeyeyess
v6 += (a2[3] + (v7 >> 5)) ^ (delata + v7) ^ (a2[2] + 16 * v7);
}
*input_8 = v7;
result = 4;
input_8[1] = v6;
return result;
}
最后加密的结果要为0x1cd6202d,0x31792ac4
写脚本进行解密
#include<stdio.h>
#include<windows.h>
void decrypt(unsigned long *v, unsigned long *k) {
unsigned long y = v[0], z = v[1], sum = 0xC6EF3720, i; /* set up */
unsigned long delta = 0x9e3779b9; /* a key schedule constant*/
unsigned long a = k[0], b = k[1], c = k[2], d = k[3]; /* cache key */
for (i = 0; i<32; i++) { /* basic cyclestart */
z -= ((y << 4) + c) ^ (y + sum) ^ ((y >> 5) + d);
y -= ((z << 4) + a) ^ (z + sum) ^ ((z >> 5) + b);
sum -= delta; /* end cycle */
}
v[0] = y;
v[1] = z;
}
int main()
{
DWORD cmp_teas[2] = { 0x1cd6202d, 0x31792ac4 };
char key[9] = { "yeyeyess" };
DWORD keys[2] = { 0 };
key[8] = '\0';
memcpy(key, "yeyeyess", 8);
memcpy(keys, key, 8);
decrypt(cmp_teas, keys);
for (int i = 0; i < 2; ++i)
{
printf("%x\n", cmp_teas[i]);
}
system("pause");
return 0;
}
打印结果为
676e6150 对应ASCII码gnaP
6e696c6f 对应ASCII码nil0
因为大端小端的问题 翻译过来就是
Pangolin
所以flag就是122333-Pangolin