frida-java-bridge 7.0.4 → 7.0.6

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.
Files changed (2) hide show
  1. package/lib/android.js +120 -31
  2. package/package.json +1 -1
package/lib/android.js CHANGED
@@ -956,43 +956,132 @@ function tryGetArtClassLinkerSpec (runtime, runtimeSpec) {
956
956
  }
957
957
 
958
958
  export function getArtClassSpec (vm) {
959
- let apiLevel;
960
- try {
961
- apiLevel = getAndroidApiLevel();
962
- } catch (e) {
963
- return null;
964
- }
959
+ const MAX_OFFSET = 0x100;
965
960
 
966
- if (apiLevel >= 36) {
967
- return {
968
- offset: {
969
- ifields: 0x28,
970
- methods: 0x28 + 0x8,
971
- sfields: 0,
972
- copiedMethodsOffset: 0x6c,
973
- }
961
+ let spec = null;
962
+
963
+ vm.perform(env => {
964
+ const fieldSpec = getArtFieldSpec(vm);
965
+ const methodSpec = getArtMethodSpec(vm);
966
+
967
+ const fInfo = {
968
+ artArrayLengthSize: 4,
969
+ artArrayEntrySize: fieldSpec.size,
970
+ // java/io/File has 15 fields on Android 16.
971
+ artArrayMax: 25
974
972
  };
975
- } else if (apiLevel >= 26) {
976
- return {
977
- offset: {
978
- ifields: 0x28,
979
- methods: 0x28 + 0x8,
980
- sfields: 0x28 + 0x10,
981
- copiedMethodsOffset: 0x74,
973
+
974
+ const mInfo = {
975
+ artArrayLengthSize: pointerSize,
976
+ artArrayEntrySize: methodSpec.size,
977
+ // java/io/File has 63 methods on Android 16.
978
+ artArrayMax: 100
979
+ };
980
+
981
+ const readArtArray = (objectBase, fieldOffset, lengthSize) => {
982
+ const header = objectBase.add(fieldOffset).readPointer();
983
+ if (header.isNull()) {
984
+ return null;
982
985
  }
986
+
987
+ const length = (lengthSize === 4) ? header.readU32() : header.readU64().valueOf();
988
+ if (length <= 0) {
989
+ return null;
990
+ }
991
+
992
+ return {
993
+ length,
994
+ data: header.add(lengthSize)
995
+ };
983
996
  };
984
- } else if (apiLevel >= 24) {
985
- return {
986
- offset: {
987
- ifields: 0x38,
988
- methods: 0x38 + 0x8,
989
- sfields: 0x38 + 0x10,
990
- copiedMethodsOffset: 0x7c,
997
+
998
+ const hasEntry = (objectBase, offset, needle, info) => {
999
+ try {
1000
+ const artArray = readArtArray(objectBase, offset, info.artArrayLengthSize);
1001
+ if (artArray === null) {
1002
+ return false;
1003
+ }
1004
+
1005
+ const artArrayEnd = Math.min(artArray.length, info.artArrayMax);
1006
+ for (let i = 0; i !== artArrayEnd; i++) {
1007
+ const fieldPtr = artArray.data.add(i * info.artArrayEntrySize);
1008
+ if (fieldPtr.equals(needle)) {
1009
+ return true;
1010
+ }
1011
+ }
1012
+ } catch {
991
1013
  }
1014
+
1015
+ return false;
992
1016
  };
993
- } else {
994
- return null;
995
- }
1017
+
1018
+ const clazz = env.findClass('java/io/File');
1019
+ const clazzRef = env.newGlobalRef(clazz);
1020
+
1021
+ try {
1022
+ let object;
1023
+ withRunnableArtThread(vm, env, thread => {
1024
+ object = getApi()['art::JavaVMExt::DecodeGlobal'](vm, thread, clazzRef);
1025
+ });
1026
+
1027
+ const fieldInstance = env.getFieldId(clazzRef, 'path', 'Ljava/lang/String;');
1028
+ const fieldStatic = env.getStaticFieldId(clazzRef, 'separatorChar', 'C');
1029
+
1030
+ let offsetStatic = -1;
1031
+ let offsetInstance = -1;
1032
+ for (let offset = 0; offset !== MAX_OFFSET; offset += 4) {
1033
+ if (offsetStatic === -1 && hasEntry(object, offset, fieldStatic, fInfo)) {
1034
+ offsetStatic = offset;
1035
+ }
1036
+ if (offsetInstance === -1 && hasEntry(object, offset, fieldInstance, fInfo)) {
1037
+ offsetInstance = offset;
1038
+ }
1039
+ }
1040
+ if (offsetInstance === -1 || offsetStatic === -1) {
1041
+ throw new Error('Unable to find fields in java/io/File; please file a bug');
1042
+ }
1043
+ const sfieldOffset = (offsetInstance !== offsetStatic) ? offsetStatic : 0;
1044
+ const ifieldOffset = offsetInstance;
1045
+
1046
+ let offsetMethods = -1;
1047
+ const methodInstance = env.getMethodId(clazzRef, 'length', '()J');
1048
+ for (let offset = 0; offset !== MAX_OFFSET; offset += 4) {
1049
+ if (offsetMethods === -1 && hasEntry(object, offset, methodInstance, mInfo)) {
1050
+ offsetMethods = offset;
1051
+ }
1052
+ }
1053
+ if (offsetMethods === -1) {
1054
+ throw new Error('Unable to find methods in java/io/File; please file a bug');
1055
+ }
1056
+
1057
+ let offsetCopiedMethods = -1;
1058
+ const methodsArray = readArtArray(object, offsetMethods, mInfo.artArrayLengthSize);
1059
+ const methodsArraySize = methodsArray.length;
1060
+ for (let offset = offsetMethods; offset !== MAX_OFFSET; offset += 4) {
1061
+ if (object.add(offset).readU16() === methodsArraySize) {
1062
+ offsetCopiedMethods = offset;
1063
+ break;
1064
+ }
1065
+ }
1066
+ if (offsetCopiedMethods === -1) {
1067
+ throw new Error('Unable to find copied methods in java/io/File; please file a bug');
1068
+ }
1069
+
1070
+ spec = {
1071
+ offset: {
1072
+ ifields: ifieldOffset,
1073
+ methods: offsetMethods,
1074
+ sfields: sfieldOffset,
1075
+ copiedMethodsOffset: offsetCopiedMethods,
1076
+ }
1077
+ };
1078
+ } finally {
1079
+ env.deleteLocalRef(clazz);
1080
+ env.deleteGlobalRef(clazzRef);
1081
+ }
1082
+ });
1083
+
1084
+ return spec;
996
1085
  }
997
1086
 
998
1087
  function _getArtMethodSpec (vm) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "frida-java-bridge",
3
- "version": "7.0.4",
3
+ "version": "7.0.6",
4
4
  "description": "Java runtime interop from Frida",
5
5
  "keywords": [
6
6
  "frida-gum",