Нужно было быстренько перехватить вызов нативной функции и посмотреть значение переменной в Android приложении. Как то давно использовал для этого замечательную утилиту Frida. Установил на планшет frida-server (root уже был) и клиент на PC, написал классический JS хук, но он не работал:
defineHandler({
onEnter(log, args, state) {
conslole.log('decoder_CRC_check()');
},
onLeave(log, retval, state) {
const libc = Module.findBaseAddress('libc.so');
console.log(hexdump(libc, {
/* address: ptr('0x1000'), -- to override the base address */
offset: 0,
length: 64,
header: true,
ansi: true
}));
}
});
В консоли лишь получал TypeError: not a function at onEnter (D:\Distrib\Android TV\frida\hook.js:7)
Убил полдня в поисках "чего я делаю не так", при том что и официальная дока и нейронки твердят, что именно так и нужно получать базовый адрес модуля и, при необходимости, функций. Оказалось, во Frida 17 автор полностью удалил некоторые функции (а дока и нейронки еще не обновились):
Module.ensureInitialized()
Module.findBaseAddress()
Module.getBaseAddress()
Module.findExportByName()
Module.getExportByName()
Module.findSymbolByName()
Module.getSymbolByName()
Туда же статические функции Memory
И теперь надо писать цепочку вызовов:
const lib = Process.findModuleByName("libc.so");
console.log("[*] libc.so loaded at base: " + lib.base);
const funcAddr = lib.findExportByName("decoder_CRC_t_init");
Итог получился такой универсальный скрипт:
Java.perform(function () {
const System = Java.use("java.lang.System");
const Runtime = Java.use('java.lang.Runtime');
const SystemLoadLibrary = System.loadLibrary.overload('java.lang.String');
const VMStack = Java.use('dalvik.system.VMStack');
// "ожидание"\перехват динамической загрузки нативных библиотек
SystemLoadLibrary.implementation = function(library) {
console.log("Loading dynamic library => " + library);
const loaded = Runtime.getRuntime().loadLibrary0(
VMStack.getCallingClassLoader(), library
);
if (library.includes("mylibname")) {
console.log("\n[+] Hooked mylibname");
// перехватываем только нужную нам
hookNativeFunc();
}
return loaded;
}
});
function hookNativeFunc() {
//тут имя полностью как называется сам файл в ресурсах
const lib = Process.findModuleByName("libmylibname.so");
console.log("[*] mylibname.so loaded at base: " + lib.base);
const funcAddr = lib.findExportByName("decoder_CRC_t_init");
if (!funcAddr) {
console.log("[-] Function not found!");
return;
}
console.log("[+] Found decoder_CRC_t_init at: " + funcAddr);
Interceptor.attach(funcAddr, {
onEnter: function (args) {
var result = args[0];
var inputPtr = args[1];
var len = args[2].toInt32();
console.log("\n[+] decoder_CRC_t_init called");
console.log(" result: " + result);
console.log(" inputPtr: " + inputPtr);
console.log(" len: " + len);
},
onLeave: function (retval) {
//нужный адрес массива, например из IDA PRO
const wordArrayOffset = 0x5B2C04;
const wordArray = lib.base.add(wordArrayOffset);
var ptr = new NativePointer(wordArray); // современный вариант чтения
console.log("[*] 5B2C04 contents:");
try {
console.log(hexdump(ptr, {
offset: 0,
length: 512,
header: true,
ansi: true
}));
} catch (e) {
console.log("[!] Error reading 5B2C04:", e);
}
console.log("Return value:", retval);
}
});
}
Запускается так frida -U -f com.android.app -l hook.js