-
-
[原创]KCTF2020秋季赛 第四题 突破重围writeup
-
发表于: 2020-11-23 12:38 3829
-
我们直接来调试分析未加壳的包
直接来看so中的Java_com_kanxue_crackme_MyCrack_crackjni
函数,经过调试发现两处关键:
sub_7D60;这个函数很明显是一个AES加密函数。我们去网上找一个AES算法,经过对比我们发现跟网上找的代码S盒完全一样,但有三处值得注意:
a. 这个so中没有逆S盒;
b. so中没有解密函数;
c. 扩展密钥算法不同;
下面是题目中的扩展密钥算法
下面是网络流传的AES扩展密钥算法
我们通过调试拿到题目的扩展密钥,直接把扩展密钥替换到网络流传算发中,不需要关注细节了。
替换完扩展密钥以后,我们使用网络流传AES的算法进行加密,发现跟调试so的加密结果完全一致。这个时候我们就不需要在so里再去调试这个AES算法了。我们只需要知道对比时用的result,把这个result使用流传的AES算法来解密,就拿到flag了!
看图我们可以知道,题目会把“l+x7fKd2FBaaEY4NV4309A==\n”这个字符串赋值到java中,用这个字符串来和Base64.encodeToString(crypt(result), 0)做对比。
我们用下面代码来计算result
然后使用前面的AES算法解密,这样就得到了crackjni的入参,由于crypt是一个完全可逆的算法,我们直接对这个入参执行crypt(),应该就拿到flag了!
但是事与愿违,我们拿到一堆乱码。经过反复的调试,我们发现了猫腻。
看截图中的圆圈中的代码。dword_CD9E53D8其实是b.txt这个dex的起始地址,那后面的0x16D3A6是什么呢?
我们把b.txt改名成b.dex,拖进IDA,发现:
嗯,这原来是一个smila中的字符串赋值操作,google官方解释如下
也就是说,so中修改了dex中的字符串索引,导致java在执行crypt函数的时候,使用的不再是"kaokaonio"。我们把原来的CF3D改成截图中的D33D:
在观察一下:
“keepGoing”!好了,我们把计算result时用的crypt函数修改一下
得到了新的result:{40, -128, -114, -30, 10, -79, 122, 37, -62, 22, 120, 86, 58, 74, 127, -85}
将这个result进行AES解密得到:{3,-7,-126,26,117,6,-16,-77,46,-21,89,69,25,104,9,85,}
再使用原来的crypt函数计算输入字符串
得到输出flag{thisiskey!}
String s1
=
"l+x7fKd2FBaaEY4NV4309A=="
;
byte[] ss1
=
Base64.getDecoder().decode(s1);
System.out.println(Arrays.toString(crypt(ss1)));
String s1
=
"l+x7fKd2FBaaEY4NV4309A=="
;
byte[] ss1
=
Base64.getDecoder().decode(s1);
System.out.println(Arrays.toString(crypt(ss1)));
1a
const
-
string vAA, string@BBBB
21C
op vAA, string@BBBB
A: 目标寄存器(
8
位)
B: 字符串索引 将通过给定索引指定的字符串的引用移到指定的寄存器中。
1a
const
-
string vAA, string@BBBB
21C
op vAA, string@BBBB
A: 目标寄存器(
8
位)
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!