frida-java-bridge 7.0.8 → 7.0.9

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 CHANGED
@@ -415,11 +415,25 @@ declare module "frida-java-bridge" {
415
415
  [name: string]: any;
416
416
  };
417
417
 
418
- interface MethodDispatcher<Holder extends Members<Holder> = {}> extends Method<Holder> {
418
+ type IsEmptyArray<T extends any[]> = T extends [] ? true : false;
419
+
420
+ type Overload<Identifiers extends Array<string> = [], Types extends Array<any> = [], Return = any> = [Identifiers, Types, Return];
421
+
422
+ type OverloadsMethods<
423
+ Holder extends Members<Holder> = {},
424
+ OLs extends ReadonlyArray<Overload<any, any, any>> = []
425
+ > = {
426
+ [K in keyof OLs]:
427
+ OLs[K] extends Overload<any, infer A extends any[], infer R>
428
+ ? Method<Holder, A, R>
429
+ : never
430
+ };
431
+
432
+ interface MethodDispatcher<Holder extends Members<Holder> = {}, Overloads extends Array<Overload<Array<any>, Array<any>, any>> = []> extends Method<Holder> {
419
433
  /**
420
434
  * Available overloads.
421
435
  */
422
- overloads: Array<Method<Holder>>;
436
+ overloads: IsEmptyArray<Overloads> extends true ? Array<Method<Holder>> : OverloadsMethods<Holder, Overloads>;
423
437
 
424
438
  /**
425
439
  * Obtains a specific overload.
@@ -430,8 +444,8 @@ declare module "frida-java-bridge" {
430
444
  overload(...args: string[]): Method<Holder>;
431
445
  }
432
446
 
433
- interface Method<Holder extends Members<Holder> = {}> {
434
- (...params: any[]): any;
447
+ interface Method<Holder extends Members<Holder> = {}, Params extends any[] = any[], Return = any> {
448
+ (...params: Params): Return;
435
449
 
436
450
  /**
437
451
  * Name of this method.
@@ -458,7 +472,7 @@ declare module "frida-java-bridge" {
458
472
  * replace the original implementation. Assign `null` at a future point
459
473
  * to revert back to the original implementation.
460
474
  */
461
- implementation: MethodImplementation<Holder> | null;
475
+ implementation: MethodImplementation<Holder, Params, Return> | null;
462
476
 
463
477
  /**
464
478
  * Method return type.
@@ -481,10 +495,10 @@ declare module "frida-java-bridge" {
481
495
  * Useful for e.g. setting `traps: "all"` to perform execution tracing
482
496
  * in conjunction with Stalker.
483
497
  */
484
- clone: (options: NativeFunctionOptions) => Method<Holder>;
498
+ clone: (options: NativeFunctionOptions) => Method<Holder, Params, Return>;
485
499
  }
486
500
 
487
- type MethodImplementation<This extends Members<This> = {}> = (this: Wrapper<This>, ...params: any[]) => any;
501
+ type MethodImplementation<This extends Members<This> = {}, Params extends any[] = any[], Return = any> = (this: Wrapper<This>, ...params: Params) => Return;
488
502
 
489
503
  interface Field<Value = any, Holder extends Members<Holder> = {}> {
490
504
  /**
package/lib/android.js CHANGED
@@ -88,6 +88,7 @@ const getArtThreadStateTransitionImpl = memoize(_getArtThreadStateTransitionImpl
88
88
  export const getAndroidVersion = memoize(_getAndroidVersion);
89
89
  const getAndroidCodename = memoize(_getAndroidCodename);
90
90
  export const getAndroidApiLevel = memoize(_getAndroidApiLevel);
91
+ export const getArtApexVersion = memoize(_getArtApexVersion);
91
92
  const getArtQuickFrameInfoGetterThunk = memoize(_getArtQuickFrameInfoGetterThunk);
92
93
 
93
94
  const makeCxxMethodWrapperReturningPointerByValue =
@@ -253,6 +254,7 @@ function _getApi () {
253
254
  this['art::StackVisitor::GetCurrentQuickFrameInfo'] = makeArtQuickFrameInfoGetter(address);
254
255
  },
255
256
 
257
+ _ZN3art7Context6CreateEv: ['art::Context::Create', 'pointer', []],
256
258
  _ZN3art6Thread18GetLongJumpContextEv: ['art::Thread::GetLongJumpContext', 'pointer', ['pointer']],
257
259
 
258
260
  _ZN3art6mirror5Class13GetDescriptorEPNSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEE: function (address) {
@@ -352,6 +354,7 @@ function _getApi () {
352
354
  '_ZNK3art12StackVisitor9GetMethodEv',
353
355
  '_ZNK3art12StackVisitor16DescribeLocationEv',
354
356
  '_ZNK3art12StackVisitor24GetCurrentQuickFrameInfoEv',
357
+ '_ZN3art7Context6CreateEv',
355
358
  '_ZN3art6Thread18GetLongJumpContextEv',
356
359
  '_ZN3art6mirror5Class13GetDescriptorEPNSt3__112basic_stringIcNS2_11char_traitsIcEENS2_9allocatorIcEEEE',
357
360
  '_ZN3art6mirror5Class11GetLocationEv',
@@ -461,6 +464,11 @@ function _getApi () {
461
464
  const instrumentationOffset = runtimeOffset.instrumentation;
462
465
  temporaryApi.artInstrumentation = (instrumentationOffset !== null) ? artRuntime.add(instrumentationOffset) : null;
463
466
 
467
+ const instrumentationIsPointer = getArtApexVersion() >= 360_000_000;
468
+ if (instrumentationIsPointer && temporaryApi.artInstrumentation != null) {
469
+ temporaryApi.artInstrumentation = temporaryApi.artInstrumentation.readPointer();
470
+ }
471
+
464
472
  temporaryApi.artHeap = artRuntime.add(runtimeOffset.heap).readPointer();
465
473
  temporaryApi.artThreadList = artRuntime.add(runtimeOffset.threadList).readPointer();
466
474
 
@@ -691,7 +699,11 @@ function _getArtRuntimeSpec (api) {
691
699
  throw new Error('Unable to determine Runtime field offsets');
692
700
  }
693
701
 
694
- spec.offset.instrumentation = tryDetectInstrumentationOffset(api);
702
+ const instrumentationIsPointer = getArtApexVersion() >= 360_000_000;
703
+ spec.offset.instrumentation = instrumentationIsPointer
704
+ ? tryDetectInstrumentationPointer(api)
705
+ : tryDetectInstrumentationOffset(api);
706
+
695
707
  spec.offset.jniIdsIndirection = tryDetectJniIdsIndirectionOffset(api);
696
708
 
697
709
  return spec;
@@ -771,6 +783,78 @@ function parseArm64InstrumentationOffset (insn) {
771
783
  return offset;
772
784
  }
773
785
 
786
+ const instrumentationPointerParser = {
787
+ ia32: parsex86InstrumentationPointer,
788
+ x64: parsex86InstrumentationPointer,
789
+ arm: parseArmInstrumentationPointer,
790
+ arm64: parseArm64InstrumentationPointer
791
+ };
792
+
793
+ function tryDetectInstrumentationPointer (api) {
794
+ const impl = api['art::Runtime::DeoptimizeBootImage'];
795
+ if (impl === undefined) {
796
+ return null;
797
+ }
798
+
799
+ return parseInstructionsAt(impl, instrumentationPointerParser[Process.arch], { limit: 30 });
800
+ }
801
+
802
+ function parsex86InstrumentationPointer (insn) {
803
+ if (insn.mnemonic !== 'mov') {
804
+ return null;
805
+ }
806
+
807
+ const ops = insn.operands;
808
+
809
+ const dst = ops[0];
810
+ if (dst.value !== 'rax') {
811
+ return null;
812
+ }
813
+
814
+ const src = ops[1];
815
+ if (src.type !== 'mem') {
816
+ return null;
817
+ }
818
+
819
+ const mem = src.value;
820
+ if (mem.base !== 'rdi') {
821
+ return null;
822
+ }
823
+
824
+ const offset = mem.disp;
825
+ if (offset < 0x100 || offset > 0x400) {
826
+ return null;
827
+ }
828
+ return offset;
829
+ }
830
+
831
+ function parseArmInstrumentationPointer (insn) {
832
+ return null;
833
+ }
834
+
835
+ function parseArm64InstrumentationPointer (insn) {
836
+ if (insn.mnemonic !== 'ldr') {
837
+ return null;
838
+ }
839
+
840
+ const ops = insn.operands;
841
+
842
+ if (ops[0].value === 'x0') {
843
+ return null;
844
+ }
845
+
846
+ const mem = ops[1].value;
847
+ if (mem.base !== 'x0') {
848
+ return null;
849
+ }
850
+
851
+ const offset = mem.disp;
852
+ if (offset < 0x100 || offset > 0x400) {
853
+ return null;
854
+ }
855
+ return offset;
856
+ }
857
+
774
858
  const jniIdsIndirectionOffsetParsers = {
775
859
  ia32: parsex86JniIdsIndirectionOffset,
776
860
  x64: parsex86JniIdsIndirectionOffset,
@@ -1364,6 +1448,39 @@ function _getAndroidApiLevel () {
1364
1448
  return parseInt(getAndroidSystemProperty('ro.build.version.sdk'), 10);
1365
1449
  }
1366
1450
 
1451
+ function _getArtApexVersion () {
1452
+ try {
1453
+ const mountInfo = File.readAllText('/proc/self/mountinfo');
1454
+
1455
+ let artSource = null;
1456
+ const sourceVersions = new Map();
1457
+ for (const line of mountInfo.trimEnd().split('\n')) {
1458
+ const elements = line.split(' ');
1459
+
1460
+ const mountRoot = elements[4];
1461
+ if (!mountRoot.startsWith('/apex/com.android.art')) {
1462
+ continue;
1463
+ }
1464
+
1465
+ const mountSource = elements[10];
1466
+ if (mountRoot.includes('@')) {
1467
+ sourceVersions.set(mountSource, mountRoot.split('@')[1]);
1468
+ } else {
1469
+ artSource = mountSource;
1470
+ }
1471
+ }
1472
+
1473
+ const strVersion = sourceVersions.get(artSource);
1474
+ return (strVersion !== undefined) ? parseInt(strVersion) : computeArtApexVersionFromApiLevel();
1475
+ } catch {
1476
+ return computeArtApexVersionFromApiLevel();
1477
+ }
1478
+ }
1479
+
1480
+ function computeArtApexVersionFromApiLevel () {
1481
+ return getAndroidApiLevel() * 10_000_000;
1482
+ }
1483
+
1367
1484
  let systemPropertyGet = null;
1368
1485
  const PROP_VALUE_MAX = 92;
1369
1486
 
@@ -2534,7 +2651,7 @@ extern GumTlsKey current_backtrace;
2534
2651
 
2535
2652
  extern void (* perform_art_thread_state_transition) (JNIEnv * env);
2536
2653
 
2537
- extern ArtContext * art_thread_get_long_jump_context (ArtThread * thread);
2654
+ extern ArtContext * art_make_context (ArtThread * thread);
2538
2655
 
2539
2656
  extern void art_stack_visitor_init (ArtStackVisitor * visitor, ArtThread * thread, void * context, StackWalkKind walk_kind,
2540
2657
  size_t num_frames, bool check_suspended);
@@ -2600,7 +2717,7 @@ _on_thread_state_transition_complete (ArtThread * thread)
2600
2717
  },
2601
2718
  };
2602
2719
 
2603
- context = art_thread_get_long_jump_context (thread);
2720
+ context = art_make_context (thread);
2604
2721
 
2605
2722
  art_stack_visitor_init (&visitor, thread, context, STACK_WALK_SKIP_INLINED_FRAMES, 0, true);
2606
2723
  visitor.vtable = &visitor.vtable_storage;
@@ -2885,7 +3002,7 @@ std_string_get_data (StdString * str)
2885
3002
  `, {
2886
3003
  current_backtrace: Memory.alloc(Process.pointerSize),
2887
3004
  perform_art_thread_state_transition: performImpl,
2888
- art_thread_get_long_jump_context: api['art::Thread::GetLongJumpContext'],
3005
+ art_make_context: api['art::Thread::GetLongJumpContext'] ?? api['art::Context::Create'],
2889
3006
  art_stack_visitor_init: api['art::StackVisitor::StackVisitor'],
2890
3007
  art_stack_visitor_walk_stack: api['art::StackVisitor::WalkStack'],
2891
3008
  art_stack_visitor_get_method: api['art::StackVisitor::GetMethod'],
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "frida-java-bridge",
3
- "version": "7.0.8",
3
+ "version": "7.0.9",
4
4
  "description": "Java runtime interop from Frida",
5
5
  "keywords": [
6
6
  "frida-gum",