原文链接: https://frida.re/docs/javascript-api/#java
欢迎加入 Frida 交流群: 1049977261
Java
Java.available
: 一个指明当前进程是否有 Java 虚拟机 ( Dalvik 或 ART ) 被加载的布尔值.
请不要在这个值为 false 时调用其他任何的Java
属性或方法.Java.androidVersion
: 一个指明了当前运行环境的 Android 版本字符串.-
Java.enumerateLoadedClasses(callbacks)
:
列举当前已加载的类,callbacks
是一个包含以下方法的对象:onMatch: function (name, handle)
:
对于已加载的每一个类调用一次,name
可用于传递给use()
来获得一个 JavaScript 包裹对象. 您也可以对handle
进行Java.cast()
来转换成java.lang.Class
.onComplete: function ()
: 当所有的类都列举完时被调用.
Java.enumerateLoadedClassesSync()
:
enumerateLoadedClasses()
的同步版本, 返回一个包含类名的数组.-
Java.enumerateClassLoaders(callbacks)
:
列举当前 Java 虚拟机中存在的类加载器,callbacks
是一个包含以下方法的对象:onMatch: function (loader)
:
对于每一个类加载器调用一次,loader
是特定java.lang.ClassLoader
的包裹对象.onComplete: function ()
: 当所有的类加载器都列举完时被调用.
您必须将一个加载器传递给
Java.ClassFactory.get()
以便能够对特定加载器中的类进行Java.use()
. Java.enumerateClassLoadersSync()
:
enumerateClassLoaders()
的同步版本, 返回一个类加载器的数组.Java.scheduleOnMainThread(fn)
: 在虚拟机的主线程上运行fn
.Java.perform(fn)
:
确保当前线程已附加到虚拟机并调用fn
. (这在 Java 的回调中是不必要的.)
如果应用的类加载器不可用时, 将会延时调用fn
.
如果不需要接触应用中的类, 则可以使用Java.performNow()
.
Java.perform(function () {
var Activity = Java.use('android.app.Activity');
Activity.onResume.implementation = function () {
send('onResume() got called! Let\'s call the original implementation');
this.onResume();
};
});
Java.performNow(fn)
:
确保当前线程已附加到虚拟机并调用fn
. (这在 Java 的回调中是不必要的.)Java.use(className)
:
动态的获得一个类className
的 JavaScript 包裹对象, 您可以通过在这个对象上调用$new()
执行它的构造器来实例化对象. 对实例调用$dispose()
来显示的清理掉它 (或者等 JavaScript 对象被垃圾回收或脚本被卸载). 静态与非静态方法都可用, 您甚至可以替换掉一个方法的实现, 并从中抛出异常:
Java.perform(function () {
var Activity = Java.use('android.app.Activity');
var Exception = Java.use('java.lang.Exception');
Activity.onResume.implementation = function () {
throw Exception.$new('Oh noes!');
};
});
默认使用应用的类加载器, 但您可以通过给
Java.classFactory.loader
赋值一个不同的加载器实例来进行自定义.
请注意, 所有的方法包裹都提供了clone(options)
API 来配合 NativeFunction 选项创造一个新的方法包裹对象.
-
Java.openClassFile(filePath)
:
打开filePath
处的 dex 文件, 返回一个包含以下方法的对象:load()
: 将包含的类加载进虚拟机.getClassNames()
: 包含的类名称的数组.
-
Java.choose(className, callbacks)
:
通过扫描 Java 栈堆来列举className
的存活实例,callbacks
是一个包含以下方法的对象:-
onMatch: function (instance)
:
对于每一个找到的存活实例instance
被调用一次.这个方法可以通过返回字符串 "stop" 来提前终止扫描.
onComplete: function ()
: 当所有的实例都被列举时调用.
-
Java.retain(obj)
:
复制 JavaScript 包裹对象obj
, 以便之后在替换方法之外使用.
Java.perform(function () {
var Activity = Java.use('android.app.Activity');
var lastActivity = null;
Activity.onResume.implementation = function () {
lastActivity = Java.retain(this);
this.onResume();
};
});
-
Java.cast(handle, klass)
:
通过将已有的实例handle
与Java.use()
返回的指定类型klass
一起创建一个新的 JavaScript 包裹对象. 这个包裹对象有一个class
属性可用于获得它的类型的包裹, 以及一个代表着它类名的$className
字符串.
var Activity = Java.use('android.app.Activity');
var activity = Java.cast(ptr('0x1234'), Activity);
-
Java.array(type, elements)
:
使用 JavaScript 的数组element
创建一个指定类型type
的 Java 数组. 返回的 Java 数组的行为与 JavaScript 数组的行为相似, 但可用于 Java API, 以便这些 API 可以修改它的内容.
var values = Java.array('int', [ 1003, 1005, 1007 ]);
var JString = Java.use('java.lang.String');
var str = JString.$new(Java.array('byte', [ 0x48, 0x65, 0x69 ]));
Java.isMainThread()
: 判断调用者是否处于主线程.-
Java.registerClass(spec)
:
创建一个新的 Java 类, 并返回它的包裹对象,spec
是一个包含以下属性的对象:-
name
: 类名字符串. -
superClass
: (可选的) 父类. 省略的话则继承自java.lang.Object
. -
implements
: (可选的) 这个类实现的接口的数组. -
fields
: (可选的) 指明了名称与类型的待公开的字段对象. -
methods
: (可选的) 指明了实现的方法.
-
var SomeBaseClass = Java.use('com.example.SomeBaseClass');
var X509TrustManager = Java.use('javax.net.ssl.X509TrustManager');
var MyTrustManager = Java.registerClass({
name: 'com.example.MyTrustManager',
implements: [X509TrustManager],
methods: {
checkClientTrusted: function (chain, authType) {
},
checkServerTrusted: function (chain, authType) {
},
getAcceptedIssuers: function () {
return [];
},
}
});
var MyWeirdTrustManager = Java.registerClass({
name: 'com.example.MyWeirdTrustManager',
superClass: SomeBaseClass,
implements: [X509TrustManager],
fields: {
description: 'java.lang.String',
limit: 'int',
},
methods: {
$init: function () {
console.log('Constructor called');
},
checkClientTrusted: function (chain, authType) {
console.log('checkClientTrusted');
},
checkServerTrusted: [{
returnType: 'void',
argumentTypes: ['[Ljava.security.cert.X509Certificate;', 'java.lang.String'],
implementation: function (chain, authType) {
console.log('checkServerTrusted A');
}
}, {
returnType: 'java.util.List',
argumentTypes: ['[Ljava.security.cert.X509Certificate;', 'java.lang.String', 'java.lang.String'],
implementation: function (chain, authType, host) {
console.log('checkServerTrusted B');
return null;
}
}],
getAcceptedIssuers: function () {
console.log('getAcceptedIssuers');
return [];
},
}
});
Java.deoptimizeEverything()
:
强制虚拟机通过解释器执行任何代码. 这在某些情况下需要阻止绕过方法钩子的优化时很有必要, 并且允许 ART 的 Instrumentation API 可用于运行时的跟踪.-
Java.vm
: 一个包含以下方法的对象:perform(fn)
:
确保当前线程已附加到虚拟机并调用fn
. (这在 Java 的回调中是不必要的.)getEnv()
:
获得当前线程的JNIEnv
对象的包裹. 如果当前线程没有附加到虚拟机上, 则抛出异常.tryGetEnv()
:
获得当前线程的JNIEnv
对象的包裹. 如果当前线程没有附加到虚拟机上, 则返回null
.
Java.classFactory
:
默认的类工厂用于实现Java.use()
等. 它使用应用的主要类加载器.-
Java.ClassFactory
: 包含以下属性与方法的类:-
get(classLoader)
:
获得指定类加载器的类工厂实例. 默认的类工厂仅与应用的主要类加载器互动. 其他的类加载器可以通过Java.enumerateClassLoaders()
来发现, 并通过这个 API 进行互动.
loader
:
当前正在被使用的类加载器的只读属性.
对于默认的类加载器, 这个值在第一次调用Java.perform()
时被更新.cacheDir
:
当前正在使用的缓存文件夹的路径字符串.
对于默认的类加载器, 这个值在第一次调用Java.perform()
时被更新.tempFileNaming
:
指明了临时文件命名规则的对象. 默认值是:{ prefix: 'frida', suffix: 'dat' }
.use(className)
:
类似于Java.use()
, 但使用指定的类加载器.openClassFile(filePath)
:
类似于Java.openClassFile()
, 但使用指定的类加载器.choose(className, callbacks)
:
类似于Java.choose()
, 但使用指定的类加载器.retain(obj)
:
类似于Java.retain()
, 但使用指定的类加载器.cast(handle, klass)
:
类似于Java.cast()
, 但使用指定的类加载器.array(type, elements)
:
类似于Java.array()
, 但使用指定的类加载器.registerClass(spec)
:
类似于Java.registerClass()
, 但使用指定的类加载器.
-
WeakRef
-
WeakRef.bind(value, fn)
:
监控value
并在value
被当做垃圾回收或者脚本被卸载时调用回调fn
.
返回一个可以传递给WeakRef.unbind()
的用于清理的 id.当你在构建一种语言时十分有用.