本文只是介绍破解NDK层签名校验的过程,至于破解Apk签名校验的整个流程以及破解思路,请看博客:去除小黄人快跑ver2.6.5签名校验的过程 我就是参考这篇博客学习破解NDK层的签名校验。下面以手游小黄人快跑(版本为2.6.5)为例,从已经确定该Apk采用的是NDK层签名校验的步骤开始,简单介绍一下破解NDK层签名校验的流程:
0x00 反编译小黄人快跑Apk
将小黄人快跑Apk放入某个文件夹中,在该文件夹中打开命令提示符,
输入命令:apktool d xiaohuanrenkuaipaos_33lc.apk
如图1所示:
图1 反编译小黄人快跑客户端
0x01 定位获取当前Apk签名的函数
使用Notepad++的“在文件中查找”功能定位到反编译apk所得到的\lib\armeabi-v7a文件夹,然后搜索签名信息对应的关键字:
” [Landroid/content/pm/Signature”。具体如图2和图3 所示:
图2 使用Notepad++在文件中查找字符串的功能
图3 在反编译得到的lib文件夹中查找签名字符串
搜索完毕后,我们会发现有两个so文件用到了签名信息,分别是libcipher.so和libdespicablemefree.so。具体如图4所示:
图4 查找签名关键字所命中的目标
(1)我们先用IDA Pro加载libcipher.so进行静态分析,
我们输入关键字” [Landroid/content/pm/Signature”查找签名信息,可以发现libcipher.so中的Java_com_wandoujia_base_utils_CipherUtil_getAESKeyNative函数使用了签名信息,具体如图5所示:
图5 查找libcipher.so中使用签名信息的函数
所以我们要重点分析Java_com_wandoujia_base_utils_CipherUtil_getAESKeyNative 这个函数,通过分析我们可以发现该函数只是获取了Apk的签名信息,但是并没有被其他函数调用,所以我们可以断定Apk签名校验函数并不在libcipher.so中。而且该函数名字中出现了wandoujia这样的关键字,因此我们可以判定这个函数可能与豌豆荚有关,并不是我们所要寻找的获取当前Apk签名的函数。
(2)我们接着用IDA Pro加载libdespicablemefree.so进行静态分析,与分析libcipher.so的过程类似,我们输入关键字” [Landroid/content/pm/Signature”查找签名信息,可以发现libdespicablemefree.so中的nativeGetApkSignature函数使用了签名信息,具体如图6所示:
图6 查找libdespicablemefree.so中使用签名信息的函数
通过分析nativeGetApkSignature函数的内部实现,还有nativeGetApkSignature这个函数名字,我们可以断定该函数应该是获取当前Apk签名的函数。
0x02 定位和分析Apk签名校验函数
通过分析nativeGetApkSignature函数,我们发现该函数的右边出现了
; CODE XREF: sub_50DF64+58 p 这样的关键字,如图7所示:
图7 nativeGetApkSignature函数
双击字符串 ; CODE XREF: sub_50DF64+58 p,我们就能找到调用nativeGetApkSignature函数的代码,该代码在libdespicablemefree.so中的偏移地址是0x0050DFBC,具体如图8 所示:
图8 调用nativeGetApkSignature函数的代码
该代码位于函数sub_50DF64中,所以我们需要重点分析sub_50DF64这个函数。我们将鼠标定位到函数sub_50DF64处,然后再按键盘上的F5键就可以得到函数sub_50DF64对应的C代码(这样做的前提是,你的IDA Pro必须支持F5功能),具体的C代码如图9所示:
图9 函数sub_50DF64对应的C代码
通过分析C代码,我们能发现函数sub_50DF64的设计流程:先调用函数nativeGetApkSignature获取系统的签名信息;然后调用strcmp函数将该签名信息与某个字符串(我想这个字符串应该就是正版Apk的签名信息)进行比较,如果二者不相同,则调用kill函数终止当前进程的运行。函数sub_50DF64应该就是Apk签名校验函数。
0x03 修改Apk签名校验函数
找到Apk签名校验函数后,我想到了两个破解办法:
(1)找到调用函数sub_50DF64的语句 BL sub_50DF64,将其nop掉,即将BL sub_50DF64改为空操作;
(2) 更改函数sub_50DF64的执行流程,让其在执行过程中避开nativeExit, kill, __stack_chk_fail这些函数,直接跳转到函数的末尾处。
显然办法(1)更简单,所以接下来我使用的是办法(1)。
/*办法(2)也是可以破解成功的,感兴趣的童鞋可以自己尝试一下*/
先按下快捷键Alt + t,然后输入查找关键字”sub_50DF64”,我们可以找到语句”BL sub_50DF64”,该语句在libdespicablemefree.so中的偏移地址是0x005046B8,如图10所示:
BL sub_50DF64对应的机器码为” 29 26 00 EB”,如图11所示:
图11 BL sub_50DF64语句对应的机器码
我们可以使用二进制编辑软件UltraEdit将该机器码改为”00 00 00 00”,如图12所示:
图12 nop掉BL sub_50DF64指令
为了和原版App进行区分,我将values\strings.xml中icon_label的值改成了”小黄人快跑签名破解版”,如图13所示:
图13 修改APP的名字
0x04 二次打包apk并进行签名
打开命令提示符,
输入命令:apktool b xiaohuanrenkuaipaos_33lc
对小黄人快跑进行二次打包,具体如图14所示:
图14 重新打包apk
然后再用签名工具对二次打包生成的Apk进行签名即可。
因为我提早就知道了该版本的小黄人快跑采用的是基于NDK层的签名校验,所以整个破解过程才会显得一气呵成。其实一般的逆向过程不可能像博客中这么顺利,需要仔细阅读逆向得到的代码,耐心地去挖掘线索,根据线索来寻找破解的突破点。
本文资源下载地址:安卓逆向学习笔记(8)
本文只做技术交流之用,请勿用于其他用途。