0.frida api 查询
Frida 官网(api查询)
1.签名
.overload('[S')
.overload('[J')
.overload('[Ljava.lang.Object;')
.overload('[B')
.overload('[Z')
.overload('[C')
.overload('[I')
.overload('[D')
.overload('[F')
2.Gson的安装与使用
作用就是把java数据转换成Json数据
将gson.dex放置在 安卓设备/data/local/tmp下. 与frida-server同目录下
Java.openClassFile("/data/local/tmp/gson.dex").load();
const gson = Java.use("com.r0ysue.gson.Gson");
console.log(gson.$new().toJson(xxx));
3.返回值,参数 解析
function main(){
Java.perform(function(){
//hook toString
Java.use("java.lang.Character").toString.overload('char').implementation = function(x){
var result = this.toString(x);
console.log(result);
return result;
}
//解析array
Java.use("java.util.Arrays").toString.overload('[C').implementation = function(x){
var result = this.toString(x);
console.log(JSON.stringify(x),"-------------",result)
//Gson解析 Java参数
//Java.openClassFile("/data/local/tmp/gson.dex").load();
//const gson = Java.use("com.r0ysue.gson.Gson");
//console.log(gson.$new().toJson(x),"------",result);
return result
}
//解析bytesArray
Java.use("java.util.Arrays").toString.overload('[B').implementation = function(x){
var result = this.toString(x)
var bytesArray = JSON.stringify(x)
console.log("x,result",x,result)
return result;
}
})
}
setImmediate(main)
map解析
Java.choose("com.r0ysue.a0526printout.MainActivity",{
onMatch:function(instance){
//这里接收一个map对象
var map_1 = instance.get_map_instance()
var result = "";
var keyset = map_1.keySet();
var it = keyset.iterator();
while(it.hasNext()){
var keystr = it.next().toString();
var valuestr = map_1.get(keystr).toString();
var map = keystr+":"+valuestr+"\n";
result +=map
}
console.log(result);
},
onComplete:function(){
console.log("end onComplete!")
}
})
2.调用hashmap自带的toString()
3.用Gson
4.构造Java参数
创建array类型
var charArray = Java.array('char', ['锄','禾','日','当','午'])
var intArray = Java.array('int', [100,200,300,400,500])
创建Java字符串
function main(){
Java.perform(function(){
Java.use("java.util.Arrays").toString.overload('[C').implementation = function(x){
var charArray = Java.array('char', ['锄','禾','日','当','午'])
var result = this.toString(charArray);
console.log(JSON.stringify(charArray),"-------------",result)
return Java.use('java.lang.String').$new("构造字符串返回")
}
})
}
setImmediate(main)
创建 类 实例对象
function main(){
Java.perform(function(){
var Waterhandle = null;
Java.choose("com.r0ysue.a0526printout.Water",{
onMatch:function(instance){
console.log("this is Water instance:",instance);
//Water对象调用 still方法~ 参数是自身实例对象
console.log("Water Call still:",instance.still(instance));
//保存实例对象
Waterhandle = instance;
},onComplete:function(){console.log("")}
})
})
}
setImmediate(main)
Java类型的强制转换,向上向下转型
//向下转~ 具体参考父类转子类
//实例对象 要转成什么
var JuiceHandle = Java.cast(Waterhandle,Java.use("com.r0ysue.a0526printout.Juice"));
//调用方法
console.log("Juice Call fillEnergy",JuiceHandle.fillEnergy())
Java类型强制转换
var Juicehandle = null;
Java.choose("com.r0ysue.a0526printout.Juice",{
onMatch:function(instance){
Juicehandle = instance;
},onComplete:function(){console.log("end onComplete!!!!!!!")}
})
//实例对象 要转成什么
var Waterhandle = Java.cast(Juicehandle,Java.use("com.r0ysue.a0526printout.Water"))
//调用方法
console.log("this is Waterhandle Call still :",Waterhandle.still(Waterhandle))
创建一个类 并 实现一个接口
function main(){
Java.perform(function(){
//beer类
//注册类
const beer = Java.registerClass({
//类名
name: 'com.r0ysue.a0526printout.beer',
//接口列表
implements: [Java.use("com.r0ysue.a0526printout.liquid")],
//方法
methods: {
//实现接口中的方法
flow(){
console.log("this is a beer!!")
return "beer!!"
}
}
});
//实例化要$new()
一下 ,用对象调用方法
console.log(beer.$new().flow())
})
}
setImmediate(main)
用frida 创建一个线程
var JavaRunnable = Java.use("java.lang.Runnable");
var JavaMethod = Java.use("java.lang.reflect.Method");
var TestRunnable = Java.registerClass({
name:"com.ingeek.TestRunnable",
implements:[JavaRunnable],
fields:{
methodObject:'java.lang.reflect.Method',
methodInvoke:'java.lang.Object',
methodArgs:'[Ljava.lang.Object;'
},
methods:{
$init:[{
returnType:"void",
argumentTypes:["java.lang.reflect.Method","java.lang.Object","[Ljava.lang.Object;"],
implementation:function(methodObj,methodInv,methodAs){
this.methodObject = methodObj;
this.wethodInvoke = methodInv;
this.methodArgs = methodAs;
console.log("TestRunnable cons is called!");
}
}],
run:[{
return Type: 'void',
implementation:function(){
try{
Java.cast(this.methodObject,JavaMethod).invoke(this.methodInvoke,this.methodArgs);
} catch (e){
console.log("TestRunnable run error!",e);
}
console.log("TestRunnable run is called!");
}
}]
}
})
hook枚举
//枚举类名 可以把枚举当做类,获取他的实例对象
Java.choose("com.r0ysue.a0526printout.Signal",{
//instance为实例对象(如果在内存中加载过就会hook到)
onMatch:function(instance){
console.log(instance)
console.log("getDeclaringClass:",instance.getDeclaringClass())
},onComplete:function(){
console.log("end onComplete")
}
})
关于枚举大佬笔记
枚举 Map
Java.choose("java.util.HashMap",{
onMatch:function(instance){
if(instance.toString().indexOf("ISBN")!=-1){
console.log(instance)
}
},
onComplete:function(){
console.log("end!!!!")
}
})
Hook Map.put()方法
注意~ 要在类的初始化的时候就要hook ~ 如果类已经生成在hook是没有用的!
Java.use("java.util.HashMap").put.implementation = function(arg1,arg2){
var result = this.put(arg1,arg2)
console.log("arg1,arg2,result:",arg1,arg2,result);
return result
}
Non-ASCII
比如说
int ֏(int x) {
return x + 100;
}
甚至有一些不可视, 所以可以先编码打印出来, 再用编码后的字符串去 hook.
Java.perform(
function x() {
var targetClass = "com.example.hooktest.MainActivity";
var hookCls = Java.use(targetClass);
var methods = hookCls.class.getDeclaredMethods();
for (var i in methods) {
console.log(methods[i].toString());
console.log(encodeURIComponent(methods[i].toString().replace(/^.*?\.([^\s\.\(\)]+)\(.*?$/, "$1")));
}
hookCls[decodeURIComponent("%D6%8F")]
.implementation = function (x) {
console.log("original call: fun(" + x + ")");
var result = this[decodeURIComponent("%D6%8F")](900);
return result;
}
}
)