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 +21 -7
- package/lib/android.js +121 -4
- package/package.json +1 -1
package/index.d.ts
CHANGED
|
@@ -415,11 +415,25 @@ declare module "frida-java-bridge" {
|
|
|
415
415
|
[name: string]: any;
|
|
416
416
|
};
|
|
417
417
|
|
|
418
|
-
|
|
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:
|
|
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:
|
|
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
|
-
|
|
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 *
|
|
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 =
|
|
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
|
-
|
|
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'],
|