frida-java-bridge 4.5.1 → 5.2.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/index.js +1 -1
- package/lib/android.js +27 -5
- package/lib/class-factory.js +3 -3
- package/lib/env.js +5 -1
- package/lib/types.js +16 -3
- package/package.json +1 -2
package/index.js
CHANGED
package/lib/android.js
CHANGED
|
@@ -22,6 +22,8 @@ const kAccCriticalNative = 0x00200000;
|
|
|
22
22
|
const kAccFastInterpreterToInterpreterInvoke = 0x40000000;
|
|
23
23
|
const kAccSkipAccessChecks = 0x00080000;
|
|
24
24
|
const kAccSingleImplementation = 0x08000000;
|
|
25
|
+
const kAccNterpEntryPointFastPathFlag = 0x00100000;
|
|
26
|
+
const kAccNterpInvokeFastPathFlag = 0x00200000;
|
|
25
27
|
const kAccPublicApi = 0x10000000;
|
|
26
28
|
const kAccXposedHookedMethod = 0x10000000;
|
|
27
29
|
|
|
@@ -908,7 +910,7 @@ function _getArtMethodSpec (vm) {
|
|
|
908
910
|
const entrypointFieldSize = (apiLevel <= 21) ? 8 : pointerSize;
|
|
909
911
|
|
|
910
912
|
const expectedAccessFlags = kAccPublic | kAccStatic | kAccFinal | kAccNative;
|
|
911
|
-
const
|
|
913
|
+
const relevantAccessFlagsMask = ~(kAccPublicApi | kAccNterpInvokeFastPathFlag) >>> 0;
|
|
912
914
|
|
|
913
915
|
let jniCodeOffset = null;
|
|
914
916
|
let accessFlagsOffset = null;
|
|
@@ -926,7 +928,7 @@ function _getArtMethodSpec (vm) {
|
|
|
926
928
|
|
|
927
929
|
if (accessFlagsOffset === null) {
|
|
928
930
|
const flags = field.readU32();
|
|
929
|
-
if ((flags &
|
|
931
|
+
if ((flags & relevantAccessFlagsMask) === expectedAccessFlags) {
|
|
930
932
|
accessFlagsOffset = offset;
|
|
931
933
|
remaining--;
|
|
932
934
|
}
|
|
@@ -1539,7 +1541,7 @@ set_replacement_method (gpointer original_method,
|
|
|
1539
1541
|
g_mutex_lock (&lock);
|
|
1540
1542
|
|
|
1541
1543
|
g_hash_table_insert (methods, original_method, replacement_method);
|
|
1542
|
-
|
|
1544
|
+
g_hash_table_insert (replacements, replacement_method, original_method);
|
|
1543
1545
|
|
|
1544
1546
|
g_mutex_unlock (&lock);
|
|
1545
1547
|
}
|
|
@@ -1561,6 +1563,20 @@ delete_replacement_method (gpointer original_method)
|
|
|
1561
1563
|
g_mutex_unlock (&lock);
|
|
1562
1564
|
}
|
|
1563
1565
|
|
|
1566
|
+
gpointer
|
|
1567
|
+
translate_method (gpointer method)
|
|
1568
|
+
{
|
|
1569
|
+
gpointer translated_method;
|
|
1570
|
+
|
|
1571
|
+
g_mutex_lock (&lock);
|
|
1572
|
+
|
|
1573
|
+
translated_method = g_hash_table_lookup (replacements, method);
|
|
1574
|
+
|
|
1575
|
+
g_mutex_unlock (&lock);
|
|
1576
|
+
|
|
1577
|
+
return (translated_method != NULL) ? translated_method : method;
|
|
1578
|
+
}
|
|
1579
|
+
|
|
1564
1580
|
gpointer
|
|
1565
1581
|
find_replacement_method_from_quick_code (gpointer method,
|
|
1566
1582
|
gpointer thread)
|
|
@@ -1689,6 +1705,7 @@ on_leave_gc_concurrent_copying_copying_phase (GumInvocationContext * ic)
|
|
|
1689
1705
|
get: new NativeFunction(cm.get_replacement_method, 'pointer', ['pointer'], fastOptions),
|
|
1690
1706
|
set: new NativeFunction(cm.set_replacement_method, 'void', ['pointer', 'pointer'], fastOptions),
|
|
1691
1707
|
delete: new NativeFunction(cm.delete_replacement_method, 'void', ['pointer'], fastOptions),
|
|
1708
|
+
translate: new NativeFunction(cm.translate_method, 'pointer', ['pointer'], fastOptions),
|
|
1692
1709
|
findReplacementFromQuickCode: cm.find_replacement_method_from_quick_code
|
|
1693
1710
|
},
|
|
1694
1711
|
getOatQuickMethodHeaderImpl,
|
|
@@ -1791,6 +1808,10 @@ function makeMethodMangler (methodId) {
|
|
|
1791
1808
|
return new MethodMangler(methodId);
|
|
1792
1809
|
}
|
|
1793
1810
|
|
|
1811
|
+
function translateMethod (methodId) {
|
|
1812
|
+
return artController.replacedMethods.translate(methodId);
|
|
1813
|
+
}
|
|
1814
|
+
|
|
1794
1815
|
function revertGlobalPatches () {
|
|
1795
1816
|
patchedClasses.forEach(entry => {
|
|
1796
1817
|
entry.vtablePtr.writePointer(entry.vtable);
|
|
@@ -2316,14 +2337,14 @@ class ArtMethodMangler {
|
|
|
2316
2337
|
|
|
2317
2338
|
patchArtMethod(replacementMethodId, {
|
|
2318
2339
|
jniCode: impl,
|
|
2319
|
-
accessFlags: ((originalFlags & ~(kAccCriticalNative | kAccFastNative)) | kAccNative) >>> 0,
|
|
2340
|
+
accessFlags: ((originalFlags & ~(kAccCriticalNative | kAccFastNative | kAccNterpEntryPointFastPathFlag)) | kAccNative) >>> 0,
|
|
2320
2341
|
quickCode: api.artClassLinker.quickGenericJniTrampoline,
|
|
2321
2342
|
interpreterCode: api.artInterpreterToCompiledCodeBridge
|
|
2322
2343
|
}, vm);
|
|
2323
2344
|
|
|
2324
2345
|
// Remove kAccFastInterpreterToInterpreterInvoke and kAccSkipAccessChecks to disable use_fast_path
|
|
2325
2346
|
// in interpreter_common.h
|
|
2326
|
-
let hookedMethodRemovedFlags = kAccFastInterpreterToInterpreterInvoke | kAccSingleImplementation;
|
|
2347
|
+
let hookedMethodRemovedFlags = kAccFastInterpreterToInterpreterInvoke | kAccSingleImplementation | kAccNterpEntryPointFastPathFlag;
|
|
2327
2348
|
if ((originalFlags & kAccNative) === 0) {
|
|
2328
2349
|
hookedMethodRemovedFlags |= kAccSkipAccessChecks;
|
|
2329
2350
|
}
|
|
@@ -4043,6 +4064,7 @@ module.exports = {
|
|
|
4043
4064
|
ArtStackVisitor,
|
|
4044
4065
|
ArtMethod,
|
|
4045
4066
|
makeMethodMangler,
|
|
4067
|
+
translateMethod,
|
|
4046
4068
|
revertGlobalPatches,
|
|
4047
4069
|
deoptimizeEverything,
|
|
4048
4070
|
deoptimizeBootImage,
|
package/lib/class-factory.js
CHANGED
|
@@ -265,7 +265,7 @@ class ClassFactory {
|
|
|
265
265
|
wrap (handle, klass, env) {
|
|
266
266
|
const C = klass.$C;
|
|
267
267
|
const wrapper = new C(handle, STRATEGY_VIRTUAL, env, false);
|
|
268
|
-
wrapper.$r =
|
|
268
|
+
wrapper.$r = Script.bindWeak(wrapper, vm.makeHandleDestructor(handle));
|
|
269
269
|
return wrapper;
|
|
270
270
|
}
|
|
271
271
|
|
|
@@ -746,7 +746,7 @@ function Wrapper (handle, strategy, env, owned = true) {
|
|
|
746
746
|
if (owned) {
|
|
747
747
|
const h = env.newGlobalRef(handle);
|
|
748
748
|
this.$h = h;
|
|
749
|
-
this.$r =
|
|
749
|
+
this.$r = Script.bindWeak(this, vm.makeHandleDestructor(h));
|
|
750
750
|
} else {
|
|
751
751
|
this.$h = handle;
|
|
752
752
|
this.$r = null;
|
|
@@ -834,7 +834,7 @@ Object.defineProperties(Wrapper.prototype, {
|
|
|
834
834
|
const ref = this.$r;
|
|
835
835
|
if (ref !== null) {
|
|
836
836
|
this.$r = null;
|
|
837
|
-
|
|
837
|
+
Script.unbindWeak(ref);
|
|
838
838
|
}
|
|
839
839
|
|
|
840
840
|
if (this.$h !== null) {
|
package/lib/env.js
CHANGED
|
@@ -229,7 +229,7 @@ Env.prototype.throwIfExceptionPending = function () {
|
|
|
229
229
|
|
|
230
230
|
const error = new Error(descriptionStr);
|
|
231
231
|
error.$h = handle;
|
|
232
|
-
|
|
232
|
+
Script.bindWeak(error, makeErrorHandleDestructor(this.vm, handle));
|
|
233
233
|
|
|
234
234
|
throw error;
|
|
235
235
|
};
|
|
@@ -531,6 +531,10 @@ Env.prototype.monitorExit = proxy(218, 'int32', ['pointer', 'pointer'], function
|
|
|
531
531
|
return impl(this.handle, obj);
|
|
532
532
|
});
|
|
533
533
|
|
|
534
|
+
Env.prototype.getDirectBufferAddress = proxy(230, 'pointer', ['pointer', 'pointer'], function (impl, obj) {
|
|
535
|
+
return impl(this.handle, obj);
|
|
536
|
+
});
|
|
537
|
+
|
|
534
538
|
Env.prototype.getObjectRefType = proxy(232, 'int32', ['pointer', 'pointer'], function (impl, ref) {
|
|
535
539
|
return impl(this.handle, ref);
|
|
536
540
|
});
|
package/lib/types.js
CHANGED
|
@@ -446,7 +446,15 @@ function getArrayType (typeName, unbox, factory) {
|
|
|
446
446
|
}
|
|
447
447
|
}
|
|
448
448
|
|
|
449
|
-
|
|
449
|
+
// The type name we get is not always the correct representation of the type so we make it so here.
|
|
450
|
+
const internalTypeName = '[L' + elementTypeName.replace(/\./g, '/') + ';';
|
|
451
|
+
try {
|
|
452
|
+
result.$w = factory.cast(arr, factory.use(internalTypeName), owned);
|
|
453
|
+
} catch (e) {
|
|
454
|
+
// We need to load the array type before using it.
|
|
455
|
+
factory.use('java.lang.reflect.Array').newInstance(factory.use(elementTypeName).class, 0);
|
|
456
|
+
result.$w = factory.cast(arr, factory.use(internalTypeName), owned);
|
|
457
|
+
}
|
|
450
458
|
|
|
451
459
|
result.$dispose = disposeObjectArray;
|
|
452
460
|
|
|
@@ -580,7 +588,7 @@ function PrimitiveArray (handle, spec, type, length, env, owned = true) {
|
|
|
580
588
|
if (owned) {
|
|
581
589
|
const h = env.newGlobalRef(handle);
|
|
582
590
|
this.$h = h;
|
|
583
|
-
this.$r =
|
|
591
|
+
this.$r = Script.bindWeak(this, env.vm.makeHandleDestructor(h));
|
|
584
592
|
} else {
|
|
585
593
|
this.$h = handle;
|
|
586
594
|
this.$r = null;
|
|
@@ -654,7 +662,7 @@ Object.defineProperties(PrimitiveArray.prototype, {
|
|
|
654
662
|
const ref = this.$r;
|
|
655
663
|
if (ref !== null) {
|
|
656
664
|
this.$r = null;
|
|
657
|
-
|
|
665
|
+
Script.unbindWeak(ref);
|
|
658
666
|
}
|
|
659
667
|
}
|
|
660
668
|
},
|
|
@@ -726,6 +734,11 @@ Object.defineProperties(PrimitiveArray.prototype, {
|
|
|
726
734
|
return values;
|
|
727
735
|
});
|
|
728
736
|
}
|
|
737
|
+
},
|
|
738
|
+
toString: {
|
|
739
|
+
value () {
|
|
740
|
+
return this.toJSON().toString();
|
|
741
|
+
}
|
|
729
742
|
}
|
|
730
743
|
});
|
|
731
744
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "frida-java-bridge",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "5.2.0",
|
|
4
4
|
"description": "Java runtime interop from Frida",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"files": [
|
|
@@ -48,7 +48,6 @@
|
|
|
48
48
|
"ThumbWriter",
|
|
49
49
|
"UnixInputStream",
|
|
50
50
|
"UnixOutputStream",
|
|
51
|
-
"WeakRef",
|
|
52
51
|
"X86Relocator",
|
|
53
52
|
"X86Writer",
|
|
54
53
|
"ptr",
|