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 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 => {
@@ -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, env.javaLangClass().getDeclaredConstructors);
1331
+ const constructors = invokeObjectMethodNoArgs(env.handle, classHandle, Class.getDeclaredConstructors);
1330
1332
  try {
1331
1333
  const n = env.getArrayLength(constructors);
1332
1334
 
1333
- for (let i = 0; i !== n; i++) {
1334
- let methodId, types;
1335
- const constructor = env.getObjectArrayElement(constructors, i);
1336
- try {
1337
- methodId = env.fromReflectedMethod(constructor);
1338
- types = invokeObjectMethodNoArgs(env.handle, constructor, Constructor.getGenericParameterTypes);
1339
- } finally {
1340
- env.deleteLocalRef(constructor);
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
- let jsArgTypes;
1344
- try {
1345
- jsArgTypes = readTypeNames(env, types).map(name => factory._getType(name));
1346
- } finally {
1347
- env.deleteLocalRef(types);
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
- jsCtorMethods.push(makeMethod(methodName, classWrapper, CONSTRUCTOR_METHOD, methodId, jsRetType, jsArgTypes, env));
1351
- jsInitMethods.push(makeMethod(methodName, classWrapper, INSTANCE_METHOD, methodId, jsVoidType, jsArgTypes, env));
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) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "frida-java-bridge",
3
- "version": "6.2.6",
3
+ "version": "6.3.0",
4
4
  "description": "Java runtime interop from Frida",
5
5
  "main": "index.js",
6
6
  "files": [