Created
March 2, 2025 20:44
-
-
Save Ahmeth4n/8b0a21228fc2437864bb58b9402180ad to your computer and use it in GitHub Desktop.
simple PairIP executeVM() analyzer frida script.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function hookNative() { | |
const jniOnLoad = moduleHandle.findExportByName("JNI_OnLoad"); | |
if (!jniOnLoad) { | |
console.log("[-] JNI_OnLoad not found!"); | |
return; | |
} | |
console.log("[+] JNI_OnLoad founded:", jniOnLoad); | |
var hook3 = Interceptor.attach(jniOnLoad, { | |
onEnter: function(args) { | |
console.log("[+] JNI_OnLoad called"); | |
console.log("JavaVM pointer:", args[0]); | |
console.log("reserved:", args[1]); | |
console.log("Backtrace:\n" + Thread.backtrace(this.context, Backtracer.ACCURATE) | |
.map(DebugSymbol.fromAddress).join("\n")); | |
startStalker(this.threadId, Process.getModuleByName('libpairipcore.so')); | |
}, | |
onLeave: function(retval) { | |
console.log("[+] JNI_OnLoad return value:", retval); | |
stopStalker(this.threadId); | |
hook3.detach(); | |
} | |
}); | |
const moduleHandle = Process.findModuleByName('libpairipcore.so'); | |
if (!moduleHandle) { | |
console.log("[-] libpairipcore.so not found!"); | |
return; | |
} | |
const registerNativesOffset = moduleHandle.base.add(0x6a3b4); | |
Interceptor.attach(registerNativesOffset, { | |
onEnter: function(args) { | |
console.log("[+] RegisterNatives called"); | |
console.log(" JNIEnv*:", this.context.x0); | |
console.log(" jclass:", this.context.x1); | |
console.log(" JNINativeMethod*:", this.context.x2); | |
console.log(" nMethods:", this.context.x3); | |
const nMethods = this.context.x3.toInt32(); | |
const methods = this.context.x2; | |
for(let i = 0; i < nMethods; i++) { | |
const methodInfo = methods.add(i * Process.pointerSize * 3); | |
const name = methodInfo.readPointer().readCString(); | |
const sig = methodInfo.add(Process.pointerSize).readPointer().readCString(); | |
const fnPtr = methodInfo.add(Process.pointerSize * 2).readPointer(); | |
const ghidraOffset = ptr(fnPtr).sub(moduleHandle.base).add(0x00100000); | |
console.log(` Method[${i}]:`); | |
console.log(` name: ${name}`); | |
console.log(` signature: ${sig}`); | |
console.log(` fnPtr: ${fnPtr}`); | |
console.log(` ghidraOffset: ${ghidraOffset}`); | |
console.log(` Ghidra offset: 0x${ghidraOffset.toString(16)}`); | |
console.log(`[+] ${name} function's memory dump:`); | |
const dumpSize = 128; | |
const dumpData = Memory.readByteArray(fnPtr, dumpSize); | |
console.log(hexdump(dumpData, { | |
offset: 0, | |
length: dumpSize, | |
header: true, | |
ansi: false | |
})); | |
} | |
}, | |
onLeave: function(retval) { | |
console.log("[+] RegisterNatives finished, return value is:", retval); | |
} | |
}); | |
} | |
function startStalker(threadId, targetModule){ | |
Stalker.follow(threadId, { | |
transform: function(iterator){ | |
var instruction; | |
while((instruction = iterator.next()) != null){ | |
if(instruction.address <= targetModule.base.add(targetModule.size) && | |
instruction.address >= targetModule.base){ | |
var offset = instruction.address.sub(targetModule.base); | |
console.log(`[+] ${offset}: ${instruction.toString()}`); | |
if (instruction.mnemonic.startsWith('bl') || instruction.mnemonic.startsWith('b.')) { | |
iterator.putCallout(function(context) { | |
console.log(` x8=${context.x8.toString(16)}`); | |
console.log(` x0=${context.x0.toString(16)}`); | |
var moduleDetails = Process.findModuleByAddress(context.x8); | |
if (moduleDetails) { | |
console.log(` Module: ${moduleDetails.name}`); | |
console.log(` Base: ${moduleDetails.base}`); | |
console.log(` Offset in module: 0x${context.x8.sub(moduleDetails.base).toString(16)}`); | |
var symbol = DebugSymbol.fromAddress(context.x8); | |
if (symbol && symbol.name && symbol.name.indexOf("0x") == -1) { | |
console.log(` Symbol: ${symbol.name}`); | |
} | |
} | |
}); | |
} | |
} | |
iterator.keep(); | |
} | |
} | |
}); | |
} | |
function stopStalker(threadId){ | |
Stalker.unfollow(threadId); | |
Stalker.flush(); | |
} | |
var libnative_loaded = 0; | |
var do_dlopen = null; | |
var call_ctor = null; | |
Process.findModuleByName('linker64').enumerateSymbols().forEach(function (sym) { | |
if (sym.name.indexOf('do_dlopen') >= 0) { | |
do_dlopen = sym.address; | |
} else if (sym.name.indexOf('call_constructor') >= 0) { | |
call_ctor = sym.address; | |
} | |
}); | |
Interceptor.attach(do_dlopen, function () { | |
var libraryPath = this.context.x0.readCString(); | |
if (libraryPath.indexOf('libpairipcore.so') > -1) { | |
console.log(`libpairipcore.so loaded.`); | |
Interceptor.attach(call_ctor, function () { | |
if (libnative_loaded == 0) { | |
var native_mod = Process.findModuleByName('libpairipcore.so'); | |
console.warn(`[+] libpairipcore.so loaded @${native_mod.base}`); | |
hookNative(); | |
} | |
libnative_loaded = 1; | |
}); | |
} | |
}); | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment