学长出的RE题

来源:互联网 发布:网络推广经理职责 编辑:程序博客网 时间:2024/05/16 14:54

学长出的RE题

学长说,做出我这到题,你就可以到网上找CrackMe做了。那就做做看吧。(´・ω・`)

  • 引言

  • 分析

  • 追踪


引言

  • RE程序来自学长
  • 截图:
  • 这里写图片描述

  • 下载:链接:http://pan.baidu.com/s/1b2WNgU 密码:8c4s

分析

学长给了个提示:

找到key!听说这个程序还能当计算器用??喵喵喵?

先随便输输,发现输错不会有任何提示,会让你不断重输,没什么发现,直接OD载入先。

追踪

老方法,先查找字符串,找到一些:
这里写图片描述
上下翻翻发现这些:
这里写图片描述
向下f8,可以发现,就是这个jnz让我们不断输入key:
这里写图片描述
观察后发现eax存的是我们输入的key的长度,说明key必须为20位长度。根据下面两个jnz以及printf,我猜测CALL 004010A0和CALL 00401000为两个关键CALL。见下
这里写图片描述

  • CALL 004010A0的分析
    这里用到IDA,f5分析得:
// a1=eax=12FE14,a2=ebx=key_address,a3=edi=lengthsigned int __usercall sub_4010A0@<eax>(int a1@<eax>, int a2@<ebx>, unsigned int a3@<edi>){  unsigned int v3; // esi@1  char v4; // cl@2  unsigned int v5; // ecx@5  v3 = 0;                                       // v3为位数计数器  if ( a3 )  {    do                                          // do for each char    {      v4 = *(_BYTE *)(v3 + a2);                 // v4 = each char      if ( v4 == 61 )                           // key第一位不能为'='        break;      if ( v4 < 43 )                            // 第一位不能小于43'+'        return 1;      if ( v4 > 122 )                           // 第一位不能大于122'Z'        return 1;      v5 = byte_4020CD[v4];                     // 在4020CD上的相应的字符      if ( v5 == -1 )                           // eof不用管        return 1;      switch ( v3 & 3 )                         // 结果依次为0,1,2,3 x5组      {        case 0u:                                // 【a1=eax=12FE14 , a2=ebx=key_address , a3=edi=length】          *(_BYTE *)a1 = 4 * v5;                // 乘4          break;        case 1u:          *(_BYTE *)a1++ += (v5 >> 4) & 3;      // +=(v5 >> 4) & 3          if ( v3 < a3 - 3 || *(_BYTE *)(a2 + a3 - 2) != 61 )       //不是最后三位 或 倒数第三位 不等于 '='            *(_BYTE *)a1 = 16 * v5;             // 16 * v5          break;        case 2u:          *(_BYTE *)a1++ += (v5 >> 2) & 0xF;    // +=(v5 >> 2) & 15          if ( v3 < a3 - 2 || *(_BYTE *)(a2 + a3 - 1) != 61 )       //不是最后两位 或 倒数第二位 不等于 '='            *(_BYTE *)a1 = (_BYTE)v5 << 6;      // v5 << 6          break;        case 3u:          *(_BYTE *)a1++ += v5;                 +=v5          break;        default:          break;      }      ++v3;    }    while ( v3 < a3 );  }  return 0;}

ps.我分析完以后才发现此处为base64解密,水平不够,哪怕发现了是3/4的转换也没想到base64,分析代码的时候并没有发现,耗了很多时间

以下为4020CD之后的一些二进制数据:

004020CD  00 00 00 00 00 00 00 FD   63 62 58 00 00 00 00 02004020DD  00 00 00 67 00 00 00 B8   21 00 00 B8 11 00 00 50004020ED  31 40 00 A8 31 40 00 00   00 00 00 3E FF FF FF 3F004020FD  34 35 36 37 38 39 3A 3B   3C 3D FF FF FF FF FF FF0040210D  FF 00 01 02 03 04 05 06   07 08 09 0A 0B 0C 0D 0E0040211D  0F 10 11 12 13 14 15 16   17 18 19 FF FF FF FF FF0040212D  FF 1A 1B 1C 1D 1E 1F 20   21 22 23 24 25 26 27 280040213D  29 2A 2B 2C 2D 2E 2F 30   31 32 33 6B 65 79 00 730040214D  75 63 63 65 73 73 66 75   6C 00 00 67 69 76 65 200040215D  6D 65 20 25 73 3A 00 25   73 00 00 66 61 69 6C 000040216D  00 00 00 48 00 00 00 00   00 00 00 00 00 00 00 00

看完没什么思路。转向401000的分析。

  • CALL 401000的分析

IDA分析得:

__int64 __cdecl sub_401000(const char *a1){  unsigned int v1; // eax@1  signed int v2; // edi@1  unsigned int v3; // ebx@1  int v4; // esi@4  const char v5; // al@5  int v6; // eax@7  __int64 v8; // [sp+Ch] [bp-8h]@1  v1 = strlen(a1);                              // v1=变化后的字符串的长度  v2 = 0;  v3 = v1;                                      // v3=v1  v8 = 0i64;                                    // v8最终结果,初始化  if ( !v1 || (signed int)v1 > 13 )             // 在13位之前有一位为0,字符串长度小于等于13(没有0则等于15)    goto LABEL_13;  if ( (signed int)v1 > 0 )  {    v4 = 8 * v1 + 4206760;                      //v4为地址常量 (8 * v1 + 0x4030A8)    do    {      v5 = a1[v2];                              //v5为变化字符串的每一位,变化后的字符串中不是数字就是大写字母      if ( v5 < 48 || v5 > 57 )                       {        if ( v5 < 65 || v5 > 90 )                         goto LABEL_13;        v6 = v5 - 55;                           // v5是大写字母,v6=v5-55 v6属于[10,35]      }      else                                            {        v6 = v5 - 48;                           // v5是数字,v6=v5-48     v6属于[0,9] ,综上,v6属于[0,35]      }      v8 += v6 * *(_QWORD *)v4;                 // v8 += v6 * (v4上的值)      ++v2;      v4 -= 8;                                  // v4 -= 8    }    while ( v2 < (signed int)v3 );              // 对变化字符串每一位操作    if ( v8 < 0 )                               // v8 == 7089074166928978739 'base2333' '0x 62617365 32333333'LABEL_13:      exit(1);  }  return v8;}

以下为0x4030A8后的一些二进制数据:

0x4030A8    0x59000000 5A000000            0x01000000 00000000            0x24000000 00000000            0x10050000 00000000            0x40B60000 00000000            0X00A11900 00000000            0X00A49A03 00000000            0x0010BF81 00000000            0x0040DE3E 12000000            0x000041D7 90020000            0x00002445 5E5C0000            0x000010B9 41FD0C00            0x00004006 3E9DD301            0x000000E1 B81CC241

由Little-Endian知,v4实际读取到的数据为:

0000005A000000590000000000000001  36^00000000000000024  36^10000000000000510  36^2000000000000B640  36^3000000000019A100  36^400000000039AA400  36^50000000081BF1000  36^6000000123EDE4000  36^700000290D7410000  36^800005C5E45240000  36^9000CFD41B9100000  36^1001D39D3E06400000  36^1141C21CB8E1000000  36^12

发现其实是一个36进制到16进制的转换,转换的结果为6261736532333333h,反向计算的经过004010A0加密以后的字符串应该为1HUXV29D2KFUB

  • 再转向CALL 004010A0
    既然知道了加密后的字符串,通过004020CD处的数据慢慢解密(真的很慢,如果发现是base64就是几秒钟的事情了)可以得到最终的key:MUhVWFYyOUQyS0ZVQg==

我艰辛的过程大致如下:

01 |a*4|   |   |   |   |   |   |   |   |   |   |   |   |   |   | 77  M02 |b  |b*F|   |   |   |   |   |   |   |   |   |   |   |   |   | 85  U03 |   |c  |c  |   |   |   |   |   |   |   |   |   |   |   |   | 104 h04 |   |   |d  |   |   |   |   |   |   |   |   |   |   |   |   | 86  V05 |   |   |   |e*4|   |   |   |   |   |   |   |   |   |   |   | 87  W06 |   |   |   |f  |f*F|   |   |   |   |   |   |   |   |   |   | 70  F07 |   |   |   |   |g  |g  |   |   |   |   |   |   |   |   |   | 89  Y08 |   |   |   |   |   |h  |   |   |   |   |   |   |   |   |   | 121 y09 |   |   |   |   |   |   |i*4|   |   |   |   |   |   |   |   | 79  O10 |   |   |   |   |   |   |j  |j*F|   |   |   |   |   |   |   | 85  U11 |   |   |   |   |   |   |   |k  |k  |   |   |   |   |   |   | 81  Q12 |   |   |   |   |   |   |   |   |l  |   |   |   |   |   |   | 121 y13 |   |   |   |   |   |   |   |   |   |m*4|   |   |   |   |   | 83  S14 |   |   |   |   |   |   |   |   |   |n  |n*F|   |   |   |   | 48  015 |   |   |   |   |   |   |   |   |   |   |o  |o  |   |   |   | 90  Z16 |   |   |   |   |   |   |   |   |   |   |   |p  |   |   |   | 86  V17 |   |   |   |   |   |   |   |   |   |   |   |   |q*4|   |   | 81  Q18 |   |   |   |   |   |   |   |   |   |   |   |   |2  |0  |   | 103 g19 |   |   |   |   |   |   |   |   |   |   |   |   |   |0  |s  |     =20 |   |   |   |   |   |   |   |   |   |   |   |   |   |   |t  |     =   | 49| 72| 85| 88| 86| 50| 57| 68| 50| 75| 70| 85| 66| 00| 00|      1   H   U   X   V   2   9   D   2   K   F   U   B
  • 后记

虽说key是解出来了,但毕竟是入门的题目,解了这么就还是太慢,反思自己,连常见加密的算法都不熟练,是该努力了。

0 0
原创粉丝点击