Frida安装
python虚拟环境安装代码语言:javascript复制pip config --global set global.index-url https://mirrors.cloud.tencent.com/pypi/simple
pip install virtualenvwrapper-win设置环境变量WORKON_HOME为下面自己建立好的路径,当然默认也可以不设置,默认在用户目录下
代码语言:javascript复制C:\WORKON_HOME新建环境mkvirtualenv fridatest
代码语言:javascript复制c新建环境
rmvirtualenv 删除环境下次打开cmd进入环境
代码语言:javascript复制workon fridatestFrida安装以及多版本处理代码语言:javascript复制pip install frida-toolsFrida-server代码语言:javascript复制(fridatest) C:\Users\PF>pip list
Package Version
----------------- -------
colorama 0.4.6
frida 16.2.1
frida-tools 12.3.0
pip 24.0
prompt-toolkit 3.0.43
Pygments 2.17.2
setuptools 69.1.0
typing_extensions 4.10.0
wcwidth 0.2.13
wheel 0.42.0上面frida 是16.2.1,所以也下载16.2.1
解压,push到手机,给执行权限并运行
代码语言:javascript复制adb push frida-server-16.2.1-android-arm64 /data/local/tmp
adb shell
su
OnePlus3:/data/local/tmp # chmod +x frida-server-16.2.1-android-arm64
OnePlus3:/data/local/tmp # ./frida-server-16.2.1-android-arm64自定义端口运行
代码语言:javascript复制./frida-server-16.2.1-android-arm64 -l 0.0.0.0:6666通过在电脑端,执行下面命令,可以看到手机进程说明没问题了
代码语言:javascript复制frida-ps -UFrida基础知识1.基础指令1.frida-ps -U 查看当前手机运行的进程
2.frida-ps –help 查看help指令
2.操作模式:操作模式
描述
优点
主要用途
CLI(命令行)模式
通过命令行直接将JavaScript脚本注入进程中,对进程进行操作
便于直接注入和操作
在较小规模的操作或者需求比较简单的场景中使用
RPC模式
使用Python进行JavaScript脚本的注入工作,实际对进程进行操作的还是JavaScript脚本,可以通过RPC传输给Python脚本来进行复杂数据的处理
在对复杂数据的处理上可以通过RPC传输给Python脚本来进行,有利于减少被注入进程的性能损耗
在大规模调用中更加普遍,特别是对于复杂数据处理的需求
3.注入模式与启动命令注入模式
描述
命令或参数
优点
主要用途
Spawn模式
将启动App的权利交由Frida来控制,即使目标App已经启动,在使用Frida注入程序时还是会重新启动App
在CLI模式中,Frida通过加上 -f 参数指定包名以spawn模式操作App
适合于需要在App启动时即进行注入的场景,可以在App启动时即捕获其行为
当需要监控App从启动开始的所有行为时使用
Attach模式
在目标App已经启动的情况下,Frida通过ptrace注入程序从而执行Hook的操作
在CLI模式中,如果不添加 -f 参数,则默认会通过attach模式注入App
适合于已经运行的App,不会重新启动App,对用户体验影响较小
在App已经启动,或者我们只关心特定时刻或特定功能的行为时使用
Spawn模式
代码语言:javascript复制frida -U -f 包名 -l hook.jsattach模式 :
代码语言:javascript复制frida -U 进程名 -l hook.jslogcat |grep "D.zj2595"日志捕获
adb connect 127.0.0.1:62001模拟器端口转发
4. 基础语法API名称
描述
Java.use(className)
获取指定的Java类并使其在JavaScript代码中可用。
Java.perform(callback)
确保回调函数在Java的主线程上执行。
Java.choose(className, callbacks)
枚举指定类的所有实例。
Java.cast(obj, cls)
将一个Java对象转换成另一个Java类的实例。
Java.enumerateLoadedClasses(callbacks)
枚举进程中已经加载的所有Java类。
Java.enumerateClassLoaders(callbacks)
枚举进程中存在的所有Java类加载器。
Java.enumerateMethods(targetClassMethod)
枚举指定类的所有方法。
5.日志输出语法区别日志方法
描述
区别
console.log()
使用JavaScript直接进行日志打印
多用于在CLI模式中,console.log()直接输出到命令行界面,使用户可以实时查看。在RPC模式中,console.log()同样输出在命令行,但可能被Python脚本的输出内容掩盖。
send()
Frida的专有方法,用于发送数据或日志到外部Python脚本
多用于RPC模式中,它允许JavaScript脚本发送数据到Python脚本,Python脚本可以进一步处理或记录这些数据。
6.Hook框架模板代码语言:javascript复制function main(){
Java.perform(function(){
hookTest1();
});
}
setImmediate(main);7.Frida常用API1.Hook普通方法、打印参数和修改返回值代码语言:javascript复制//定义一个名为hookTest1的函数
function hookTest1(){
//获取一个名为"类名"的Java类,并将其实例赋值给JavaScript变量utils
var utils = Java.use("类名");
//修改"类名"的"method"方法的实现。这个新的实现会接收两个参数(a和b)
utils.method.implementation = function(a, b){
//将参数a和b的值改为123和456。
a = 123;
b = 456;
//调用修改过的"method"方法,并将返回值存储在`retval`变量中
var retval = this.method(a, b);
//在控制台上打印参数a,b的值以及"method"方法的返回值
console.log(a, b, retval);
//返回"method"方法的返回值
return retval;
}
}实例
代码语言:javascript复制
//定义一个名为hookTest1的函数
function hookTest1(){
//获取一个名为"类名"的Java类,并将其实例赋值给JavaScript变量utils
var utils = Java.use("com.zj.wuaipojie.Demo");
//修改"类名"的"a"方法的实现。这个新的实现会接收两个参数(a和b)
utils.a.implementation = function(teststr){
//将参数a和b的值改为123和456。
teststr = "hahaha,frida!";
//调用修改过的"a"方法,并将返回值存储在`retval`变量中
var retval = this.a(teststr);
//在控制台上打印参数a,b的值以及"a"方法的返回值
console.log(teststr, retval);
//返回"a"方法的返回值
return retval;
}
}
function main(){
Java.perform(function(){
hookTest1();
});
}
setImmediate(main);hook
代码语言:javascript复制frida -U wuaipojie -l hook.js2.Hook重载参数代码语言:javascript复制// .overload()
// .overload('自定义参数')
// .overload('int')
function hookTest2(){
var utils = Java.use("com.zj.wuaipojie.Demo");
//overload定义重载函数,根据函数的参数类型填
utils.Inner.overload('com.zj.wuaipojie.Demo$Animal','java.lang.String').implementation = function(a, b){
b = "自定义参数已经被修改";
this.Inner(a,b);
console.log(b);
}
}3.Hook构造函数代码语言:javascript复制function hookTest3(){
var utils = Java.use("com.zj.wuaipojie.Demo");
//修改类的构造函数的实现,$init表示构造函数
utils.$init.overload('java.lang.String').implementation = function(str){
// 原来的参数
console.log(str);
str = "52破解hook33333";
this.$init(str);
}
}4.Hook字段代码语言:javascript复制function hookTest5(){
Java.perform(function(){
//静态字段的修改
var utils = Java.use("com.zj.wuaipojie.Demo");
//修改类的静态字段"flag"的值
utils.staticField.value = "我是被修改的静态变量";
console.log(utils.staticField.value);
//非静态字段的修改
//使用`Java.choose()`枚举类的所有实例
Java.choose("com.zj.wuaipojie.Demo", {
onMatch: function(obj){
//修改实例的非静态字段"_privateInt"的值为"123456",并修改非静态字段"privateInt"的值为9999。
// obj._privateInt.value = "123456"; //字段名与函数名相同 前面加个下划线
console.log("here!")
obj.publicInt.value = 8888;
obj.privateInt.value = 9999;
//由于样本代码的原因,需要再主动调用一下Demo类日志输出函数test(),才能在adb的log界面看到输出改变
obj.test();
console.log(obj.privateInt.value )
},
onComplete: function(){
}
});
});
}5.Hook内部类不过好像不太行,eeeeeeee没有输出
代码语言:javascript复制function hookTest6(){
Java.perform(function(){
//内部类
var innerClass = Java.use("com.zj.wuaipojie.Demo$innerClass");
console.log(innerClass);
innerClass.$init.implementation = function(){
console.log("eeeeeeee");
}
});
}6.枚举所有的类与类的所有方法代码语言:javascript复制function hookTest7(){
Java.perform(function(){
//枚举所有的类与类的所有方法,异步枚举
Java.enumerateLoadedClasses({
onMatch: function(name,handle){
//过滤类名
if(name.indexOf("com.zj.wuaipojie.Demo") !=-1){
console.log(name);
var clazz =Java.use(name);
console.log(clazz);
var methods = clazz.class.getDeclaredMethods();
console.log(methods);
}
},
onComplete: function(){}
})
})
}7.枚举所有方法代码语言:javascript复制function hookTest8(){
Java.perform(function(){
var Demo = Java.use("com.zj.wuaipojie.Demo");
//getDeclaredMethods枚举所有方法
var methods =Demo.class.getDeclaredMethods();
for(var j=0; j < methods.length; j++){
var methodName = methods[j].getName();
console.log(methodName);
for(var k=0; k Demo[methodName].overloads[k].implementation = function(){ for(var i=0;i console.log(arguments[i]); } return this[methodName].apply(this,arguments); } } } }) }8.主动调用静态方法 代码语言:javascript复制function hookTest9(){ Java.perform(function(){ var ClassName=Java.use("com.zj.wuaipojie.Encode"); var ret = ClassName.encode("aaaaaaaaaaaa"); console.log(ret); }) }非静态方法 代码语言:javascript复制function hookTest10(){ var ret = null; Java.perform(function () { Java.choose("com.zj.wuaipojie.Demo",{ //要hook的类 onMatch:function(instance){ ret=instance.privateFunc("aaaaaaa"); //要hook的方法 }, onComplete:function(){ // console.log("result: " + ret); } }); }) //return ret; }