• BUUCTF [2019红帽杯]easyRE WriteUp


    题目地址

    https://buuoj.cn/challenges#[2019%E7%BA%A2%E5%B8%BD%E6%9D%AF]easyRE

    题解

    IDA64打开,一开始F5报错Decompilation failure: 400896: positive sp value has been found,然后我Alt+K瞎改了一下sp就能F5了(我也不知道我是怎么改的。。。看不太懂sp的变化)

    改成下面这样就行了

    image

    F5后如下

    image

    进入sub_4009C6,代码如下

      1 signed __int64 sub_4009C6()
      2 {
      3   __int64 v0; // rax
      4   signed __int64 result; // rax
      5   unsigned __int64 v2; // rax
      6   __int64 v3; // rax
      7   __int64 v4; // ST10_8
      8   __int64 v5; // ST18_8
      9   __int64 v6; // ST20_8
     10   __int64 v7; // ST28_8
     11   __int64 v8; // ST30_8
     12   __int64 v9; // ST38_8
     13   __int64 v10; // ST40_8
     14   __int64 v11; // ST48_8
     15   __int64 v12; // ST50_8
     16   __int64 v13; // ST58_8
     17   char *v14; // rsi
     18   int i; // [rsp+Ch] [rbp-114h]
     19   char v16; // [rsp+60h] [rbp-C0h]
     20   char v17; // [rsp+61h] [rbp-BFh]
     21   char v18; // [rsp+62h] [rbp-BEh]
     22   char v19; // [rsp+63h] [rbp-BDh]
     23   char v20; // [rsp+64h] [rbp-BCh]
     24   char v21; // [rsp+65h] [rbp-BBh]
     25   char v22; // [rsp+66h] [rbp-BAh]
     26   char v23; // [rsp+67h] [rbp-B9h]
     27   char v24; // [rsp+68h] [rbp-B8h]
     28   char v25; // [rsp+69h] [rbp-B7h]
     29   char v26; // [rsp+6Ah] [rbp-B6h]
     30   char v27; // [rsp+6Bh] [rbp-B5h]
     31   char v28; // [rsp+6Ch] [rbp-B4h]
     32   char v29; // [rsp+6Dh] [rbp-B3h]
     33   char v30; // [rsp+6Eh] [rbp-B2h]
     34   char v31; // [rsp+6Fh] [rbp-B1h]
     35   char v32; // [rsp+70h] [rbp-B0h]
     36   char v33; // [rsp+71h] [rbp-AFh]
     37   char v34; // [rsp+72h] [rbp-AEh]
     38   char v35; // [rsp+73h] [rbp-ADh]
     39   char v36; // [rsp+74h] [rbp-ACh]
     40   char v37; // [rsp+75h] [rbp-ABh]
     41   char v38; // [rsp+76h] [rbp-AAh]
     42   char v39; // [rsp+77h] [rbp-A9h]
     43   char v40; // [rsp+78h] [rbp-A8h]
     44   char v41; // [rsp+79h] [rbp-A7h]
     45   char v42; // [rsp+7Ah] [rbp-A6h]
     46   char v43; // [rsp+7Bh] [rbp-A5h]
     47   char v44; // [rsp+7Ch] [rbp-A4h]
     48   char v45; // [rsp+7Dh] [rbp-A3h]
     49   char v46; // [rsp+7Eh] [rbp-A2h]
     50   char v47; // [rsp+7Fh] [rbp-A1h]
     51   char v48; // [rsp+80h] [rbp-A0h]
     52   char v49; // [rsp+81h] [rbp-9Fh]
     53   char v50; // [rsp+82h] [rbp-9Eh]
     54   char v51; // [rsp+83h] [rbp-9Dh]
     55   char v52[32]; // [rsp+90h] [rbp-90h]
     56   int v53; // [rsp+B0h] [rbp-70h]
     57   char v54; // [rsp+B4h] [rbp-6Ch]
     58   char v55; // [rsp+C0h] [rbp-60h]
     59   char v56; // [rsp+E7h] [rbp-39h]
     60   char v57; // [rsp+100h] [rbp-20h]
     61   unsigned __int64 v58; // [rsp+108h] [rbp-18h]
     62 
     63   v58 = __readfsqword(0x28u);
     64   v16 = 73;
     65   v17 = 111;
     66   v18 = 100;
     67   v19 = 108;
     68   v20 = 62;
     69   v21 = 81;
     70   v22 = 110;
     71   v23 = 98;
     72   v24 = 40;
     73   v25 = 111;
     74   v26 = 99;
     75   v27 = 121;
     76   v28 = 127;
     77   v29 = 121;
     78   v30 = 46;
     79   v31 = 105;
     80   v32 = 127;
     81   v33 = 100;
     82   v34 = 96;
     83   v35 = 51;
     84   v36 = 119;
     85   v37 = 125;
     86   v38 = 119;
     87   v39 = 101;
     88   v40 = 107;
     89   v41 = 57;
     90   v42 = 123;
     91   v43 = 105;
     92   v44 = 121;
     93   v45 = 61;
     94   v46 = 126;
     95   v47 = 121;
     96   v48 = 76;
     97   v49 = 64;
     98   v50 = 69;
     99   v51 = 67;
    100   memset(v52, 0, sizeof(v52));
    101   v53 = 0;
    102   v54 = 0;
    103   sub_4406E0(0LL, (__int64)v52);
    104   v54 = 0;
    105   LODWORD(v0) = sub_424BA0((const __m128i *)v52);
    106   if ( v0 == 36 )
    107   {
    108     for ( i = 0; ; ++i )
    109     {
    110       LODWORD(v2) = sub_424BA0((const __m128i *)v52);
    111       if ( i >= v2 )
    112         break;
    113       if ( (unsigned __int8)(v52[i] ^ i) != *(&v16 + i) )
    114       {
    115         result = 0xFFFFFFFELL;
    116         goto LABEL_13;
    117       }
    118     }
    119     sub_410CC0((const __m128i *)"continue!", (signed __int64)v52);
    120     memset(&v55, 0, 0x40uLL);
    121     v57 = 0;
    122     sub_4406E0(0LL, (__int64)&v55);
    123     v56 = 0;
    124     LODWORD(v3) = sub_424BA0((const __m128i *)&v55);
    125     if ( v3 == 39 )
    126     {
    127       v4 = sub_400E44((__int64)&v55);
    128       v5 = sub_400E44(v4);
    129       v6 = sub_400E44(v5);
    130       v7 = sub_400E44(v6);
    131       v8 = sub_400E44(v7);
    132       v9 = sub_400E44(v8);
    133       v10 = sub_400E44(v9);
    134       v11 = sub_400E44(v10);
    135       v12 = sub_400E44(v11);
    136       v13 = sub_400E44(v12);
    137       v14 = off_6CC090;
    138       if ( !(unsigned int)sub_400360(v13, (__int64)off_6CC090) )
    139       {
    140         sub_410CC0((const __m128i *)"You found me!!!", (signed __int64)v14);
    141         sub_410CC0((const __m128i *)"bye bye~", (signed __int64)v14);
    142       }
    143       result = 0LL;
    144     }
    145     else
    146     {
    147       result = 4294967293LL;
    148     }
    149   }
    150   else
    151   {
    152     result = 0xFFFFFFFFLL;
    153   }
    154 LABEL_13:
    155   if ( __readfsqword(0x28u) != v58 )
    156     sub_444020();
    157   return result;
    158 }

    网上大佬说有两个输入,我猜他是指sub_4406E0。

    先看113行,将第一次输入的每个字符与索引异或,判断是否与v16到v51的字符串相等,可以写出一个脚本

      1 l = [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]
      2 for i in range(len(l)):
      3     print(chr(l[i]^i),end='')

    运行结果:Info:The first four chars are `flag`

    然后看127到136行的函数,点进去再进一层发现类似Base64合法字符集,认为是base64加密,将第二次输入字符串base64加密10次,138行判断是否与off_6CC90相等,可以再写出一个脚本

      1 import base64
      2 off = "Vm0wd2VHUXhTWGhpUm1SWVYwZDRWVll3Wkc5WFJsbDNXa1pPVlUxV2NIcFhhMk0xVmpKS1NHVkdXbFpOYmtKVVZtcEtTMUl5VGtsaVJtUk9ZV3hhZVZadGVHdFRNVTVYVW01T2FGSnRVbGhhVjNoaFZWWmtWMXBFVWxSTmJFcElWbTAxVDJGV1NuTlhia0pXWWxob1dGUnJXbXRXTVZaeVdrWm9hVlpyV1hwV1IzaGhXVmRHVjFOdVVsWmlhMHBZV1ZSR1lWZEdVbFZTYlhSWFRWWndNRlZ0TVc5VWJGcFZWbXR3VjJKSFVYZFdha1pXWlZaT2NtRkhhRk5pVjJoWVYxZDBhMVV3TlhOalJscFlZbGhTY1ZsclduZGxiR1J5VmxSR1ZXSlZjRWhaTUZKaFZqSktWVkZZYUZkV1JWcFlWV3BHYTFkWFRrZFRiV3hvVFVoQ1dsWXhaRFJpTWtsM1RVaG9hbEpYYUhOVmJUVkRZekZhY1ZKcmRGTk5Wa3A2VjJ0U1ExWlhTbFpqUldoYVRVWndkbFpxUmtwbGJVWklZVVprYUdFeGNHOVhXSEJIWkRGS2RGSnJhR2hTYXpWdlZGVm9RMlJzV25STldHUlZUVlpXTlZadE5VOVdiVXBJVld4c1dtSllUWGhXTUZwell6RmFkRkpzVWxOaVNFSktWa1phVTFFeFduUlRhMlJxVWxad1YxWnRlRXRXTVZaSFVsUnNVVlZVTURrPQ=="
      3 for i in range(10):
      4     off = base64.b64decode(off)
      5 print(off)

    运行结果:b'https://bbs.pediy.com/thread-254172.htm',打开是一篇很长的文章(没看完)

    上面两个都是混淆的,非真正flag。

    刚才那个用于base64解密的字符串下方还有一个常量,被函数sub_400D35使用(我是真想不到从这里找flag。。)

    image

    进入sub_400D35,代码如下:

      1 __int64 sub_400D35()
      2 {
      3   __int64 result; // rax
      4   unsigned __int64 v1; // rt1
      5   unsigned int v2; // [rsp+Ch] [rbp-24h]
      6   signed int i; // [rsp+10h] [rbp-20h]
      7   signed int j; // [rsp+14h] [rbp-1Ch]
      8   unsigned int v5; // [rsp+24h] [rbp-Ch]
      9   unsigned __int64 v6; // [rsp+28h] [rbp-8h]
     10 
     11   v6 = __readfsqword(0x28u);
     12   v2 = sub_43FD20(0LL) - qword_6CEE38;
     13   for ( i = 0; i <= 1233; ++i )
     14   {
     15     sub_40F790(v2);
     16     sub_40FE60();
     17     sub_40FE60();
     18     v2 = (unsigned __int64)sub_40FE60() ^ 0x98765432;
     19   }
     20   v5 = v2;
     21   if ( ((unsigned __int8)v2 ^ byte_6CC0A0[0]) == 102 && (HIBYTE(v5) ^ (unsigned __int8)byte_6CC0A3) == 103 )
     22   {
     23     for ( j = 0; j <= 24; ++j )
     24       sub_410E90((unsigned __int8)(byte_6CC0A0[j] ^ *((_BYTE *)&v5 + j % 4)));
     25   }
     26   v1 = __readfsqword(0x28u);
     27   result = v1 ^ v6;
     28   if ( v1 != v6 )
     29     sub_444020();
     30   return result;
     31 }

    首先用第21行的异或,102和103对应的字符分别是”f”和”g”,而且byte_6CC0A0[0]和byte_6CC0A3刚好是一个字符串的第一位和第四位。那么可以想到是”flag”与前四位异或,然后得到一个key,再进行下面for循环的异或。(其实我还是不懂,21行的v5异或得到”g”,应该是key的第4位,但是为什么下面循环的时候却是从key的第一位开始?)

    脚本:

      1 list1 =[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]
      2 flag = "flag"
      3 key = []
      4 for i in range(4):
      5     key.append(list1[i]^ord(flag[i]))
      6 for j in range(25):
      7     print(chr(list1[j]^key[j%4]),end='')

    参考

    2019 红帽杯 Re WP

  • 相关阅读:
    IP地址
    ACL访问控制列表
    DHCP原理及配置
    VRRP原理及配置
    ASP.NET CORE RAZOR :向 Razor 页面应用添加模型
    HBuilder + PHP开发环境配置
    添加相关功能
    基于stm32的水质监测系统项目基础部分详细记录
    表单数据验证方法(二)——ASP.NET后台验证
    表单数据验证方法(一)—— 使用validate.js实现表单数据验证
  • 原文地址:https://www.cnblogs.com/hardcoreYutian/p/12804111.html
Copyright © 2020-2023  润新知