作为一个逆向小白,学了点加密算法就来BUU找点乐子,前7题蛮简单的,然后做到了reverse3,典型的base64加密算法,让我折腾了好久,写篇博客记录一下
顺便说下很多博客并没有对这里的加密算法进行代码上的分析,对于小白可能不太友好,但是本文详细地介绍了我的理解!!
先can can题
从网上学来的技巧,从后往前看
可以知道大概的逻辑就是,输入字符串赋值给给Str这个字符串数组,然后在sub_4110BE()这个函数里面进行加密得到V4,然后把V4赋值给Destination这个变量
如果Destination这个变量和Str2这个变量相同,则可以判断出一开始输入的字符串就是flag
我们点进去sub_4110BE()这个加密函数看看
卧槽,这一看就是明显的base64嘛
开玩笑的,尼玛我当时没看出来,因为只知道base64加密的原理,而不清楚base64加密具体代码的实现咋写的
ok,我看了很多博客,大多没有对这个Base64加密代码进行解析的,这也是我写这篇博客的原因。
首先我们要先了解base64加密的一个原理
这里附上wiki的讲解,注意注意,一次是取出3个字节的数据!!
当然最理想的情况是一次可以加密三个字节的数据,也有可能取不到三字节,只有一个字节或者两个字节,当然没有关系,base64有自己的处理方式
比如下面这张表格就可以清晰的看到加密的原理
填充后就是这样
如果原数据那一栏只有一个或者两个字符,那么在原数据(二进制)那里就用0补,最终也可以获得四个加密后的字符
原理讲完看看代码
首先是这个地方,讲讲V10是咋来的。
首先我们利用var_20这个变量去存我们可以从原字符串可以获得多少组原数据(3个字符一组)
然后v10=var_20*4得到的就是经过base64加密后可以得到的加密字符的个数
接着是这个部分
这段代码就是开始分割字符串得到原数据,如果可以去的三个字符,那么 i 就为3,如果只能取到两个字符,那 i 就等于2,如果只能取到一个字符,那么 i 就等于1
这里讲一下Base64是由一个自己的字符表的,变量BASE64_table_417B30就是对应base64专用字母表
接下来就是加密的核心代码了
我们先看case 3
首先将原数据(二进制)右移2位,也就是取它的高6位,得到新的字符。
然后是*((_BYTE *)v12 + v7) = BASE64_table_417B30[((byte_41A144[1] & 0xF0) >> 4) | (16 * (byte_41A144[0] & 3))]; 这个代码的作用是取byte_41A144[1]的高四位,再右移四位充当第二个加密字符的低四位,然后再取byte_41A144[0]的低2位再左移4位充当第二个加密字符的高二位(这里的*16就是相当于 <<4 )。
其实后面也是同理,就不继续赘述了
就这样我们明白了base64的加密代码的大概流程长什么样子了。
另外值得注意的是这个程序不止base64加密,它还很坏地摆了一道
但是无所谓,我们还原一下就行
#include <iostream>
using namespace std;
int main()
{char flag[] = "e3nifIH9b_C@n@dH";int lenth = strlen(flag);for (int i = 0; i < lenth; i++){flag[i] = flag[i] - i;}cout << flag << endl;
}
然后我们就得到了一个base64加密后的数据 e2lfbDB2ZV95b3V9
放到base64解码工具解码
就可以得到flag啦!!
flag: flag{i_l0ve_you}