[2019红帽杯]easyRE1题解

迷蒙马背眠,月随残梦天边远,淡淡起茶烟。

                                                        ——松尾芭蕉

目录

1.查壳

2.拖入64位IDA,找到主函数

3.静态分析主函数

4.wp


1.查壳

ELF文件,64bit

2.拖入64位IDA,找到主函数

 没有标明main函数,我们打开string窗口跟踪一下存储的字符串常量

 发现一个base64编码表,base64不懂的查看博文base64

点击这个编码表跟进

 将光标放在上面按下快捷键X查看调用这个字符串的地方

 点击进入

按下F5反汇编

 while ( v2 < v4 - 2 )
  {
    *(_BYTE *)(v6 + v2) = aAbcdefghijklmn[*(_BYTE *)(v3 + a1) >> 2];
    *(_BYTE *)(v6 + v2 + 1LL) = aAbcdefghijklmn[(16 * (*(_BYTE *)(v3 + a1) & 3)) | (*(_BYTE *)(v3 + 1LL + a1) >> 4)];
    *(_BYTE *)(v6 + v2 + 2LL) = aAbcdefghijklmn[(4 * (*(_BYTE *)(v3 + 1LL + a1) & 0xF)) | (*(_BYTE *)(v3 + 2LL + a1) >> 6)];
    *(_BYTE *)(v6 + v2 + 3LL) = aAbcdefghijklmn[*(_BYTE *)(v3 + 2LL + a1) & 0x3F];
    v3 += 3;
    v2 += 4;
  }

这是base64编码的代码,需要知道base64编码算法的特征

这个函数有传入的参数,应该不是主函数

将光标放在函数名出,按下快捷键N重命名为base64encode

我们继续回到string窗口,查看别的可疑字符串

我们用同样的方法找到You find me字符串被使用的函数

 这个函数应该是主函数

 可以重命名一下函数名,光标放在函数名上,按下快捷键N

int __cdecl main(int argc, const char **argv, const char **envp)
{
  __int64 v3; // rax
  int result; // eax
  unsigned __int64 v5; // rax
  __int64 v6; // rax
  int i; // [rsp+Ch] [rbp-114h]
  __int64 v8; // [rsp+10h] [rbp-110h]
  __int64 v9; // [rsp+18h] [rbp-108h]
  __int64 v10; // [rsp+20h] [rbp-100h]
  __int64 v11; // [rsp+28h] [rbp-F8h]
  __int64 v12; // [rsp+30h] [rbp-F0h]
  __int64 v13; // [rsp+38h] [rbp-E8h]
  __int64 v14; // [rsp+40h] [rbp-E0h]
  __int64 v15; // [rsp+48h] [rbp-D8h]
  __int64 v16; // [rsp+50h] [rbp-D0h]
  __int64 v17; // [rsp+58h] [rbp-C8h]
  char v18; // [rsp+60h] [rbp-C0h]
  char v19; // [rsp+61h] [rbp-BFh]
  char v20; // [rsp+62h] [rbp-BEh]
  char v21; // [rsp+63h] [rbp-BDh]
  char v22; // [rsp+64h] [rbp-BCh]
  char v23; // [rsp+65h] [rbp-BBh]
  char v24; // [rsp+66h] [rbp-BAh]
  char v25; // [rsp+67h] [rbp-B9h]
  char v26; // [rsp+68h] [rbp-B8h]
  char v27; // [rsp+69h] [rbp-B7h]
  char v28; // [rsp+6Ah] [rbp-B6h]
  char v29; // [rsp+6Bh] [rbp-B5h]
  char v30; // [rsp+6Ch] [rbp-B4h]
  char v31; // [rsp+6Dh] [rbp-B3h]
  char v32; // [rsp+6Eh] [rbp-B2h]
  char v33; // [rsp+6Fh] [rbp-B1h]
  char v34; // [rsp+70h] [rbp-B0h]
  char v35; // [rsp+71h] [rbp-AFh]
  char v36; // [rsp+72h] [rbp-AEh]
  char v37; // [rsp+73h] [rbp-ADh]
  char v38; // [rsp+74h] [rbp-ACh]
  char v39; // [rsp+75h] [rbp-ABh]
  char v40; // [rsp+76h] [rbp-AAh]
  char v41; // [rsp+77h] [rbp-A9h]
  char v42; // [rsp+78h] [rbp-A8h]
  char v43; // [rsp+79h] [rbp-A7h]
  char v44; // [rsp+7Ah] [rbp-A6h]
  char v45; // [rsp+7Bh] [rbp-A5h]
  char v46; // [rsp+7Ch] [rbp-A4h]
  char v47; // [rsp+7Dh] [rbp-A3h]
  char v48; // [rsp+7Eh] [rbp-A2h]
  char v49; // [rsp+7Fh] [rbp-A1h]
  char v50; // [rsp+80h] [rbp-A0h]
  char v51; // [rsp+81h] [rbp-9Fh]
  char v52; // [rsp+82h] [rbp-9Eh]
  char v53; // [rsp+83h] [rbp-9Dh]
  char v54[32]; // [rsp+90h] [rbp-90h]
  int v55; // [rsp+B0h] [rbp-70h]
  char v56; // [rsp+B4h] [rbp-6Ch]
  char v57; // [rsp+C0h] [rbp-60h]
  char v58; // [rsp+E7h] [rbp-39h]
  char v59; // [rsp+100h] [rbp-20h]
  unsigned __int64 v60; // [rsp+108h] [rbp-18h]

  v60 = __readfsqword(0x28u);
  v18 = 73;
  v19 = 111;
  v20 = 100;
  v21 = 108;
  v22 = 62;
  v23 = 81;
  v24 = 110;
  v25 = 98;
  v26 = 40;
  v27 = 111;
  v28 = 99;
  v29 = 121;
  v30 = 127;
  v31 = 121;
  v32 = 46;
  v33 = 105;
  v34 = 127;
  v35 = 100;
  v36 = 96;
  v37 = 51;
  v38 = 119;
  v39 = 125;
  v40 = 119;
  v41 = 101;
  v42 = 107;
  v43 = 57;
  v44 = 123;
  v45 = 105;
  v46 = 121;
  v47 = 61;
  v48 = 126;
  v49 = 121;
  v50 = 76;
  v51 = 64;
  v52 = 69;
  v53 = 67;
  memset(v54, 0, sizeof(v54));
  v55 = 0;
  v56 = 0;
  sub_4406E0(0LL, v54, 37LL);
  v56 = 0;
  LODWORD(v3) = sub_424BA0((const __m128i *)v54);
  if ( v3 == 36 )
  {
    for ( i = 0; ; ++i )
    {
      LODWORD(v5) = sub_424BA0((const __m128i *)v54);
      if ( i >= v5 )
        break;
      if ( (unsigned __int8)(v54[i] ^ i) != *(&v18 + i) )
      {
        result = -2;
        goto LABEL_13;
      }
    }
    sub_410CC0("continue!");
    memset(&v57, 0, 0x40uLL);
    v59 = 0;
    sub_4406E0(0LL, &v57, 64LL);
    v58 = 0;
    LODWORD(v6) = sub_424BA0((const __m128i *)&v57);
    if ( v6 == 39 )
    {
      v8 = base64encode((__int64)&v57);
      v9 = base64encode(v8);
      v10 = base64encode(v9);
      v11 = base64encode(v10);
      v12 = base64encode(v11);
      v13 = base64encode(v12);
      v14 = base64encode(v13);
      v15 = base64encode(v14);
      v16 = base64encode(v15);
      v17 = base64encode(v16);
      if ( !(unsigned int)sub_400360(v17, off_6CC090) )
      {
        sub_410CC0("You found me!!!");
        sub_410CC0("bye bye~");
      }
      result = 0;
    }
    else
    {
      result = -3;
    }
  }
  else
  {
    result = -1;
  }
LABEL_13:
  if ( __readfsqword(0x28u) != v60 )
    sub_444020();
  return result;
}

3.静态分析主函数

if ( v3 == 36 )
  {
    for ( i = 0; ; ++i )
    {
      LODWORD(v5) = sub_424BA0((const __m128i *)v54);
      if ( i >= v5 )
        break;
      if ( (unsigned __int8)(v54[i] ^ i) != *(&v18 + i) )
      {
        result = -2;
        goto LABEL_13;
      }
    }

关注这部分

if ( i >= v5 )
        break;

这是循环结束的条件

照着这个循环用脚本模拟一下,看看会输出什么

string=[73,111,100,108,62,81,110,98,40,111,99,121,127,121,46,105,127,100,96,51,119,125,119,101,107,57,123,105,121,61,126,121,76,64,69,67]
flag=""
for i in range(0,35):
    flag+=chr(string[i]^i)
print(flag)

输出:

Info:The first four chars are `flag`

前四个字符是flag

继续往下分析

 是一组base64加密

黄色部分是一个strcmp函数

跟进off_6CC090

 继续跟进aVm0wd2vhuxhtwg

 这是一个base64编码将这个base64编码多次解码

解密网站

 不断解密

进入这个网址

 没什么用,纯属干扰解题的坑

下面有一个数据,使用快捷键X交叉引用查看一下

 到这个函数中分析一下

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;
}
if ( ((unsigned __int8)v1 ^ byte_6CC0A0[0]) == 'f' && (HIBYTE(v4) ^ (unsigned __int8)byte_6CC0A3) == 'g' )
  {
    for ( j = 0; j <= 24; ++j )
      sub_410E90((unsigned __int8)(byte_6CC0A0[j] ^ *((_BYTE *)&v4 + j % 4)));
  }

v1是unsigned int 四个字节,高字节与低字节抑或分别是f和g,中间还有两个字节,那么很可能按位与其抑或就是flag

然后循环取出这四个字节与数据段异或就是flag

4.wp

data=[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]
four=['f','l','a','g']
data2=[]
flag=""
for i in range(4):
    data2.append(data[i]^ord(four[i]))   #两次异或等于没有异或
for i in range(len(data)):
    flag+=chr(data[i]^data2[i%4])
print(flag)

flag{Act1ve_Defen5e_Test}

其他题解请关注我的专栏reverse

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

烨鹰

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值