首页
论坛
课程
招聘
[原创]2019redhat Reverse部分writeup
2019-11-13 00:34 4388

[原创]2019redhat Reverse部分writeup

2019-11-13 00:34
4388

周末打了一下红帽杯,Reverse比较简单,简略写下writeup,好久没发帖子了,水一水

0x01 XX

程序首先校验前四个字符是否在"qwertyuiopasdfghjklzxcvbnm1234567890"这个字符集

v17 = xxtea((__int64)Code, v3, (unsigned __int8 *)&v30, &Size);

之后进行xxtea加密,密钥为前四个字符,明文为输入的19个字符+0x00000013,密文为6*32bits,24个字符

 

接下来是一个一一映射的关系,改变密文顺序,最后是一个比较简单的异或算法,结果与常量进行比较

*(_QWORD *)&v30 = 0xC0953A7C6B40BCCEi64;
  v25 = v20 - (_BYTE *)&v30;
  *((_QWORD *)&v30 + 1) = 0x3502F79120209BEFi64;
  v26 = 0i64;
  v31 = 0xC8021823;
  v32 = 0xFA5656E7;

直接还原出xxtea密文,爆破密钥,复杂度为36**4

#include <stdbool.h>
#include <stdio.h>
#define MX \
  ((z >> 5 ^ y << 2) + (y >> 3 ^ z << 4) ^ (sum ^ y) + (k[p & 3 ^ e] ^ z))
bool btea(unsigned int* v, int n, unsigned int* k) {
  unsigned int z = v[n - 1], y = v[0], sum = 0, e, DELTA = 0x9e3779b9;
  unsigned int p, q;
  if (n > 1) {
    return 0;
  } else if (n < -1) {
    n = -n;
    q = 6 + 52 / n;
    sum = q * DELTA;
    while (sum != 0) {
      e = (sum >> 2) & 3;
      for (p = n - 1; p > 0; p--)
        z = v[p - 1], y = v[p] -= MX;
      z = v[n - 1];
      y = v[0] -= MX;
      sum -= DELTA;
    }
    return 0;
  }
  return 1;
}

int main(int argc, char const* argv[]) {
  __uint8_t res[24] = {0xCE, 0xBC, 0x40, 0x6B, 0x7C, 0x3A, 0x95, 0xC0,
                       0xEF, 0x9B, 0x20, 0x20, 0x91, 0xF7, 0x02, 0x35,
                       0x23, 0x18, 0x02, 0xC8, 0xE7, 0x56, 0x56, 0xFA};

  for (size_t i = 23; i > 0; i--) {
    for (size_t j = 0; j < i / 3; j++) {
      res[i] ^= res[j];
    }
  }
  for (size_t i = 0; i < 24; i++) {
    printf("%x ", res[i]);
  }

  __uint8_t bteares[24] = {0};
  bteares[2] = *res;
  *bteares = res[1];
  bteares[3] = res[2];
  bteares[1] = res[3];
  bteares[6] = res[4];
  bteares[4] = res[5];
  bteares[7] = res[6];
  bteares[5] = res[7];
  bteares[10] = res[8];
  bteares[8] = res[9];
  bteares[11] = res[10];
  bteares[9] = res[11];
  bteares[14] = res[12];
  bteares[12] = res[13];
  bteares[15] = res[14];
  bteares[13] = res[15];
  bteares[18] = res[16];
  bteares[16] = res[17];
  bteares[19] = res[18];
  bteares[17] = res[19];
  bteares[22] = res[20];
  bteares[20] = res[21];
  bteares[23] = res[22];
  bteares[21] = res[23];
  __uint32_t vres[6] = {0};
  __uint32_t tmp[6] = {0};
  for (size_t i = 0; i < 24; i += 4) {
    vres[i / 4] = bteares[i] + (((__uint32_t)bteares[i + 1]) << 8) +
                  (((__uint32_t)bteares[i + 2]) << 16) +
                  (((__uint32_t)bteares[i + 3]) << 24);
    tmp[i / 4] = vres[i / 4];
  }
  int index = 0;
  unsigned int key[4] = {0, 0, 0, 0};
  __uint8_t vvv[36] = {0x71, 0x77, 0x65, 0x72, 0x74, 0x79, 0x75, 0x69, 0x6f,
                       0x70, 0x61, 0x73, 0x64, 0x66, 0x67, 0x68, 0x6a, 0x6b,
                       0x6c, 0x7a, 0x78, 0x63, 0x76, 0x62, 0x6e, 0x6d, 0x31,
                       0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x30};
  for (size_t i = 0; i < 36; i++) {
    for (size_t j = 0; j < 36; j++) {
      for (size_t k = 0; k < 36; k++) {
        for (size_t z = 0; z < 36; z++) {
          key[0] = vvv[i] + (((__uint32_t)vvv[j]) << 8) +
                   (((__uint32_t)vvv[k]) << 16) + (((__uint32_t)vvv[z]) << 24);
          for (size_t ii = 0; ii < 6; ii++) {
            vres[ii] = tmp[ii];
          }
          btea(vres, -6, key);
          if (vres[0] == key[0]) {
            puts("");
            printf("%x%x", vres[0], vres[1]);
            printf("%x%x", vres[2], vres[3]);
            printf("%x%x\n", vres[4], vres[5]);
            for (size_t ii = 0; ii < 6; ii++) {
              for (size_t jj = 0; jj < 4; jj++) {
                printf("%c", ((vres[ii] >> (jj * 8)) & 0xff));
              }
            }
          }
        }
      }
    }
  }
  return 0;
}

flag{CXXand++tea}

0x02 easyRE

main函数解出了一个提示还有彩蛋

➜  hmb ./easyRE

Info:The first four chars are `flag`

continue!

https://bbs.pediy.com/thread-254172.htm

You found me!!!

bye bye~

根据提示最后发现了

unsigned __int64 sub_400D35()
{
  unsigned __int64 result; // rax
  unsigned int v1; // [rsp+Ch] [rbp-24h]
  int i; // [rsp+10h] [rbp-20h]
  int j; // [rsp+14h] [rbp-1Ch]
  unsigned int v4; // [rsp+24h] [rbp-Ch]
  unsigned __int64 v5; // [rsp+28h] [rbp-8h]

  v5 = __readfsqword(0x28u);
  v1 = sub_43FD20(0LL) - qword_6CEE38;
  for ( i = 0; i <= 1233; ++i )
  {
    sub_40F790(v1);
    sub_40FE60();
    sub_40FE60();
    v1 = (unsigned __int64)sub_40FE60() ^ 0x98765432;
  }
  v4 = v1;
  if ( ((unsigned __int8)v1 ^ byte_6CC0A0[0]) == 102 && (HIBYTE(v4) ^ (unsigned __int8)byte_6CC0A3) == 103 )
  {
    for ( j = 0; j <= 24; ++j )
      sub_410E90((unsigned __int8)(byte_6CC0A0[j] ^ *((_BYTE *)&v4 + j % 4)));
  }
  result = __readfsqword(0x28u) ^ v5;
  if ( result )
    sub_444020();
  return result;
}

尝试解一下

byte_6CC0A0 = [0x40,0x35,0x20,0x56,0x5d,0x18,0x22,0x45,0x17,0x2f,0x24,0x6e,0x62,0x3c,0x27,0x54,0x48,0x6c,0x24,0x6e,0x72,0x3c,0x32,0x45,0x5b]
v4 = [byte_6CC0A0[0]^ord('f'),byte_6CC0A0[1]^ord('l'),byte_6CC0A0[2]^ord('a'),byte_6CC0A0[3]^ord('g')]
flag = ''
for i in range(len(byte_6CC0A0)):
    flag+=chr(byte_6CC0A0[i] ^v4[i%4])
print (flag)

flag{Act1ve_Defen5e_Test}

0x03 childRE

前面是一个一一映射关系,改变输入字符串顺序,先不管

 

之后对输入字符串反修饰C++ 符号名

UnDecorateSymbolName(v5, outputString, 0x100u, 0);

限定输入长度为31,输出长度为62,之后是一个简单的比较算法

do
    {
      v14 = outputString[v13];
      v15 = v14 % 23;
      if ( a1234567890Qwer[v15] != *(_BYTE *)(v13 + 5368722552i64) )
        _exit(v12);
      if ( a1234567890Qwer[v14 / 23] != *(_BYTE *)(v13 + 5368722488i64) )
        _exit(v12 * v12);
      ++v12;
      ++v13;
    }
    while ( v12 < 0x3E );

先还原出c++函数名

src ='1234567890-=!@#$%^&*()_+qwertyuiop[]QWERTYUIOP{}asdfghjkl;\x27ASDFGHJKL:"ZXCVBNM<>?zxcvbnm,./'
s1= '55565653255552225565565555243466334653663544426565555525555222'
s2='(_@4620!08!6_0*0442!@186%%0@3=66!!974*3234=&0^3&1@=&0908!6_0*&'
l = []
for i in range(62):
    a = src.find(s1[i])
    b = src.find(s2[i])
    l.append(a*23+b)
print(''.join(map(chr,l)))

得到原函数名

 

private: char __thiscall R0Pxx::My_Aut0_PWN(unsigned char )

 

根据c++规范手撸修饰后的符号,得到

 

?My_Aut0_PWN@R0Pxx@@AAEPADPAE@Z

 

前面说过有一个一一映射的关系,懒得逆了,输入

 

1234567890abcdefghijklmnopqrstu

 

得到输出

 

fg8hi94jk0lma52nobpqc6rsdtue731

 

直接将结果映射回去得到真正的输入,md5得到flag

s1 = 'fg8hi94jk0lma52nobpqc6rsdtue731'
s2 = '1234567890abcdefghijklmnopqrstu'
res = '?My_Aut0_PWN@R0Pxx@@AAEPADPAE@Z'

l = ['0' for _ in range(31)]
for i in range(31):
    a = s1[i]
    l[s2.find(a)] = res[i]
input = ''.join(l)
print("flag{%s}"%md5(input).hexdigest())

flag{63b148e750fed3a33419168ac58083f5}

0x04 Calc

这道题是赛后才搞出来的,cpp、stl太恶心(还是太菜了

 

主要都是动态调试调出来的,程序逻辑大概就是输入三个整数然后计算

v24 = (char *)x[0];
  v25 = (x[1] - x[0]) >> 2;
  v26 = z[0];
  v27 = (z[1] - z[0]) >> 2;
  v28 = (char *)y[0];
  if ( v25 == v27 )
  {
    v30 = v25 - 1;
    if ( (int)v25 - 1 < 0 )
      goto LABEL_47;
    v31 = v30;
    v32 = (char *)z[0] + 4 * v30;
    while ( *(_DWORD *)((char *)v32 + x[0] - z[0]) == *v32 )
    {
      --v30;
      --v32;
      if ( --v31 < 0 )
        goto LABEL_47;
    }
    v29 = *((_DWORD *)x[0] + v30) < *((_DWORD *)z[0] + v30);
  }
  else
  {
    v29 = v25 < v27;
  }
  if ( !v29 )
    goto LABEL_47;
  v35 = (y[1] - y[0]) >> 2;
  if ( v35 != v25 )
  {
    v36 = v35 < v25;
    goto LABEL_62;
  }
  v37 = v35 - 1;
  if ( (int)v35 - 1 < 0 )
  {
LABEL_47:
    v33 = -1;
    goto LABEL_48;
  }
  v38 = v37;
  v39 = (char *)x[0] + 4 * v37;
  while ( *(_DWORD *)((char *)v39 + y[0] - x[0]) == *v39 )
  {
    --v37;
    --v39;
    if ( --v38 < 0 )
      goto LABEL_47;
  }
  v36 = *((_DWORD *)y[0] + v37) < *((_DWORD *)x[0] + v37);

上面这一段是校验 输入的三个整数 x、y、z 中 x<z && y<x

 

接下来就是 加、减、乘、幂运算了,连蒙带猜理清了一些逻辑关系

  v40 = mul(&v146, v135, x);                    // v40 = 3*x
  v41 = mul(&v143, v40, x);                     // v41 = 3*x*x
  v42 = mul(&v140, v41, y);                     // v42 = 3*x*x*y
  v43 = pow(&v137, y, v133);                    // v43 = y*y
  v44 = mul(&v161, v131, x);                    // v44 = 3*x
  v45 = mul(&v150, v44, v43);                   // v45 = 3*x*y*y
  ………………
  v54 = add(Memory, v124, y);                   // v54 = x+y
  v55 = pow(&v149, v54, v129);                  // v55 = (x+y)**3
  v154 = v55;
  v56 = mov(&v163, v45);
  v57 = sub(v55, v56);                          // v57 = (x+y)**3 - 3*x*y*y
  ………………
  v60 = sub(v122, v59);                         // v60 = (x+y)**3 - 3*x*y*y - 3*x*x*y

这一部分计算了 (x+y)**3 - 3x\y*y - 3*x*x*y

 

下面还有一部分计算了 (z+4)**3 - 12*(z**2) - z*48 - 22

 

最终校验两部分是否相等

 

化简可以得到一个丢番图方程

 

x**3+y**3-z**3 == 42

 

参考https://en.wikipedia.org/wiki/Sums_of_three_cubes

 

得到结果

x == 80435758145817515
y == 12602123297335631
z == 80538738812075974

flag{MD5("804357581458175151260212329733563180538738812075974").tolower()}

 

get flag flag{951e27be2b2f10b7fa22a6dc8f4682bd}


第五届安全开发者峰会(SDC 2021)议题征集正式开启!

最后于 2019-11-13 11:52 被丿feng编辑 ,原因:
上传的附件:
收藏
点赞1
打赏
分享
最新回复 (7)
雪    币: 9168
活跃值: 活跃值 (3741)
能力值: ( LV12,RANK:252 )
在线值:
发帖
回帖
粉丝
一半人生 活跃值 4 2019-11-13 08:48
2
0
厉害
最后于 2019-11-13 08:50 被一半人生编辑 ,原因:
雪    币: 3766
活跃值: 活跃值 (1628)
能力值: (RANK:200 )
在线值:
发帖
回帖
粉丝
roysue 活跃值 3 2019-11-13 11:32
3
0
给个样本呢大佬
雪    币: 7088
活跃值: 活跃值 (192)
能力值: ( LV12,RANK:256 )
在线值:
发帖
回帖
粉丝
丿feng 活跃值 3 2019-11-13 11:53
4
0
roysue 给个样本呢大佬
我给忘了,已添加在附件了
雪    币: 3766
活跃值: 活跃值 (1628)
能力值: (RANK:200 )
在线值:
发帖
回帖
粉丝
roysue 活跃值 3 2019-11-13 13:15
5
0
丿feng 我给忘了,已添加在附件了
多谢大佬~
雪    币: 150
活跃值: 活跃值 (1213)
能力值: ( LV5,RANK:75 )
在线值:
发帖
回帖
粉丝
Vinadiak 活跃值 1 2019-11-13 22:04
6
0
多谢分享,想问下大佬ChildRe那个函数是怎样判断是映射关系的,求指导,我在那个函数那里卡得挺久的
最后于 2019-11-14 00:05 被Vinadiak编辑 ,原因:
雪    币: 7088
活跃值: 活跃值 (192)
能力值: ( LV12,RANK:256 )
在线值:
发帖
回帖
粉丝
丿feng 活跃值 3 2019-11-14 00:14
7
0
Vinadiak 多谢分享,想问下大佬ChildRe那个函数是怎样判断是映射关系的,求指导,我在那个函数那里卡得挺久的
动态调一下就可以发现只改变了字符的顺序
雪    币: 279
活跃值: 活跃值 (45)
能力值: ( LV4,RANK:40 )
在线值:
发帖
回帖
粉丝
pangpwn 活跃值 2019-12-16 09:03
8
0
Vinadiak 多谢分享,想问下大佬ChildRe那个函数是怎样判断是映射关系的,求指导,我在那个函数那里卡得挺久的
用x64dbg动态调试,在16CD地址处下断,观察寄存器窗口即可发现只有字符位置偏移上的变化
游客
登录 | 注册 方可回帖
返回