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