深入探究安卓逆向中的本地库(Native Library)

前言

在安卓开发中,开发者可以为提升性能或增强安全性而编写本地库(Native Library)。这些库通常用C/C++编写,并以.so为后缀名。在编译打包成APK后,这些库文件会被放入APK的lib子目录中,为Java层提供接口,使得我们可以在安卓开发中的Java代码里调用这些C/C++编写的函数。

实例

假设现在有一个安卓应用,可以计算两个数的和,但点击计算后弹出需要付费完整版的提示。点击去激活后,提示要输入激活码,随意输入内容后,显示用户名或序列号错误。

图片[1]-深入探究安卓逆向中的本地库(Native Library)-山海云端论坛

我们开始分析这个软件,首先使用Android Killer打开该软件。在smali/com/example/myapplication文件夹下发现了LicenseFragment.smali,这显然是该软件的验证界面。在这几个文件中,LicenseFragment$1.smali文件中有一个onClick的事件处理函数,这就是验证页面上的按钮。

图片[2]-深入探究安卓逆向中的本地库(Native Library)-山海云端论坛

这里调用了checkserial方法,将返回值放到p1(112行),下面的if-nez语句判断p1(即checkserial的返回值)是否为0。如果不为0,则跳转到:cond_1,否则执行124行,124行的unicode字符解码后为“注册成功”。这意味着当checkserial返回0时,表示注册成功。

我们尝试在所有代码中找到checkserial函数,发现在LicenseFragment.smali文件中声明了checkserial函数,但声明语句中有一个native,这表示这个函数位于native library中。

图片[3]-深入探究安卓逆向中的本地库(Native Library)-山海云端论坛

继续查看LicenseFragment.smali文件,发现该Fragment确实导入了一个名为native-lib的文件,根据命名规则,导入的文件应该是libnative-lib.so。

图片[4]-深入探究安卓逆向中的本地库(Native Library)-山海云端论坛

我们在lib文件夹下查看,发现有几个文件夹对应了不同的平台,每个平台文件夹下都有libnative-lib.so文件,dalvik虚拟机会根据不同平台加载不同的库文件。

图片[5]-深入探究安卓逆向中的本地库(Native Library)-山海云端论坛

我们打开arm64-v8a下的libnative.so,这个系统架构也就是arm64,是现在安卓系统的架构。使用Ghidra打开这个文件,在左上角的函数列表中,看到了几个可疑的函数。第一个是Java_com_example_myapplication_LicenseFragment_checkserial,这毫无疑问就是我们的checkserial函数。第二个是strcmp函数,我们可以猜测这个函数是用来比较序列号的。

图片[6]-深入探究安卓逆向中的本地库(Native Library)-山海云端论坛

我们从strcmp函数入手,发现这个函数正好被checkserial引用了,那么直接跳转过去。在这里,我们发现这里确实在比较字符串并做出判断。

图片[7]-深入探究安卓逆向中的本地库(Native Library)-山海云端论坛

我们分析一下这段汇编代码,在分析之前,补充一点ARM汇编的语句。

  • mov:移动指令
  • bl:分支链接,相当于x86汇编中的call
  • ldr:从内存中取出值放到寄存器中
  • ldur:跟ldr作用大致相同,但ldr需要字节对齐,ldur不需要
  • b.cc:跳转指令,后面可以跟cc写条件,比如b.ne当不相等的时候跳转
  • ldp:同时取两个值到两个寄存器
  • add:加法指令
  • csetm:根据后面指定的条件,如果满足条件给寄存器置为1

在这段关键代码中,我们发现checkserial返回0还是其他,取决于csetm w0,ne这一条语句。我们只需要修改这条语句,让它给w0赋值为0就可以注册成功了。修改该语句为mov w0, #0,函数的返回值就永远为0,那么就可以注册成功。

图片[8]-深入探究安卓逆向中的本地库(Native Library)-山海云端论坛

导出文件,然后覆盖掉源文件,在Android Killer中重新编译安装APK。再次随便输入,然后点击检查按钮,显示注册成功,软件修改完成。

图片[9]-深入探究安卓逆向中的本地库(Native Library)-山海云端论坛

注意

需要注意的是,如果使用的是x86版本的模拟器,例如Android Studio的模拟器,或者是一些Android x86镜像,我们需要修改x86_64下的libnative-lib.so。使用Ghidra打开这个文件,现在是x86下的汇编。

我们分析这段判断代码。这里设置返回值为0还是-1,关键的语句就是sbb eax, eax。我们修改该语句为正常的sub语句,就能保证eax一直为0。

导出文件并覆盖源so,然后在Android Killer中编译。运行程序尝试注册,发现注册成功。

© 版权声明
THE END
喜欢就支持一下吧
点赞8 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容