I'm using Frida to reverse-engineer an Android app that uses a library (libapp.so). I have a list of function names and their offsets, and I'm successfully hooking them
My goal is to log the return value of these native functions as a readable string.
Here’s my current script
Java.perform(function () {
var libapp = null;
const libName = "libapp.so";
const checkInterval = 200;
const maxWaitTime = 10000;
let waited = 0;
const waitForLibApp = setInterval(function () {
libapp = Module.findBaseAddress(libName);
if (libapp !== null || waited > maxWaitTime) {
clearInterval(waitForLibApp);
if (libapp === null) {
console.log("[-] libapp.so not found in memory.");
return;
}
console.log("[+] libapp.so loaded at", libapp);
hookTargetFunctions(libapp);
}
waited += checkInterval;
}, checkInterval);
function hookTargetFunctions(base) {
const functionList = [
{ name: "addData", offset: 0x795b4c },
{ name: "getData", offset: 0x795cbc },
];
functionList.forEach(func => {
try {
const addr = base.add(ptr(func.offset));
Interceptor.attach(addr, {
onEnter: function (args) {
console.log(`[+] Called ${func.name} @ ${addr}`);
},
onLeave: function (retval) {
// This is where I want to convert the return value to a readable string
}
});
} catch (err) {
console.error(`[-] Error hooking ${func.name}:`, err);
}
});
}
});
-
Are the two functions you have hooked JNI functions that are called from Java or are they pure native functions that are called internally by lib app.so? How do you know they return a string? Do you know the type of the string? On native level there are multiple ways to define a string, e.g. null terminated strings where each byte is one character.Robert– Robert2025年04月11日 22:51:14 +00:00Commented Apr 11, 2025 at 22:51
1 Answer 1
Your question does miss some details so I had to guess:
I assume the return value is pointer to a common null terminated string containing ASCII or UTF-8 characters. In Frida those strings are called "CString" and "Utf8String".
Interceptor.attach(addr, {
onEnter: function (args) {
console.log(`[+] Called ${func.name} @ ${addr}`);
},
onLeave: function (retval) {
let str = retval.readCString();
console.log(`returned string: ${str}`);
}
});
Depending on the string type to be read Frida has this functions:
readCString()readUtf8String()readUtf16String()readAnsiString()
See also Frida documentation on NativePointer