Нужно было быстренько перехватить вызов нативной функции и посмотреть значение переменной в 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
