yang神脚本大全:
https://codeooo.blog.csdn.net/article/details/122988215
pip install unicorn
pip install androidemu
AndroidNativeEmu
https://gitee.com/keji8/ExAndroidNativeEmu/
https://github.com/AeonLucid/AndroidNativeEmu
# -*- coding: utf-8 -*-
# @Author : Codeooo
# @Time : 2022-09-29
import logging
import posixpath
import sys
import os
from unicorn import *
from unicorn.arm_const import *
from androidemu.emulator import Emulator
from androidemu.java.java_class_def import JavaClassDef
from androidemu.java.java_method_def import java_method_def
import androidemu.utils.debug_utils
from androidemu.utils.chain_log import ChainLogger
from androidemu.java.classes.string import String
import capstone
import traceback
g_cfd = ChainLogger(sys.stdout, "./ins-jni.txt")
# Add debugging.
def hook_code(mu, address, size, user_data):
try:
emu = user_data
if (not emu.memory.check_addr(address, UC_PROT_EXEC)):
logger.error("addr 0x%08X out of range" % (address,))
sys.exit(-1)
#
# androidemu.utils.debug_utils.dump_registers(mu, sys.stdout)
androidemu.utils.debug_utils.dump_code(emu, address, size, g_cfd)
except Exception as e:
logger.exception("exception in hook_code")
sys.exit(-1)
#
#
def hook_mem_read(uc, access, address, size, value, user_data):
pc = uc.reg_read(UC_ARM_REG_PC)
if (address == 0xCBC80640):
logger.debug("read mutex")
data = uc.mem_read(address, size)
v = int.from_bytes(data, byteorder='little', signed=False)
logger.debug(
">>> Memory READ at 0x%08X, data size = %u, data value = 0x%08X, pc: 0x%08X," % (address, size, v, pc))
#
#
def hook_mem_write(uc, access, address, size, value, user_data):
pc = uc.reg_read(UC_ARM_REG_PC)
if (address == 0xCBC80640):
logger.debug("write mutex")
logger.debug(
">>> Memory WRITE at 0x%08X, data size = %u, data value = 0x%08X, pc: 0x%08X" % (address, size, value, pc))
#
#
class MainActivity(metaclass=JavaClassDef, jvm_name='com/roysue/easyso1/MainActivity'):
def __init__(self):
pass
@java_method_def(name='decrypt', signature='(Ljava/lang/String;)Ljava/lang/String;', native=True)
def decrypt(self, mu):
pass
def test(self):
pass
logger = logging.getLogger(__name__)
# Initialize emulator
emulator = Emulator(
vfs_root=posixpath.join(posixpath.dirname(__file__), "vfs")
)
# Register Java class.
emulator.java_classloader.add_class(MainActivity)
# emulator.mu.hook_add(UC_HOOK_CODE, hook_code, emulator)
# emulator.mu.hook_add(UC_HOOK_MEM_WRITE, hook_mem_write)
# emulator.mu.hook_add(UC_HOOK_MEM_READ, hook_mem_read)
# Load all libraries.
lib_module = emulator.load_library("tests/bin/libroysue2.so")
# androidemu.utils.debug_utils.dump_symbols(emulator, sys.stdout)
# Show loaded modules.
logger.info("Loaded modules:")
for module in emulator.modules:
logger.info("=> 0x%08x - %s" % (module.base, module.filename))
try:
# Run JNI_OnLoad.
# JNI_OnLoad will call 'RegisterNatives'.
emulator.call_symbol(lib_module, 'JNI_OnLoad', emulator.java_vm.address_ptr, 0x00)
# Do native stuff.
# main_activity = MainActivity()
# logger.info("Response from JNI call: %s" % main_activity.string_from_jni(emulator))
logger.info(
"Response from JNI call: %s" % emulator.call_symbol(lib_module, "Java_com_roysue_easyso1_MainActivity_method01",
emulator.java_vm.jni_env.address_ptr, 0x00,
String('Hellor0ysue12345')))
logger.info(
"Response from JNI call: %s" % emulator.call_symbol(lib_module, "_Z8method02P7_JNIEnvP7_jclassP8_jstring",
emulator.java_vm.jni_env.address_ptr, 0x00, String(
'9979a01fb97395969d358aa0f4c8fbdc3828d9b706c8cac023c4346a9d9c424e')))
# Dump natives found.
logger.info("Exited EMU.")
# logger.info("Native methods registered to MainActivity:")
except UcError as e:
print("Exit at %x" % emulator.mu.reg_read(UC_ARM_REG_PC))
raise
h2.js
function hookJava(){
Java.perform(function(){
console.log("hooking java...")
Java.use("com.roysue.easyso1.MainActivity").decrypt.implementation = function(str){
var result = this.decrypt(str)
console.log("str,result => ,",str,result)
return result;
}
})
}
function invokeJava(){
Java.perform(function(){
var result = Java.use("com.roysue.easyso1.MainActivity").decrypt("82e8edd5b05654bf0fedcdfc1c9b4b0f")
console.log("result => ,",result)
})
}
var is_hook_libart = false;
function hook_dlopen() {
Interceptor.attach(Module.findExportByName(null, "dlopen"), {
onEnter: function(args) {
var pathptr = args[0];
if (pathptr !== undefined && pathptr != null) {
var path = ptr(pathptr).readCString();
console.log("dlopen:", path);
if (path.indexOf("libroysue.so") >= 0) {
this.can_hook_libart = true;
console.log("[dlopen:]", path);
}
}
},
onLeave: function(retval) {
if (this.can_hook_libart && !is_hook_libart) {
is_hook_libart = true;
}
}
})
Interceptor.attach(Module.findExportByName(null, "android_dlopen_ext"), {
onEnter: function(args) {
var pathptr = args[0];
if (pathptr !== undefined && pathptr != null) {
var path = ptr(pathptr).readCString();
console.log("android_dlopen_ext:", path);
if (path.indexOf("libroysue.so") >= 0) {
this.can_hook_libart = true;
console.log("[android_dlopen_ext:]", path);
}
}
},
onLeave: function(retval) {
if (this.can_hook_libart && !is_hook_libart) {
is_hook_libart = true;
var method01 = Module.findExportByName("libroysue.so", "Java_com_roysue_easyso1_MainActivity_method01")
var method02 = Module.findExportByName("libroysue.so", "_Z8method02P7_JNIEnvP7_jclassP8_jstring")
console.log("method01 address is =>",method01)
console.log("method02 address is =>",method02)
// Interceptor.attach(method01,{
// onEnter:function(args){
// console.log("arg[2=>",args[2])
// },onLeave:function(retval){
// console.log("retval=>",retval)
// }
// })
// Interceptor.attach(method02,{
// onEnter:function(args){
// console.log("method02 arg[2=>",Java.vm.getEnv().getStringUtfChars(args[2], null).readCString())
// },onLeave:function(retval){
// console.log("method02 retval=>",Java.vm.getEnv().getStringUtfChars(retval, null).readCString())
// }
// })
}
}
});
}
function main(){
console.log("Entering main...")
// hookJava()
hook_dlopen()
}
setImmediate(main)
动态注册魔改:
var ENV = null;
var JCLZ = null;
var method01addr = null;
var method02addr = null;
var method02 = null;
var addrNewStringUTF = null;
var NewStringUTF = null;
function hook_RegisterNatives() {
var symbols = Module.enumerateSymbolsSync("libart.so");
var addrRegisterNatives = null;
for (var i = 0; i < symbols.length; i++) {
var symbol = symbols[i];
//_ZN3art3JNI15RegisterNativesEP7_JNIEnvP7_jclassPK15JNINativeMethodi
if (symbol.name.indexOf("art") >= 0 &&
symbol.name.indexOf("JNI") >= 0 &&
symbol.name.indexOf("NewStringUTF") >= 0 &&
symbol.name.indexOf("CheckJNI") < 0) {
addrNewStringUTF = symbol.address;
console.log("NewStringUTF is at ", symbol.address, symbol.name);
NewStringUTF = new NativeFunction(addrNewStringUTF,'pointer',['pointer','pointer'])
}
if (symbol.name.indexOf("art") >= 0 &&
symbol.name.indexOf("JNI") >= 0 &&
symbol.name.indexOf("RegisterNatives") >= 0 &&
symbol.name.indexOf("CheckJNI") < 0) {
addrRegisterNatives = symbol.address;
console.log("RegisterNatives is at ", symbol.address, symbol.name);
}
}
if (addrRegisterNatives != null) {
Interceptor.attach(addrRegisterNatives, {
onEnter: function (args) {
console.log("[RegisterNatives] method_count:", args[3]);
var env = args[0];
ENV = args[0];
var java_class = args[1];
JCLZ = args[1];
var class_name = Java.vm.tryGetEnv().getClassName(java_class);
//console.log(class_name);
var methods_ptr = ptr(args[2]);
var method_count = parseInt(args[3]);
for (var i = 0; i < method_count; i++) {
var name_ptr = Memory.readPointer(methods_ptr.add(i * Process.pointerSize * 3));
var sig_ptr = Memory.readPointer(methods_ptr.add(i * Process.pointerSize * 3 + Process.pointerSize));
var fnPtr_ptr = Memory.readPointer(methods_ptr.add(i * Process.pointerSize * 3 + Process.pointerSize * 2));
var name = Memory.readCString(name_ptr);
var sig = Memory.readCString(sig_ptr);
var find_module = Process.findModuleByAddress(fnPtr_ptr);
console.log("[RegisterNatives] java_class:", class_name, "name:", name, "sig:", sig, "fnPtr:", fnPtr_ptr, "module_name:", find_module.name, "module_base:", find_module.base, "offset:", ptr(fnPtr_ptr).sub(find_module.base));
if(name.indexOf("method01")>=0){
// method01addr = fnPtr_ptr;
continue;
}else if (name.indexOf("decrypt")>=0){
method02addr = fnPtr_ptr;
method02 = new NativeFunction(method02addr,'pointer',['pointer','pointer','pointer']);
method01addr = Module.findExportByName("libroysue.so", "Java_com_roysue_easyso1_MainActivity_method01")
}else{
continue;
}
}
}
});
}
}
function invokemethod01(contents){
console.log("method01_addr is =>",method01addr)
var method01 = new NativeFunction(method01addr,'pointer',['pointer','pointer','pointer']);
var NewStringUTF = new NativeFunction(addrNewStringUTF,'pointer',['pointer','pointer'])
var result = null;
Java.perform(function(){
console.log("Java.vm.getEnv()",Java.vm.getEnv())
var JSTRING = NewStringUTF(Java.vm.getEnv(),Memory.allocUtf8String(contents))
result = method01(Java.vm.getEnv(),JSTRING,JSTRING);
console.log("result is =>",result)
console.log("result is ",Java.vm.getEnv().getStringUtfChars(result, null).readCString())
result = Java.vm.getEnv().getStringUtfChars(result, null).readCString();
})
return result;
}
function invokemethod02(contents){
var result = null;
Java.perform(function(){
var JSTRING = NewStringUTF(Java.vm.getEnv(),Memory.allocUtf8String(contents))
result = method02(Java.vm.getEnv(),JSTRING,JSTRING);
result = Java.vm.getEnv().getStringUtfChars(result, null).readCString();
})
return result;
}
rpc.exports = {
invoke1:invokemethod01,
invoke2:invokemethod02
};
setImmediate(hook_RegisterNatives);
/*
java_class: com.example.demoso1.MainActivity name: method01 sig: (Ljava/lang/String;)Ljava/lang/String; fnPtr: 0x73e2cd1018 module_name: libnative-lib.so module_base: 0x73e2cc1000 offset: 0x10018
java_class: com.example.demoso1.MainActivity name: method02 sig: (Ljava/lang/String;)Ljava/lang/String; fnPtr: 0x73e2cd0efc module_name: libnative-lib.so module_base: 0x73e2cc1000 offset: 0xfefc
function hookmethod(addr){
Interceptor.attach(addr,{
onEnter:function(args){
console.log("args[0]=>",args[0])
console.log("args[1]=>",args[1])
console.log("args[2]=>",Java.vm.getEnv().getStringUtfChars(args[2], null).readCString())
},onLeave:function(retval){
console.log(Java.vm.getEnv().getStringUtfChars(retval, null).readCString())
}
})
}
function replacehook(addr){
//> 能够hook上,就能主动调用
var addrfunc = new NativeFunction(addr,'pointer',['pointer','pointer','pointer']);
Interceptor.replace(addr,new NativeCallback(function(arg1,arg2,arg3){
// 确定主动调用可以成功,只要参数合法,地址正确
var result = addrfunc(arg1,arg2,arg3)
console.log(arg1,arg2,arg3)
console.log("result is ",Java.vm.getEnv().getStringUtfChars(result, null).readCString())
return result;
},'pointer',['pointer','pointer','pointer']))
}
*/
frida -U --no-pause -f package_name -l hook_art.js
const STD_STRING_SIZE = 3 * Process.pointerSize;
class StdString {
constructor() {
this.handle = Memory.alloc(STD_STRING_SIZE);
}
dispose() {
const [data, isTiny] = this._getData();
if (!isTiny) {
Java.api.$delete(data);
}
}
disposeToString() {
const result = this.toString();
this.dispose();
return result;
}
toString() {
const [data] = this._getData();
return data.readUtf8String();
}
_getData() {
const str = this.handle;
const isTiny = (str.readU8() & 1) === 0;
const data = isTiny ? str.add(1) : str.add(2 * Process.pointerSize).readPointer();
return [data, isTiny];
}
}
function prettyMethod(method_id, withSignature) {
const result = new StdString();
Java.api['art::ArtMethod::PrettyMethod'](result, method_id, withSignature ? 1 : 0);
return result.disposeToString();
}
/*
GetFieldID is at 0xe39b87c5 _ZN3art3JNI10GetFieldIDEP7_JNIEnvP7_jclassPKcS6_
GetMethodID is at 0xe39a1a19 _ZN3art3JNI11GetMethodIDEP7_JNIEnvP7_jclassPKcS6_
NewStringUTF is at 0xe39cff25 _ZN3art3JNI12NewStringUTFEP7_JNIEnvPKc
RegisterNatives is at 0xe39e08fd _ZN3art3JNI15RegisterNativesEP7_JNIEnvP7_jclassPK15JNINativeMethodi
GetStaticFieldID is at 0xe39c9635 _ZN3art3JNI16GetStaticFieldIDEP7_JNIEnvP7_jclassPKcS6_
GetStaticMethodID is at 0xe39be0ed _ZN3art3JNI17GetStaticMethodIDEP7_JNIEnvP7_jclassPKcS6_
GetStringUTFChars is at 0xe39d06e5 _ZN3art3JNI17GetStringUTFCharsEP7_JNIEnvP8_jstringPh
FindClass is at 0xe399ae5d _ZN3art3JNI9FindClassEP7_JNIEnvPKc
*/
function hook_libart() {
var symbols = Module.enumerateSymbolsSync("libart.so");
var addrGetStringUTFChars = null;
var addrNewStringUTF = null;
var addrFindClass = null;
var addrGetMethodID = null;
var addrGetStaticMethodID = null;
var addrGetFieldID = null;
var addrGetStaticFieldID = null;
var addrRegisterNatives = null;
var so_name = "lib"; //TODO 这里写需要过滤的so
for (var i = 0; i < symbols.length; i++) {
var symbol = symbols[i];
if (symbol.name.indexOf("art") >= 0 &&
symbol.name.indexOf("JNI") >= 0 &&
symbol.name.indexOf("CheckJNI") < 0 &&
symbol.name.indexOf("_ZN3art3JNIILb0") >= 0
) {
if (symbol.name.indexOf("GetStringUTFChars") >= 0) {
addrGetStringUTFChars = symbol.address;
console.log("GetStringUTFChars is at ", symbol.address, symbol.name);
} else if (symbol.name.indexOf("NewStringUTF") >= 0) {
addrNewStringUTF = symbol.address;
console.log("NewStringUTF is at ", symbol.address, symbol.name);
} else if (symbol.name.indexOf("FindClass") >= 0) {
addrFindClass = symbol.address;
console.log("FindClass is at ", symbol.address, symbol.name);
} else if (symbol.name.indexOf("GetMethodID") >= 0) {
addrGetMethodID = symbol.address;
console.log("GetMethodID is at ", symbol.address, symbol.name);
} else if (symbol.name.indexOf("GetStaticMethodID") >= 0) {
addrGetStaticMethodID = symbol.address;
console.log("GetStaticMethodID is at ", symbol.address, symbol.name);
} else if (symbol.name.indexOf("GetFieldID") >= 0) {
addrGetFieldID = symbol.address;
console.log("GetFieldID is at ", symbol.address, symbol.name);
} else if (symbol.name.indexOf("GetStaticFieldID") >= 0) {
addrGetStaticFieldID = symbol.address;
console.log("GetStaticFieldID is at ", symbol.address, symbol.name);
} else if (symbol.name.indexOf("RegisterNatives") >= 0) {
addrRegisterNatives = symbol.address;
console.log("RegisterNatives is at ", symbol.address, symbol.name);
} else if (symbol.name.indexOf("CallStatic") >= 0) {
console.log("CallStatic is at ", symbol.address, symbol.name);
Interceptor.attach(symbol.address, {
onEnter: function (args) {
var module = Process.findModuleByAddress(this.returnAddress);
if (module != null && module.name.indexOf(so_name) == 0) {
var java_class = args[1];
var mid = args[2];
var class_name = Java.vm.tryGetEnv().getClassName(java_class);
if (class_name.indexOf("java.") == -1 && class_name.indexOf("android.") == -1) {
var method_name = prettyMethod(mid, 1);
console.log("<>CallStatic:", DebugSymbol.fromAddress(this.returnAddress), class_name, method_name);
}
}
},
onLeave: function (retval) { }
});
} else if (symbol.name.indexOf("CallNonvirtual") >= 0) {
console.log("CallNonvirtual is at ", symbol.address, symbol.name);
Interceptor.attach(symbol.address, {
onEnter: function (args) {
var module = Process.findModuleByAddress(this.returnAddress);
if (module != null && module.name.indexOf(so_name) == 0) {
var jobject = args[1];
var jclass = args[2];
var jmethodID = args[3];
var obj_class_name = Java.vm.tryGetEnv().getObjectClassName(jobject);
var class_name = Java.vm.tryGetEnv().getClassName(jclass);
if (class_name.indexOf("java.") == -1 && class_name.indexOf("android.") == -1) {
var method_name = prettyMethod(jmethodID, 1);
console.log("<>CallNonvirtual:", DebugSymbol.fromAddress(this.returnAddress), class_name, obj_class_name, method_name);
}
}
},
onLeave: function (retval) { }
});
} else if (symbol.name.indexOf("Call") >= 0 && symbol.name.indexOf("Method") >= 0) {
console.log("Call<>Method is at ", symbol.address, symbol.name);
Interceptor.attach(symbol.address, {
onEnter: function (args) {
var module = Process.findModuleByAddress(this.returnAddress);
if (module != null && module.name.indexOf(so_name) == 0) {
var java_class = args[1];
var mid = args[2];
var class_name = Java.vm.tryGetEnv().getObjectClassName(java_class);
if (class_name.indexOf("java.") == -1 && class_name.indexOf("android.") == -1) {
var method_name = prettyMethod(mid, 1);
console.log("<>Call<>Method:", DebugSymbol.fromAddress(this.returnAddress), class_name, method_name);
}
}
},
onLeave: function (retval) { }
});
}
}
}
if (addrGetStringUTFChars != null) {
Interceptor.attach(addrGetStringUTFChars, {
onEnter: function (args) {
},
onLeave: function (retval) {
if (retval != null) {
var module = Process.findModuleByAddress(this.returnAddress);
if (module != null && module.name.indexOf(so_name) == 0) {
var bytes = Memory.readCString(retval);
console.log("[GetStringUTFChars] result:" + bytes, DebugSymbol.fromAddress(this.returnAddress));
}
}
}
});
}
if (addrNewStringUTF != null) {
Interceptor.attach(addrNewStringUTF, {
onEnter: function (args) {
if (args[1] != null) {
var module = Process.findModuleByAddress(this.returnAddress);
if (module != null && module.name.indexOf(so_name) == 0) {
var string = Memory.readCString(args[1]);
console.log("[NewStringUTF] bytes:" + string, DebugSymbol.fromAddress(this.returnAddress));
}
}
},
onLeave: function (retval) { }
});
}
if (addrFindClass != null) {
Interceptor.attach(addrFindClass, {
onEnter: function (args) {
if (args[1] != null) {
var module = Process.findModuleByAddress(this.returnAddress);
if (module != null && module.name.indexOf(so_name) == 0) {
var name = Memory.readCString(args[1]);
console.log("[FindClass] name:" + name, DebugSymbol.fromAddress(this.returnAddress));
}
}
},
onLeave: function (retval) { }
});
}
if (addrGetMethodID != null) {
Interceptor.attach(addrGetMethodID, {
onEnter: function (args) {
if (args[2] != null) {
var clazz = args[1];
var class_name = Java.vm.tryGetEnv().getClassName(clazz);
var module = Process.findModuleByAddress(this.returnAddress);
if (module != null && module.name.indexOf(so_name) == 0) {
var name = Memory.readCString(args[2]);
if (args[3] != null) {
var sig = Memory.readCString(args[3]);
console.log("[GetMethodID] class_name:" + class_name + " name:" + name + ", sig:" + sig, DebugSymbol.fromAddress(this.returnAddress));
} else {
console.log("[GetMethodID] class_name:" + class_name + " name:" + name, DebugSymbol.fromAddress(this.returnAddress));
}
}
}
},
onLeave: function (retval) { }
});
}
if (addrGetStaticMethodID != null) {
Interceptor.attach(addrGetStaticMethodID, {
onEnter: function (args) {
if (args[2] != null) {
var clazz = args[1];
var class_name = Java.vm.tryGetEnv().getClassName(clazz);
var module = Process.findModuleByAddress(this.returnAddress);
if (module != null && module.name.indexOf(so_name) == 0) {
var name = Memory.readCString(args[2]);
if (args[3] != null) {
var sig = Memory.readCString(args[3]);
console.log("[GetStaticMethodID] class_name:" + class_name + " name:" + name + ", sig:" + sig, DebugSymbol.fromAddress(this.returnAddress));
} else {
console.log("[GetStaticMethodID] class_name:" + class_name + " name:" + name, DebugSymbol.fromAddress(this.returnAddress));
}
}
}
},
onLeave: function (retval) { }
});
}
if (addrGetFieldID != null) {
Interceptor.attach(addrGetFieldID, {
onEnter: function (args) {
if (args[2] != null) {
var module = Process.findModuleByAddress(this.returnAddress);
if (module != null && module.name.indexOf(so_name) == 0) {
var name = Memory.readCString(args[2]);
if (args[3] != null) {
var sig = Memory.readCString(args[3]);
console.log("[GetFieldID] name:" + name + ", sig:" + sig, DebugSymbol.fromAddress(this.returnAddress));
} else {
console.log("[GetFieldID] name:" + name, DebugSymbol.fromAddress(this.returnAddress));
}
}
}
},
onLeave: function (retval) { }
});
}
if (addrGetStaticFieldID != null) {
Interceptor.attach(addrGetStaticFieldID, {
onEnter: function (args) {
if (args[2] != null) {
var module = Process.findModuleByAddress(this.returnAddress);
if (module != null && module.name.indexOf(so_name) == 0) {
var name = Memory.readCString(args[2]);
if (args[3] != null) {
var sig = Memory.readCString(args[3]);
console.log("[GetStaticFieldID] name:" + name + ", sig:" + sig, DebugSymbol.fromAddress(this.returnAddress));
} else {
console.log("[GetStaticFieldID] name:" + name, DebugSymbol.fromAddress(this.returnAddress));
}
}
}
},
onLeave: function (retval) { }
});
}
if (addrRegisterNatives != null) {
Interceptor.attach(addrRegisterNatives, {
onEnter: function (args) {
console.log("[RegisterNatives] method_count:", args[3], DebugSymbol.fromAddress(this.returnAddress));
var env = args[0];
var java_class = args[1];
var class_name = Java.vm.tryGetEnv().getClassName(java_class);
var methods_ptr = ptr(args[2]);
var method_count = parseInt(args[3]);
for (var i = 0; i < method_count; i++) {
var name_ptr = Memory.readPointer(methods_ptr.add(i * Process.pointerSize * 3));
var sig_ptr = Memory.readPointer(methods_ptr.add(i * Process.pointerSize * 3 + Process.pointerSize));
var fnPtr_ptr = Memory.readPointer(methods_ptr.add(i * Process.pointerSize * 3 + Process.pointerSize * 2));
var name = Memory.readCString(name_ptr);
var sig = Memory.readCString(sig_ptr);
var find_module = Process.findModuleByAddress(fnPtr_ptr);
console.log("[RegisterNatives] java_class:", class_name, "name:", name, "sig:", sig, "fnPtr:", fnPtr_ptr, "module_name:", find_module.name, "module_base:", find_module.base, "offset:", ptr(fnPtr_ptr).sub(find_module.base));
}
},
onLeave: function (retval) { }
});
}
}
setImmediate(hook_libart);
frida -U --no-pause -f package_name -l hook_artmethod.js -o hook_artmethod.log
const STD_STRING_SIZE = 3 * Process.pointerSize;
class StdString {
constructor() {
this.handle = Memory.alloc(STD_STRING_SIZE);
}
dispose() {
const [data, isTiny] = this._getData();
if (!isTiny) {
Java.api.$delete(data);
}
}
disposeToString() {
const result = this.toString();
this.dispose();
return result;
}
toString() {
const [data] = this._getData();
return data.readUtf8String();
}
_getData() {
const str = this.handle;
const isTiny = (str.readU8() & 1) === 0;
const data = isTiny ? str.add(1) : str.add(2 * Process.pointerSize).readPointer();
return [data, isTiny];
}
}
function prettyMethod(method_id, withSignature) {
const result = new StdString();
Java.api['art::ArtMethod::PrettyMethod'](result, method_id, withSignature ? 1 : 0);
return result.disposeToString();
}
function hook_dlopen(module_name, fun) {
var android_dlopen_ext = Module.findExportByName(null, "android_dlopen_ext");
if (android_dlopen_ext) {
Interceptor.attach(android_dlopen_ext, {
onEnter: function (args) {
var pathptr = args[0];
if (pathptr) {
this.path = (pathptr).readCString();
if (this.path.indexOf(module_name) >= 0) {
this.canhook = true;
console.log("android_dlopen_ext:", this.path);
}
}
},
onLeave: function (retval) {
if (this.canhook) {
fun();
}
}
});
}
var dlopen = Module.findExportByName(null, "dlopen");
if (dlopen) {
Interceptor.attach(dlopen, {
onEnter: function (args) {
var pathptr = args[0];
if (pathptr) {
this.path = (pathptr).readCString();
if (this.path.indexOf(module_name) >= 0) {
this.canhook = true;
console.log("dlopen:", this.path);
}
}
},
onLeave: function (retval) {
if (this.canhook) {
fun();
}
}
});
}
console.log("android_dlopen_ext:", android_dlopen_ext, "dlopen:", dlopen);
}
function hook_native() {
var module_libart = Process.findModuleByName("libart.so");
var symbols = module_libart.enumerateSymbols();
var ArtMethod_Invoke = null;
for (var i = 0; i < symbols.length; i++) {
var symbol = symbols[i];
var address = symbol.address;
var name = symbol.name;
var indexArtMethod = name.indexOf("ArtMethod");
var indexInvoke = name.indexOf("Invoke");
var indexThread = name.indexOf("Thread");
if (indexArtMethod >= 0
&& indexInvoke >= 0
&& indexThread >= 0
&& indexArtMethod < indexInvoke
&& indexInvoke < indexThread) {
console.log(name);
ArtMethod_Invoke = address;
}
}
if (ArtMethod_Invoke) {
Interceptor.attach(ArtMethod_Invoke, {
onEnter: function (args) {
var method_name = prettyMethod(args[0], 0);
if (!(method_name.indexOf("java.") == 0 || method_name.indexOf("android.") == 0)) {
console.log("ArtMethod Invoke:" + method_name + ' called from:\n' +
Thread.backtrace(this.context, Backtracer.ACCURATE)
.map(DebugSymbol.fromAddress).join('\n') + '\n');
}
}
});
}
}
function main() {
hook_dlopen("libart.so", hook_native);
hook_native();
}
setImmediate(main);