Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Method with argument of type array of array cannot be instrumented #313

Open
histausse opened this issue Apr 22, 2024 · 2 comments
Open

Comments

@histausse
Copy link

histausse commented Apr 22, 2024

Hello,
I run into a problem while trying to instrument methods that take an array of array of byte as argument. For exemple:

package com.example.testclassloader;

public class TestA {
    public static int array_of_array(byte[][] arrays) {
        int size = 0;
        for (byte[] arr: arrays) {
            size += arr.length;
        }
        return size;
    }
}
[Android Emulator 5554::TestClassLoader ]-> Java.performNow(() => { })
[Android Emulator 5554::TestClassLoader ]-> TestA =  Java.use("com.example.testclassloader.TestA")
"<class: com.example.testclassloader.TestA>"
[Android Emulator 5554::TestClassLoader ]-> method = TestA.array_of_array
function
[Android Emulator 5554::TestClassLoader ]-> method.argumentTypes
[
    {
        "className": "[[B",
        "defaultValue": "0x0",
        "name": "[[B",
        "size": 1,
        "type": "pointer"
    }
]
[Android Emulator 5554::TestClassLoader ]-> method.overload('[[B').implementation = function(arrays) { s =
 method(arrays); console.log(s); return s; };
function

# after triggering the method in the app:

[Android Emulator 5554::TestClassLoader ]-> Process crashed: java.lang.ClassNotFoundException: Didn't find class "[L[B;" on path: DexPathList[[dex file "/data/data/com.example.testclassloader/code_cache/.overlay/base.apk/classes3.dex", zip file "/data/app/~~NRqmDlxjA4t3ccEvxe4Qlw==/com.example.testclassloader-JhUO40ypsrxE2AIa8f1k4A==/base.apk"],nativeLibraryDirectories=[/data/app/~~NRqmDlxjA4t3ccEvxe4Qlw==/com.example.testclassloader-JhUO40ypsrxE2AIa8f1k4A==/lib/x86_64, /system/lib64, /system_ext/lib64]]

I believe the issue comes from here:

const internalTypeName = '[L' + elementTypeName.replace(/\./g, '/') + ';';

I think something like this could be a rough solution, but I did not manage to get frida to use patched version of frida-java-bridge:

diff --git a/lib/types.js b/lib/types.js
index 6a0f977..9b8d91f 100644
--- a/lib/types.js
+++ b/lib/types.js
@@ -477,7 +477,13 @@ function getArrayType (typeName, unbox, factory) {
       }

       // The type name we get is not always the correct representation of the type so we make it so here.
-      const internalTypeName = '[L' + elementTypeName.replace(/\./g, '/') + ';';
+      let internalElementTypeName = '';
+      if (elementTypeName.replace[0] === '[') {
+        internalElementTypeName = elementTypeName.replace(/\./g, '/');
+      } else {
+        internalElementTypeName = 'L' + elementTypeName.replace(/\./g, '/') + ';';
+      }
+      const internalTypeName = '[' + internalElementTypeName;
       try {
         result.$w = factory.cast(arr, factory.use(internalTypeName), owned);
       } catch (e) {

PS: Is there some documentation for running a patched java-bridge? I tried https://github.com/frida/frida-tools?tab=readme-ov-file#loading-your-custom-frida-java-bridge and failled

histausse pushed a commit to histausse/frida-java-bridge that referenced this issue Apr 23, 2024
@WanQingGit
Copy link

I fixed the problem that the jni type name was wrong for arrays of type primary. Here's my fix

https://zhuanlan.zhihu.com/p/696631835

@WanQingGit
Copy link

function makeBaseJniObjectTypeName(typeName) {
if (typeName.length === 1)
return typeName
let convertType = typeName.replace(/./g, '/')
if (convertType[0] !== 'L'){
convertType = 'L' + convertType +';'
}
return convertType
}

function makeJniObjectTypeName(typeName) {
let arrayCount = 0;
while (typeName[arrayCount] === '[') {
arrayCount += 1;
}
if (typeName.length === arrayCount + 1) {
return typeName
}
if (arrayCount > 0) {
const baseType = makeBaseJniObjectTypeName(typeName.slice(arrayCount));
return "[".repeat(arrayCount) + baseType;
}
return makeBaseJniObjectTypeName(typeName);
}

  // const internalTypeName = '[L' + elementTypeName.replace(/\./g, '/') + ';';
  const internalTypeName = '[' + makeJniObjectTypeName(elementTypeName);

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants