From 1284c9257df3ed17cb6138ed629ca64aa0b1db12 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ole=20Andr=C3=A9=20Vadla=20Ravn=C3=A5s?= Date: Fri, 13 Dec 2024 12:06:13 +0100 Subject: [PATCH] WIP --- lib/android.js | 126 ++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 105 insertions(+), 21 deletions(-) diff --git a/lib/android.js b/lib/android.js index 849ee64..1506136 100644 --- a/lib/android.js +++ b/lib/android.js @@ -578,27 +578,10 @@ function tryGetEnvJvmti (vm, runtime) { let env = null; vm.perform(() => { - let ensurePluginLoadedAddr = Module.findExportByName('libart.so', '_ZN3art7Runtime18EnsurePluginLoadedEPKcPNSt3__112basic_stringIcNS3_11char_traitsIcEENS3_9allocatorIcEEEE'); - if (ensurePluginLoadedAddr === null) { - const libopenjdkjvmtiSoString = '6c 69 62 6f 70 65 6e 6a 64 6b 6a 76 6d 74 69 2e 73 6f'; - const libopenjdkjvmtiSoAddr = findStringInRodata('libart.so', libopenjdkjvmtiSoString); - if (libopenjdkjvmtiSoAddr !== null) { - if (Process.arch === 'arm64') { - ensurePluginLoadedAddr = findPcRelativeReferenceToString('libart.so', '?1 ?? ff ?0 21 ?? ?? 91', 0, libopenjdkjvmtiSoAddr, - match => scanForward(match.last.next, 4, insn => { - const mnemonic = insn.mnemonic; - return (mnemonic === 'b' || mnemonic === 'bl') ? ptr(insn.operands[0].value) : null; - }) - ); - } else { - ensurePluginLoadedAddr = findPcRelativeReferenceToString('libart.so', '49 0d f1 ?? 0a', -1, libopenjdkjvmtiSoAddr, - match => scanForward(match.last.next, 4, insn => { - return (insn.mnemonic === 'bl') ? ptr(insn.operands[0].value).or(1) : null; - }) - ); - } - } - } + const t1 = Date.now(); + const ensurePluginLoadedAddr = findArtEnsurePluginMatbrik(); + const t2 = Date.now(); + console.log(`Found EnsurePluginLoaded in ${t2 - t1} ms`); if (ensurePluginLoadedAddr === null) { return; } @@ -630,6 +613,107 @@ function tryGetEnvJvmti (vm, runtime) { return env; } +function findArtEnsurePluginMatbrik () { + const impl = Module.findExportByName('libart.so', '_ZN3art7Runtime18EnsurePluginLoadedEPKcPNSt3__112basic_stringIcNS3_11char_traitsIcEENS3_9allocatorIcEEEE'); + if (impl !== null) { + return impl; + } + + const results = findString('libopenjdkjvmti.so', 'libart.so'); + const pattern = makeArm64PcRelAddPattern(results[0].address, 'x1'); + const patternResults = findPattern(pattern, 'libart.so'); + return patternResults.map((match) => { + const possibleBranch = match.address.add(4); + const disasm = Instruction.parse(possibleBranch); + if (disasm.mnemonic === 'b') { + return ptr(disasm.operands[0].value); + } + return null; + }).filter(element => element !== null).flat()[0]; +} + +function findArtEnsurePluginHackcatml () { + const impl = Module.findExportByName('libart.so', '_ZN3art7Runtime18EnsurePluginLoadedEPKcPNSt3__112basic_stringIcNS3_11char_traitsIcEENS3_9allocatorIcEEEE'); + if (impl !== null) { + return impl; + } + + const libopenjdkjvmtiSoString = '6c 69 62 6f 70 65 6e 6a 64 6b 6a 76 6d 74 69 2e 73 6f'; + const libopenjdkjvmtiSoAddr = findStringInRodata('libart.so', libopenjdkjvmtiSoString); + if (libopenjdkjvmtiSoAddr === null) { + return null; + } + + if (Process.arch === 'arm64') { + return findPcRelativeReferenceToString('libart.so', '?1 ?? ff ?0 21 ?? ?? 91', 0, libopenjdkjvmtiSoAddr, + match => scanForward(match.last.next, 4, insn => { + const mnemonic = insn.mnemonic; + return (mnemonic === 'b' || mnemonic === 'bl') ? ptr(insn.operands[0].value) : null; + }) + ); + } else { + return findPcRelativeReferenceToString('libart.so', '49 0d f1 ?? 0a', -1, libopenjdkjvmtiSoAddr, + match => scanForward(match.last.next, 4, insn => { + return (insn.mnemonic === 'bl') ? ptr(insn.operands[0].value).or(1) : null; + }) + ); + } +} + +// TODO: Move these + +function findString (string, moduleName) { + const module = Process.getModuleByName(moduleName); + const ranges = module.enumerateRanges('r--'); + const pattern = stringToBytesHex(string); + return ranges.map((range) => { + const base = range.base; + const size = range.size; + const result = Memory.scanSync(base, size, pattern); + if (result.length > 0) return result; + return null; + }).filter(element => element !== null).flat(); +} + +function findPattern (pattern, moduleName) { + const module = Process.getModuleByName(moduleName); + const ranges = module.enumerateRanges('r-x'); + return ranges.map((range) => { + const base = range.base; + const size = range.size; + const result = Memory.scanSync(base, size, pattern); + if (result.length !== 0) return result; + return null; + }).filter(element => element !== null).flat(); +} + +function makeArm64PcRelAddPattern (address, register) { + const buf = Memory.alloc(4); + const cw = new Arm64Writer(buf); + cw.putAddRegRegImm(register, register, address.and(0xfff).toUInt32()); + const code = new Uint8Array(ArrayBuffer.wrap(buf, 4)); + return Array.from(code).map(toHexByte).join(' '); +} + +function stringToBytesHex (str) { + const bytes = []; + const n = str.length; + for (let i = 0; i !== n; i++) { + bytes.push(toHexByte(str.charCodeAt(i))); + } + return bytes.join(' '); +} + +function toHexByte (val) { + const str = val.toString(16); + if (str.length === 1) { + return '0' + str; + } + return str; +} + +// + function ensureClassInitialized (env, classRef) { const api = getApi(); if (api.flavor !== 'art') {