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