frida-java-bridge 6.2.6 → 6.3.0
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/lib/android.js +3 -1
- package/lib/class-factory.js +32 -17
- package/lib/env.js +2 -0
- package/lib/types.js +19 -2
- package/package.json +1 -1
package/lib/android.js
CHANGED
|
@@ -483,6 +483,7 @@ function _getApi () {
|
|
|
483
483
|
|
|
484
484
|
temporaryApi.artQuickGenericJniTrampoline = getArtQuickEntrypointFromTrampoline(quickGenericJniTrampoline, vm);
|
|
485
485
|
temporaryApi.artQuickToInterpreterBridge = getArtQuickEntrypointFromTrampoline(quickToInterpreterBridgeTrampoline, vm);
|
|
486
|
+
temporaryApi.artQuickResolutionTrampoline = getArtQuickEntrypointFromTrampoline(quickResolutionTrampoline, vm);
|
|
486
487
|
|
|
487
488
|
if (temporaryApi['art::JavaVMExt::AddGlobalRef'] === undefined) {
|
|
488
489
|
temporaryApi['art::JavaVMExt::AddGlobalRef'] = makeAddGlobalRefFallbackForAndroid5(temporaryApi);
|
|
@@ -1825,7 +1826,8 @@ function instrumentArtQuickEntrypoints (vm) {
|
|
|
1825
1826
|
// Entrypoints that dispatch method invocation from the quick ABI.
|
|
1826
1827
|
const quickEntrypoints = [
|
|
1827
1828
|
api.artQuickGenericJniTrampoline,
|
|
1828
|
-
api.artQuickToInterpreterBridge
|
|
1829
|
+
api.artQuickToInterpreterBridge,
|
|
1830
|
+
api.artQuickResolutionTrampoline
|
|
1829
1831
|
];
|
|
1830
1832
|
|
|
1831
1833
|
quickEntrypoints.forEach(entrypoint => {
|
package/lib/class-factory.js
CHANGED
|
@@ -1318,37 +1318,52 @@ function makeSuperHandleGetter (classWrapper) {
|
|
|
1318
1318
|
function makeConstructor (classHandle, classWrapper, env) {
|
|
1319
1319
|
const { $n: className, $f: factory } = classWrapper;
|
|
1320
1320
|
const methodName = basename(className);
|
|
1321
|
+
const Class = env.javaLangClass();
|
|
1321
1322
|
const Constructor = env.javaLangReflectConstructor();
|
|
1322
1323
|
const invokeObjectMethodNoArgs = env.vaMethod('pointer', []);
|
|
1324
|
+
const invokeUInt8MethodNoArgs = env.vaMethod('uint8', []);
|
|
1323
1325
|
|
|
1324
1326
|
const jsCtorMethods = [];
|
|
1325
1327
|
const jsInitMethods = [];
|
|
1326
1328
|
const jsRetType = factory._getType(className, false);
|
|
1327
1329
|
const jsVoidType = factory._getType('void', false);
|
|
1328
1330
|
|
|
1329
|
-
const constructors = invokeObjectMethodNoArgs(env.handle, classHandle,
|
|
1331
|
+
const constructors = invokeObjectMethodNoArgs(env.handle, classHandle, Class.getDeclaredConstructors);
|
|
1330
1332
|
try {
|
|
1331
1333
|
const n = env.getArrayLength(constructors);
|
|
1332
1334
|
|
|
1333
|
-
|
|
1334
|
-
let
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1335
|
+
if (n !== 0) {
|
|
1336
|
+
for (let i = 0; i !== n; i++) {
|
|
1337
|
+
let methodId, types;
|
|
1338
|
+
const constructor = env.getObjectArrayElement(constructors, i);
|
|
1339
|
+
try {
|
|
1340
|
+
methodId = env.fromReflectedMethod(constructor);
|
|
1341
|
+
types = invokeObjectMethodNoArgs(env.handle, constructor, Constructor.getGenericParameterTypes);
|
|
1342
|
+
} finally {
|
|
1343
|
+
env.deleteLocalRef(constructor);
|
|
1344
|
+
}
|
|
1342
1345
|
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1346
|
+
let jsArgTypes;
|
|
1347
|
+
try {
|
|
1348
|
+
jsArgTypes = readTypeNames(env, types).map(name => factory._getType(name));
|
|
1349
|
+
} finally {
|
|
1350
|
+
env.deleteLocalRef(types);
|
|
1351
|
+
}
|
|
1352
|
+
|
|
1353
|
+
jsCtorMethods.push(makeMethod(methodName, classWrapper, CONSTRUCTOR_METHOD, methodId, jsRetType, jsArgTypes, env));
|
|
1354
|
+
jsInitMethods.push(makeMethod(methodName, classWrapper, INSTANCE_METHOD, methodId, jsVoidType, jsArgTypes, env));
|
|
1355
|
+
}
|
|
1356
|
+
} else {
|
|
1357
|
+
const isInterface = invokeUInt8MethodNoArgs(env.handle, classHandle, Class.isInterface);
|
|
1358
|
+
if (isInterface) {
|
|
1359
|
+
throw new Error('cannot instantiate an interface');
|
|
1348
1360
|
}
|
|
1349
1361
|
|
|
1350
|
-
|
|
1351
|
-
|
|
1362
|
+
const defaultClass = env.javaLangObject();
|
|
1363
|
+
const defaultConstructor = env.getMethodId(defaultClass, '<init>', '()V');
|
|
1364
|
+
|
|
1365
|
+
jsCtorMethods.push(makeMethod(methodName, classWrapper, CONSTRUCTOR_METHOD, defaultConstructor, jsRetType, [], env));
|
|
1366
|
+
jsInitMethods.push(makeMethod(methodName, classWrapper, INSTANCE_METHOD, defaultConstructor, jsVoidType, [], env));
|
|
1352
1367
|
}
|
|
1353
1368
|
} finally {
|
|
1354
1369
|
env.deleteLocalRef(constructors);
|
package/lib/env.js
CHANGED
|
@@ -667,6 +667,7 @@ Env.prototype.javaLangClass = function () {
|
|
|
667
667
|
getDeclaredFields: get('getDeclaredFields', '()[Ljava/lang/reflect/Field;'),
|
|
668
668
|
isArray: get('isArray', '()Z'),
|
|
669
669
|
isPrimitive: get('isPrimitive', '()Z'),
|
|
670
|
+
isInterface: get('isInterface', '()Z'),
|
|
670
671
|
getComponentType: get('getComponentType', '()Ljava/lang/Class;')
|
|
671
672
|
};
|
|
672
673
|
} finally {
|
|
@@ -683,6 +684,7 @@ Env.prototype.javaLangObject = function () {
|
|
|
683
684
|
try {
|
|
684
685
|
const get = this.getMethodId.bind(this, handle);
|
|
685
686
|
javaLangObject = {
|
|
687
|
+
handle: register(this.newGlobalRef(handle)),
|
|
686
688
|
toString: get('toString', '()Ljava/lang/String;'),
|
|
687
689
|
getClass: get('getClass', '()Ljava/lang/Class;')
|
|
688
690
|
};
|
package/lib/types.js
CHANGED
|
@@ -233,6 +233,8 @@ const primitiveTypes = {
|
|
|
233
233
|
}
|
|
234
234
|
};
|
|
235
235
|
|
|
236
|
+
const primitiveTypesNames = new Set(Object.values(primitiveTypes).map(t => t.name));
|
|
237
|
+
|
|
236
238
|
function getPrimitiveType (name) {
|
|
237
239
|
const result = primitiveTypes[name];
|
|
238
240
|
return (result !== undefined) ? result : null;
|
|
@@ -436,10 +438,27 @@ function getArrayType (typeName, unbox, factory) {
|
|
|
436
438
|
let elementTypeName = typeName.substring(1);
|
|
437
439
|
const elementType = getType(elementTypeName, unbox, factory);
|
|
438
440
|
|
|
441
|
+
let numInternalArrays = 0;
|
|
442
|
+
const end = elementTypeName.length;
|
|
443
|
+
while (numInternalArrays !== end && elementTypeName[numInternalArrays] === '[') {
|
|
444
|
+
numInternalArrays++;
|
|
445
|
+
}
|
|
446
|
+
elementTypeName = elementTypeName.substring(numInternalArrays);
|
|
447
|
+
|
|
439
448
|
if (elementTypeName[0] === 'L' && elementTypeName[elementTypeName.length - 1] === ';') {
|
|
440
449
|
elementTypeName = elementTypeName.substring(1, elementTypeName.length - 1);
|
|
441
450
|
}
|
|
442
451
|
|
|
452
|
+
// The type name we get is not always the correct representation of the type so we make it so here.
|
|
453
|
+
let internalElementTypeName = elementTypeName.replace(/\./g, '/');
|
|
454
|
+
if (primitiveTypesNames.has(internalElementTypeName)) {
|
|
455
|
+
internalElementTypeName = '['.repeat(numInternalArrays) + internalElementTypeName;
|
|
456
|
+
} else {
|
|
457
|
+
internalElementTypeName = '['.repeat(numInternalArrays) + 'L' + internalElementTypeName + ';';
|
|
458
|
+
}
|
|
459
|
+
const internalTypeName = '[' + internalElementTypeName;
|
|
460
|
+
elementTypeName = '['.repeat(numInternalArrays) + elementTypeName;
|
|
461
|
+
|
|
443
462
|
return {
|
|
444
463
|
name: typeName.replace(/\./g, '/'),
|
|
445
464
|
type: 'pointer',
|
|
@@ -476,8 +495,6 @@ function getArrayType (typeName, unbox, factory) {
|
|
|
476
495
|
}
|
|
477
496
|
}
|
|
478
497
|
|
|
479
|
-
// The type name we get is not always the correct representation of the type so we make it so here.
|
|
480
|
-
const internalTypeName = '[L' + elementTypeName.replace(/\./g, '/') + ';';
|
|
481
498
|
try {
|
|
482
499
|
result.$w = factory.cast(arr, factory.use(internalTypeName), owned);
|
|
483
500
|
} catch (e) {
|