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进行一系列操作后给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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值