frida-java-bridge 6.3.9 → 7.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/index.d.ts +779 -0
- package/index.js +13 -13
- package/lib/alloc.js +1 -3
- package/lib/android.js +52 -77
- package/lib/api.js +5 -3
- package/lib/class-factory.js +15 -17
- package/lib/class-model.js +10 -13
- package/lib/env.js +1 -3
- package/lib/jvm.js +28 -25
- package/lib/jvmti.js +4 -10
- package/lib/lru.js +1 -3
- package/lib/machine-code.js +1 -5
- package/lib/memoize.js +1 -3
- package/lib/mkdex.js +4 -4
- package/lib/result.js +2 -7
- package/lib/types.js +6 -14
- package/lib/vm.js +3 -7
- package/package.json +8 -10
package/lib/jvm.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
|
|
1
|
+
import {
|
|
2
2
|
jvmtiVersion,
|
|
3
3
|
jvmtiCapabilities,
|
|
4
4
|
EnvJvmti
|
|
5
|
-
}
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
5
|
+
} from './jvmti.js';
|
|
6
|
+
import { parseInstructionsAt } from './machine-code.js';
|
|
7
|
+
import memoize from './memoize.js';
|
|
8
|
+
import { checkJniResult } from './result.js';
|
|
9
|
+
import VM from './vm.js';
|
|
10
10
|
|
|
11
11
|
const jsizeSize = 4;
|
|
12
12
|
const { pointerSize } = Process;
|
|
@@ -31,7 +31,7 @@ let manglersScheduled = false;
|
|
|
31
31
|
const replaceManglers = new Map();
|
|
32
32
|
const revertManglers = new Map();
|
|
33
33
|
|
|
34
|
-
function getApi () {
|
|
34
|
+
export function getApi () {
|
|
35
35
|
if (cachedApi === null) {
|
|
36
36
|
cachedApi = _getApi();
|
|
37
37
|
}
|
|
@@ -53,7 +53,7 @@ function _getApi () {
|
|
|
53
53
|
|
|
54
54
|
const pending = Process.platform === 'windows'
|
|
55
55
|
? [{
|
|
56
|
-
module: vmModule
|
|
56
|
+
module: vmModule,
|
|
57
57
|
functions: {
|
|
58
58
|
JNI_GetCreatedJavaVMs: ['JNI_GetCreatedJavaVMs', 'int', ['pointer', 'int', 'pointer']],
|
|
59
59
|
JVM_Sleep: ['JVM_Sleep', 'void', ['pointer', 'pointer', 'long']],
|
|
@@ -94,7 +94,7 @@ function _getApi () {
|
|
|
94
94
|
}]
|
|
95
95
|
// If platform is not Windows
|
|
96
96
|
: [{
|
|
97
|
-
module: vmModule
|
|
97
|
+
module: vmModule,
|
|
98
98
|
functions: {
|
|
99
99
|
JNI_GetCreatedJavaVMs: ['JNI_GetCreatedJavaVMs', 'int', ['pointer', 'int', 'pointer']],
|
|
100
100
|
|
|
@@ -105,6 +105,7 @@ function _getApi () {
|
|
|
105
105
|
_ZN6Method24restore_unshareable_infoEP10JavaThread: ['Method::restore_unshareable_info', 'void', ['pointer', 'pointer']],
|
|
106
106
|
// JDK < 17
|
|
107
107
|
_ZN6Method24restore_unshareable_infoEP6Thread: ['Method::restore_unshareable_info', 'void', ['pointer', 'pointer']],
|
|
108
|
+
_ZN6Method11link_methodERK12methodHandleP10JavaThread: ['Method::link_method', 'void', ['pointer', 'pointer', 'pointer']],
|
|
108
109
|
_ZN6Method10jmethod_idEv: ['Method::jmethod_id', 'pointer', ['pointer']],
|
|
109
110
|
_ZN6Method10clear_codeEv: function (address) {
|
|
110
111
|
const clearCode = new NativeFunction(address, 'void', ['pointer'], nativeFunctionOptions);
|
|
@@ -236,6 +237,7 @@ function _getApi () {
|
|
|
236
237
|
optionals: [
|
|
237
238
|
'_ZN6Method24restore_unshareable_infoEP10JavaThread',
|
|
238
239
|
'_ZN6Method24restore_unshareable_infoEP6Thread',
|
|
240
|
+
'_ZN6Method11link_methodERK12methodHandleP10JavaThread',
|
|
239
241
|
'_ZN6Method10clear_codeEv',
|
|
240
242
|
'_ZN6Method10clear_codeEb',
|
|
241
243
|
|
|
@@ -275,19 +277,18 @@ function _getApi () {
|
|
|
275
277
|
const missing = [];
|
|
276
278
|
|
|
277
279
|
pending.forEach(function (api) {
|
|
280
|
+
const module = api.module;
|
|
278
281
|
const functions = api.functions || {};
|
|
279
282
|
const variables = api.variables || {};
|
|
280
283
|
const optionals = new Set(api.optionals || []);
|
|
281
284
|
|
|
282
|
-
const tmp =
|
|
283
|
-
.enumerateExports(api.module)
|
|
285
|
+
const tmp = module.enumerateExports()
|
|
284
286
|
.reduce(function (result, exp) {
|
|
285
287
|
result[exp.name] = exp;
|
|
286
288
|
return result;
|
|
287
289
|
}, {});
|
|
288
290
|
|
|
289
|
-
const exportByName =
|
|
290
|
-
.enumerateSymbols(api.module)
|
|
291
|
+
const exportByName = module.enumerateSymbols()
|
|
291
292
|
.reduce(function (result, exp) {
|
|
292
293
|
result[exp.name] = exp;
|
|
293
294
|
return result;
|
|
@@ -348,7 +349,7 @@ function _getApi () {
|
|
|
348
349
|
};
|
|
349
350
|
|
|
350
351
|
for (const [name, [rawName, retType, argTypes]] of Object.entries(allocatorFunctions)) {
|
|
351
|
-
let address = Module.
|
|
352
|
+
let address = Module.findGlobalExportByName(rawName);
|
|
352
353
|
if (address === null) {
|
|
353
354
|
address = DebugSymbol.fromName(rawName).address;
|
|
354
355
|
if (address.isNull()) {
|
|
@@ -398,7 +399,7 @@ function makeThreadFromJniHelper (api) {
|
|
|
398
399
|
if (tryParse !== undefined) {
|
|
399
400
|
const vm = new VM(api);
|
|
400
401
|
const findClassImpl = vm.perform(env => env.handle.readPointer().add(6 * pointerSize).readPointer());
|
|
401
|
-
offset = parseInstructionsAt(findClassImpl, tryParse, { limit:
|
|
402
|
+
offset = parseInstructionsAt(findClassImpl, tryParse, { limit: 11 });
|
|
402
403
|
}
|
|
403
404
|
|
|
404
405
|
if (offset === null) {
|
|
@@ -425,7 +426,7 @@ function parseX64ThreadOffset (insn) {
|
|
|
425
426
|
return disp;
|
|
426
427
|
}
|
|
427
428
|
|
|
428
|
-
function ensureClassInitialized (env, classRef) {
|
|
429
|
+
export function ensureClassInitialized (env, classRef) {
|
|
429
430
|
}
|
|
430
431
|
|
|
431
432
|
class JvmMethodMangler {
|
|
@@ -663,7 +664,7 @@ function _getJvmThreadSpec () {
|
|
|
663
664
|
};
|
|
664
665
|
}
|
|
665
666
|
|
|
666
|
-
function makeMethodMangler (methodId) {
|
|
667
|
+
export function makeMethodMangler (methodId) {
|
|
667
668
|
return new JvmMethodMangler(methodId);
|
|
668
669
|
}
|
|
669
670
|
|
|
@@ -758,6 +759,15 @@ function nativeJvmMethod (method, impl, thread) {
|
|
|
758
759
|
|
|
759
760
|
api['Method::restore_unshareable_info'](newMethod.method, thread);
|
|
760
761
|
|
|
762
|
+
if (api.version >= 17) {
|
|
763
|
+
// Only certain JDK versions of restore_unshareable_info() call
|
|
764
|
+
// link_method(). Manually call if necessary.
|
|
765
|
+
const methodHandle = Memory.alloc(2 * pointerSize);
|
|
766
|
+
methodHandle.writePointer(newMethod.method);
|
|
767
|
+
methodHandle.add(pointerSize).writePointer(thread);
|
|
768
|
+
api['Method::link_method'](newMethod.method, methodHandle, thread);
|
|
769
|
+
}
|
|
770
|
+
|
|
761
771
|
return newMethod;
|
|
762
772
|
}
|
|
763
773
|
|
|
@@ -974,12 +984,5 @@ function parseX64VTableOffset (insn) {
|
|
|
974
984
|
return defaultVtableIndicesOffset + 16;
|
|
975
985
|
}
|
|
976
986
|
|
|
977
|
-
function deoptimizeEverything (vm, env) {
|
|
987
|
+
export function deoptimizeEverything (vm, env) {
|
|
978
988
|
}
|
|
979
|
-
|
|
980
|
-
module.exports = {
|
|
981
|
-
getApi,
|
|
982
|
-
ensureClassInitialized,
|
|
983
|
-
makeMethodMangler,
|
|
984
|
-
deoptimizeEverything
|
|
985
|
-
};
|
package/lib/jvmti.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
|
|
1
|
+
import { checkJniResult } from './result.js';
|
|
2
2
|
|
|
3
|
-
const jvmtiVersion = {
|
|
3
|
+
export const jvmtiVersion = {
|
|
4
4
|
v1_0: 0x30010000,
|
|
5
5
|
v1_2: 0x30010200
|
|
6
6
|
};
|
|
7
7
|
|
|
8
|
-
const jvmtiCapabilities = {
|
|
8
|
+
export const jvmtiCapabilities = {
|
|
9
9
|
canTagObjects: 1
|
|
10
10
|
};
|
|
11
11
|
|
|
@@ -14,7 +14,7 @@ const nativeFunctionOptions = {
|
|
|
14
14
|
exceptions: 'propagate'
|
|
15
15
|
};
|
|
16
16
|
|
|
17
|
-
function EnvJvmti (handle, vm) {
|
|
17
|
+
export function EnvJvmti (handle, vm) {
|
|
18
18
|
this.handle = handle;
|
|
19
19
|
this.vm = vm;
|
|
20
20
|
this.vtable = handle.readPointer();
|
|
@@ -54,9 +54,3 @@ function proxy (offset, retType, argTypes, wrapper) {
|
|
|
54
54
|
return wrapper.apply(this, args);
|
|
55
55
|
};
|
|
56
56
|
}
|
|
57
|
-
|
|
58
|
-
module.exports = {
|
|
59
|
-
jvmtiVersion,
|
|
60
|
-
jvmtiCapabilities,
|
|
61
|
-
EnvJvmti
|
|
62
|
-
};
|
package/lib/lru.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// Based on https://stackoverflow.com/a/46432113
|
|
2
2
|
|
|
3
|
-
class LRU {
|
|
3
|
+
export default class LRU {
|
|
4
4
|
constructor (capacity, destroy) {
|
|
5
5
|
this.items = new Map();
|
|
6
6
|
this.capacity = capacity;
|
|
@@ -42,5 +42,3 @@ class LRU {
|
|
|
42
42
|
items.set(key, val);
|
|
43
43
|
}
|
|
44
44
|
}
|
|
45
|
-
|
|
46
|
-
module.exports = LRU;
|
package/lib/machine-code.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
function parseInstructionsAt (address, tryParse, { limit }) {
|
|
1
|
+
export function parseInstructionsAt (address, tryParse, { limit }) {
|
|
2
2
|
let cursor = address;
|
|
3
3
|
let prevInsn = null;
|
|
4
4
|
|
|
@@ -16,7 +16,3 @@ function parseInstructionsAt (address, tryParse, { limit }) {
|
|
|
16
16
|
|
|
17
17
|
return null;
|
|
18
18
|
}
|
|
19
|
-
|
|
20
|
-
module.exports = {
|
|
21
|
-
parseInstructionsAt
|
|
22
|
-
};
|
package/lib/memoize.js
CHANGED
package/lib/mkdex.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
import { Buffer } from 'buffer';
|
|
2
2
|
|
|
3
3
|
const kAccPublic = 0x0001;
|
|
4
4
|
const kAccNative = 0x0100;
|
|
@@ -430,9 +430,9 @@ class DexBuilder {
|
|
|
430
430
|
dex.writeUInt32LE(offset, itemOffset + 8);
|
|
431
431
|
});
|
|
432
432
|
|
|
433
|
-
const hash = new
|
|
433
|
+
const hash = new Checksum('sha1');
|
|
434
434
|
hash.update(dex.slice(signatureOffset + signatureSize));
|
|
435
|
-
Buffer.from(hash.
|
|
435
|
+
Buffer.from(hash.getDigest()).copy(dex, signatureOffset);
|
|
436
436
|
|
|
437
437
|
dex.writeUInt32LE(adler32(dex, signatureOffset), checksumOffset);
|
|
438
438
|
|
|
@@ -930,4 +930,4 @@ function adler32 (buffer, offset) {
|
|
|
930
930
|
return ((b << 16) | a) >>> 0;
|
|
931
931
|
}
|
|
932
932
|
|
|
933
|
-
|
|
933
|
+
export default mkdex;
|
package/lib/result.js
CHANGED
|
@@ -1,12 +1,7 @@
|
|
|
1
|
-
const JNI_OK = 0;
|
|
1
|
+
export const JNI_OK = 0;
|
|
2
2
|
|
|
3
|
-
function checkJniResult (name, result) {
|
|
3
|
+
export function checkJniResult (name, result) {
|
|
4
4
|
if (result !== JNI_OK) {
|
|
5
5
|
throw new Error(name + ' failed: ' + result);
|
|
6
6
|
}
|
|
7
7
|
}
|
|
8
|
-
|
|
9
|
-
module.exports = {
|
|
10
|
-
checkJniResult,
|
|
11
|
-
JNI_OK: 0
|
|
12
|
-
};
|
package/lib/types.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
import Env from './env.js';
|
|
2
2
|
|
|
3
3
|
const JNILocalRefType = 1;
|
|
4
4
|
|
|
@@ -6,7 +6,7 @@ let vm = null;
|
|
|
6
6
|
|
|
7
7
|
let primitiveArrayHandler = null;
|
|
8
8
|
|
|
9
|
-
function initialize (_vm) {
|
|
9
|
+
export function initialize (_vm) {
|
|
10
10
|
vm = _vm;
|
|
11
11
|
}
|
|
12
12
|
|
|
@@ -14,7 +14,7 @@ function initialize (_vm) {
|
|
|
14
14
|
* http://docs.oracle.com/javase/6/docs/technotes/guides/jni/spec/types.html#wp9502
|
|
15
15
|
* http://www.liaohuqiu.net/posts/android-object-size-dalvik/
|
|
16
16
|
*/
|
|
17
|
-
function getType (typeName, unbox, factory) {
|
|
17
|
+
export function getType (typeName, unbox, factory) {
|
|
18
18
|
let type = getPrimitiveType(typeName);
|
|
19
19
|
if (type === null) {
|
|
20
20
|
if (typeName.indexOf('[') === 0) {
|
|
@@ -235,7 +235,7 @@ const primitiveTypes = {
|
|
|
235
235
|
|
|
236
236
|
const primitiveTypesNames = new Set(Object.values(primitiveTypes).map(t => t.name));
|
|
237
237
|
|
|
238
|
-
function getPrimitiveType (name) {
|
|
238
|
+
export function getPrimitiveType (name) {
|
|
239
239
|
const result = primitiveTypes[name];
|
|
240
240
|
return (result !== undefined) ? result : null;
|
|
241
241
|
}
|
|
@@ -425,7 +425,7 @@ function makePrimitiveArrayType (shorty, name) {
|
|
|
425
425
|
};
|
|
426
426
|
}
|
|
427
427
|
|
|
428
|
-
function getArrayType (typeName, unbox, factory) {
|
|
428
|
+
export function getArrayType (typeName, unbox, factory) {
|
|
429
429
|
const primitiveType = primitiveArrayTypes[typeName];
|
|
430
430
|
if (primitiveType !== undefined) {
|
|
431
431
|
return primitiveType;
|
|
@@ -789,7 +789,7 @@ Object.defineProperties(PrimitiveArray.prototype, {
|
|
|
789
789
|
}
|
|
790
790
|
});
|
|
791
791
|
|
|
792
|
-
function makeJniObjectTypeName (typeName) {
|
|
792
|
+
export function makeJniObjectTypeName (typeName) {
|
|
793
793
|
return 'L' + typeName.replace(/\./g, '/') + ';';
|
|
794
794
|
}
|
|
795
795
|
|
|
@@ -800,11 +800,3 @@ function toTitleCase (str) {
|
|
|
800
800
|
function identity (value) {
|
|
801
801
|
return value;
|
|
802
802
|
}
|
|
803
|
-
|
|
804
|
-
module.exports = {
|
|
805
|
-
initialize,
|
|
806
|
-
getType,
|
|
807
|
-
getPrimitiveType,
|
|
808
|
-
getArrayType,
|
|
809
|
-
makeJniObjectTypeName
|
|
810
|
-
};
|
package/lib/vm.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
import Env from './env.js';
|
|
2
|
+
import { JNI_OK, checkJniResult } from './result.js';
|
|
3
3
|
|
|
4
4
|
const JNI_VERSION_1_6 = 0x00010006;
|
|
5
5
|
|
|
@@ -9,7 +9,7 @@ const jsThreadID = Process.getCurrentThreadId();
|
|
|
9
9
|
const attachedThreads = new Map();
|
|
10
10
|
const activeEnvs = new Map();
|
|
11
11
|
|
|
12
|
-
function VM (api) {
|
|
12
|
+
export default function VM (api) {
|
|
13
13
|
const handle = api.vm;
|
|
14
14
|
let attachCurrentThread = null;
|
|
15
15
|
let detachCurrentThread = null;
|
|
@@ -166,7 +166,3 @@ VM.dispose = function (vm) {
|
|
|
166
166
|
vm.detachCurrentThread();
|
|
167
167
|
}
|
|
168
168
|
};
|
|
169
|
-
|
|
170
|
-
module.exports = VM;
|
|
171
|
-
|
|
172
|
-
/* global Memory, NativeFunction, NULL, Process */
|
package/package.json
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "frida-java-bridge",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "7.0.1",
|
|
4
4
|
"description": "Java runtime interop from Frida",
|
|
5
|
+
"type": "module",
|
|
5
6
|
"main": "index.js",
|
|
6
7
|
"files": [
|
|
7
8
|
"/index.js",
|
|
9
|
+
"/index.d.ts",
|
|
8
10
|
"/lib/**/*.js",
|
|
9
11
|
"/lib/**/*.d.ts"
|
|
10
12
|
],
|
|
@@ -21,15 +23,11 @@
|
|
|
21
23
|
"lint": "eslint lib",
|
|
22
24
|
"fix": "eslint --fix lib"
|
|
23
25
|
},
|
|
24
|
-
"dependencies": {
|
|
25
|
-
"jssha": "^3.1.2"
|
|
26
|
-
},
|
|
27
26
|
"devDependencies": {
|
|
28
|
-
"
|
|
29
|
-
"
|
|
30
|
-
"eslint
|
|
31
|
-
"eslint
|
|
32
|
-
"
|
|
33
|
-
"eslint-plugin-promise": "^6.1.1"
|
|
27
|
+
"@types/frida-gum": "^18.7.2",
|
|
28
|
+
"frida-compile": "^16.4.1",
|
|
29
|
+
"@eslint/js": "^9.20.0",
|
|
30
|
+
"eslint": "^9.20.0",
|
|
31
|
+
"neostandard": "^0.12.1"
|
|
34
32
|
}
|
|
35
33
|
}
|