2015 海峡两岸CTF 一个APK逆向试试吧
一道比较简单的题目
JEB里可以看出,调用了一个so,把输入的字符串传进so里的一个函数进行验证,验证成功弹出输入的字符串,相当于字符串就是Flag

使用IDA载入so,发现有JNI_OnLoad(),猜测有动态注册,跟入
找到动态注册的函数表

每个Item有三个数据下面的hello()函数并没有什么实际意义,重点是上面这个abcdefghijklmn()
明确这里是动态注册后,双击abcdefghijklmn()过去修改函数名为Java_com_testFlag()
首先对长度进行判断,长度必须0x10,也就是16字节
在判断完长度后,如果长度为0x10,进入第一个循环计算,此时R6相当于计数器,起始为0,到8结束,也就是循环八次,R2为传入字符串的首地址,然后计算出结果存储在s2里
总结就是
计算完前8字节的数据后,获取seed字符串进行对比
seed字符串的定义
第一部分对比成功,进入第二部分的对比,先获取Java层的一个Class
获取类Calc的方法calcKey()的MethodID
获取类Calc的方法calcKey()的字段key的FieldID
通过FieldID获取Field,并将Java的String类型数据转为C语言的char字符串数组
进入第二部分的计算循环,计算规则和第一部分一样

还原一下
将两部分进行对比
总结整个对比过程:将输入的16字节字符串进行处理,然后使用两个8字节字符串与处理过后的输入数据进行对比
写个小程序来处理一下
输出
把这串字符串输入CrackMe进入验证,弹出Wrong Flag
纳尼
再回过头来分析,可能是JNI_OnLoad()里有什么函数对字符串进行了修改,刚才分析并没有注意到
可惜除了注册函数之外并没有其余调用函数的操作,那么现在就只可能在.init_array段了
找到.init_array段,果然在这里调用了__init_my()函数
跟入__init_my()

将seed字符串循环减3
根据这个我们最终还原
flag是:NdkMobiL4cRackEr
其实动态调试一下马上就看到结果了
在这个地方下断点,此时对比的数据就是最终计算出的数据

没有反调试什么的,直接IDA attach上去
有一点要注意的是要输入任意16字节数据,不然第一个长度校验过不了
跑起来后,输入数据,断在这里数据窗口跟随R0,可以看到我们需要的数据

和阿里某一年的挑战赛试题很像,有兴趣的同学可以找一找
Last updated