Android-frida-hook-java层

adb基础命令

1
2
adb reboot #重启
adb help #查看ADB 帮助

查看设备

1
adb devices #查看可连接操作的设备

连接设备

1
2
3
4
5
6
7
8
adb [-d|-e|-s <serialNumber>] <command>
连接指定设备

参数:
-d 指定当前唯一通过USB 连接的Android 设备为命令目标
-e 指定当前唯一运行的模拟器为命令目标
-s <serialNumber> 指定相应serialNumber 号的设备/模拟器为命令目标
command 为所需对设备执行的命令

示例:

1
2
3
adb connect 127 0.0.1:7555 # 以 WLAN 网络方式连接(比如:连接电脑上模拟器 MUMU 等)
adb disconnect 127.0.0.1:16416 #断开连接
adb -s cf27456f shell # 指定连接设备使用命令,以USB、串口等方式连接真手机、平板等

安装、卸载APP应用

1.安装应用

1
2
3
adb install test.apk #安装应用
adb install -r demo.apk #保留数据和缓存文件,重新安装apk
adb install -s test.apk #安装apk 到sd 卡

2.卸载应用

1
2
adb uninstall cn.com.test.mobile #卸载应用,需要指定包
adb uninstall -k cn.com.test.mobile #卸载app 但保留数据和缓存文件

-k: 卸载 APP 但保留数据和缓存文件

停止进程

比如,还没进入root环境(su)就先启动了frida-server服务,可以先杀死进程,再进入su进入root环境,启动frida-server

1
2
3
ps -a | grep frida-server # 查找进程
kill PID # 停止进程
kill -9 PID # 强制停止进程

启动frida-server服务

模拟器(雷电模拟器),到雷电模拟器安装目录下输入cmd,回车进入shell

1
2
3
4
5
6
7
8
D:\Program Green\leidian\LDPlayer9>adb shell		# 进入手机shell
marlin:/ $ su # 进入root环境,#代表root,$代表没root,一般模拟器都有root,没有去开启就行
:/ # cd /data/local/tmp/ # frida-server安装路径,
:/data/local/tmp # ls
frida-x86_64 oat
:/data/local/tmp # ./frida-x86_64 & # ./xxx 运行,&代表后台运行
[1] 2817 # PID,用ps -a 可以查找到进程和PID
:/data/local/tmp #

PixPin_2025-03-28_22-05-51

电脑端,再打开一个命令行窗口进行端口转发,

1
2
adb forward tcp:27042 tcp:27042	# frida默认转发端口为27042
adb forward tcp:27043 tcp:27043 # 不行就试试27043

frida hook java层

python+frida实现hook

1
2
3
4
5
6
7
8
9
10
11
'''
spawn模式,Frida会自行启动并注入进目标App,Hook的时机非常早
'''
# device=frida.get_remote_device()
# pid=device.spawn([com.jx885.reward*]) #包名
# device.resume(pid)
# time.sleep(1)
# session = device.attach(pid)
'''
attach模式,Frida会附加到当前的目标进程中,即需要App处于启动状态,这也意味着只能从当前时机往后Hook,
'''

python脚本

Frida.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# -*- coding=utf-8 -*-

import frida
import sys


def on_message(message, data): # js中执行send函数后要回调的函数
print(message)


session = frida.get_remote_device().attach('应用名') # APPNAME
with open("./frida.js") as f:
script = session.create_script(f.read())
script.on('message', on_message) # 加载回调函数,也就是js中执行send函数规定要执行的python函数

script.load() # 加载脚本
sys.stdin.read()

hook 普通java层函数

frida.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function main() {
console.log("脚本加载成功!");
Java.perform(function() {
console.log("进入java层成功!!");
var MainActivity = Java.use('包名.类名')
console.log("成功找到包名.类名!!!");
MainActivity.方法名.implementation = function (参数1, 参数2, ...) {
var retval = 方法名(参数1, 参数2, ...); // 如果需要返回值,这样会避免递归调用
console.log("key:" + retval);
return retval;
}
});
}

setImmediate(main); // 相当于 setTimeout(main, 0);

hook java层重载(overload)函数

frida.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function main() {
console.log("脚本加载成功!");
Java.perform(function() {
console.log("进入java层成功!!");
var MainActivity = Java.use('包名.类名')
console.log("成功找到包名.类名!!!");
MainActivity.方法名.overload('类型1', '类型2', ...).implementation = function (参数1, 参数2, ...) { // hook 重载函数
var retval = 方法名(参数1, 参数2, ...); // 如果需要返回值,这样会避免递归调用
console.log(参数1, 参数2, ...); // 打印参数
return retval;
}
});
}

setImmediate(main); // 相当于 setTimeout(main, 0);

java层主动调用

主动调用:强制调用一个函数去执行,直接执行函数,更具主动性

被动调用:有app的按照正常逻辑执行,需完成前置交互

java中类方法可分为:类方法和实例方法;

如果是类函数的主动调用,直接使用Java.use()函数找到类进行调用即可,

如果是实例方法的主动调用,则需找到对应实例后对方法调用,使用frida的api函数Java.choose()可以在java堆中找到指定类的实例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
function main() {
console.log("脚本加载成功!");
Java.perform(function() {
console.log("进入java层成功!!");

// 静态函数主动调用
var MainActivity = Java.use('包名.类名')
console.log("成功找到包名.类名!!!");
MainActivity.方法名(参数1, 参数2, ...);

// 实例函数主动调用
Java.choose('包名.类名'), {
onEnter: function (实例) {
console.log("已找到实例" + 实例);
实例.方法(参数1, 参数2, ...);
},
onCompelete: function () {
console.log("完成" );
}
});
}

setImmediate(main); // 相当于 setTimeout(main, 0);

rpc及其自动化(修改python与js脚本)