adb+Frida操作方法总结
adb + Frida操作方法总结
本文多借鉴于SWDD师傅的博客哇,感谢师傅~
0x01 adb简介
一、什么是adb
ADB 全称为 Android Debug Bridge,起到调试桥的作用,是一个客户端-服务器端程序。其中客户端是用来操作的电脑,服务端是 Android 设备。
ADB 也是 Android SDK 中的一个工具,可以直接操作管理 Android 模拟器或者真实的 Android 设备。
二、为什么要用adb
运行设备的 shell(命令行)
管理模拟器或设备的端口映射
计算机和设备之间上传/下载文件
可以对设备的应用进行卸载安装等
在 App 遇到 ANR/Crash 等 bug 时,可以通过 ADB 来抓取日志
简而言之,ADB 就是连接 Android 手机与 PC 端的桥梁,所以ADB又称为安卓调试桥(注意:是安卓,不是iOS),可以让用户在电脑上对手机进行全面的操作!
三、adb命令详解
1、基本命令
adb version : 显示adb版本
adb help :帮助信息,查看adb所支持的所有命令
adb devices:查看当前连接的设备,已连接的设备会显示出来
adb get-serialno:也可以查看设备号
2、权限命令
adb root:获取Android管理员(root用户)的权限。
注意:一般测试机可使用root权限。
Android版本9以上,不支持商用机使用root权限,但可以修改底层一些配置
adb shell:登录设备 shell,该命令将登录设备的shell(内核),登录shell后,可以使用 cd,ls,rm 等Linux命令
3、建立连接
adb -d:如果同时连了usb,又开了模拟器,连接当前唯一通过usb连接的安卓设备
adb -e shell:指定当前连接此电脑的唯一的一个模拟器
adb -s <设备号> shell:当电脑插多台手机或模拟器时,指定一个设备号进行连接
exit:退出
adb kill-server:杀死当前adb服务,如果连不上设备时,杀掉重启。(没事不要用它)
adb start-server:杀掉后重启
四、使用问题详解
解决ADB卡在等待调试器的问题 Waiting For Debugger is waiting for the debugger to attach.
调试 Android 应用时,习惯于看到“等待调试器”对话框。 此对话框将显示,直到调试器附加到要调试的应用的进程,以便对其进行调试。
有时,由于各种未知和奇怪的原因,可能会发生此对话框不会消失的情况,因此无法继续调试会话。
解决方案可能是重新启动您的设备/模拟器,并杀死/重新启动Android Studio。 这是一个相当沉重的解决方案,会让您浪费大量时间。
您只需在终端中运行以下代码即可避免所有这些重新启动:
adb shell am clear-debug-app
然后重启一下adb服务,正常连接调试设备即可
0x02 Frida简介
一、什么是Frida
Frida 是一款基于 Python + JavaScript 的 Hook 与调试框架。
Firda 是一款易用的跨平 Hook 工具, Java 层到 Native 层的 Hook 无所不能,是一种 动态 的插桩工具,可以插入代码到原生 App 的内存空间中,动态的去监视和修改行为,原生平台包括 Win、Mac、Linux、Android、iOS 全平台。
静态二进制插桩:在程序执行前插入额外的代码和数据,生成一个永久改变的可执行文件。
动态二进制插桩:在程序运行时实时地插入额外代码和数据,对可执行文件没有任何永久改变。
Frida 的功能如同油猴插件,通过油猴插件编写的脚本可以直接改变网页的编码方式。
大部分 App 对于我们来说都是黑盒,对 App 进行逆向和动态调试、或自动化分析、需要不断的进行动态调试,Frida 通过使用 Python 注入 JavaScript 脚本,都是通过 JS 脚本来操作设备上的 Java代码。
如果需要持久化的 Hook 还是需要通过 Xposed 等框架,但是 Frida 的动态和灵活性对逆向和自动化逆向提供了很大帮助。
对于逆向操作破解来说方便,安装环境和配置环境要求简单兼容性好。
选择动态调试函数会遇到各种反调试、崩溃,相比xposed而言,frida优势是其动态执行不需要重启。
因为Frida大致原理是手机端安装一个server程序,然后把手机端的端口转到PC端,PC端写python脚本进行通信,而python脚本中需要hook的代码采用javascript语言。
二、Frida的用途
访问进程的内存:
- Frida 可以直接访问并修改目标进程的内存内容。这对于调试和逆向工程非常有用,特别是在需要分析或修改应用程序数据时。
应用程序运行时覆盖功能:
- 通过 Frida,开发者可以在运行时覆盖应用程序的某些功能。这意味着可以在不修改源代码的情况下,改变应用程序的行为,进行功能测试和故障排除。
从导入的类调用函数:
- Frida 允许开发者在运行时调用应用程序中的任意函数,包括那些从外部库导入的函数。这对于调试和功能扩展非常有用,因为可以直接与应用程序的内部逻辑交互。
动态 Hook 跟踪、拦截函数:
- Frida 的动态 Hook 功能使得开发者可以拦截并修改函数调用。这意味着可以在函数调用之前或之后执行自定义代码,记录调用信息,甚至改变函数的输入输出。这对于安全研究、调试和性能分析都非常有帮助。
三、如何使用
Frida
分为客户端和服务端。
客户端:PC(控制端)
服务器:手机设备(被控制端)
客户端编写的 Python
代码,用于连接远程设备,提交要注入的 JS
代码到服务端,接受服务端发来的消息。
服务端中需要用 JS
代码注入到目标进程,操作内存数据,给客户端发送消息。
使用命令frida-ps
查看客户端的进程情况,使用命令frida-ps -U
查看服务端的进程情况。
0x03 Frida 实战(正文开始)
一、前备知识
Hook(Hooking)简介
让我们从非常基础的知识开始。
什么是钩子?
Hook是指拦截和修改应用程序或Android系统中函数或方法行为的过程。例如,我们可以钩取我们应用程序中的一个方法,并通过插入我们自己的实现来改变其功能。
现在,让我们尝试在一个应用程序中钩取一个方法。我们将使用JavaScript API 来完成这个任务,但值得注意的是,Frida也支持Python的调用,我们同样可以使用python代码并插入js片段来实现frida的一系列操作。
二、使用Hook修改被调用的方法的逻辑,返回值,传入参数
1、基本模板
首先展示一下注入的模板:
1 | Java.perform(function() { |
Java.perform
是 Frida 中用于创建一个特殊上下文的函数,让你的脚本能够与 Android 应用程序中的 Java 代码进行交互。它就像是打开了一扇门,让你能够访问并操纵应用程序内部运行的 Java 代码。一旦进入这个上下文,你就可以执行诸如钩取方法或访问 Java 类等操作来控制或观察应用程序的行为。var <class_reference> = Java.use("<package_name>.<class>");
在这里,你声明一个变量<class_reference>
来表示目标 Android 应用程序中的一个 Java 类。你使用Java.use
函数指定要使用的类,该函数接受类名作为参数。<package_name>
表示 Android 应用程序的包名,<class>
表示你想要与之交互的类。<class_reference>.<method_to_hook>.implementation = function(<args>) {}
在所选的类内部,通过<class_reference>.<method_to_hook>
符号访问你想要钩取的方法。这是你可以定义自己的逻辑以在钩取的方法被调用时执行的地方。<args>
表示传递给函数的参数。
来个实例如下:
其中<package_name>
:com.ad2001.frida0x1
2、例题讲解
通过Jadx分析Frida-labs 0x1
onCreate方法
1 | public void onCreate(Bundle bundle) { |
可以发现,在onCreate方法中,有一个监听事件,监听了button的点击,当按钮点击下去之后,程序首先判断输入是不是数字,是数字的话,就将其从string转化为int,再进入check中与i比较,因此我们需要检查check方法。
check方法
1 | void check(int i, int i2) { |
本方法显而易见就是检查输入是否能够满足i*2 + 4 == i2,如果满足则将flag输出到f103t1所绑定的textView控件上,其中用于判断的i则来自get_random。
get_random
1 | int get_random() { |
显而易见,本方法就只是普通的返回一个随机数。
Hook begin!
对于本样例程序,首先我们可以直接hook程序逻辑。更改随机产生的值为一个固定值。或者hook check方法更改check方法传入的参数
Hook get_random方法
实现代码
1 | function hook(){ |
代码解释如下:
- 首先定义了一个名为
hook
的JavaScript函数,其中包含了对目标应用特定方法的hook逻辑。hook
函数通过Frida的Java API来获取目标应用中的MainActivity
类。- 然后,它通过
Java.use()
方法获取了MainActivity
类的引用,使得我们可以访问该类的方法。 - 最后,
hook
函数将MainActivity
类中的get_random
方法进行了修改。它用自定义的实现替换了原有方法的实现,使得每次调用get_random
方法时都返回固定值0。
- 接着定义了一个名为
main
的JavaScript函数,其中包含了Frida的Java.perform()
方法,用于执行指定的hook逻辑。 - 最后,通过
setImmediate()
函数调用main
函数,确保在Frida脚本启动后立即执行。