强网杯企业组 - SimpleRe

ELF64程序,无壳,IDA反编译main函数,这里我稍微做了重命名,看起来比较清楚:

__int64 __fastcall main(int a1, char **a2, char **a3)
{
  __int64 result; // rax
  char suf_flag[33]; // [rsp+0h] [rbp-250h] BYREF
  char pre_flag[15]; // [rsp+21h] [rbp-22Fh] BYREF
  char v6[256]; // [rsp+30h] [rbp-220h] BYREF
  char encode_flag[256]; // [rsp+130h] [rbp-120h] BYREF
  void *src; // [rsp+230h] [rbp-20h]
  void *dest; // [rsp+238h] [rbp-18h]
  int v10; // [rsp+244h] [rbp-Ch]
  int j; // [rsp+248h] [rbp-8h]
  int i; // [rsp+24Ch] [rbp-4h]

  printf("your flag:");
  __isoc99_scanf("%s", v6);
  putchar(10);
  if ( v6[15] == '-' )
  {
    for ( i = 0; i <= 14; ++i )
      pre_flag[i] = v6[i];
    for ( j = 0; j <= 17; ++j )
      suf_flag[j] = v6[j + 16];
    v10 = decode_puzzle((__int64)pre_flag);
    if ( v10 == 1 )
    {
      dest = mmap(0LL, 0x1000uLL, 7, 33, -1, 0LL);
      src = (void *)generate_machine_code();
      memcpy(dest, src, 0x28CuLL);
      ((void (__fastcall *)(char *, char *, void *))dest)(encode_flag, suf_flag, &unk_404320);
      v10 = check_encode(encode_flag);
      if ( v10 )
        puts("congratulations!");
      else
        printf("nonono");
      result = 0LL;
    }
    else
    {
      printf("nonono");
      result = 0LL;
    }
  }
  else
  {
    printf("nonono");
    result = 0LL;
  }
  return result;
}

可以看到flag是通过-分成两部分进行校验:

第一部分是通过一个迷宫puzzle,其走法即为上半部分flag,这里只能走.,终点为B:

__int64 __fastcall sub_401192(__int64 a1)
{
  int v1; // eax
  int i; // [rsp+Ch] [rbp-Ch]
  int line; // [rsp+10h] [rbp-8h]
  int row; // [rsp+14h] [rbp-4h]

  row = 1;
  line = 0;
  for ( i = 0; i <= 14; ++i )
  {
    v1 = *(unsigned __int8 *)(i + a1);
    if ( v1 == 'w' )
    {
      --line;
    }
    else if ( *(unsigned __int8 *)(i + a1) <= 0x77u )
    {
      if ( v1 == 's' )
      {
        ++line;
      }
      else if ( *(unsigned __int8 *)(i + a1) <= 0x73u )
      {
        if ( v1 == 'a' )
        {
          --row;
        }
        else if ( v1 == 'd' )
        {
          ++row;
        }
      }
    }
    if ( aAB[11 * line + row] == 'B' )
      return 1LL;
    if ( aAB[11 * line + row] != '.' )
      return 0LL;
  }
  return 0LL;
}

根据下标的获取,很容易知道这是一个11列的矩阵,根据这个就可以划出迷宫了:

*A*********
*.***.....*
*.....***.*
********..*
********B**

得到上半部分的flag:ssddddwddddssas

下半部分的关键在这五行代码:

dest = mmap(0LL, 0x1000uLL, 7, 33, -1, 0LL);
src = (void *)generate_machine_code();
memcpy(dest, src, 0x28CuLL);
((void (__fastcall *)(char *, char *, void *))dest)(encode_flag, suf_flag, &unk_404320);
v10 = check_encode(encode_flag);

IDA反编译中调用mmap进行地址映射,然后调用generate_machine_code()来生成机器码,将这里的数据赋值到mmap映射的地址中,然后传入三个参数,将suf_flag作为text,unk_404320作为key进行加密,得到的结果存入encode_flag中,最后与r60ihyZ/m4lseHt+m4t+mIkc进行比较
所以这里关键就在机器码生成和key的处理:

_BYTE *generate_machine_code()
{
  _BYTE *v1; // [rsp+8h] [rbp-18h]
  int j; // [rsp+14h] [rbp-Ch]
  int i; // [rsp+18h] [rbp-8h]
  int v4; // [rsp+1Ch] [rbp-4h]

  v1 = malloc(0x200uLL);
  v4 = 0;
  for ( i = 0; i < 652; ++i )
  {
    if ( v4 == 64 )
      v4 = 0;
    v1[i] = byte_404080[i] ^ byte_404360[v4++];
  }
  for ( j = 0; j <= 63; ++j )
    byte_404320[j] ^= byte_404360[j];
  return v1;
}

python脚本生成一下数据,生成机器码和加密用的key:

byte_404360 = ['3E', '7A', '40', '64', '27', '25', '48', '4', '4F', '63', '19', '60', '0B', '3A', '75', '5D', '11', '4E', '7', '44', '30', '4C', '4B', '6', '5F', '73', '0D', '1A', '38', '8', '34', '78', '45', '47', '58', '3B', '74', '7D', '2C', '2B', '4A', '3C', '29', '13', '1', '3F', '3', '61', '70', '52', '65', '9', '22', '0', '7F', '59', '6C', '77', '72', '3D', '32', '55', '41', '49']
byte_404320 = ['4D', '20', '7', '5', '43', '15', '7A', '73', '39', '1', '7F', '53', '66', '4E', '0D', '18', '60', '76', '75', '0', '58', '15', '0', '32', '68', '3F', '78', '7F', '7B', '64', '4E', '49', '0F', '2E', '3F', '0D', '0D', '0D', '64', '66', '61', '53', '6', '44', '34', '6E', '69', '2F', '20', '14', '37', '6A', '49', '55', '36', '37', '23', '23', '2A', '6B', '73', '6', '78', '0B']
byte_404380 = ['6B', '32', 'C9', '81', '6F', 'AC', '35', 'DC', '7', 'EA', '6C', 'B', '43', 'B3', '2', '95', '59', 'C5', '52', 'B4', '78', 'C7', '0E', 'D6', '17', '72', 'DD', '15', '8E', '8', 'B', 'B8', '31', '4', '1', 'B8', '31', '8D', '2D', 'C', 'AD', 'AC', '61', 'D4', '44', 'C7', '3', '61', '7', '52', '2D', '82', '6F', 'F', '37', 'E3', '3A', '22', '27', '68', '67', '0', '14', '1C', '76', 'F3', '88', '2C', 'D', 'CF', '0', '8D', '81', '2B', 'D8', '9E', '34', '72', 'FC', '8D', '59', '67', 'F7', '0C', 'B9', '8E', '3', '7', '8D', '3B', '0C', 'D8', '7', '81', 'FC', '3', '6C', '97', '1', 'BE', 'B4', '8', '4', '63', 'C1', '71', 'D9', '5B', 'BB', '69', '56', '34', '25', '7', '3', '5C', '77', '48', 'F6', '91', '24', '8', '98', '75', 'F3', 'AC', '7E', '1', 'B7', 'AA', '8', '4D', 'EF', '6D', '89', 'E4', '4D', '2B', '9', '25', 'F3', 'D1', '5F', '15', '9A', '3', 'F7', '0C', '8A', '1A', '1E', '53', '0A', '26', '58', '4F', '6D', '4', 'BD', 'B', '0D', 'B', 'B2', '73', 'B5', '84', '13', '63', 'C3', 'EC', '61', '3A', 'C9', '77', '8', 'A1', '71', '1A', 'A4', 'E9', '2', '48', 'F6', '1C', '94', '3F', 'F9', '68', 'CA', '1D', 'CA', '0C', 'E6', '32', '41', 'B4', 'E1', '25', '48', 'C3', '0A', '8F', '19', '6', '0B', '3A', 'B2', '18', 'F9', '4E', '7', '44', '3', 'A5', '54', '7', '5F', '73', '86', '5F', 'D', '4', '57', 'A8', '0D', 'CC', '1D', 'EB', '3C', '7C', 'FC', '24', 'FC', '3C', 'E9', 'FB', '3', '3', 'B5', 'B1', '38', 'D9', '2', 'C1', '6A', '1', 'AF', 'D2', '39', '9B', '3A', '5E', 'F8', '1D', 'CA', '1C', 'E6', '32', '41', 'AE', '28', '93', '48', '8C', '4D', 'E8', '5C', '88', '43', '59', 'A5', '15', '9A', '0B', 'D7', '0C', '31', '9C', '44', 'B', '5F', '7C', 'BB','DA', 'F9', 'E8', '3', 'FB', 'A5', '77', 'D1', 'F9', 'FF', '38', 'C4', '63', 'D2', '74', 'A4', '5B', '0', '77', '88', '24', 'A', '1A', '64', 'C1', '2D','B6', '7F', '99', '84', '73', '7D', '8B', 'F2', '5C', '91', '1', '5D', 'AA', '8', 'EF', '62', 'ED', '0', '5', '9F', 'E8', '4C', '8C', '43', '59', 'A7', '15', '9C', '4', '6', '0C', 'BB', '19', '93', '4E', '5E', 'B9', '2', 'AC', '38', '8', '36', 'F3', '0', 'AF', '1', 'A3', '3C', 'F', '7C', '2A', '2', 'B7', '6C', 'C3', '49', '3E', 'D3', '6E', 'C6', '52', '6A', 'BF', 'E2', 'C1', '9F', '5B', 'EF', '97', '4E', 'B4', 'F', 'DE', '4', 'A1', '76', 'E2', '8', 'E9', '6F','27', '0', '8F', '0A', 'B3', '51', '61', 'C3', '35', 'C3', '5D', 'D1', 'A6', '1', '4B', '86', '8C', '42', 'D6', '17', '1', 'DD', '52', 'B3', '4D', 'FC', '3','44', '97', 'D3', '6E', '98', '35', '4F', 'F9', '2', 'B1', '63', '11', '49', 'B4', '56', 'B9', '38', '53', 'AF', '6', '94', '0', 'F7', '5B', 'E7', '32', '9A','75', 'AA', '1D', 'CC', '19', '3C', '32', 'CB', '21', 'F7', '6D', '49', 'D4', '4', 'D5', '19', '6F', 'BD', 'FA', 'F6', 'BD', '2E', '6', '8E', '86', '78', 'C7', '0E', 'CE', '17', '72', 'DD', '91', '6D', 'E4', '7C', '1B', '97', '0F', 'D5', '71', '77', '35', 'A7', '7E', '92', '74', '28', 'D9', '0E', '89', '3', 'E9', '72', 'D1', '2', 'E1', '21', '83', '3A', 'B5', '68', 'FC', '37', 'D1', '7A', 'CD', '9', 'C2', '6B', '82', '8', 'E7', 'CD', '27', '0', '3D', '9F', '6C', '95', 'AB', 'F5', 'C5', '8A', '15', '9A', '3', 'F7', '0C', '8A', '1A', '1E', '53', '0A', '26', '58', '4F', '6D', '4', 'BD', 'B', '0D', 'B', 'B2', '73', 'FD', 'B3', '64', 'EA', 'B4', '3', '61', '9A', 'D1', '77', '2A', '91', '38', 'DB', 'A7', '41', '23', 'D2', '37', '58', 'AE', '3F', 'FB', 'F5', '7A', '7C', '91', '1', 'BD', '82', '41', '1', '2F', '6D', 'CB', 'FC', '4D', '17', '33', '8B', '37', 'B1', '3', 'B1', '59', 'D6', '4F', 'C9', '6', 'B2', '3', '8D', '1A', 'AB', '45', '1B', 'E8', 'CE', '34', '45', 'CE', '2', 'B4', '73', 'EC', '35', 'A1', '7B', 'B5', '74', 'A2', '56', 'D9', '77', '2', 'B1', 'B6', '52', '58', 'E2', '36', '8B', '3A', 'B5', '24', 'EF', '3A', 'B', '62', 'AA', '9', 'C2', '7B', 'A2', '8', '65', 'F7', 'E3', '48', '39', 'DF', 'F3', '44', 'A3']

tmp_404360 = []
tmp_404320 = []
tmp_404380 = []

# 将16进制全部转成10进制
for i in byte_404360:
    tmp_404360.append(int(i, 16))
byte_404360 = tmp_404360

print(byte_404360)

for i in byte_404320:
	tmp_404320.append(int(i, 16))
byte_404320 = tmp_404320

print(byte_404320)

for i in byte_404380:
	tmp_404380.append(int(i, 16))
byte_404380 = tmp_404380

print(byte_404380)

# 获取OPCODE
opcode = []
for i in range(0, len(byte_404380)):
    tmp = byte_404380[i] ^ byte_404360[i % 64]
    src.append(hex(tmp))

print(opcode)

# 获取KEY
key = []
for i in range(0, len(byte_404320)):
    key.append(byte_404320[i] ^ byte_404360[i])
  
print(key)

这里看到加密后的数据,很容易联想到是base64处理后的数据,这里key又是64个字符,所以猜测应该是修改了码表的base64,尝试验证一下,先将异或后的key转成字符:

key = [115, 90, 71, 97, 100, 48, 50, 119, 118, 98, 102, 51, 109, 116, 120, 69, 113, 56, 114, 68, 104, 89, 75, 52, 55, 76, 117, 101, 67, 108, 122, 49, 74, 105, 103, 54, 121, 112, 72, 77, 43, 111, 47, 87, 53, 81, 106, 78, 80, 70, 82, 99, 107, 85, 73, 110, 79, 84, 88, 86, 65, 83, 57, 66]

base64_xor_table = ''
for i in key:
	base64_xor_table += chr(i)

可以发现该key并未存在字母重复,猜测应该就是base64码表替换:sZGad02wvbf3mtxEq8rDhYK47LueClz1Jig6ypHM+o/W5QjNPFRckUInOTXVAS9B

import base64
encode_flag = 'r60ihyZ/m4lseHt+m4t+mIkc'

outtab = 'sZGad02wvbf3mtxEq8rDhYK47LueClz1Jig6ypHM+o/W5QjNPFRckUInOTXVAS9B'
intab = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'

suf_flag = base64.b64decode(encode_flag.translate(str.maketrans(outtab, intab)))

得到:J1aR@j1w@nch1sh3m3

拼接得到最终flag:

flag{ssddddwddddssas-J1aR@j1w@nch1sh3m3}
a2956a140145cc321e734ba4cf1aa9d.png

完整exp:

byte_404360 = ['3E', '7A', '40', '64', '27', '25', '48', '4', '4F', '63', '19', '60', '0B', '3A', '75', '5D', '11', '4E', '7', '44', '30', '4C', '4B', '6', '5F', '73', '0D', '1A', '38', '8', '34', '78', '45', '47', '58', '3B', '74', '7D', '2C', '2B', '4A', '3C', '29', '13', '1', '3F', '3', '61', '70', '52', '65', '9', '22', '0', '7F', '59', '6C', '77', '72', '3D', '32', '55', '41', '49']
byte_404320 = ['4D', '20', '7', '5', '43', '15', '7A', '73', '39', '1', '7F', '53', '66', '4E', '0D', '18', '60', '76', '75', '0', '58', '15', '0', '32', '68', '3F', '78', '7F', '7B', '64', '4E', '49', '0F', '2E', '3F', '0D', '0D', '0D', '64', '66', '61', '53', '6', '44', '34', '6E', '69', '2F', '20', '14', '37', '6A', '49', '55', '36', '37', '23', '23', '2A', '6B', '73', '6', '78', '0B']

tmp_404360 = []
tmp_404320 = []

# 将16进制全部转成10进制
for i in byte_404360:
    tmp_404360.append(int(i, 16))
byte_404360 = tmp_404360

for i in byte_404320:
	tmp_404320.append(int(i, 16))
byte_404320 = tmp_404320

# 获取KEY
key = []
for i in range(0, len(byte_404320)):
    key.append(byte_404320[i] ^ byte_404360[i])
  
#print(key)

outtab = ''
for i in key:
    outtab += chr(i)

#print(outtab)

import base64

pre_flag = 'ssddddwddddssas'
encode_flag = 'r60ihyZ/m4lseHt+m4t+mIkc'

intab = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
suf_flag = base64.b64decode(encode_flag.translate(str.maketrans(outtab, intab)))

flag = 'flag{' + pre_flag + '-' + suf_flag.decode() + '}'
print(flag)
avatar