Mas0n
to be reverse engineer🐧
翻车鱼

第四届美团网络安全高校挑战赛

第四届美团网络安全高校挑战赛

蚌埠住了,32位调用64位代码遇到N次了。后面又来个movfuscator混淆的题因为多开打比赛(我好菜啊……),比赛结束了几十分钟才出。

题目算不上质量高,好在又学到新东西了?

Random

伪随机数异或

ida动调拿xorkey

# 0x07C1181
reg = "al"
data.append(idc.get_reg_value(reg))

一把梭

xorkey = [0x58, 0xa1, 0xcb, 0xe9, 0xed, 0x2c, 0xec, 0xfb, 0xe9, 0xc4, 0x16, 0x97, 0x99, 0xb1, 0xa4, 0xe9, 0xc3, 0xc6, 0x80, 0xbf, 0x3e, 0x44, 0x18, 0x2e, 0x73, 0x56, 0x52, 0xb8, 0x5b, 0x66, 0xed, 0xbc, 0x8a, 0xd8, 0x36, 0x8f, 0xe6, 0xd3, 0xb1, 0x51, 0xb9, 0x59, 0xd3, 0x5a]

flag = bytearray([0x3E, 0xCD, 0xAA, 0x8E, 0x96, 0x1F, 0x89, 0xCD, 0xDB, 0xF1, 0x70, 0xF2, 0xA9, 0x9C, 0xC2, 0x8B, 0xF2, 0xFE, 0xAD, 0x8B, 0x58, 0x7C, 0x2F, 0x03, 0x4A, 0x65, 0x31, 0x89, 0x76, 0x57, 0x88, 0xDF, 0xB8, 0xE9, 0x01, 0xE9, 0xDE, 0xE5, 0x86, 0x68, 0x8F, 0x24, 0xD3, 0x5A])
for i in range(len(flag)):
    flag[i] ^= xorkey[i]
print(flag)

wow

遇到N次这类题目了,32位运行64位代码

https://cdn.shi1011.cn/2021/12/d924e7d06079297a9db103c6f965b369.png?imageMogr2/format/webp/interlace/0/quality/90|watermark/2/text/wqlNYXMwbg/font/bXN5aGJkLnR0Zg/fontsize/14/fill/IzMzMzMzMw/dissolve/80/gravity/southeast/dx/5/dy/5

windbg跑起来动调

这里有个坑,需要改成固定基址

https://cdn.shi1011.cn/2021/12/a4186d06856f3a9ea6bce8e3696140f9.png?imageMogr2/format/webp/interlace/0/quality/90|watermark/2/text/wqlNYXMwbg/font/bXN5aGJkLnR0Zg/fontsize/14/fill/IzMzMzMzMw/dissolve/80/gravity/southeast/dx/5/dy/5

修改PE头强制IDA反编译

Rebase

定位402176,创建函数

void __fastcall sub_402176(unsigned int *a1)
{
  unsigned int v1; // er9
  int v2; // ebp
  unsigned int v3; // esi
  unsigned int *v4; // rdi
  unsigned int *v5; // r10
  unsigned int v6; // ebx
  unsigned int i; // er11
  unsigned int v8; // er8
  int v9; // edx
  unsigned int v10; // eax
  unsigned int v11; // er9
  unsigned int v12; // er8
  int v13; // ebx
  int v14; // ebx
  int v15; // ebx
  int v16; // edx
  unsigned int v17; // eax
  unsigned int v18; // er9

  v1 = a1[8];
  v2 = 12;
  v3 = 0;
  while ( 1 )
  {
    v3 += 0x67452301;
    v4 = a1 + 1;
    v5 = a1;
    v6 = v3 >> 2;
    for ( i = 0; i < 8; ++i )
    {
      v8 = *v4;
      if ( (((unsigned __int8)i ^ (unsigned __int8)v6) & 3) != 0 )
      {
        switch ( ((unsigned __int8)i ^ (unsigned __int8)v6) & 3 )
        {
          case 1:
            v9 = (v1 >> 5) ^ (4 * v8);
            v10 = v1;
            v11 = v1 ^ 0x10325476;
            break;
          case 2:
            v9 = (v1 >> 5) ^ (4 * v8);
            v10 = v1;
            v11 = v1 ^ 0x98BADCFE;
            break;
          case 3:
            v9 = (v1 >> 5) ^ (4 * v8);
            v10 = v1;
            v11 = v1 ^ 0xC3D2E1F0;
            break;
          default:
            goto LABEL_12;
        }
      }
      else
      {
        v9 = (v1 >> 5) ^ (4 * v8);
        v10 = v1;
        v11 = v1 ^ 0xEFCDAB89;
      }
      *v5 += (v11 + (v3 ^ v8)) ^ (((16 * v10) ^ (v8 >> 3)) + v9);
      v1 = *v5;
LABEL_12:
      ++v4;
      ++v5;
    }
    v12 = *a1;
    v13 = ((unsigned __int8)i ^ (unsigned __int8)v6) & 3;
    if ( !v13 )
    {
      v16 = (v1 >> 5) ^ (4 * v12);
      v17 = v1;
      v18 = v1 ^ 0xEFCDAB89;
      goto LABEL_21;
    }
    v14 = v13 - 1;
    if ( !v14 )
    {
      v16 = (v1 >> 5) ^ (4 * v12);
      v17 = v1;
      v18 = v1 ^ 0x10325476;
      goto LABEL_21;
    }
    v15 = v14 - 1;
    if ( !v15 )
    {
      v16 = (v1 >> 5) ^ (4 * v12);
      v17 = v1;
      v18 = v1 ^ 0x98BADCFE;
LABEL_21:
      a1[8] += (v18 + (v3 ^ v12)) ^ (((16 * v17) ^ (v12 >> 3)) + v16);
      v1 = a1[8];
      goto LABEL_22;
    }
    if ( v15 == 1 )
    {
      v16 = (v1 >> 5) ^ (4 * v12);
      v17 = v1;
      v18 = v1 ^ 0xC3D2E1F0;
      goto LABEL_21;
    }
LABEL_22:
    if ( !--v2 )
      __asm { retfq }
  }
}

魔改的XXTEA,手动化简一下

void __fastcall sub_402176(unsigned int *v)
{
    DWORD z; // rax
    unsigned int sum; // er11
    unsigned int e; // edx
    int i; // r9
    unsigned int y; // er8

    uint32_t k[4] = {0xEFCDAB89, 0x10325476, 0x98BADCFE, 0xC3D2E1F0};
    z = v[8];
    sum = 0;
    do
    {
        sum += 0x67452301;
        for ( i = 0; i < 8; ++i )
        {
            e = (sum >> 2) & 3;
            y = v[i + 1];
            z = v[i] + (((z>>5^y<<2) + (y>>3^z<<4)) ^ ((sum^y) + (k[(i&3)^e] ^ z)));
            v[i] = z;
        }
        y = v[0];
        z = v[8] + (((z>>5^y<<2) + (y>>3^z<<4)) ^ ((sum^y) + (k[(i&3)^e] ^ z)));
        v[8] = z;
    }
    while (sum != 0xD73DA40C );

}

解密脚本

void __fastcall sub_402176ss(unsigned int *v)
{
    DWORD z; // rax
    unsigned int sum; // er11
    unsigned int e; // edx
    int i; // r9
    unsigned int y; // er8

    uint32_t k[4] = {0xEFCDAB89, 0x10325476, 0x98BADCFE, 0xC3D2E1F0};
    y = v[0];
    sum = 0xD73DA40C;

    do
    {
        for ( i = 8; i > 0; --i )
        {
            e = (sum >> 2) & 3;
            z = v[i - 1];
            y = v[i] -= (((z>>5^y<<2) + (y>>3^z<<4)) ^ ((sum^y) + (k[(i&3)^e] ^ z)));
        }
        z = v[8];
        y = v[0] -= (((z>>5^y<<2) + (y>>3^z<<4)) ^ ((sum^y) + (k[(i&3)^e] ^ z)));
        sum -= 0x67452301;
    }
    while (sum != 0 );

}
int main() {
    uint32_t v[9] = {
            0xD8F758F5, 0x526849DB, 0xE2D72563, 0x485EEFAC, 0x608F4BC6, 0x5859F76A, 0xB03565A3, 0x3E4091C1,
            0xD3DB5B9A
    };
    sub_402176ss(v);
    for (int i = 0; i < 9; ++i) {
        printf("0x%x, ", v[i]);
    }
    return 0;
}

小端序完事

Un(ix)zip

linux下解压,python脚本梭

"""
@Author: Mas0n
@File: mtctf1.py
@Time: 2021-12-11 9:58
@Desc: It's all about getting better.
"""
import os


path = "ppp"

def getListFiles(path):
  assert os.path.isdir(path), '%s not exist.' % path
  ret = []
  for root, dirs, files in os.walk(path):
    for filespath in files:
      ret.append([os.path.split(root)[1], int(filespath, 10)])
  return ret


lis = getListFiles(path)
flags = bytearray([0] * (len(lis)+1))
for al in lis:
    flags[al[1]] = ord(al[0])

print(flags.decode(), flags[::-1])
# base64decode

Superflat

mov混淆介绍

domas_2015_the_movfuscator.pdf

Battelle/movfuscator

找到个反混淆工具

kirschju/demovfuscator

偷懒直接拿docker跑了

sudo docker pull iyzyi/demovfuscator
···
cp superflat /home/
sudo docker run --name demov -it -v /home/mason/Desktop/:/home/ iyzyi/demovfuscator /bin/bash
cd demovfuscator
./demov /home/superflat -g /home/superflat.dot -o /home/fix_superflat

dot -tPng superflat.dot > superflat.png

拿到一个流程图和初步修复好的文件,虽然说不是完全修复,凑活看

https://cdn.shi1011.cn/2021/12/637bcc3ceee4748334962e735ba91709.png?imageMogr2/format/webp/interlace/0/quality/90|watermark/2/text/wqlNYXMwbg/font/bXN5aGJkLnR0Zg/fontsize/14/fill/IzMzMzMzMw/dissolve/80/gravity/southeast/dx/5/dy/5

通过流程图,可以猜测范围区间内的功能

翻找下特征

这里能看到AES的特征Sbox,其实是障眼法…

https://cdn.shi1011.cn/2021/12/9bd3675212ca8daba3915ec3813257b1.png?imageMogr2/format/webp/interlace/0/quality/90|watermark/2/text/wqlNYXMwbg/font/bXN5aGJkLnR0Zg/fontsize/14/fill/IzMzMzMzMw/dissolve/80/gravity/southeast/dx/5/dy/5

看到两组42位的数组

https://cdn.shi1011.cn/2021/12/f89854a26ccf0f1c92ad610d0eab0e59.png?imageMogr2/format/webp/interlace/0/quality/90|watermark/2/text/wqlNYXMwbg/font/bXN5aGJkLnR0Zg/fontsize/14/fill/IzMzMzMzMw/dissolve/80/gravity/southeast/dx/5/dy/5

动调起来,关键处打断点,单步观察寄存器及指令,反复调试几遍结合合理推测:

  • 输入长度为0x2A
  • Sbox作为映射表
  • unknown2作为xorkey

伪代码如下

for i in range(42):
    sbox[flag[i]] ^ unknown2[i] == unknown1[i]

逆过程即可

# -*- coding:utf-8 -*-
"""
@Author: Mas0n
@File: mtctf2.py
@Time: 2021-12-11 21:22
@Desc: It's all about getting better.
"""

sbox = [0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, 0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76, 0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0, 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0, 0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC, 0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15, 0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A, 0x07, 0x12, 0x80, 0xE2, 0xEB, 0x27, 0xB2, 0x75, 0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0, 0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84, 0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B, 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF, 0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85, 0x45, 0xF9, 0x02, 0x7F, 0x50, 0x3C, 0x9F, 0xA8, 0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5, 0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2, 0xCD, 0x0C, 0x13, 0xEC, 0x5F, 0x97, 0x44, 0x17, 0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73, 0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88, 0x46, 0xEE, 0xB8, 0x14, 0xDE, 0x5E, 0x0B, 0xDB, 0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C, 0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79, 0xE7, 0xC8, 0x37, 0x6D, 0x8D, 0xD5, 0x4E, 0xA9, 0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08, 0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6, 0xE8, 0xDD, 0x74, 0x1F, 0x4B, 0xBD, 0x8B, 0x8A, 0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E, 0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E, 0xE1, 0xF8, 0x98, 0x11, 0x69, 0xD9, 0x8E, 0x94, 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF, 0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68, 0x41, 0x99, 0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16]
xorkey = [0x44, 0xCA, 0x41, 0xBB, 0x8D, 0x29, 0x1F, 0xB0, 0x22, 0x9A, 0x0D, 0x50, 0xC8, 0xAC, 0x27, 0x36, 0x87, 0xC3, 0x25, 0xAE, 0xD7, 0x94, 0x06, 0xB9, 0xE6, 0xBF, 0xC7, 0x32, 0x55, 0x7A, 0x72, 0x92, 0xF8, 0xE0, 0x42, 0xF8, 0x40, 0x8E, 0x51, 0x99, 0x39, 0x8D]
enc = [0x77, 0x9A, 0xAE, 0x3E, 0xAC, 0x6A, 0x1B, 0xB5, 0x11, 0x9E, 0xA7, 0xAB, 0x33, 0x74, 0x35, 0xF5, 0xCA, 0xC7, 0xFD, 0xBC, 0x2C, 0x02, 0xAC, 0x61, 0x21, 0xBA, 0x00, 0x7F, 0x8D, 0x37, 0xB5, 0x8A, 0xFD, 0xF8, 0x85, 0x62, 0x45, 0xCD, 0x92, 0x8B, 0xAF, 0x72]

flag = bytearray([0] * 42)

for i in range(42):
    flag[i] = sbox.index(xorkey[i] ^ enc[i])
print(flag)
本文链接:https://blog.shi1011.cn/ctf/1955
本文采用 CC BY-NC-SA 4.0 Unported 协议进行许可

Mas0n

文章作者

发表回复

textsms
account_circle
email

  • Komorebi

    师傅,我想请问一下那个 wow:我改64位,Rebase之后,定位到402176,但是发现那里是一堆数据,没办法创建函数,这种情况怎么破?

    2年前 回复

翻车鱼

第四届美团网络安全高校挑战赛
蚌埠住了,32位调用64位代码遇到N次了。后面又来个movfuscator混淆的题因为多开打比赛(我好菜啊……),比赛结束了几十分钟才出。 题目算不上质量高,好在又学到新东西了? Random …
扫描二维码继续阅读
2021-12-12