2017 SSCTF Login 200

Java层上了一堆中文变量

在一顿修复之后,大概的能梳理出校验过程

校验的地方

一层一层分析,这是一个native函数,需要使用IDA分析

使用IDA载入对应的so文件,有一个关键的encode()函数

跟入发现白茫茫一片

使用流程图查看,发现调用关系断开

先去掉下面这个块的函数尾

然后Force BL Call

即可修复,F5之后的代码也比较正常可读

伪代码

入口处看到了长度由12变为16位,也就是三位扩充成4位,猜测是Base64算法

找到一个转换表

使用WinHex找到对应偏移,C Source模式拷贝出来

IDA里没显示完全,其实应该是下面这样的

正常的Base64编码表如下

所以在这里写还原代码的时候不能使用下面这种常规编码表的方式

而是根据对应的char来查找index,然后拼接到一个int型数据里去,由于编码表是变形的,所以只能使用循环来查找

这里我放一份比较常规的Base64编码的C语言实现,可以跟反编译后的代码进行对比

Base64编码基于的一个原理就是6位01即可表示64个不同的字符在取第一个字符的时候,只需要取前6位,转为index,找到编码表对应的字符即可,但是这里的算法还进行了一次异或,所以最终的编码在计算的时候,需要把每4个字节的第一个字节跟0x3F进行异或,再去找对应的字符下标index

第二字节同样做了异或操作

第三和第四字节常规的编码,没有其余操作

结合输入的注册码为12位,那么我们还原的代码如下,对于后面的判断我就省略了

因为上一题的套路,我猜后面那个32位字符串就是应该用来解密的数据,所以直接拿来测试

输出

为了确定整个流程,再次回到Java层进行流程的分析

首先是DecryptUtils.extensionTo32(),用于将byte[]转为32位字符串

最终的DecryptUtils.checkRegCode()很有意思,一不小心就会被带到坑里去

如果反推,马上就可以得到答案,如果正向走下来

我们正向走一遍,首先是CTF1(),将每个字符拆成2个4位,然后再挑数据拼接

接下来进行对比计算

计算完后有一个MD5值的对比,尝试解密这个MD5

那么说明计算完j是0

回头看计算过程,j一直是相加的计算,想让j是0,那么在异或的时候两个值一定要相等,说明两个字符串相等,回溯到最前面,说明传进来的两个字符串相等,那么直接拿上面的32位字符串去解密,就可以得到正确的输入数据,输入那个数据,就可以弹出flag

输入VVe1lD0ne^-^,弹出flag

Last updated