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的变化)
改成下面这样就行了
F5后如下
进入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。。)
进入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='')