glass
题目解压之后发现是apk文件,更改后缀为.zip,再次解压
看到有.dex文件。dex文件是Android系统的可执行文件,包含应用程序的全部操作指令以及运行时数据。我们使用dex2jar反编译该文件。
把class.dex复制到dex2jar.bat所在目录,即dex2jar目录下。打开cmd,进入dex2jar所在的目录然后运行dex2jar.bat classes.dex,生成classes-dex2jar.jar就是所要转化jar包。
使用jd-gui打开classes-dex2jar.jar
我们可以看到函数里面存在native定义,并且,在整个java代码里面没有checkFlag的定义,只有一个声明,这些都说明函数是定义在so文件之中的。
我们来寻找需要的so文件。
题目的lib文件里面只有一个so文件,正好也是寻找的native的so文件。
使用ida对其进行反编译。
通过搜索checkFlag函数找到该函数
我们可以知道flag的长度应该是39位的
接下来看函数sub_FFC
和sub_1088
sub_FFC:
sub_1088:
可以很明显的可以看出来是RC4加密,不清楚的同学可以对照百度百科上面的代码比较,会发现非常相像。同时,RC4的加密脚本也就是它的解密脚本。
那么checkFlag中的12345678就是key。
我们再查看函数sub_10D4
:
可以看到对RC4处理完成的字符串再次进行处理,先进行异或,后面还有一些处理,看似复杂但是不用太在意,写脚本的时候直接倒回去就可以。
返回主checkFlag,我们发现最后得到的字符要和unk_497C
进行比较。
unk_497C:
Shift+E提取一下
写脚本破解
1 |
|
flag是:CISCN{6654d84617f627c88846c172e0f4d46c}
baby.bc
查看文件类型
LLVM IR bitcode,二进制文件。需要转换成.s,然后再转成可执行文件。
在当前目录下打开终端,输入如下命令:
1 | clang baby.bc -o baby |
可以看到生成的文件已经是可执行文件了
将该生成的文件使用IDA打开
查看main函数
那么接下来就查看fill_number
和docheck
两个函数了
fill_number():
1 | __int64 __fastcall fill_number(__int64 a1) |
由这段代码可得,五个字符是一循环,分别判断其每一行的1~5位的数字。分析if/else,主要就是说map[]不为0时,当前的输入字符必须是’0’;如果map[]为0,当前的map字符为输入字符的ASCII码减去48。
map[]是一个二维数组,我们可以查看它的值。
1 | unsigned char ida_chars[] = |
fill_number函数的功能是:
当5*5的map二维矩阵中的值为0时,将该值转化为输入字符的ASCII码减去48;不为0时,对应的输入值为字符一定要为’0’。因为返回的是v6&1,这个值需要返回是真值才可以出flag
docheck():
第一部分就是说map每行和每一列没有重复的数字
循环取输入的值,然后将取到值的对应位置写1,然后在后面循环中,如果该位置已经是1了,说明之前有出现过相同的数字,就是这样判断的。
接下来的row和col:
我们可以通过分析循环的次数和判断条件来得出如下的结果,代码比较长,需要耐心分析才行
最后得到的应该是如上的数独图
数独大佬可以自己解,变成大佬可以写代码用Z3
14253
53142
35421
21534
42315
根据上面的要求改map[2][2]和map[3][3]为0,md5之后得到flag
flag:CISCN{8a04b4597ad08b83211d3adfa1f61431}