本文主要是介绍encrypt-掘安杯-sha1和TEA,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
使用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进行一系列操作后给v23for ( k = 0; k < 20; ++k )wsprintfA(&v71encode + 2 * k, "%02x", (unsigned __int8)*(&v23 + k));// 格式化字符串数据不足2位是再前加0进行不足,并传递给encodesub_4111F9((int)&Str1); // 将每个字符减去8if ( !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; // eaxchar v2; // clsigned int i; // [esp+D0h] [ebp-8h]for ( i = 0; i < 40; ++i ){v1 = i & 0x80000000; // v1始终为0if ( (i & 0x80000000 & 0x80000000) != 0 )v1 = 0;if ( v1 )v2 = *(_BYTE *)(i + str1) + 3;elsev2 = *(_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_4signed int result; // eaxsigned 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为yeyeyessv6 += (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
这篇关于encrypt-掘安杯-sha1和TEA的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!