1、常用命令
adb connect 127.0.0.1:62001 连接设备
adb shell 进入shell
adb kill-server 关闭服务
adb start-server 关闭服务
adb reboot 重启服务
adb forwardtcp:27042 tcp:27042 端口转发
adb shelldumpsys activity top 查看APK包名
frida-ls-devices 列出所有连接计算机的设备
frida-ps -U 查看正在运行进程
frida-ps -Uai 列出安装的程序
frida-ps -Ua 列出运行中的程序
frida-ps -D "设备ID" 连接frida到指定设备
frida-trace-U -f Name-i "函数名" 跟踪某个函数
frida-trace-U -f Name-m "方法名" 跟踪某个方法
frida-U -l name.js "进程ID" 加载js脚本
frida-discover-n Name 发现程序内部函数
frida-discover-p pid 发现程序内部函数
frida-kill -U "进程ID" 结束进程
2、Hook的基本语法
setTimeout(
function(){
Java.perform(function(){
console.log("Hello world")
})
}
)
3、注入指定 js 文件 -U参数是指USB设备 -l参数用于指定注入脚本所在路径 最后是进程名
frida -U -l hello_world.js com.android.keychain
4、查看frida版本
frida --version
5、通过friad的cli模式以attach模式注入(不带改变参数)
function main(){
console.log("脚本加载开始......")
Java.perform(function(){
console.log("内部java注入开始......")
var MainActivity = Java.use('com.example.demo01.MainActivity')
console.log("定位类成功......")
MainActivity.fun.implementation = function(x,y){
console.log("x => ", x, "y => ", y)
var ret_value = this.fun(x,y);
return ret_value
}
})
}
setImmediate(main)
6、通过friad的cli模式以attach模式注入(改变参数)
function main() {
console.log("脚本加载开始......")
Java.perform(function () {
console.log("内部java注入开始......")
var MainActivity = Java.use('com.example.demo01.MainActivity')
console.log("定位类成功......")
MainActivity.fun.implementation = function (x, y) {
console.log("x => ", x, "y => ", y)
var ret_value = this.fun(10, 1);
return ret_value
}
})
}
setImmediate(main)
7、通过friad的cli模式以attach模式注入(方法重载就是有两个一样的方法如何hook)
function main() {
console.log("脚本加载开始......")
Java.perform(function () {
console.log("内部java注入开始......")
var MainActivity = Java.use('com.example.demo01.MainActivity')
console.log("定位类成功......")
//重载方法测试
MainActivity.fun.overload('int', 'int').implementation = function (x, y) {
console.log("x => ", x, "y => ", y)
var ret_value = this.fun(133, 1);
return ret_value
}
})
}
setImmediate(main)
8、java层主动调用(概念:主动调用就是强制一个函数去执行,被动调用就是按照app的正常逻辑去执行函数,函数的执行完全依靠与用户完成交互逻辑从而间接完成到关键函数,而主动调用则可以主动直接调用到关键行函数主动性更强),载java中函数可分为两种:类函数和实力方法,就是静态的方法和动态的方法,类函数使用关键字static修饰和对应的类是绑定的如果类函数还是被public关键词修饰的在外部就可以直接通过类去掉用,实例方法则是没有关键词static关键词修饰在外部只能通过创建对应类的实例在通过实例去访问,在frida中的主动调用的类型会根据方法类型区分开,如果是类函数的主动调用直接使用java.use()函数找到类去进行调用就可,如果是实例方法的主动调用则需要找到对应的实例后对方法进行调用,这里用到了非常重要的一个api函数java.choose()这个函数可以找到java堆中寻找制定类的实例。
function main() {
console.log("脚本加载开始......")
Java.perform(function () {
console.log("内部java注入开始......")
//静态函数主动调用
var MainActivity = Java.use('com.example.demo01.MainActivity')
MainActivity.staticSecret()
//动态函数主动调用
Java.choose('com.example.demo01.MainActivity', {
onMatch: function(instance){
console.log("instance found", instance)
instance.secret()
},
onComplete: function(){
console.log('search onComplete')
}
})
})
}
setImmediate(main)
9、rpc及自动化
js Hook 文件 hook_demo01_rpc.js
function CallSecretFunc(){
Java.perform(function(){
//动态函数主动调用
Java.choose('com.example.demo01.MainActivity', {
onMatch: function(instance){
instance.secret()
},
onComplete: function(){
}
})
})
}
function getTotalValue(){
Java.perform(function(){
console.log("内部java注入开始......")
var MainActivity = Java.use('com.example.demo01.MainActivity')
//动态函数主动调用
Java.choose('com.example.demo01.MainActivity',{
onMatch: function(instance){
console.log("total value = ", instance.total.value)
},
onComplete: function(){
console.log('search Complete')
}
})
})
}
//setImmediate(getTotalValue)
//rpc导出函数用于使用
rpc.exports = {
callsecretfunc: CallSecretFunc,
gettotalvalue: getTotalValue
}
python 文件加载js文件最终实现RPC
#!/usr/bin/python
# -*- coding:utf-8 -*-
import sys
import frida
def on_message(message, data):
if message['type'] == 'send':
print("[*] {0}".format(message['payload']))
else:
print(message)
devices = frida.get_usb_device()
process = devices.attach('demo01')
with open('hook_demo01_rpc.js') as f:
jscode = f.read()
script = process.create_script(jscode)
script.on('message', on_message)
script.load()
command = ''
while 1 == 1:
command = input("\nEnter command:\n1: Exit \n2:Call secret function \n3: Get Total Value \nchoice:")
if command == "1":
break
elif command == "2": #在这里调用
script.exports.callsecretfunc()
elif command == "3":
script.exports.gettotalvalue()