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

posted @ 2020-04-29 19:20  平静的雨田  阅读(1901)  评论(0编辑  收藏  举报