1

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.

Robert
43.5k18 gold badges114 silver badges181 bronze badges
asked May 4, 2025 at 0:49
2
  • Java is to Javascript as Ham is to Hamster: Entirely unrelated. The name is just confusing. I've removed the 'java' tag. Commented May 4, 2025 at 2:14
  • 1
    @rzwitserloot Frida is one of the rare cases where both tags can be set together because Frida is a hooking system that allows you to hook into processes (e.g. Java JVMs) and modify them using JavaScript code. But in this case the Android tag would be more suitable as the hooked process seems to be a Android app and not a J2SE JVM. Commented May 4, 2025 at 6:21

1 Answer 1

2

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.

answered May 4, 2025 at 6:53
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.