导航菜单

在之前一篇文章中,我们介绍了如何在安卓app中添加C/C++代码。本文将以上文的app为示例,hook其中用C编写的Jniint函数。

这篇文章中有一些你可能感兴趣的Frida代码示例。

本文适合刚入门的新手,目的是介绍如何使用Frida hook方法,尤其是native方法。我们将详细介绍整个流程中的每个步骤。如果你想下载本文的APK示例,链接在此。

在本教程中,我们会处理Java方法和C函数。我不会刻意区分这些术语,因为它们意思是一样的。

第一步是检测APK是否包含共享库。简单的方法是解压APK。别忘了APK是实际app的打包,所以可以像解压压缩包一样提取APK内容。选择你常用的解压程序解压APK。

解压后的文件结构应该类似于:

12345678910111213 ├── AndroidManifest.xml├── classes2.dex├── classes.dex├── lib│   ├── arm64-v8a│   │   └── libnative-lib.so│   ├── armeabi-v7a│   │   └── libnative-lib.so│   ├── x86│   │   └── libnative-lib.so│   └── x86_64│       └── libnative-lib.so├── [...more here...]

lib文件夹下,我们看到了针对不同架构的库的编译版本。选择适配设备的,我们选的是x86。我们需要分析该共享对象内部的函数,命令为nm --demangle --dynamic libnative-lib.so。结果如下:

123456789101112 $ nm --demangle --dynamic libnative-lib.so00002000 A __bss_start         U __cxa_atexit         U __cxa_finalize00002000 A _edata00002000 A _end00000630 T Java_com_erev0s_jniapp_MainActivity_Jniint000005d0 T Jniint         U rand         U srand         U __stack_chk_fail         U time

我们首先注意到了两个函数:Java_com_erev0s_jniapp_MainActivity_JniintJniint。如果你想了解关于这两个函数的更多信息,请阅读另一篇文章的相关部分。我们要做的是改变APK的执行流程,让Jniint返回我们自定义的值。

方法有二:

  1. Hook Java层,即劫持Java JNI调用,此方法可以不用处理C代码;
  2. 深入native层在Jniint函数上做手脚。

一般来说,方法一比较容易,但是有时候方法二操作会更方便。这完全取决于app本身和你的目的。两种方法我们都会尝试,并且对其步骤做评价。

配置测试环境

本教程中所使用的,以及我在进行常规安卓安全测试中所使用的,都是Genymotion。Genymotion是一个非常不错的模拟器,非常轻巧,也可集成到Android Studio中。在测试环境中,挑选的设备/模拟器一定要有root访问权限。其实root对于执行hook而言也不是必须的(有其他替代方法),但本文中的教程需要root权限。Genymotion默认情况下具有root访问权限。

安装Frida

此步骤非常简单,只需Python环境并且运行两个命令。第一个命令是pip install frida-tools,用以安装基本组件,第二个命令是pip install frida,用以安装一些在使用Frida过程中有用的Python bindings(Python bindings的作用是允许用Python调用其他语言的方法)。

在设备上运行frida-server

首先下载最新版本的frida-server,链接在此。搜索frida-server并选择设备对应的安卓架构,Genymotion对应的是x86。下载完成后,解压并重命名一个好记的名字,比如frida-server。接下来将其传至设备上并运行。往设备上传文件需要adb。如果目录下没有adb,你需要下载adb。你可以在adb目录下运行,也可以将目录路径添加至环境变量。部分教程在此。

现在adb就绪,并且已经将设备连接至电脑,或者配置好了模拟器。执行命令adb push path/to/your/frida-server /tmp。该命令会将电脑上的frida-server文件传到设备的/tmp目录下。

最后,在设备上运行frida-server。步骤是:先打开adb shell,进入/tmp目录,然后执行chmod +x frida-server使其可执行,最后执行./frida-server,并且不要关闭命令行窗口。

验证正确配置和操作的方式是,打开另一个命令行窗口,执行frida-ps -U。如果看到结果是一个很长的进程列表,那就说明没问题,否则重新阅读本小节并严格按步骤执行。

如果你是按照上一篇文章的步骤执行的,别忘了安装从此处下载APK样本,或者自己编译APK。有多种安装APK的方法,其中之一是运行adb install nameOfApk.apk

基于Frida框架用Java API hook

我们要hook的方法是Jniint,在此之前,请先在此查阅Frida的Java API,会对你理解后续的操作有帮助。

首先,点击app图标启动app。点击按钮后会弹出一个数字,如下所示:

使用Frida框架hook安卓native方法(适合新手)

我们接下来创建一个给Frida使用的JavaScript文件,来hook我们想hook的函数(Jniint)。JavaScript文件内容如下:

1234567891011 Java.perform(function () {  // we create a javascript wrapper for MainActivity  var Activity = Java.use('com.erev0s.jniapp.MainActivity');  // replace the Jniint implementation  Activity.Jniint.implementation = function () {    // console.log is used to report information back to us    console.log("Inside Jniint now...");    // return this number of our choice    return 80085  };});

代码的意思直接明了,我们首先给MainActivity类创建了一个包装对象,然后替换MainActivity类中的Jniint。保存文件,命名为myhook.js。在设备中打开app时,我们需要在JavaScript文件的目录下打开命令行终端。

命令是frida -U -l myhook.js com.erev0s.jniapp

-U表示通过USB连接设备,-l表示使用JavaScript文件,最后是指定hook的app。注意此命令要求app已经在设备上运行,它不会自动启动。如果想自动启动app,则需使用命令frida -U -l hookNative.js -f com.erev0s.jniapp --no-pause-f会启动指定的app,--no-pause会在app启动后执行主线程。

不论用何种方式,结果是一样的,你会看到类似如下的界面:

使用Frida框架hook安卓native方法(适合新手)

如你所见,按下按钮后,结果已更改为我们在JavaScript代码中定义的值。至此,我们已经使用Frida的Java API成功更改了Jniint的返回值。

基于Frida框架直接hook native层代码

在我们需要处理C/C++的函数并且仅更改返回结果无法满足需求的情况下,此方法特别有用。比如找出一个加密函数中的特殊参数(也许是密钥)。步骤与上文一致,唯一的变动是JavaScript文件myhook.js的内容有变化:

12345678 Interceptor.attach(Module.getExportByName('libnative-lib.so''Jniint'), {    onEnter: function(args) {    },    onLeave: function(retval) {      // simply replace the value to be returned with 0      retval.replace(0);    }});

此处用的API介绍见该链接,它会在libnative-lib.so中自动搜寻Jniint函数,libnative-lib.so即为我们之前解压APK时看到的库文件的名字。调用retval.replace(0)以替换返回值。

以与之前相同的方式执行Frida时,会看到报错!不用担心,这是预期内的,因为我们正在尝试hook Jniint,但是由于还未按下按钮,该函数尚未被加载!因此,Frida告诉我们找不到"Jniint"。按下按钮,调用Jniint,然后就可以了。我们唯一要做的就是再次保存我们的JavaScript文件,Frida将自动重新加载之,现在如果再次按下按钮,我们会得到以下信息:

使用Frida框架hook安卓native方法(适合新手)

结论

在本文中,我们详细介绍了两种hook native方法并更改其返回值的方法,并介绍了如何配置环境以及安装所有必需的工具。如果你想深入研究Frida,请查阅官方API文档,因为你会找到几乎所有你所需的内容。建议在一开始练习的时候节奏不要太快,因为可能会遇到一些复杂情况。希望你喜欢这篇文章,并能从中学到一些东西。如有任何问题或评论,请随时与我联系,我将尽力回答。

原文链接:https://erev0s.com/blog/how-hook-android-native-methods-frida-noob-friendly/

翻译:看雪翻译小组 SpearMint

校对:看雪翻译小组 skeep

 

相关推荐

CVE-2020-0904:Hyper-V类型混淆任意地址解引用漏洞分析

译文声明 本文是翻译文章,文章原作者Daniel Fernandez Kuehr,文章来源:labs.bluefrostseC++urity.de 原文地址:https://labs.bluefrostsecurity.de/advisories/bfs-sa-2020-003/ 译文仅供参考,具体内容表达以...

JustSystems Ichitaro(一太郎)缓冲区溢出漏洞

  漏洞简介 IC++hitaro(一太郎)是日本JustSystems公司的一套文字处理软件。 JustSystems Ichitaro在处理JTD文档的过程中存在基于堆的缓冲区溢出漏洞,允许远程攻击者可利用该漏洞构建恶意文件,诱使用户解...