本文为2016年京津冀挑战赛中possible的writeup。
Writeup
首先点我下载题目。直接使用jeb反编译,关键代码如下:
在SO层通过反射得到num
和indexArray
两个数组,当符合一定条件时将answerNum
设置成解密密钥,继而进行三重AES解密。符合SO层条件的answerNum
会有多个,但是只有一个answerNum
能解密密文,其他answerNum
解密密文时会报错。
ARM子函数调用:当参数小于4个时,ARM首先会用R0-R3四个寄存器来传递参数;当参数个数大于4个时,使用栈来传递参数。函数返回值默认通过R0寄存器传递,但是不一定!具体根据ARM指令分析。
伪代码显示不全,没有将返回值赋给变量,这时要看ARM指令,分析过程如下。
最后可知R1寄存器存放idivmod
的返回值。根据ARM指令可还原相关代码:
answerNum = 0;
int i = 0;
int v20 = 0;
int v15, v16, v17, result;
while (i < array.length) {
v15 = array[i];
i++;
v16 = num[v15];
v17 = v16 % 1011;
v20 = (v20 + v17) % 1011;
answerNum ^= v16;
}
result = v20 % 1011;
注意:check
中j_j___aeabi_idivmod
伪代码显示错误,j_j___aeabi_idivmod
表示取余。
AES解密是在Android环境下进行,故在Android下进行算法还原。经测试,Java下解密会报错。
解密程序点我下载。
答案:38
和508
。