【CTF攻略】百度杯2月第三周Reverse专题writeup

Reverse-1 project1


by 渡师傅

运行一下,看到Input the flag:,本着去找这个字符串的想法,在ida里找,可惜没找到,但有别的发现BCDFGHJKMPQRTVWXY2346789,凭经验可以推出,这个字符串有问题,跟到他调用的位置sub_404820

char sub_404820()
{
  int v0; // esi@1
  unsigned int v1; // ebx@1
  unsigned int v2; // eax@1
  int v3; // ecx@1
  int v4; // edi@2
  unsigned int v5; // esi@2
  char *v6; // ebx@3
  char *v7; // eax@3
  unsigned __int8 v8; // bl@6
  int v9; // edx@9
  int v10; // eax@11
  int v11; // ecx@11
  int v12; // ecx@11
  unsigned int v14; // [sp+10h] [bp-8h]@1
  unsigned __int8 v15; // [sp+17h] [bp-1h]@1
  v0 = dword_40A6E8;
  v1 = 0;
  v15 = 0;
  v14 = 0;
  v3 = strlen((const char *)dword_40A6E8);
  if ( v3 )
  {
    do
    {
      v4 = v0 + v1;
      v5 = 0;
      do
      {
        v6 = strchr("BCDFGHJKMPQRTVWXY2346789", *(_BYTE *)(v4 + 2 * v5));
        v7 = strchr("BCDFGHJKMPQRTVWXY2346789", *(_BYTE *)(v4 + 2 * v5 + 1));
        v3 = (int)v7;
        if ( !v6 )
          break;
        if ( !v7 )
          break;
        *(&v15 + v5++) = (unsigned int)&Str[-(_BYTE)v7 + 23] | 16
                                                             * ((_BYTE)v6 - (unsigned int)"BCDFGHJKMPQRTVWXY2346789");
      }
      while ( v5 < 1 );
      v8 = v15 & 0xF;
      switch ( (unsigned int)v15 >> 4 )
      {
        case 0xEu:
          up(v15 & 0xF);
          goto LABEL_14;
        case 0xCu:
          down(v15 & 0xF);
          goto LABEL_14;
        case 0xDu:                              // left
          v9 = position - v8;
          goto LABEL_11;
        case 0xFu:                              // right
          v9 = v8 + position;
LABEL_11:
          v10 = (unsigned __int8)byte_4076A0[v9];
          v11 = (unsigned __int8)byte_4072C0[v9];
          count += v8;
          v12 = (v10 ^ v11) - (unsigned __int8)byte_407410[v9];
          position = v9;
          v3 = v12 - (unsigned __int8)byte_407550[v9];
          if ( v3 || !v8 )
            goto LABEL_13;
          break;
        default:
LABEL_13:
          dword_40A6F4(v3, 0);
LABEL_14:
          v9 = position;
          break;
      }
      v0 = dword_40A6E8;
      v14 += 2;
      v1 = v14;
      v2 = strlen((const char *)dword_40A6E8);
    }
    while ( v14 < v2 );
  }
  else
  {
    v9 = position;
  }
  if ( count != 54 || v9 != 271 )
    LOBYTE(v2) = dword_40A6F4(v3, 0);
  return v2;
}

dword_40A6E8存的内容是什么还不清楚,不过根据

v3 = strlen((const char *)dword_40A6E8);

能推测出dword40A6E8上是字符串,后面就是对这个dword40A6E8读数据,一次读两字节,求出其在BCDFGHJKMPQRTVWXY2346789中的索引,然后组合成新的字节,再switch这个新字节

switch有4个case,仔细比较的话,可以看出来他们唯一的不同点就是对position的处理比如 case 0xEu: position += -17*a1; case 0xCu: position += 17*a1;这很像走地图的上下左右,而那部分异或比较是校验我们当前position是不是可行的,所以我们可以由此反推出地图,再根据地图退出路径,不过在移动时,不是一步一步移动,而且还限制了总步数,所以我们求最短的操作方式就行了,代码如下:

d_6a0 = [0x87,0xae,0x99,0x3c,0x59,0x41,0x2e,0x1d,0x84,0x23,0x30,0x23,0x26,0x10,0x83,0x5,0x29,0x9d,0xa0,0x16,0xdb,0x41,0x72,0xe7,0x4f,0x64,0x7b,0x8b,0xfe,0x4b,0xff,0x8b,0xf8,0x70,0xa8,0xf3,0x1d,0x20,0x4,0x2a,0x46,0x12,0x74,0x17,0xaa,0x2f,0x23,0xd,0x8e,0xce,0xd5,0x1c,0xe8,0x34,0x7a,0xfa,0x27,0x40,0xe2,0x81,0x3a,0xcb,0xaf,0xff,0x6,0x3,0xe0,0xdd,0x43,0xe9,0xd8,0x9b,0x39,0x52,0xdb,0x57,0x9c,0x73,0x98,0x80,0x46,0xdd,0xa5,0xd8,0xec,0x51,0xde,0x98,0xd7,0x18,0x3d,0xd8,0x7e,0x6,0xdd,0xa0,0x5c,0xd0,0xcd,0x27,0x1f,0x39,0xc6,0x79,0x0,0x93,0xde,0x68,0xd8,0x57,0x53,0x7f,0x10,0x5a,0x3c,0x2c,0x58,0xd8,0x71,0xaa,0x6c,0x7c,0x2e,0x54,0x31,0x74,0x15,0x50,0xd,0xd1,0x88,0x4e,0x98,0xca,0x71,0x99,0xdc,0xf4,0x7e,0x22,0x1b,0x95,0xb,0xfb,0x18,0xea,0x70,0x41,0x8e,0x2b,0x35,0x54,0x32,0xe3,0xff,0xf4,0x75,0x2a,0xbb,0xeb,0x70,0x73,0xc,0x3b,0x90,0x9c,0x31,0x66,0x8c,0xfd,0xd6,0xe6,0x82,0x2e,0xba,0x97,0xdc,0xa2,0x8e,0xd,0xe9,0x72,0x85,0x7,0x1d,0xe2,0x20,0x6c,0x3d,0xa,0x8d,0xa9,0x1,0x5b,0x91,0xb5,0xa2,0x8b,0xd5,0xdc,0x20,0xd5,0x3f,0x7e,0x14,0xae,0x97,0x25,0xfd,0xf,0x43,0x2f,0x12,0xbc,0xc5,0x28,0x2a,0x62,0x35,0xf,0xfc,0x99,0xf6,0x35,0xda,0xc0,0xf,0xe9,0x49,0x49,0x6,0x1d,0x37,0xfa,0x0,0xab,0x47,0xd7,0xc2,0x15,0x39,0x42,0xeb,0x5e,0x13,0x16,0x66,0x82,0xc5,0x89,0x41,0xd2,0x34,0xf9,0x73,0x73,0x4a,0x6,0xcd,0x6,0xc7,0xe9,0xd2,0xc9,0xec,0x69,0xd8,0x4,0x32,0x21,0x43,0xc7,0xc6,0xf0,0x9,0x90,0x11,0xde,0xfe,0xc1,0xef,0x9e,0xac,0x22,0xfd,0x92,0x61,0x59,0x1e]
d_2c0 = [0x10,0x27,0x1b,0x44,0x2e,0x30,0x99,0x7f,0x1f,0xb8,0xb1,0xab,0x78,0x90,0x3a,0x58,0x9e,0x1d,0x9b,0x5d,0x58,0x55,0x3,0x7e,0x28,0x3,0x1a,0x13,0x1c,0x11,0x77,0x27,0x60,0x6,0x93,0x5f,0x56,0xe,0x7d,0x5c,0x29,0x7a,0x10,0x62,0x9e,0x87,0xa3,0xb9,0x6b,0x63,0xbf,0x53,0x4d,0xad,0x16,0xb0,0x15,0x7c,0x71,0xbf,0x2,0xa4,0x2b,0x46,0x55,0x74,0x9d,0x43,0xa1,0x83,0x99,0x94,0x62,0x2d,0x5b,0x14,0x4f,0x18,0x3c,0x7,0x33,0xbc,0x29,0xb8,0x78,0x22,0x94,0xa0,0x5,0x2b,0x69,0x8a,0x4a,0x55,0x44,0x75,0x18,0xba,0xa1,0x3a,0x77,0x99,0x94,0x2e,0x72,0x59,0xba,0xa,0xb6,0x4b,0x6f,0x9,0x9b,0x30,0x41,0x92,0x2,0xbb,0x25,0x97,0xa0,0x58,0xa9,0x3d,0x99,0xac,0x6a,0x7d,0x51,0x5f,0x7,0xa,0x3f,0x58,0x15,0xb4,0x3,0x47,0x14,0x4c,0x79,0xa9,0x62,0x89,0x8e,0x87,0x2f,0xaa,0x12,0x40,0xb1,0x9d,0x4f,0x89,0x99,0x20,0x1a,0xb2,0x85,0x26,0x27,0xab,0x77,0x7c,0x21,0x6,0x46,0xac,0x3a,0x3e,0x13,0x21,0x0,0xb9,0x7f,0x4d,0xb2,0x8a,0x1b,0x88,0x51,0x3a,0x21,0x3a,0x7a,0x48,0xa1,0x7a,0xb2,0xae,0xbd,0x77,0x83,0x26,0x19,0x17,0x7,0xad,0xe,0x5f,0x42,0x7,0x5e,0x13,0x34,0x3,0xad,0x9e,0x6f,0x40,0x2e,0x73,0x27,0x70,0x5b,0x75,0x48,0x1c,0x69,0x95,0x8c,0x29,0x3b,0x3a,0x4c,0x19,0x56,0xa5,0x16,0x94,0x95,0x55,0x1,0x29,0x1d,0x28,0x3d,0x90,0x94,0x44,0x6e,0x32,0x8e,0x35,0xbb,0x2a,0x88,0x57,0xa1,0x4e,0x99,0x77,0x8e,0xa9,0xa5,0xb5,0x2b,0x8b,0x14,0x6c,0xb9,0x44,0x43,0x15,0x9f,0x2c,0xb9,0xa9,0x2,0x66,0x5c,0x86,0x97,0xa6,0xa4,0x14,0xb5,0xb1,0x51,0xa8,0x6f,0xa4,0x19,0xa9,0x20,0x38,0xa5,0xb1,0x7]
d_410 = [0x4c,0x11,0x29,0x16,0x5d,0x51,0x4d,0x3e,0x6f,0x3e,0x59,0x65,0x57,0x2c,0x5d,0x2c,0x46,0x56,0x3b,0x41,0x40,0x0,0x36,0x25,0x50,0x5a,0x4c,0x33,0x79,0x28,0x46,0x5e,0x6f,0x20,0xd,0x3a,0x8,0x13,0x3f,0x3e,0x6d,0x50,0x2,0x48,0x15,0x46,0x19,0x61,0x74,0x68,0x35,0x42,0x6f,0x56,0xd,0x18,0x14,0x39,0x30,0x5,0x8,0x6e,0x1a,0x67,0x40,0x68,0x6,0x5c,0x74,0x4f,0x4,0x6,0x51,0x6d,0x4b,0xb,0x6f,0x4b,0x50,0x60,0x2,0x17,0x18,0x48,0x54,0x49,0x4a,0x17,0x73,0x7,0x8,0x3c,0x26,0x45,0x7f,0x7e,0x26,0x30,0x3d,0x6,0xb,0x4d,0x43,0x1e,0x5,0x5d,0x5c,0x38,0x4c,0x5,0x2d,0x32,0x5a,0x2b,0xc,0x58,0x57,0x23,0x16,0x2b,0x55,0xb,0x7b,0x61,0x3d,0x73,0x1d,0x2c,0x9,0x42,0x5a,0x3f,0x34,0x54,0x25,0xf,0x6f,0x68,0x5c,0x56,0x16,0x3a,0x55,0x5e,0x62,0x6c,0x3b,0x7c,0x60,0x2a,0x18,0x5a,0x22,0xe,0x32,0x7a,0x34,0x41,0x1b,0x78,0x51,0x64,0x4,0x10,0x57,0x2e,0x52,0x5f,0x79,0x56,0x74,0x6e,0x34,0x33,0x73,0x6c,0x4,0x22,0x4a,0x3b,0x57,0x28,0x79,0x2f,0x42,0x58,0x55,0x12,0x73,0x77,0x22,0x6b,0x67,0x5f,0x63,0x7f,0x5d,0x21,0x71,0x19,0xa,0x6e,0x4b,0x7,0xe,0x38,0x2d,0x65,0x27,0x14,0x64,0x1e,0x24,0x63,0x60,0x2f,0x1d,0x31,0xb,0x2e,0x62,0x5d,0x59,0xb,0x31,0x7a,0x20,0x17,0x2c,0x76,0x2b,0x42,0x9,0x79,0xa,0x29,0xc,0x10,0x2b,0x50,0x32,0xb,0x2f,0x2b,0x30,0x24,0x76,0x64,0x1b,0x61,0x7c,0x58,0x69,0x3b,0x69,0x63,0x18,0x7f,0x63,0x5d,0x2d,0x75,0x27,0x64,0x60,0x40,0x58,0x5c,0x16,0x5,0x16,0x35,0xf,0x4f,0x53,0x6c,0x61,0x32,0x62,0x55,0x25,0x2f,0x51,0x17,0x70,0x58,0x79,0x78,0x5]
d_550 = [0x4a,0x77,0x58,0x61,0x19,0x1f,0x69,0x23,0x2b,0x5c,0x27,0x22,0x6,0x53,0x5b,0x30,0x70,0x2a,0x0,0xa,0x43,0x13,0x3b,0x74,0x17,0xd,0x15,0x65,0x69,0x31,0x42,0x4e,0x29,0x55,0x2d,0x72,0x42,0x1b,0x39,0x38,0x1,0x17,0x61,0x2c,0x1e,0x62,0x66,0x52,0x70,0x45,0x34,0xc,0x36,0x42,0x5f,0x32,0x1e,0x3,0x63,0x39,0x30,0x0,0x6a,0x51,0x13,0xf,0x77,0x41,0x6d,0x1b,0x3c,0x8,0x9,0x11,0x34,0x37,0x63,0x1f,0x53,0x27,0x72,0x4a,0x73,0x17,0x3f,0x29,0x0,0x21,0x5f,0x2b,0x4c,0x16,0xe,0xe,0x1a,0x57,0x1e,0x39,0x2f,0x16,0x5d,0x52,0xe,0x39,0x6c,0x6c,0x7,0x2a,0x21,0x16,0xe,0x43,0x30,0x3e,0x70,0x66,0x2,0x40,0x3d,0x11,0x77,0x18,0xc,0x8,0x6b,0x64,0x62,0x1,0x53,0x4c,0x35,0x4,0x73,0x3e,0x3f,0x1d,0x6f,0x4a,0xd,0x18,0x4b,0x1,0x13,0x14,0x33,0x0,0x23,0x6f,0x3b,0x40,0x6b,0x6f,0x5a,0x5b,0x34,0x5a,0x3b,0x56,0x23,0x55,0x6,0x73,0x77,0x36,0x5a,0x6c,0x25,0x6b,0x3d,0x6c,0x50,0x59,0x4d,0x64,0x51,0x6e,0x69,0x5,0x4a,0x4a,0x60,0x1f,0x2a,0xd,0x24,0x51,0x2b,0x3,0x1c,0x2c,0xe,0x72,0x1b,0x1e,0x25,0x23,0x48,0x4,0x6a,0x6a,0x58,0x64,0x16,0x65,0x11,0x75,0xc,0x55,0x6a,0x3a,0x8,0x3d,0x10,0x69,0x3d,0x2e,0x44,0x4c,0x50,0x6b,0xd,0x52,0x74,0x4,0x65,0x5f,0x39,0x35,0x33,0x66,0x68,0x5,0x2d,0x5a,0x13,0x5a,0x6e,0x36,0x2a,0x1,0x24,0x64,0x35,0x40,0x77,0x17,0x77,0x71,0x48,0x65,0x5b,0x4c,0x50,0x15,0x6c,0x62,0x49,0xe,0x76,0xc,0x51,0x38,0x6a,0x78,0x13,0x5,0x9,0x51,0x1a,0x42,0x9,0xc,0x41,0x6,0x59,0x17,0x42,0x3c,0x4c,0x13,0x5a,0xa,0x63,0x73,0x6c,0x51,0x4a,0x6f,0x13]
direc = [-17,17,-1,1]#[up,down,left,right]
tab = 'BCDFGHJKMPQRTVWXY2346789'
def de_vm(n):
    global tab
    if n < 0:
        if n % 17 == 0:
            return tab[0xe]+tab[23-abs(n/17)]
        else:
            return tab[0xd]+tab[23-abs(n)]
    if n > 0:
        if n % 17 == 0:
            return tab[0xc]+tab[23-n/17]
        else:
            return tab[0xf]+tab[23-abs(n)]
def simp(path):
    tmp = 0
    n_p = []
    for v in path:
        if v == tmp :
            n_p[-1] += v
        else:
            tmp = v
            n_p += [v]
    return n_p
def search_path(pos,path,last_move):
    global t
    global over
    if pos == 271:
        flag = ''
        for v in simp(path):
            flag += de_vm(v)
        print flag
        over = 1
    if over == 1:
        return
    for v in direc:
        if pos+v in t and last_move+v != 0:
            search_path(pos+v,path+[v],v)
t = []
for i in xrange(289):
    tmp = d_6a0[i] ^ d_2c0[i]
    tmp -= d_410[i]
    tmp &= 0xff
    if tmp == d_550[i]:
        t += [i]
s = ''
for j in xrange(289):
    if j%17 == 0:
        s += 'n'
    if j in t:
        s += ' '
    else:
        s += '#'
print s
over = 0
search_path(17,[],0)

by ywway

这题目坑比较多,,难度比较大,,刚开始的md5就干扰了我大半天,

怎么推理都不对,,后来细心看了一下,出题人将几个值给改掉了。

http://p3.qhimg.com/t01405d2da43efa6ac4.png

从 cin 处开始, 是读取字符串的。 然后做一个 变种 md5加密

刚开始以为达到这里就结束了, 就要爆破了。 后来发现还有一块代码用来判断这里的值。 sub_404820

有四张表, 来形成一个高级的迷宫

(map4 ^ map1) - map2 == map

这一些值会形成一个迷宫 

http://p5.qhimg.com/t01f65316dd384115d6.png

玩一下迷宫就可以把路径找出来, , 这个还是有意思的

http://p4.qhimg.com/t014166344ffa53bc6e.png

这里输入的有一位是控制上下左右,有一位是控制距离。并且一个是那个字符串前开始找,还有一位是从后往前找的

最后得到flag 为 X6T7X7W7X2T4V2T7V7T7V7T4X4T7XT


Reverse-2 CrackMe-1


by poyoten

先试运行下,随便输入,点check,程序似乎阻塞了一段时间。拖进IDA,查看字串,发现有"This is flag"等字样。如图

http://p0.qhimg.com/t01fb5e5d09c286ae6b.png

查看引用此字串的代码位置,其伪代码如图:

http://p8.qhimg.com/t01d5a26918a3c2ed16.png

sub_401210调用的返回值如果为2345则弹出错误提示对话框,为751则提示正确,如果为5173则调用5173次sleep(),这也是之前试运行出现类似阻塞情况的原因。很明显关键算法在sub_401210中。

继续看sub_401210调用。代码比较长,我就不截图了。

大致过程为先加载一个常量数据到栈中,记为s1,取文本框的值,记为s2。 检查s1的长度不大于20,且s2的长度为s1长度的两倍。s1其实就是"BinGzLFormiChunQiu",长度为18。所以输入长度就为36。

接着检查s1的字符在[a-z][A-Z]之间,s2的字符在[0-9][A-Z]之间。

再接着初始化两个大小为40的栈区,分别对s1和s2进行变换计算,结果存放于这两个刚初始完的栈区。

最后以4字节为单位进行两个结果栈区比较。如果40字节全部相同则返回751。

下面简单说个两个字串的变换计算。静态分析来看,两个字串计算是相对独立进行的。s1计算后生成相同长度的结果字串;s2两位一计算,最后生成与s1同长度的字串,s2的每两位通过调用sub_401000进行hex解码成单字节。其中的计算过程从代码看比较繁杂。

看到这样的代码,理清这个算法我是拒绝的。仔细分析下,不理算法应该是可以解的。有这么一个推想:s1的计算因为没有s2的参与,所以其结果应该是一个定值,所以先不用理会,后面动态查看就是;s2的计算是按字节进行,各字节独立,输入值的范围是00-FF,为了避免多解,其结果范围也必然是00-FF,而且是以某种规律一一对应的。如果把s2的256种输入对应的结果全部算出来,生成一张表,最后用s1的计算结果查表就可以得出s2。

为了验证推想的正确性,上OD验证下。 输入为"123456789012345678901234567890123456"时的结果为下:

http://p3.qhimg.com/t01af366da454a7e603.png

输入为"111111111122222222223333333333444444"时的结果为下:

http://p9.qhimg.com/t01e9a6da185e49e6b5.png

图中蓝标记的分别为s1和s2的计算结果。与想象得差不多。下面就是计算出00-FF对应的所有结果了,如图:

http://p7.qhimg.com/t011cbe9415dbf86c61.png

接下来就是查表了,得出结果为838EFBFFE7D9CDDFCFC4C1C5C7CFC9CBB3C9。

这是一种笨方法,但是有效。比较省时间的应该是改写程序,循环枚举了。

by wangxiyu

很容易找到关键判断逻辑

http://p8.qhimg.com/t01d853b786939f036b.png

一排AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA输入进去之后发现是16个相同的结果,怀疑是两个为一组进行计算,并且互相独立。AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD 试了一下发现确实是互相独立。然后爆破就好

对应表:

000102030405060708090A0B0C0D0E0F1011
0x2f,0x86,0xfd,0xbc,0x5b,0x92,0x69,0x8,0x7,0x3e,0x35,0x14,0x53,0x4a,0x1,0x60,0x9f,0x36,
12131415161718191A1B1C1D1E1F20212223
0x6d,0xec,0xb,0x82,0x19,0xf8,0xb7,0x2e,0x25,0x84,0x43,0xba,0xb1,0xd0,0xcf,0xa6,0x1d,0xdc,
2425262728292A2B2C2D2E2F303132333435
0x7b,0xb2,0x89,0x28,0xa7,0xde,0x55,0x34,0xf3,0x6a,0xa1,0x0,0x3f,0xd6,0xd,0xc,0xab,0x22,
363738393A3B3C3D3E3F4041424344454647
0xb9,0x18,0x57,0x4e,0x45,0xa4,0x63,0xda,0x51,0x70,0x6f,0xc6,0x3d,0xfc,0x9b,0xd2,0xa9,0x48,
48494A4B4C4D4E4F50515253545556575859
0x47,0x7e,0x75,0x54,0x93,0x8a,0x41,0xa0,0xdf,0x76,0xad,0x2c,0x4b,0xc2,0x59,0x38,0xf7,0x6e,
5A5B5C5D5E5F606162636465666768696A6B
0x65,0xc4,0x83,0xfa,0xf1,0x10,0xf,0xe6,0x5d,0x1c,0xbb,0xf2,0xc9,0x68,0xe7,0x1e,0x95,0x74,
6C6D6E6F707172737475767778797A7B7C7D
0x33,0xaa,0xe1,0x40,0x7f,0x16,0x4d,0x4c,0xeb,0x62,0xf9,0x58,0x97,0x8e,0x85,0xe4,0xa3,0x1a,
7E7F808182838485868788898A8B8C8D8E8F0x91,0xb0,0xaf,0x6,0x7d,0x3c,0xdb,0x12,0xe9,0x88,0x87,0xbe,0xb5,0x94,0xd3,0xca,0x81,0xe0,
909192939495969798999A9B9C9D9E9FA0A1
0x1f,0xb6,0xed,0x6c,0x8b,0x2,0x99,0x78,0x37,0xae,0xa5,0x4,0xc3,0x3a,0x31,0x50,0x4f,0x26,
A2A3A4A5A6A7A8A9AAABACADAEAFB0B1B2B3
0x9d,0x5c,0xfb,0x32,0x9,0xa8,0x27,0x5e,0xd5,0xb4,0x73,0xea,0x21,0x80,0xbf,0x56,0x8d,0x8c,
B4B5B6B7B8B9BABBBCBDBEBFC0C1C2C3C4C5
0x2b,0xa2,0x39,0x98,0xd7,0xce,0xc5,0x24,0xe3,0x5a,0xd1,0xf0,0xef,0x46,0xbd,0x7c,0x1b,0x52,
C6C7C8C9CACBCCCDCECFD0D1D2D3D4D5D6D7
0x29,0xc8,0xc7,0xfe,0xf5,0xd4,0x13,0xa,0xc1,0x20,0x5f,0xf6,0x2d,0xac,0xcb,0x42,0xd9,0xb8,
D8D9DADBDCDDDEDFE0E1E2E3E4E5E6E7E8E9
0x77,0xee,0xe5,0x44,0x3,0x7a,0x71,0x90,0x8f,0x66,0xdd,0x9c,0x3b,0x72,0x49,0xe8,0x67,0x9e,
EAEBECEDEEEFF0F1F2F3F4F5F6F7F8F9FAFB
0x15,0xf4,0xb3,0x2a,0x61,0xc0,0xff,0x96,0xcd,0xcc,0x6b,0xe2,0x79,0xd8,0x17,0xe,0x5,0x64,
FCFDFEFF
0x23,0x9a,0x11,0x30

需要的结果

0x3c,0x81,0x64,0x30,0xe8,0xee,0xa,0x90,0x20,0x1b,0x46,0x52,0xc8,0x20,0xfe,0xd4,0x8c,0xfe,

剩下的就是替换得到flag了:

838EFBFFE7D9CDDFCFC4C1C5C7CFC9CBB3C9

Reverse-3 CrackMe-2


by 渡师傅

这东西要搞死人啊。。。。。IDA里面看到了

http://p2.qhimg.com/t0175f9e32b14b708e1.png

搜索ios的混淆,搜到个https://github.com/pjebs/Obfuscator-iOS   ,就是这个cm用的

根据git上的文件,字符串搜索可以定位到sub_8657()

int sub_8657()
{
  int v0; // r0@1
  int v1; // ST10_4@1
  int v2; // r0@1
  int v3; // ST08_4@1
  int v4; // r0@1
  int v6; // [sp+38h] [bp-10h]@1
  int v7; // [sp+3Ch] [bp-Ch]@1
  _objc_msgSend(&OBJC_CLASS___ViewController, "class");
  _objc_msgSend(&OBJC_CLASS___NSString, "class");
  v7 = _objc_msgSend(&OBJC_CLASS___Obfuscator, "newWithSalt:");
  v0 = _objc_msgSend(textfield, "text");
  v1 = objc_retainAutoreleasedReturnValue(v0);
  v2 = _objc_msgSend(v7, "reveal:");
  v3 = objc_retainAutoreleasedReturnValue(v2);
  v4 = _objc_msgSend(&OBJC_CLASS___ViewController, "AAA:BBB:");
  v6 = objc_retainAutoreleasedReturnValue(v4);
  objc_release(v3);
  objc_release(v1);
  sub_8688(v6);
  objc_storeStrong(&v6, 0);
  return objc_storeStrong(&v7, 0);
}

这部分可以理解为(大概的意思)

Obfuscator *o = [Obfuscator newWithSalt:[ViewController class],[NSString class], nil];
NSString *k = [o reveal:_key1];#这里要看汇编
[ViewController AAA:textfield BBB:k]

跑到AAA里面去

// ViewController + (id)AAA:(id) BBB:(id)
id __cdecl +[ViewController AAA:BBB:](struct ViewController *self, SEL a2, id a3, id a4)
{
id v4; // ST54_4@1
int v5; // r0@1
int v6; // r0@1
int v7; // ST40_4@1
int v8; // r0@1
int v9; // r0@2
int v10; // r0@2
int v11; // r0@2
int v12; // r1@2
int v13; // ST20_4@3
id result; // r0@3
int v15; // r3@3
int v16; // [sp+8h] [bp-488h]@1
int v17; // [sp+5Ch] [bp-434h]@2
int v18; // [sp+60h] [bp-430h]@1
int v19; // [sp+64h] [bp-42Ch]@1
int v20; // [sp+68h] [bp-428h]@1
int v21; // [sp+6Ch] [bp-424h]@1
int v22; // [sp+70h] [bp-420h]@1
int v23; // [sp+74h] [bp-41Ch]@1
SEL v24; // [sp+78h] [bp-418h]@1
struct ViewController *v25; // [sp+7Ch] [bp-414h]@1
char v26; // [sp+80h] [bp-410h]@1
int v27; // [sp+480h] [bp-10h]@1
v27 = __stack_chk_guard;
v25 = self;
v24 = a2;
v23 = 0;
v4 = a4;
objc_storeStrong(&v23, a3);
v22 = 0;
objc_storeStrong(&v22, v4);
v5 = _objc_msgSend(v23, "dataUsingEncoding:allowLossyConversion:");
v21 = objc_retainAutoreleasedReturnValue(v5);
memset(&v26, 0, 1u);
v20 = 0;
v6 = objc_retainAutorelease(v22);
v7 = _objc_msgSend(v6, "UTF8String");
v8 = objc_retainAutorelease(v21);
v16 = _objc_msgSend(v8, "bytes");
_objc_msgSend(v21, "length");
v19 = CCCrypt(0, 1, 3, v7);
v18 = 0;
if ( !v19 )
{
v9 = _objc_msgSend(&OBJC_CLASS___NSData, "dataWithBytes:length:");
v17 = objc_retainAutoreleasedReturnValue(v9);
v10 = _objc_msgSend(&OBJC_CLASS___GTMBase64, "stringByEncodingData:");
v11 = objc_retainAutoreleasedReturnValue(v10);
v12 = v18;
v18 = v11;
objc_release(v12);
objc_storeStrong(&v17, 0);
} v
13 = objc_retain(v18);
objc_storeStrong(&v18, 0);
objc_storeStrong(&v21, 0);
objc_storeStrong(&v22, 0);
objc_storeStrong(&v23, 0);
result = (id)objc_autoreleaseReturnValue(v13);
if ( __stack_chk_guard != v27 )
__stack_chk_fail(result, __stack_chk_guard, v27, v15, 8, 0, v16);
return result;
}

这部分代码大致意思是用我们传的第二个参数作为key,加密我们的输入, 再base64,根据CCCrypt前3个参数得知加密方式为

DES, ECB,pkcs7padding,key可以用git上的来求, 求出来是UFT-8

这部分结束了, 按照逻辑, 到了_sub_8688, 这个混淆的厉害, 完全不造执行路径, 上下翻了翻, 看到了

http://p5.qhimg.com/t01ad7ee2d78f7dddef.png

得知最后比较的串 wMnLwixufgl=, 搜索该串, 发现这个函数有32个strcmp,这就懵逼了。 。 。

看这里的汇编, 可以推出var_D4上应该是加密的结果, 搜索[R7,#var_D4], 发现有个不同的地方

__text:0000C81C MOVS R0, #0
__text:0000C81E MOV R1, SP
__text:0000C820 SUBS R1, #4
__text:0000C822 MOV SP, R1
__text:0000C824 MOV R2, SP
__text:0000C826 SUBS R2, #4
__text:0000C828 MOV SP, R2
__text:0000C82A MOV R3, SP
__text:0000C82C SUBS R3, #4
__text:0000C82E MOV SP, R3
__text:0000C830 MOV R9, SP
__text:0000C832 SUB.W R9, R9, #4
__text:0000C836 MOV SP, R9
__text:0000C838 MOV R12, SP
__text:0000C83A SUB.W R12, R12, #4
__text:0000C83E MOV SP, R12
__text:0000C840 STR R0, [R1]
__text:0000C842 MOV R0, R1
__text:0000C844 LDR.W LR, [R7,#var_20]
__text:0000C848 STR.W R1, [R7,#var_C4]
__text:0000C84C MOV R1, LR
__text:0000C84E STR.W R12, [R7,#var_C8]
__text:0000C852 STR.W R9, [R7,#var_CC]
__text:0000C856 STR.W R2, [R7,#var_D0]
__text:0000C85A STR.W R3, [R7,#var_D4]
__text:0000C85E BLX _objc_storeStrong
__text:0000C862 LDR.W R0, [R7,#var_C4]
__text:0000C866 LDR R1, [R0]
__text:0000C868 MOV R0, R1
. . . _
_
text:0000C886 STR.W R1, [R7,#var_D8]
__text:0000C88A MOV R1, R2
__text:0000C88C LDR.W R2, [R7,#var_D8]
__text:0000C890 BLX R2
__text:0000C892 LDR.W R1, [R7,#var_D0]
__text:0000C896 STR R0, [R1]
__text:0000C898 LDR R0, [R1] ; char *
__text:0000C89A BLX _strlen
__text:0000C89E ADDS R0, #1 ; size_t
__text:0000C8A0 BLX _malloc
. . . _
_
text:0000C924 LDR.W R10, [R7,#var_CC]
__text:0000C928 STR.W R0, [R10]
__text:0000C92C LDR.W R11, [R7,#var_D4]
__text:0000C930 STR.W R0, [R11]

widows: 2; word-spacing: 0px; -webki以_strlen为分界, 前面的R0应该是传过来的字符串的地址, 存在了var_D0上

后面的R0是_malloc(_strlen+1)出的地址,存到了var_D4和var_CC上, 于是搜索了[R7,#var_CC], 发现了

__text:00070460                 LDR.W           LR, [R7,#var_D0]
__text:00070464                 LDR.W           R4, [LR]
__text:00070468                 LDRB            R4, [R4]
__text:0007046A                 LDR.W           R5, [R7,#var_CC]
__text:0007046E                 LDR             R6, [R5]
__text:00070470                 STRB            R4, [R6]
.
.
.
__text:0003DEC2                 LDR.W           R8, [R7,#var_D0]
__text:0003DEC6                 LDR.W           R10, [R8]
__text:0003DECA                 ADD.W           R10, R10, #1
__text:0003DECE                 STR.W           R10, [R8]
__text:0003DED2                 LDR.W           R10, [R7,#var_CC]
__text:0003DED6                 LDR.W           R11, [R10]
__text:0003DEDA                 ADD.W           R11, R11, #1
__text:0003DEDE                 STR.W           R11, [R10]
.
.
.
__text:000C7E64                 MOVS            R1, #0x1A
__text:000C7E66                 LDR.W           R0, [R7,#var_D0]
__text:000C7E6A                 LDR             R2, [R0]
__text:000C7E6C                 LDRSB.W         R2, [R2]
__text:000C7E70                 SUBS            R2, #0x41(0x61)
__text:000C7E72                 ADDS            R0, R2, #5
__text:000C7E74                 BLX             ___modsi3
__text:000C7E78                 ADDS            R0, #0x41(0x61)
__text:000C7E7A                 LDR.W           R1, [R7,#var_CC]
__text:000C7E7E                 LDR             R2, [R1]
__text:000C7E80                 STRB            R0, [R2]

根据上面的汇编, 理理逻辑

第一, [R7,#var_CC] 和 [R7,#var_D4]上存的是同一个内存地址

第二, [R7,#var_D0] 上存放的字符串是传过来的参数, 会存在 [R7,#var_CC] 上的存的地址上, 可以理解为*(*(R7-CC)) = *(*(R7-D0))

第三, [R7,#var_D0] 上存放的字符串会进行凯撒加密, 并存到[R7,#var_CC]

第四, [R7,#var_D4] 上的字符串会与wMnLwixufgl=比较

然而, 这个函数里有32处有凯撒加密, 所以被自己误导了, 以为每个字符的加密是不一样的, 然后就在那求执行路径, 浪费了大把时间。 。 。

凯撒解密出rHiGrdspabg=

http://tool.chacuo.net/cryptdes 

在这个网址上求解,选好模式和填充方式, 填上key( 见上) ,解密即可

(完)