安恒X计划平台10月月赛逆向题BASE++题目思路

这道题比赛时就看到了名字  没下载到

一直在找题目附件  发现52破解上yechen123师傅发了帖子

就下载下来分析了一波  现在来记录一下

IDA载入静态分析可知

关键代码就在main()

程序与我们拿到flag有关的步骤就是 

0x01:判断my_str_len(ps:就是我们输入的字符串的长度)是否小于32  正确的输入最后算出来正好等于32  所以将会继续向下执行

0x02:sub_91100()将我们得输入my_str中的字母进行替换

0x03:通过sub_91360()与sub_91440()他俩配合的变种base64(ps:分析可知,只是替换了编码表而已) 进行编码

0x04:得到的串需要等于"TRLT5amLBoLT5Z6Fa5LqN6mkTomqR66Da4LqX5mgBwkkP5wmTZ6D===="

int __cdecl main(int argc, const char **argv, const char **envp)
{
  int result; // eax
  int v4; // [esp+30h] [ebp-28h]
  int v5; // [esp+34h] [ebp-24h]

  printf(std::cout, "please input your flag:");
  scanf(std::cin, my_str);
  if ( strlen(my_str) < 32 )                    // 我们的输入 my_str长度必须小于32
    goto LABEL_14;
  sub_91100(my_str);                            // 这里将my_str中的小写字母进行替换
  v5 = strcmp(my_str, "guvf_vf_n_snxr_synt_____________");
  if ( v5 )
    v5 = -(v5 < 0) | 1;
  if ( v5 )
  {
LABEL_14:
    sub_91360();                                // 替换了base32编码的密码表
    sub_91440(strlen(my_str), my_str, a0);      // 进行变种base32编码  用32个字符表示256个ASC字符,也就是说5个ASC字符一组可以生成8个Base字符
    v4 = strcmp(a0, "TRLT5amLBoLT5Z6Fa5LqN6mkTomqR66Da4LqX5mgBwkkP5wmTZ6D====");// 用变种base32加密后 与这个串进行比较
    if ( v4 )
      v4 = -(v4 < 0) | 1;
    if ( v4 )
      printf(std::cout, "soooooooooorry\n");
    else                                        // 如果v4等于0 则输出"Congratulations!!!"
      printf(std::cout, "Congratulations!!!\n");
    system("pause");
    result = 0;
  }
  else
  {
    printf(std::cout, "try harder!\n");
    result = 0;
  }
  return result;
}

IDA动态调试时

F7进入sub_91360()可以看到 地址0009507C开始存放着这么一个字符串byte_9507C

这个就是要使用的密码表

NoPqRsTuVwXyZaBcDeFgHiJkLm765432

安恒X计划平台10月月赛逆向题BASE++题目思路_第1张图片

有了编码表之后  可以很容易求得编码之前的串

import string
import base64
my_base64table = "NoPqRsTuVwXyZaBcDeFgHiJkLm765432"
std_base64table ="ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"
s = "TRLT5amLBoLT5Z6Fa5LqN6mkTomqR66Da4LqX5mgBwkkP5wmTZ6D===="
s = s.translate(string.maketrans(my_base64table,std_base64table))
print base64.b32decode(s)
#10n78ppn3ro00o70r2opop5s3roqq937

但是这里就可以发现  长度正好是32位

那就肯定经过了0x02这个步骤

signed int __thiscall sub_91100(const char *this)
{
  const char *v1; // edi
  unsigned int i; // esi
  char v3; // cl

  v1 = this;
  i = 0;
  if ( strlen(this) )        //this 就是我们的my_str
  {
    do
    {
      v3 = v1[i];
      if ( (v3 - 0x61) <= 0x19u )    //如果有小写字母就进行这种操作
        v1[i] = (v3 - 0x54) % 26 + 0x61;    
      if ( (v3 - 0x41) <= 0x19u )    //如果有大写字母就进行这种操作
        v1[i] = (v3 - 0x34) % 26 + 0x41;
      ++i;
    }
    while ( i < strlen(v1) );
  }
  return 1;
}

因为base32解码之后只有小写字母

那我们只要把它们逆一下即可

这里是yechen123师傅的脚本

先生成密码表

然后对应下标即可(ps:又get到一个姿势)

key = "10n78ppn3ro00o70r2opop5s3roqq937"
asciis = []
g = [] 
for i in range(97,123):
    asciis.append(chr(((i-84)%26)+97))#生成移位之后的表
for i in range(0,32):
    if (97<=ord(key[i])<=122):#小写才用改  数字就算了
        temp = ord(key[i])-97
        g.append(asciis[temp])
        continue
    g.append(key[i])
flag = ""
for i in g:
    flag += i
print (flag)
#10a78cca3eb00b70e2bcbc5f3ebdd937

 

推荐大家看师傅写的 非常详细

https://www.52pojie.cn/forum.php?mod=viewthread&tid=813470&extra=page%3D1&page=1

你可能感兴趣的:(我的逆向之路,我的CTF之路,------安恒CTF,我的CTF进阶之路)