一、前言
这题的解法有很多,可以通过so文件的静态分析,直接将结果写入文件达到解题的目的,不过核心思想肯定是希望我们通过逆向他的算法来获取flag.接下来我将详细的分析算法逆向的过程。
二、代码分析
java层的静态分析
打开APP先简单试玩下,发现点击不玩了或者注册码填写错误提交都会发生闪退,把代码拖入到jadx中。我们从代码找到注册页面。
通过代码可以看出,他的flag核心代码在libmyjni.so里面,调用了这iniSN()、saveSM()、work()这三个函数。在分析so文件之前,我们先解决闪退的问题,关键代码 Process.killProcess(Process.myPid());通过frida hook修改其逻辑。
1 2 3 4 5 6 7 8 |
|
so层分析
将APK解压,找到目标文件,拖入到IDA中,一眼看去并没有发现iniSN()、saveSM()、work()这个三个函数。
接着我们去JNI_OnLoad中去定位,找到他的伪C代码。
这段代码是一个 JNI(Java Native Interface)的实现,用于在Java虚拟机加载本地库时执行。然后主要看这段代码:
1 |
|
RegisterNatives 用于将本地方法与 Java 类关联起来。off_5004 是一个本地方法数组,包含要注册的本地方法的信息。这里注册了3个本地方法。在进入到off_5004后。如图所示,我们来理解下这段汇编代码。
aInitsn: 字符串,表示第一个本地方法的名字为 "initSN"
aV: 字符串,表示第一个本地方法的签名,这里是 "()V",表示无参数无返回值的方法。
n1+1: 指向 initSN 本地方法的实现函数的地址。
那么以此类推:
n1 = iniSN()
n2 = saveSM()
n3 = work()
这个时候思路就非常清晰了,先来看下这三个函数的代码:n1这个函数的执行逻辑:
打开一个文件 /sdcard/reg.dat,读取文件内容,与指定的字符串进行比较,然后通过调用 setValue 函数将结果写入内存中。最后,关闭文件并返回 fclose 函数的结果。
n2这个函数的执行逻辑:
读取指定文件中的内容,对内容进行异或加密,然后将加密后的内容写回文件中。密钥是根据字符串 "W3_arE_whO_we_ARE" 计算得到的。
n3这个函数的执行逻辑:
他再次调用了n1函数,调用 getValue 函数的值,来判断该返回什么样的内存。返回值有&unk_2E6B、&unk_2E95、&unk_2E5B。我们点进去按A。
很明显Value = getValue(a1) ==1 是我想要的结果。再回过头看n1函数。想要等于1就要满足
1 |
|
他又是从文件/sdcard/reg.dat文件取出来的,那问题来了,他又是怎么存的呢?n2函数里面的 :
1 |
|
代码逻辑是输入的值存进去的。再综合整理下代码的执行逻辑。
输入的值等于EoPAoY62@ElRD,再完成加密,保持EoPAoY62@ElRD到/sdcard/reg.dat文件中,再调用n3 (n1 里面满足了条件,设置1值)得到value=1.结束。
目标就是输入的值经过加密等于: EoPAoY62@ElRD 就得出flag
三、算法还原
通过上面的分析他的核心算法在n2中。
通过分析发现他是将我们输入的值和给定的值进行异或操作。然后我们用python 进行算法还原:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
|
将结果201608Am!2333输入到APP中:
当再次打开的是时候出现:如下。