学习网站
https://www.52pojie.cn/thread-1128884-1-1.html
环境安装
安装对应的 frida 工具
安装 frida-tools
python3 -m pip install frida-tools
安装 frida
python3 -m pip install frida
安装 objection
python3 -m pip install objection
安装模拟器
下载 genymotion
和 virtualbox
后 在genymotion
里面安装对应的Android8 的模拟器且设置网络为 桥接模式
下载对应的文件
adb push xxx/xxx/frida-server-10.7.7-android-x86 /data/local/tmp/frida-server
因为存在多个 ip 我们需要利用 -s 指定对应的模拟器
https://github.com/frida/frida/releases
启动 frida-server
1 | adb -s xxx shell |
转发对应端口
1 | adb -s 192.168.56.101:5555 forward tcp:27042 tcp:27042 |
如果使用真机push到/data/local没有权限的话可以先push到/sdcard中,然后使用adb shell进入命令行,使用su进入root状态,cp至/data/local中,然后在进入/data/local中修改权限,运行。
反编译工具使用
jadx-gui
调试需要使用
adb forward tcp:xxx tcp:xxx
转发
adb shell am start -D com.example.fridaso/.MainActivity
启动调试
开发环境
1 | git clone https://github.com/oleavr/frida-agent-example.git |
- 使用vscode打开此工程,在agent文件夹下编写js,会有智能提示。
npm run watch
会监控代码修改自动编译生成js文件- python脚本或者cli加载_agent.js
frida -U -f com.example.android --no-pause -l _agent.js
入门学习
HOOK java 层
目的
首先查看其中的 apk java层的代码
目的是 HOOK 其中 testFrida()
函数的返回字符串。
程序运行
点击 BUTTON
后
字符串会变化
步骤分析
首先我们要知道 我们模拟器里面运行的进程是什么
利用 frida-ps -U
查看
找到对应的 进行名字
我们要做的就是利用 frida 去 劫持进程从而使用 js 脚本(自己定义的) 进行hook
在运行我们的脚本的时候是需要 将模拟器端口转发出来的
1 | adb -s 192.168.56.101:5555 forward tcp:27042 tcp:27042 |
脚本步骤
- 劫持进程 利用函数
frida.get_remote_device().attach()
- 进程中创建对应的 js 脚本
process.create_script()
- 加载回调函数
script.on()
- 加载脚本
script.load()
1 | import frida |
这样我们就实现了 对 java 层的 HOOK
HOOK native 层
目的
利用 Hook 然后点击按钮后的数字为其他值。
首先运行测试功能
点击按钮
变成了字符串 变成了3
功能就是修改这个3 为其他📚
逆向代码
主要函数 FridaSoDefine.FridaSo(1,2)
我们去查看这个函数右键跟踪
发现这里是利用 静态 loadLibrary
了一个 so 文件。
这里我们就需要对 so 文件进行一个逆向
我们可以直接 修改 apk 后缀为 zip 进行解压
在 lib
目录下找到 对应的 so文件 利用 ida 进行反编译
在函数表中找到对应的 函数
反编译查看伪代码发现只是一个简单的加法
其中 利用的是 a3 a4 参数
一般so层函数第一个参数都是JniEnv,第二个参数是jclass,从第三个参数开始才是我们java层传入的参数
这里我们要实现修改的就是对于进行运算后 return 返回的值进行 hook
步骤分析
刚开始也是一样
- 劫持进程 利用函数
frida.get_remote_device().attach()
- 进程中创建对应的 js 脚本
process.create_script()
- 加载回调函数
script.on()
- 加载脚本
script.load()
但是这里我们要对我们的 自定义 js 脚本代码进行一个修改
对 java 层的 hook 我们利用的是 Java.use
来找到对应类
但是这里我们需要进行一个改变
利用 Module.findExportByName("libfridaso.so","Java_com_example_fridaso_FridaSoDefine_FridaSo")
找到对应的动态库里面的对应 jni 函数 然后利用
retval.replace(0);
将返回值 修改为 0
1 | import frida |
HOOK native 层 string
目的
hook native层函数的返回字符串。
点击按钮会修改 字符串
逆向代码
然后我们去查看 fridaSoString.FridaSo()
函数
可以发现这里是对应的 动态库
我们ida 逆向看看
只是一个返回字符串。
步骤分析
也是一样的基本步骤
1 | process = frida.get_remote_device().attach('com.example.fridasostring') |
劫持对应进程
创建js劫持脚本
设置回调函数
加载脚本
这里和 直接修改 native 的返回不一样
这里有一个新的 利用
1 | var env = Java.vm.getEnv(); |
getEnv
就是对应的第一个参数
创建新的 字符串,最后返回的字符串的hook。
1 | import frida |
深入学习
认识
利用 frida
不仅能对 安卓进行 hook 还能对iOS,pc 进行一个hook。
如果想要持久化hook 我们还需要依靠 Xposed
和 hookzz
等开发框架。
这是一种动态插装工具,可以插入一些代码到原生 app
的内存空间,动态地监视和修改其行为。
其中 frida 调用的 api 是使用 javaScript
实现的
我们可以直接利用
frida -U -l xxxx.js com.xxx.xxx
这样讲我们的 js 脚本注入进程,实现hook。
API 学习
https://frida.re/docs/javascript-api/
对于我们的基本 python payload 模板
1 | import frida |
其中 经常会用到的 API
Java.choose(className: string, callbacks: Java.ChooseCallbacks): void
通过扫描Java VM的堆来枚举className类的live instance。
Java.use(className: string): Java.Wrapper<{}>
动态获取
className
的JavaScript
包装器,您可以通过在其上调用$new()
来调用构造函数来实例化对象。 在实例上调用$dispose()
以对其进行显式清理(或等待JavaScript对象进行垃圾回收,或等待脚本卸载). 静态和非静态方法都可用,甚至可以替换方法实现并从中引发异常Java.perform(fn: () => void): void
确保当前线程已连接到VM,并调用
fn
. (在Java的回调中这不是必需的。) 如果该应用的类加载器尚不可用,则将延迟调用fn
。 如果不需要访问应用程序的类,请使用Java.performNow()
。send(message: any, data?: ArrayBuffer | number[]): void
任何JSON可序列化的值。
将JSON序列化后的message发送到您的基于Frida的应用程序,并包含(可选)一些原始二进制数据。recv(callback: MessageCallback): MessageRecvOperation
请求在从基于Frida的应用程序收到的下一条消息上调用回调。
Java.enumerateLoadedClasses(callbacks)
枚举立即加载的类,其中
callbacks
是一个指定以下内容的对象onMatch : function (name, handle):
为每个已加载的类调用,其名称可以传递给use()
以获取JavaScript包装器。 也可以使用Java.cast()
处理java.lang.Class
的handle
onComplete :function()
当所有的类都被枚举后调用
Java.enumerateLoadedClassesSync()
和上面的类似