2019安恒二月赛逆向题目cpp详解

本人首发在先知社区
https://xz.aliyun.com/t/4282

2019安恒二月赛的一道题目
这道题目运行,输入11111111111 回车,程序直接关闭,没有任何提示信息

2019安恒二月赛逆向题目cpp详解_第1张图片
Exeinfo PE查壳发现是一个C++程序并且没有加壳

2019安恒二月赛逆向题目cpp详解_第2张图片
IDA x32载入程序 shift + F12查看有没有什么可以字符串
发现一个’Please input:’
双击进去 接着双击引用
2019安恒二月赛逆向题目cpp详解_第3张图片

2019安恒二月赛逆向题目cpp详解_第4张图片
程序流程图貌似很简单的样子

2019安恒二月赛逆向题目cpp详解_第5张图片
F5查看伪代码
进行简单分析 Src是一个字符串数组 unsigned int是错误的
2019安恒二月赛逆向题目cpp详解_第6张图片
我们双击Src看下在程序中的位置

2019安恒二月赛逆向题目cpp详解_第7张图片
发现是在.data段也就是数据段(data segment),通常是指用来存放程序中已初始化的全局变量的一块内存区域,那Src是一个32位的全局字符串数组变量

双击sub_411302()进去 发现最后返回的是中间的参数 也就是result
image.png
双击sub_411352() 进行分析

2019安恒二月赛逆向题目cpp详解_第8张图片
接着双击sub_413910()

int __usercall sub_413910@<eax>(int a1@<xmm0>, char *Str)
{
  char v2; // cl
  size_t i; // [esp+D0h] [ebp-8h]

  sub_4112F8((int)&unk_421008);
  for ( i = 0; i < j_strlen(Str); ++i )         // 将Str这个字符串分为三组 分别与0x1f,0x20,0x21进行异或
  {
    if ( i % 3 )
    {
      if ( i % 3 == 1 )
        v2 = Str[i] ^ 0x20;
      else
        v2 = Str[i] ^ 0x21;
      Str[i] = v2;
    }
    else
    {
      Str[i] ^= 0x1Fu;
    }
  }
  return sub_411302(1, (int)Str, a1);           // 最后返回a1
}

总的分析

int __usercall sub_413E30@<eax>(int a1@<xmm0>)
{
  int v1; // eax
  int v3; // [esp+0h] [ebp-CCh]

  sub_4112F8((int)&unk_421008);
  sub_411276(std::cout, "Please input: ");      // cout输出提示信息
  scanf((const char *)&my_input, (unsigned int)Src, 32);// scanf输入  保存在Src
  if ( j_strlen(Src) >= 14 && j_strlen(Src) <= 32 )// 判断Src的长度是否满足大于等于14,小于等于32 若满足,就继续
  {
    v1 = strcpy_s(Str, 32u, Src);               // 用strcpy_s()函数拷贝Src到Str
    sub_411302(&v3 == &v3, v1, a1);
    sub_411352(a1, Str);                        // 对Str进行异或操作  返回a1
  }
  return sub_411302(1, 0, a1);                  // 返回0 相当于return 0
}

感觉程序没有结束但就是找不到下面的代码
看了官方WP
了解到可以查看Str的引用
因为后面一直是对Str进行处理 所以可以猜测后续还会对他进行处理

2019安恒二月赛逆向题目cpp详解_第9张图片
点击任意一个Str 点击X 可以查看到第三条是还未分析的
我们双击进去 可以发现有两个Str

2019安恒二月赛逆向题目cpp详解_第10张图片
这时候我们就是该找到新Str的来源 但是我的IDA好像找不到其他引用
所以换个思路
我们可以看 unk_421008 所在区域 一般都是在一块的 点击它 按X

2019安恒二月赛逆向题目cpp详解_第11张图片
可以发现向上游好多引用
一个一个看 最后可以发现最上面这个 就是我们要找的

2019安恒二月赛逆向题目cpp详解_第12张图片
双击可以看到

2019安恒二月赛逆向题目cpp详解_第13张图片

那么我们就可以编写脚本解出flag

str1 = ''
str2 = 'access denieda'
flag = ''
for i in range(len(str2)):
  str1 += chr(ord(str2[i])^i)
# print str1
#abafwv&cmgcnhl
for i in range(len(str2)):
  if i % 3 == 0:
    flag+= chr(ord(str1[i])^0x1f)
  elif i % 3 == 1:
    flag+= chr(ord(str1[i])^0x20)
  elif i % 3 == 2:
    flag+= chr(ord(str1[i])^0x21)
print flag
#~B@yWW9CLxCOwL

总结:当没有头绪的时候,可以查看变量或字符串的引用

这道题有涉及到虚函数表的知识
参考链接:https://www.linkedbyx.com/taskinfo/443/detail

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