frida-java-bridge 6.2.1 → 6.2.3
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.js +7 -3
- package/lib/android.js +70 -40
- package/lib/class-model.js +8 -2
- package/package.json +1 -1
package/index.js
CHANGED
|
@@ -440,9 +440,13 @@ class Runtime {
|
|
|
440
440
|
handleBindApplication.apply(this, arguments);
|
|
441
441
|
};
|
|
442
442
|
|
|
443
|
-
const
|
|
444
|
-
|
|
445
|
-
|
|
443
|
+
const getPackageInfoCandidates = ActivityThread.getPackageInfo.overloads
|
|
444
|
+
.map(m => [m.argumentTypes.length, m])
|
|
445
|
+
.sort(([arityA,], [arityB,]) => arityB - arityA)
|
|
446
|
+
.map(([_, method]) => method);
|
|
447
|
+
const getPackageInfo = getPackageInfoCandidates[0];
|
|
448
|
+
getPackageInfo.implementation = function (...args) {
|
|
449
|
+
const apk = getPackageInfo.call(this, ...args);
|
|
446
450
|
|
|
447
451
|
if (!initialized && hookpoint === 'early') {
|
|
448
452
|
initialized = true;
|
package/lib/android.js
CHANGED
|
@@ -30,7 +30,6 @@ const kAccSkipAccessChecks = 0x00080000;
|
|
|
30
30
|
const kAccSingleImplementation = 0x08000000;
|
|
31
31
|
const kAccNterpEntryPointFastPathFlag = 0x00100000;
|
|
32
32
|
const kAccNterpInvokeFastPathFlag = 0x00200000;
|
|
33
|
-
const kAccCompileDontBother = 0x02000000;
|
|
34
33
|
const kAccPublicApi = 0x10000000;
|
|
35
34
|
const kAccXposedHookedMethod = 0x10000000;
|
|
36
35
|
|
|
@@ -82,7 +81,6 @@ const SOCK_STREAM = 1;
|
|
|
82
81
|
|
|
83
82
|
const getArtRuntimeSpec = memoize(_getArtRuntimeSpec);
|
|
84
83
|
const getArtInstrumentationSpec = memoize(_getArtInstrumentationSpec);
|
|
85
|
-
const getArtClassLinkerSpec = memoize(_getArtClassLinkerSpec);
|
|
86
84
|
const getArtMethodSpec = memoize(_getArtMethodSpec);
|
|
87
85
|
const getArtThreadSpec = memoize(_getArtThreadSpec);
|
|
88
86
|
const getArtManagedStackSpec = memoize(_getArtManagedStackSpec);
|
|
@@ -104,6 +102,7 @@ const nativeFunctionOptions = {
|
|
|
104
102
|
const artThreadStateTransitions = {};
|
|
105
103
|
|
|
106
104
|
let cachedApi = null;
|
|
105
|
+
let cachedArtClassLinkerSpec = null;
|
|
107
106
|
let MethodMangler = null;
|
|
108
107
|
let artController = null;
|
|
109
108
|
const inlineHooks = [];
|
|
@@ -435,9 +434,22 @@ function _getApi () {
|
|
|
435
434
|
temporaryApi.vm = vms.readPointer();
|
|
436
435
|
|
|
437
436
|
if (isArt) {
|
|
437
|
+
const apiLevel = getAndroidApiLevel();
|
|
438
|
+
|
|
439
|
+
let kAccCompileDontBother;
|
|
440
|
+
if (apiLevel >= 27) {
|
|
441
|
+
kAccCompileDontBother = 0x02000000;
|
|
442
|
+
} else if (apiLevel >= 24) {
|
|
443
|
+
kAccCompileDontBother = 0x01000000;
|
|
444
|
+
} else {
|
|
445
|
+
kAccCompileDontBother = 0;
|
|
446
|
+
}
|
|
447
|
+
temporaryApi.kAccCompileDontBother = kAccCompileDontBother;
|
|
448
|
+
|
|
438
449
|
const artRuntime = temporaryApi.vm.add(pointerSize).readPointer();
|
|
439
450
|
temporaryApi.artRuntime = artRuntime;
|
|
440
|
-
const
|
|
451
|
+
const runtimeSpec = getArtRuntimeSpec(temporaryApi);
|
|
452
|
+
const runtimeOffset = runtimeSpec.offset;
|
|
441
453
|
const instrumentationOffset = runtimeOffset.instrumentation;
|
|
442
454
|
temporaryApi.artInstrumentation = (instrumentationOffset !== null) ? artRuntime.add(instrumentationOffset) : null;
|
|
443
455
|
|
|
@@ -452,7 +464,7 @@ function _getApi () {
|
|
|
452
464
|
*/
|
|
453
465
|
const classLinker = artRuntime.add(runtimeOffset.classLinker).readPointer();
|
|
454
466
|
|
|
455
|
-
const classLinkerOffsets = getArtClassLinkerSpec(
|
|
467
|
+
const classLinkerOffsets = getArtClassLinkerSpec(artRuntime, runtimeSpec).offset;
|
|
456
468
|
const quickResolutionTrampoline = classLinker.add(classLinkerOffsets.quickResolutionTrampoline).readPointer();
|
|
457
469
|
const quickImtConflictTrampoline = classLinker.add(classLinkerOffsets.quickImtConflictTrampoline).readPointer();
|
|
458
470
|
const quickGenericJniTrampoline = classLinker.add(classLinkerOffsets.quickGenericJniTrampoline).readPointer();
|
|
@@ -602,49 +614,57 @@ function _getArtRuntimeSpec (api) {
|
|
|
602
614
|
const endOffset = startOffset + (100 * pointerSize);
|
|
603
615
|
|
|
604
616
|
const apiLevel = getAndroidApiLevel();
|
|
617
|
+
const codename = getAndroidCodename();
|
|
605
618
|
|
|
606
619
|
let spec = null;
|
|
607
620
|
|
|
608
621
|
for (let offset = startOffset; offset !== endOffset; offset += pointerSize) {
|
|
609
622
|
const value = runtime.add(offset).readPointer();
|
|
610
623
|
if (value.equals(vm)) {
|
|
611
|
-
let
|
|
624
|
+
let classLinkerOffsets;
|
|
612
625
|
let jniIdManagerOffset = null;
|
|
613
|
-
if (apiLevel >= 33 ||
|
|
614
|
-
|
|
626
|
+
if (apiLevel >= 33 || codename === 'Tiramisu') {
|
|
627
|
+
classLinkerOffsets = [offset - (4 * pointerSize)];
|
|
615
628
|
jniIdManagerOffset = offset - pointerSize;
|
|
616
|
-
} else if (apiLevel >= 30 ||
|
|
617
|
-
|
|
629
|
+
} else if (apiLevel >= 30 || codename === 'R') {
|
|
630
|
+
classLinkerOffsets = [offset - (3 * pointerSize), offset - (4 * pointerSize)];
|
|
618
631
|
jniIdManagerOffset = offset - pointerSize;
|
|
619
632
|
} else if (apiLevel >= 29) {
|
|
620
|
-
|
|
633
|
+
classLinkerOffsets = [offset - (2 * pointerSize)];
|
|
621
634
|
} else if (apiLevel >= 27) {
|
|
622
|
-
|
|
635
|
+
classLinkerOffsets = [offset - STD_STRING_SIZE - (3 * pointerSize)];
|
|
623
636
|
} else {
|
|
624
|
-
|
|
637
|
+
classLinkerOffsets = [offset - STD_STRING_SIZE - (2 * pointerSize)];
|
|
625
638
|
}
|
|
626
639
|
|
|
627
|
-
const
|
|
628
|
-
|
|
640
|
+
for (const classLinkerOffset of classLinkerOffsets) {
|
|
641
|
+
const internTableOffset = classLinkerOffset - pointerSize;
|
|
642
|
+
const threadListOffset = internTableOffset - pointerSize;
|
|
629
643
|
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
644
|
+
let heapOffset;
|
|
645
|
+
if (apiLevel >= 24) {
|
|
646
|
+
heapOffset = threadListOffset - (8 * pointerSize);
|
|
647
|
+
} else if (apiLevel >= 23) {
|
|
648
|
+
heapOffset = threadListOffset - (7 * pointerSize);
|
|
649
|
+
} else {
|
|
650
|
+
heapOffset = threadListOffset - (4 * pointerSize);
|
|
651
|
+
}
|
|
638
652
|
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
653
|
+
const candidate = {
|
|
654
|
+
offset: {
|
|
655
|
+
heap: heapOffset,
|
|
656
|
+
threadList: threadListOffset,
|
|
657
|
+
internTable: internTableOffset,
|
|
658
|
+
classLinker: classLinkerOffset,
|
|
659
|
+
jniIdManager: jniIdManagerOffset
|
|
660
|
+
}
|
|
661
|
+
};
|
|
662
|
+
if (tryGetArtClassLinkerSpec(runtime, candidate) !== null) {
|
|
663
|
+
spec = candidate;
|
|
664
|
+
break;
|
|
646
665
|
}
|
|
647
|
-
}
|
|
666
|
+
}
|
|
667
|
+
|
|
648
668
|
break;
|
|
649
669
|
}
|
|
650
670
|
}
|
|
@@ -822,7 +842,19 @@ function _getArtInstrumentationSpec () {
|
|
|
822
842
|
};
|
|
823
843
|
}
|
|
824
844
|
|
|
825
|
-
function
|
|
845
|
+
function getArtClassLinkerSpec (runtime, runtimeSpec) {
|
|
846
|
+
const spec = tryGetArtClassLinkerSpec(runtime, runtimeSpec);
|
|
847
|
+
if (spec === null) {
|
|
848
|
+
throw new Error('Unable to determine ClassLinker field offsets');
|
|
849
|
+
}
|
|
850
|
+
return spec;
|
|
851
|
+
}
|
|
852
|
+
|
|
853
|
+
function tryGetArtClassLinkerSpec (runtime, runtimeSpec) {
|
|
854
|
+
if (cachedArtClassLinkerSpec !== null) {
|
|
855
|
+
return cachedArtClassLinkerSpec;
|
|
856
|
+
}
|
|
857
|
+
|
|
826
858
|
/*
|
|
827
859
|
* On Android 5.x:
|
|
828
860
|
*
|
|
@@ -851,11 +883,9 @@ function _getArtClassLinkerSpec (api) {
|
|
|
851
883
|
* }
|
|
852
884
|
*/
|
|
853
885
|
|
|
854
|
-
const
|
|
855
|
-
const
|
|
856
|
-
|
|
857
|
-
const classLinker = runtime.add(runtimeSpec.offset.classLinker).readPointer();
|
|
858
|
-
const internTable = runtime.add(runtimeSpec.offset.internTable).readPointer();
|
|
886
|
+
const { classLinker: classLinkerOffset, internTable: internTableOffset } = runtimeSpec.offset;
|
|
887
|
+
const classLinker = runtime.add(classLinkerOffset).readPointer();
|
|
888
|
+
const internTable = runtime.add(internTableOffset).readPointer();
|
|
859
889
|
|
|
860
890
|
const startOffset = (pointerSize === 4) ? 100 : 200;
|
|
861
891
|
const endOffset = startOffset + (100 * pointerSize);
|
|
@@ -900,8 +930,8 @@ function _getArtClassLinkerSpec (api) {
|
|
|
900
930
|
}
|
|
901
931
|
}
|
|
902
932
|
|
|
903
|
-
if (spec
|
|
904
|
-
|
|
933
|
+
if (spec !== null) {
|
|
934
|
+
cachedArtClassLinkerSpec = spec;
|
|
905
935
|
}
|
|
906
936
|
|
|
907
937
|
return spec;
|
|
@@ -3314,6 +3344,8 @@ class ArtMethodMangler {
|
|
|
3314
3344
|
}
|
|
3315
3345
|
|
|
3316
3346
|
replace (impl, isInstanceMethod, argTypes, vm, api) {
|
|
3347
|
+
const { kAccCompileDontBother, artNterpEntryPoint } = api;
|
|
3348
|
+
|
|
3317
3349
|
this.originalMethod = fetchArtMethod(this.methodId, vm);
|
|
3318
3350
|
|
|
3319
3351
|
const originalFlags = this.originalMethod.accessFlags;
|
|
@@ -3351,8 +3383,6 @@ class ArtMethodMangler {
|
|
|
3351
3383
|
|
|
3352
3384
|
// Replace Nterp quick entrypoints with art_quick_to_interpreter_bridge to force stepping out
|
|
3353
3385
|
// of ART's next-generation interpreter and use the quick stub instead.
|
|
3354
|
-
const { artNterpEntryPoint } = api;
|
|
3355
|
-
|
|
3356
3386
|
if (artNterpEntryPoint !== undefined && quickCode.equals(artNterpEntryPoint)) {
|
|
3357
3387
|
patchArtMethod(hookedMethodId, {
|
|
3358
3388
|
quickCode: api.artQuickToInterpreterBridge
|
package/lib/class-model.js
CHANGED
|
@@ -390,7 +390,10 @@ model_add_method (Model * self,
|
|
|
390
390
|
gchar * key, type;
|
|
391
391
|
const gchar * value;
|
|
392
392
|
|
|
393
|
-
|
|
393
|
+
if (name[0] == '$')
|
|
394
|
+
key = g_strdup_printf ("_%s", name);
|
|
395
|
+
else
|
|
396
|
+
key = g_strdup (name);
|
|
394
397
|
|
|
395
398
|
type = (modifiers & kAccStatic) != 0 ? 's' : 'i';
|
|
396
399
|
|
|
@@ -410,7 +413,10 @@ model_add_field (Model * self,
|
|
|
410
413
|
GHashTable * members = self->members;
|
|
411
414
|
gchar * key, type;
|
|
412
415
|
|
|
413
|
-
|
|
416
|
+
if (name[0] == '$')
|
|
417
|
+
key = g_strdup_printf ("_%s", name);
|
|
418
|
+
else
|
|
419
|
+
key = g_strdup (name);
|
|
414
420
|
while (g_hash_table_contains (members, key))
|
|
415
421
|
{
|
|
416
422
|
gchar * new_key = g_strdup_printf ("_%s", key);
|