[BUUCTF-Reverse3]
1.
根据之前的经验,我觉得放进exeinfo、然后扔进ida找关键函数再f5的操作可以省略不写了。(成长了?其实是懒狗)
2.
亲爱的伪代码在这里
直接看得出“right flag”这里,肯定是让Dest
与Str2
进行比较。
而Dest
是由输入的Str
被函数sub_4110BE
加密处理后得出的。(其实这里我一头雾水,是因为我不知道strcpy函数是复制字符串到dest)
str2
是e3nifIH9b_C@n@dH
然而还有一个步骤
意为让Dest
每一位字符串都加上对应位置数字ascii码
所以解密之前每一位还得先减去对应位置的数字。
3.
那么跟进sub_4110BE
再跟进
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71
| void *__cdecl sub_411AB0(char *a1, unsigned int a2, int *a3) { int v4; int v5; int v6; int v7; signed int i; unsigned int v9; int v10; signed int v11; void *Dst; char *v13;
if ( !a1 || !a2 ) return 0; v9 = a2 / 3; if ( (signed int)(a2 / 3) % 3 ) ++v9; v10 = 4 * v9; *a3 = v10; Dst = malloc(v10 + 1); if ( !Dst ) return 0; j_memset(Dst, 0, v10 + 1); v13 = a1; v11 = a2; v7 = 0; while ( v11 > 0 ) { byte_41A144[2] = 0; byte_41A144[1] = 0; byte_41A144[0] = 0; for ( i = 0; i < 3 && v11 >= 1; ++i ) { byte_41A144[i] = *v13; --v11; ++v13; } if ( !i ) break; switch ( i ) { case 1: *((_BYTE *)Dst + v7) = aAbcdefghijklmn[(signed int)(unsigned __int8)byte_41A144[0] >> 2]; v4 = v7 + 1; *((_BYTE *)Dst + v4++) = aAbcdefghijklmn[((byte_41A144[1] & 0xF0) >> 4) | 16 * (byte_41A144[0] & 3)]; *((_BYTE *)Dst + v4++) = aAbcdefghijklmn[64]; *((_BYTE *)Dst + v4) = aAbcdefghijklmn[64]; v7 = v4 + 1; break; case 2: *((_BYTE *)Dst + v7) = aAbcdefghijklmn[(signed int)(unsigned __int8)byte_41A144[0] >> 2]; v5 = v7 + 1; *((_BYTE *)Dst + v5++) = aAbcdefghijklmn[((byte_41A144[1] & 0xF0) >> 4) | 16 * (byte_41A144[0] & 3)]; *((_BYTE *)Dst + v5++) = aAbcdefghijklmn[((byte_41A144[2] & 0xC0) >> 6) | 4 * (byte_41A144[1] & 0xF)]; *((_BYTE *)Dst + v5) = aAbcdefghijklmn[64]; v7 = v5 + 1; break; case 3: *((_BYTE *)Dst + v7) = aAbcdefghijklmn[(signed int)(unsigned __int8)byte_41A144[0] >> 2]; v6 = v7 + 1; *((_BYTE *)Dst + v6++) = aAbcdefghijklmn[((byte_41A144[1] & 0xF0) >> 4) | 16 * (byte_41A144[0] & 3)]; *((_BYTE *)Dst + v6++) = aAbcdefghijklmn[((byte_41A144[2] & 0xC0) >> 6) | 4 * (byte_41A144[1] & 0xF)]; *((_BYTE *)Dst + v6) = aAbcdefghijklmn[byte_41A144[2] & 0x3F]; v7 = v6 + 1; break; } } *((_BYTE *)Dst + v7) = 0; return Dst; }
|
这家伙好厉害!我看不懂
于是百度,说是base64加密。这代码属实触及我的知识盲区,也许以后可以靠记忆?长得像这样的就拿base64套(雾)
其实代码里出现了好多次aAbcdefghijklmn,跟进去看看。
而这就是base64加密的关键
它是用64个可打印字符表示二进制所有数据方法。由于2的6次方等于64,所以可以用每6个位元为一个单元,对应某个可打印字符。我们知道三个字节有24个位元,就可以刚好对应于4个Base64单元,即3个字节需要用4个Base64的可打印字符来表示。在Base64中的可打印字符包括字母A-Z、a-z、数字0-9 ,这样共有62个字符,此外两个可打印符号在不同的系统中一般有所不同。但是,我们经常所说的Base64另外2个字符是:“+/”。
(我大致能理解,算课外拓展了,记得以前学过一遍。那个等于号是作后缀)
Python有base64加密解密的库,于是写脚本。
1 2 3 4 5 6 7 8
| import base64 str = 'e3nifIH9b_C@n@dH' flag='' for i in range(len(str)): x = chr(ord(str[i]) - i) flag+=x flag = base64.b64decode(flag) print(flag)
|
先减去对应位置的数字,组成新的字符串,再对他进行base64解密。
得出flag{i_l0ve_you}
总结:以前看伪代码的时候感觉眼花缭乱的,比如我刚开始在纠结那个for循环,以及下面lowword等东西是啥。其实应该赶紧抓住重点,这大概要我不断写题积累吧。也许掌握C++可能会更好?