Question: I have a Frida JS script inside a Python session, and I'm trying to pass an array of bytes (from a Bitmap image) from the JavaScript environment back to the Python environment. Here is my attempt: import frida import sys import os JS_SCRIPT = ''' setTimeout(function () {{ Java.perform(function () {{ // declare dependencies on necessary Java classes const File = Java.use("java.io.File"); const Bitmap = Java.use("android.graphics.Bitmap"); const BitmapCompressFormat = Java.use("android.graphics.Bitmap$CompressFormat"); const BitmapConfig = Java.use("android.graphics.Bitmap$Config"); const ByteArrayOutputStream = Java.use("java.io.ByteArrayOutputStream"); // instantiate a new Bitmap object const bitmap = Bitmap.createBitmap(100, 100, BitmapConfig.ARGB_8888.value); // output bitmap to a byte stream in PNG format const stream = ByteArrayOutputStream.$new(); const saved = bitmap.compress(BitmapCompressFormat.PNG.value, 100, stream); console.log("[*] Compressed as PNG:", saved); // get byte array from byte stream const byteArray = stream.toByteArray(); console.log("[*] Byte array length:", byteArray.length); // send the byte stream to the Python layer send({{ type: "bitmap", page: pageNum }}, byteArray); stream.close(); }}); }}, 1000); ''' def on_message(message, data): if message["type"] == "send" and message["payload"].get("type") == "bitmap": page = message["payload"].get("page") with open(OUTPUT_FILENAME, "wb") as f: f.write(data) print(f"[+] Saved page {page} as {OUTPUT_FILENAME}") else: print(f"[?] Unknown message: {message}") def main(): device = frida.get_usb_device(timeout=5) session = device.attach(pid) script = session.create_script(JS_SCRIPT) script.on("message", on_message) script.load() device.resume(pid) if __name__ == "__main__": main()  The problem happens on the call to send() because the second argument byteArray is not a pointer: Error: expected a pointer It's unclear to me how to get byteArray into a format that can be sent using the send() function, and I'm having trouble finding the solution in the Frida API docs.

Answer: Frida provides out of the box only methods for sending native byte arrays, thus raw data stored in ArrayBuffer or data at a certain NativePointer. Sending Java byte arrays in an efficient way requires a bit more work as you first have o convert the byte[] into a form that can b serialized by send(). The most simplest approach would is to convert byte[] to a String and send it in the first argument of send(). Luckily the hooked process seems to be an Android app, thus we can make use of the Android API to do the conversion: const base64 = Java.use('android.util.Base64'); const base64Data = base64.encodeToString(byteArray , 2)); // 2 = Base64.NO_WRAP flag send("BITMAP#" + pageNum + "#" + sendStr);  On Python side you can then split the received string on the # characters and convert the third part from base64 to a byte string. This solution is simple but has a drawback: As the byte array is converted to base64 it exists at least twice in the memory of the Android app. For large byte arrays this can cause problems if the Android app is running out of RAM, thus in such cases you may need to use the second variant of encodeToString (byte[] input, int offset, int len, int flags) that allows to convert a byte array to at once but process it in multiple blocks by specifying offset and length.