实验吧(逆向):分道扬镳

题目:

注意进入正确的流程,用最短的步骤走完迷宫。

解题链接: http://ctf5.shiyanbar.com/423/re/rev2.exe

过程

IDA打开:

顺着去找main函数:

                                            实验吧(逆向):分道扬镳_第1张图片

int main_0()
{
  size_t v0; // eax
  size_t v1; // eax
  char v3[48]; // [esp+4Ch] [ebp-3Ch]
  unsigned int v4; // [esp+7Ch] [ebp-Ch]
  unsigned int v5; // [esp+80h] [ebp-8h]
  int v6; // [esp+84h] [ebp-4h]

  v5 = 0;
  v4 = 0;
  v6 = 0 / 0;
  printf("Please input your key:\n");
  gets(v3);
  if ( strlen(v3) > 0x20 )
  {
    printf("Too long!\n");
  }
  else
  {
    v4 = 0;
    v3[strlen(v3)] = 0;
    if ( strlen(v3) )
    {
      do
      {
        if ( !isalpha(v3[v4]) && v3[v4] != 123 && v3[v4] != 125 && v3[v4] != 95 )// 不是是字母,且不是{,不是_,不是},就错了;即要求输入是字母,'{','_','}'中的一个
        {
          printf("Sorry,you are wrong!\n");
          exit(0);
        }
        ++v4;
        v0 = strlen(v3);
      }
      while ( v4 < v0 );
    }
    _strlwr(v3);                                // 将字符串中的字母转化为小写,也就是输入时不分大小写是对的
    v5 = 0;
    if ( strlen(v3) )
    {
      do
      {
        v3[v5++] += 128;
        v1 = strlen(v3);
      }
      while ( v5 < v1 );
    }
    if ( !strcmp(v3, &byte_425A30) )            // &byte_425A30中的数字减去128就是答案,长度是19个字符
      printf("Good!\n");
    else
      printf("Sorry,you are wrong!\n");
    system("pause");
  }
  system("pause");
  return 0;
}

 

.data:00425A30 byte_425A30     db 0F4h                 ; DATA XREF: _main_0:loc_401520↑o
.data:00425A31                 db 0E8h
.data:00425A32                 db 0E9h
.data:00425A33                 db 0F3h
.data:00425A34                 db 0DFh
.data:00425A35                 db 0E9h
.data:00425A36                 db 0F3h
.data:00425A37                 db 0DFh
.data:00425A38                 db 0E1h
.data:00425A39                 db 0DFh
.data:00425A3A                 db 0E6h
.data:00425A3B                 db 0E1h
.data:00425A3C                 db 0EBh
.data:00425A3D                 db 0E5h
.data:00425A3E                 db 0DFh
.data:00425A3F                 db 0E6h
.data:00425A40                 db 0ECh
.data:00425A41                 db 0E1h
.data:00425A42                 db 0E7h

写个脚本提取出来:

import idc
str = ""
#最后的地址要加一,因为range函数尾巴是小于
for i in range(0x00425A30,0x00425A42+1,1):
	str += chr(int(GetOpnd(i,1)[0:3],16)-128)
	#因为带着h所以要通过下标把h去掉[0:3]代表0F4、0E8等三个位的数,[0:2]只是0F、0E等。(i,1)代表第一个操作数
print str  

说是一个假的flag:

                             

静态分析有时候IDA还是会被欺骗,main函数不一定是核心函数

 

 

动态调试

 

实验吧(逆向):分道扬镳_第2张图片

如果单步执行的话到这里就不能再往下了,应该是前面的哪一步有反调试的手段,或者我还没学会的调试方法。

实验吧(逆向):分道扬镳_第3张图片

可以确定没有进main,也不知怎么回事,但可以发现有好几个 sorry 

实验吧(逆向):分道扬镳_第4张图片

回到IDA后字符串搜索锁定到 sub_401020

char *sub_401020()
{
  char *result; // eax
  char *v1; // [esp+50h] [ebp-CCh]
  char v2; // [esp+54h] [ebp-C8h]
  char v3; // [esp+5Dh] [ebp-BFh]
  char v4; // [esp+94h] [ebp-88h]
  char v5; // [esp+98h] [ebp-84h]
  char v6; // [esp+99h] [ebp-83h]
  __int16 v7; // [esp+10Dh] [ebp-Fh]
  char v8; // [esp+10Fh] [ebp-Dh]
  char v9; // [esp+110h] [ebp-Ch]
  char v10; // [esp+114h] [ebp-8h]
  int v11; // [esp+118h] [ebp-4h]

  v5 = 0;
  memset(&v6, 0, 116u);
  v7 = 0;
  v8 = 0;
  strcpy(&v2, "********* *    ** * ** ** * ** ** * #* ** **** **      *********");// 迷宫地图
  v1 = &v3;
  printf("Please input your key:\n");           // 输入走的过程
  gets(&v5);
  if ( strlen(&v5) != 22 )                      // 步数为22步
  {
    printf("Sorry you are wrong!\n");
    system("pause");
    exit(1);
  }
  v11 = 0;
  do
  {
    v10 = *(&v5 + v11);                         // v10就是input[i]
    if ( v10 != 'k' && v10 != 'j' && v10 != 'h' && v10 != 'l' )// 输入必须是 hjkl 字符中的一个
    {
      printf("Sorry you are wrong!\n");
      system("pause");
      exit(2);
    }
    v9 = *(&v5 + v11);                          // v9也是input[i]
    switch ( v9 )
    {
      case 'h':
        if ( --v1 < &v2 || v1 > &v4 || (result = (char *)*v1, result == (char *)'*') )
        {
          printf("Sorry you are wrong!\n");
          system("pause");
          exit(3);
        }
        if ( *v1 == '#' )
        {
LABEL_41:
          printf("Good!\n");
          system("pause");
          exit(0);
        }
        break;
      case 'j':
        v1 += 8;                                // 根据这里的 +=8 判断二维迷宫一行8个,即:
                                                //     ********
                                                //     * *    *
                                                //     * * ** *
                                                //     * * ** *
                                                //     * * #* *
                                                //     * **** *
                                                //     *      *
                                                //     ********
        if ( v1 < &v2 || v1 > &v4 || *v1 == '*' )// v2是字符串,猜测v4是0; 综合jhkl的v1关于8的操作,则j是向下,k是向上,h是向左,default即l是向右
        {
          printf("Sorry you are wrong!\n");
          system("pause");
          exit(3);
        }
        result = (char *)*v1;
        if ( result == (char *)'#' )
          goto LABEL_41;
        break;
      case 'k':
        v1 -= 8;
        if ( v1 < &v2 || v1 > &v4 || *v1 == '*' )
        {
          printf("Sorry you are wrong!\n");
          system("pause");
          exit(3);
        }
        result = v1;
        if ( *v1 == '#' )
          goto LABEL_41;
        break;
      default:
        if ( ++v1 < &v2 || v1 > &v4 || *v1 == 42 )
        {
          printf("Sorry you are wrong!\n");
          system("pause");
          exit(4);
        }
        result = v1;
        if ( *v1 == '#' )
          goto LABEL_41;
        break;
    }
    ++v11;
  }
  while ( v11 < 25 );
  return result;
}

分析一下:

试了一下从左上角出发正好是22步:jjjjjlllllkkkkkhhhjjjl

 

你可能感兴趣的:(逆向工程)