frida使用转载
2022-10-20 本文已影响0人
le_du
转的ling 大佬的
/*
首先进行初始化,初始化一些函数地址
hook功能
1. java层hook
a. hookOneMethod yes
b. hookOneClass yes
c. hookAllMethod
d. hookAllMethod2
e. hook_loadLibrary0
2. jni层hook
a. hook_JNIRegisterNatives
b. hook_JNI_OnLoad
3. native层hook
a. hook_dlopen
b. hook_libc_kill_exit
c. hook_system_property
d. hook_android_log_print
e. hook_call_function
f. hook_call_array
g. hook_ArtMethod_Invoke yes
h. hook_ArtInterpreterToInterpreterBridge yes
h. hook_ArtInterpreterToCompiledCodeBridge yes
4. objection的一些功能函数
a. objection_getCurrentActivity yes
b. objection_getActivities yes
5. 脱壳
a. dexdump_DefineClass
b. dexdump_DexCache yes
c. dexdump_Dex
d. dexdump_LoadMethod
6. find功能
a. find yes
b. find2
c. findClasses
7. 莫名其妙的崩溃原因
1. 添加了native的backtrace
*/
//需要根据情况修改
var is_spawn = 0
var is_print_java_stackTrace = 1
var hook_java_enter = 0; // 默认java 调用完之后输出log,如果方法调用完之前崩溃,是看不到输出日志的。要在调用前输出日志,设置为1.
var is_print_native_stackTrace = 0
var is_print_args = 1; // print args
var is_print_retval = 1; // print retval
var run_env_num = 1;
var run_env = null;
if (run_env_num == 1) {
run_env = "arm"
} else if (run_env_num == 2) {
run_env = "arm64"
} else if (run_env_num == 3) {
run_env = "x86"
}
////////////////////////////////
//不需要修改
var is_hooked = false;
var context = null;
var currentApplication = null;
var StringClass = null;
var Base64Class = null;
var ins_all = [];
var last_ins = null;
var frida_major_version = null;
var android_sdk_version = null;
var has_save_permission = false;
var module_libart = null;
var DefineClass_addr = null;
var LoadMethod_addr = null;
var PrettyMethod_addr = null;
var ArtMethodRegisterNative_addr = null;
var JNIRegisterNatives_addr = null
var is_print_art_param = 1; // 配置hook_ArtInterpreterToInterpreterBridge的参数和返回值,如果设置为0可以快速的查看函数调用
var is_print_art_retval = 1;
var ArtMethodInvoke_addr = null;
var ArtInterpreterToCompiledCodeBridge_addr = null;
var ArtInterpreterToInterpreterBridge_addr = null;
var artQuickToInterpreterBridge_addr = null;
var artQuickGenericJniTrampoline_addr = null;
// 打印native的参数
function print_native_log(user_log_list, tag) {
if (tag == undefined) {
tag = ""
}
var num = 20
var start_symbol = "="
var end_symbol = "-"
var now = get_now()
user_log_list.unshift(now)
var log_start = new Array(num).join(start_symbol) + "[ThreadId:" + Process.getCurrentThreadId() + "]" + tag + " start!!!" + new Array(num).join(start_symbol)
user_log_list.unshift(log_start)
if (is_print_native_stackTrace) {
// user_log_list.push(console.log('called from:\n'+Thread.backtrace(this.context, Backtracer.ACCURATE).map(DebugSymbol.fromAddress).join('\n') + '\n'))
}
var log_end = new Array(num).join(end_symbol) + "[ThreadId:" + Process.getCurrentThreadId() + "]" + tag + " end!!!" + new Array(num).join(end_symbol)
user_log_list.push(log_end)
console.log(user_log_list.join("\n"));
}
function get_native_value(value_address, valuetype, index) {
if (valuetype == undefined) {
return "(" + valuetype + ")arg[" + index + "]";
}
valuetype = valuetype.replaceAll(" ", "")
var name = "(" + valuetype + ")arg[" + index + "]";
switch (valuetype) {
case "int":
name = name + ptr(value_address) + "=>" + value_address.readUInt()
break
case "long":
name = name + ptr(value_address) + "=>" + value_address.readLong()
break
case "byte":
name = name + ptr(value_address) + "=>" + value_address.readU8()
break
case "byte[]":
if (value_address.readUInt() == 0x0) {
// 空指针
name = name + ptr(value_address) + "=>" + "bytes0x0:null"
} else {
var tmp_value_address = ptr(value_address.readUInt()).add(0xc)
var byte_length = ptr(value_address.readUInt()).add(0x8).readUInt()
// var result = tmp_value_address.readByteArray(byte_length)
// name = name + ptr(value_address) + "=> byte_length:" +byte_length+"---result:"+hexdump(tmp_value_address,{length:byte_length})
var array = []
if (byte_length > 100) {
var print_byte_length = 100
} else {
var print_byte_length = byte_length
}
for (var i = 0; i < print_byte_length; i++) {
array.push(tmp_value_address.add(i).readU8())
}
var canToString = checkByteArrayFromString(array);
if (canToString) {
var param = Java.use("java.lang.String").$new(array)
var result = "[string]:" + param
} else {
var param_hex = bytesToHex(array);
var result = "[hex]:0x" + param_hex
}
name = name + ptr(value_address) + "=> byte_length:" + byte_length + "---result:" + result
// name = name + ptr(value_address) + "=> byte_length:" +byte_length+"---result:"+result+"\r\n"+hexdump(tmp_value_address)
}
break
case "char":
name = name + ptr(value_address) + "=>" + value_address.readU8()
break
case "float":
// console.log(hexdump(value_address))
name = name + ptr(value_address) + "=>" + value_address.readFloat()
break
case "boolean":
name = name + ptr(value_address) + "=>" + value_address.readPointer()
break
case "java.lang.String":
// try {
// if (ptr(value_address).readU32() != 0x0) {
// var string_len = ptr(ptr(value_address).readU32()).add(0x8).readUInt() / 2
// console.log("String != 0x0"+"\r\n"+hexdump(value_address)+"\r\n"+hexdump(ptr(ptr(value_address).readU32()))+"\r\n"+hexdump(ptr(ptr(ptr(value_address).readU32()).readU32()))+"---len:"+string_len)
// name = name + ptr(value_address) + "=>" + ptr(ptr(value_address).readU32()).add(0x10).readCString(string_len)
// } else if (ptr(value_address).readU32() == 0x8) {
// console.log("String == 0x8")
// name = name + ptr(value_address) + "=>" + ptr(value_address).add(0x10).readCString()
// } else {
// name = name + ptr(value_address) + "=>" + value_address
// }
// } catch (e) {
// console.log("error=======>" + e + " value_address=>" + value_address + "\r\n" + hexdump(value_address))
// name = name + ptr(value_address) + "=>" + value_address
// }
try {
if (ptr(value_address).readU32() == 0x0) {
// console.log("String == 0x8")
// console.log(hexdump(value_address))
// var string_len = ptr(ptr(value_address).readU32()).add(0x8).readUInt() / 2
// name = name + ptr(value_address) + "=>" + ptr(value_address).add(0x10).readCString()
name = name + ptr(value_address) + "=>string0x0:null"
} else if (ptr(value_address).readU32() == 0x8) {
name = name + ptr(value_address) + "=>string0x8:" + "\r\n" + hexdump((value_address)) + "\r\n"
}
else if (ptr(value_address).readU32() != 0x0) {
// console.log(hexdump(ptr(ptr(value_address).readU32())))
var string_len = ptr(ptr(value_address).readU32()).add(0x8).readUInt() / 2
name = name + ptr(value_address) + "=>" + ptr(ptr(value_address).readU32()).add(0x10).readCString(string_len)
} else {
// name = name + ptr(value_address) + "=>stringothers:" + value_address + "\r\n" + hexdump(ptr(ptr(value_address).readU32()))
name = name + ptr(value_address) + "=>stringothers:" + hexdump(value_address)
}
} catch (e) {
console.log("error=======>" + value_address + "\r\n" + e + " " + ptr(value_address.readUInt()) + "\r\n" + hexdump(value_address) + "\r\n")
name = name + ptr(value_address) + "=>" + value_address
}
// name = name + ptr(value_address) + "=>" + "\r\n" + hexdump(value_address) + "\r\n" + "ptr(value_address).readU32()" + ptr(value_address).readU32()
break
case "void":
break
default:
name = name + ptr(value_address) + "=>" + value_address
}
return name
}
// 获取当前时间
function get_now() {
var date = new Date()
var year = date.getFullYear()
var month = date.getMonth()
var day = date.getDate()
var hour = date.getHours()
var min = date.getMinutes()
var seconds = date.getSeconds()
var millsec = date.getMilliseconds()
var result1 = [year, month, day]
var result2 = [hour, min, seconds, millsec]
return "[CurrentTime]" + result1.join("-") + " " + result2.join(":")
}
// 将java的参数和返回值组装打印
function print_java_log(user_log_list, tag) {
Java.performNow(function () {
if (tag == undefined) {
tag = ""
}
var num = 20
var start_symbol = "="
var end_symbol = "-"
var now = get_now()
user_log_list.unshift(now)
var log_start = new Array(num).join(start_symbol) + "[ThreadId:" + Process.getCurrentThreadId() + "]" + tag + " start!!!" + new Array(num).join(start_symbol)
user_log_list.unshift(log_start)
if (is_print_java_stackTrace) {
user_log_list.push(Java.use("android.util.Log").getStackTraceString(Java.use("java.lang.Exception").$new()))
}
var log_end = new Array(num).join(end_symbol) + "[ThreadId:" + Process.getCurrentThreadId() + "]" + tag + " end!!!" + new Array(num).join(end_symbol)
user_log_list.push(log_end)
console.log(user_log_list.join("\n"));
})
}
function get_java_value(param, paramType, i) {
var result = ""
var name = null;
if (i == undefined) {
name = "(" + paramType + ")retval";
} else {
name = "(" + paramType + ")arg[" + i + "]";
}
if (param == null) {
return name + " = null"
}
switch (paramType) {
case "[C"://TODO
case "[B":
var canToString = checkByteArrayFromString(param);
if (canToString) {
result = name + " _bytearray= " + StringClass.$new(param)
} else {
var param_hex = bytesToHex(param);
result = name + "_hex = " + param_hex
}
break;
case "[I":
result = name + "=" + JSON.stringify(param)
// var canToString = checkByteArrayFromString(param);
// if (canToString) {
// result = name + " _bytearray= " + StringClass.$new(param)
// } else {
// var param_hex = bytesToHex(param);
// result = name + "_hex = " + param_hex
// }
break;
case "java.util.Map":
case "Ljava/util/Map;":
var keys = param.keySet().toArray()
var obj = {}
for (var j = 0; j < keys.length; j++) {
var value = param.get(keys[j])
obj[keys[j]] = value.toString()
}
result = name + "=" + JSON.stringify(obj)
break;
case "java.util.List":
var list = []
for(var i = 0;i<param.length;i++){
list.push(param[i])
}
result = name + "=" + new Array(list).join(",")
break
case "java.security.Key":
var param_bytearray = param.getEncoded();
var canToString = checkByteArrayFromString(param_bytearray);
if (canToString) {
result = name + "_key_str= " + StringClass.$new(param_bytearray)
} else {
var param_hex = bytesToHex(param_bytearray);
result = name + "_key_hex = " + param_hex
}
break;
case "java.security.spec.AlgorithmParameterSpec":
case "Ljavax/crypto/spec/IvParameterSpec;":
var IVClass = Java.use("javax.crypto.spec.IvParameterSpec");
var ivObject = Java.cast(param, IVClass);
var ivByte = ivObject.getIV();
var canToString = checkByteArrayFromString(ivByte);
if (canToString) {
result = name + "_iv_str= " + StringClass.$new(ivByte)
} else {
var param_hex = bytesToHex(ivByte);
result = name + "_iv_hex = " + param_hex
}
break;
case "Ljavax/crypto/spec/SecretKeySpec;":
var keyByte = param.getEncoded();
var canToString = checkByteArrayFromString(keyByte);
if (canToString) {
result = name + "_key_str= " + StringClass.$new(keyByte)
} else {
var param_hex = bytesToHex(keyByte);
result = name + "_key_hex = " + param_hex
}
break
case "okio.BufferedSink":
// result = name + "=" + param.buffer().readUtf8()
// break
default:
result = name + "=" + param
break;
}
return result
}
function isVisible(value) {
if (value >= 32 && value <= 126) {
return true;
}
return false;
}
function checkByteArrayFromString(bytearray) {
var bytearray0 = Java.array("byte", bytearray);
for (var i = 0; i < bytearray0.length; i++) {
if (isVisible(bytearray[i]) == false) {
return false;
}
}
return true;
}
function bytesToHex(arr) {
var str = "";
var k, j;
for (var i = 0; i < arr.length; i++) {
k = arr[i];
j = k;
if (k < 0) {
j = k + 256;
}
if (j < 16) {
str += "0";
}
str += j.toString(16);
}
return str;
}
/*
hook一个方法,根据正则,过滤重载
hookOneMethod("java.net.URL.$init")
hookOneMethod("android.util.Base64.encodeToString")
hookOneMethod("javax.crypto.Cipher.doFinal","[B")
*/
function hookOneMethod(fullMethodName, overloadFilter) {
/*
hookOneMethod("java.net.URL.$init") // trace all method of $init
hookOneMethod("java.net.URL.$init","java.lang.String")
hookOneMethod("java.net.URL.$init","java.net.URL,java.lang.String")
*/
var split_length = fullMethodName.split(".").length;
var method = fullMethodName.split(".")[split_length - 1];
var classname = fullMethodName.slice(0, fullMethodName.length - method.length - 1); // -1是为了去掉那个点
Java.performNow(function () {
var tmpClass = Java.use(classname);
if (tmpClass[method] == undefined) {
} else {
tmpClass[method].overloads.forEach(function (m) {
var argumentTypes = m.argumentTypes;
var returnType = m.returnType.name;
var parameterStrArray = [];
for (var tmpArg of argumentTypes) {
parameterStrArray.push(tmpArg["className"]);
}
if (overloadFilter != undefined && overloadFilter != parameterStrArray.join(",")) {
// console.log("your overloadFilter do not match")
return true
} else {
console.log("hooking " + classname + "." + method + "(" + parameterStrArray.join(",") + ")");
m.implementation = function () {
var user_log_list = []
var user_log_list = ["called " + classname + "." + method + "(" + parameterStrArray.join(",") + ")"]
for (var i = 0; i < arguments.length; i++) {
if (is_print_args) {
// if (arguments[i] == null) continue
var tmp_java_value = get_java_value(arguments[i], parameterStrArray[i], i);
user_log_list.push(tmp_java_value)
}
}
if (hook_java_enter) {
// user_log_list.push("java called before hook!")
print_java_log(user_log_list, classname)
}
var retval = m.apply(this, arguments);
if (is_print_retval) {
var tmp_java_value = get_java_value(retval, returnType);
user_log_list.push(tmp_java_value)
}
if (!hook_java_enter) {
// user_log_list.push("java called over hook!")
print_java_log(user_log_list, classname)
}
return retval;
};
}
});
}
});
}
/*
hook一个类,根据正则,过滤方法名和重载
hookOneClass("javax.crypto.Cipher")
hookOneClass("javax.crypto.Cipher","doFinal")
hookOneClass("javax.crypto.Cipher","doFinal","[B")
*/
function hookOneClass(fullClassName, methodFilter, overloadFilter) {
Java.performNow(function () {
var toBeHookingMethods = []
var tmpClass = Java.use(fullClassName)
var method_init_all = tmpClass.class.getDeclaredConstructors();
if (method_init_all.length > 0) {
if (methodFilter == undefined) {
toBeHookingMethods.push(fullClassName + ".$init")
} else if (methodFilter != undefined && methodFilter == "$init") {
toBeHookingMethods.push(fullClassName + "." + "$init")
}
}
var method_all = tmpClass.class.getDeclaredMethods()
for (var i = 0; i < method_all.length; i++) {
var tmpMethod = method_all[i]
var tmpMethodName = tmpMethod.getName()
if (methodFilter != undefined && tmpMethodName.indexOf(methodFilter) != -1) {
toBeHookingMethods.push(fullClassName + "." + tmpMethodName)
} else if (methodFilter == undefined) {
toBeHookingMethods.push(fullClassName + "." + tmpMethodName)
}
}
toBeHookingMethods = Array.from(new Set(toBeHookingMethods))
console.log("[traceOneClass]toBeHookingMethods.length=", toBeHookingMethods.length)
for (var i = 0; i < toBeHookingMethods.length; i++) {
var method = toBeHookingMethods[i]
hookOneMethod(method, overloadFilter)
}
})
}
function query(classname, method) {
// query("Base64")
// query("Cipher","doFinal")
if (frida_major_version < 14) {
console.log("frida major version must >= 14")
return
}
var filterPattern = "*Base64*!*encode*";
var groups = null;
if (classname == undefined && method == undefined) {
console.log("please enter classname or method");
return groups;
}
if (!classname) {
classname = "*";
}
if (!method) {
method = "*";
}
var filterPattern = "*" + classname + "*" + "!" + "*" + method + "*";
Java.performNow(function () {
groups = Java.enumerateMethods(filterPattern);
});
return groups;
}
function find(classname, method) {
/*
find("*.Cipher") // find all classes endswith .Cipher
find("","doFinal") // find all methods equal doFinal
find("*Base64*","*encode*") // find all classes match Base64 and methods match encode
*/
var groups = query(classname, method)
if (groups != "") {
for (var group of groups) {
var classes = group["classes"];
for (var cls of classes) {
var classname = cls["name"];
var methods = cls["methods"];
console.log("found class => " + classname);
for (var method of methods) {
console.log("found method => " + classname + "." + method);
}
console.log("found " + methods.length + " methods");
}
}
console.log("search finished");
} else {
console.log("search finished and found 0 method");
}
}
function hookAllMethod(classnameFilter, methodFilter, overloadFilter) {
/*
hookAllMethod2("Base64") // trace all class match Base64
hookAllMethod2("","encode","[B,int") // trace all class and method equals encode and overload equals [B,int
hookAllMethod2("Base64","encode","[B,int") // trace class match Base64 and method match encode and overload equals [B,int
*/
var groups = query(classnameFilter, methodFilter)
if (groups != "") {
for (var group of groups) {
var classes = group["classes"];
for (var cls of classes) {
var classname = cls["name"];
var methods = cls["methods"];
for (var method of methods) {
var fullMethodName = classname + "." + method
console.log("string=>" + fullMethodName.toString())
try {
hookOneMethod(fullMethodName.toString(), overloadFilter);
} catch (e) {
}
}
}
}
} else {
console.log("search finished and found 0 method");
}
}
// objection的获取当前Activity
function R(name, type) {
// const context = getApplicationContext();
return context.getResources().getIdentifier(name, type, context.getPackageName());
}
function objection_getCurrentActivity() {
Java.performNow(function () {
const activityThread = Java.use("android.app.ActivityThread");
const activity = Java.use("android.app.Activity");
const activityClientRecord = Java.use("android.app.ActivityThread$ActivityClientRecord");
const currentActivityThread = activityThread.currentActivityThread();
const activityRecords = currentActivityThread.mActivities.value.values().toArray();
let currentActivity;
for (const i of activityRecords) {
const activityRecord = Java.cast(i, activityClientRecord);
if (!activityRecord.paused.value) {
currentActivity = Java.cast(Java.cast(activityRecord, activityClientRecord).activity.value, activity);
break;
}
}
if (currentActivity) {
console.log(currentActivity.$className)
const fm = currentActivity.getFragmentManager();
const fragment = fm.findFragmentById(R("content_frame", "id"));
console.log(fragment.$className)
}
})
}
// objection的获取所有的Activities
function objection_getActivities() {
Java.performNow(function () {
const packageManager = Java.use("android.content.pm.PackageManager");
const GET_ACTIVITIES = packageManager.GET_ACTIVITIES.value;
var ActivityThreadClass = Java.use("android.app.ActivityThread");
var context = ActivityThreadClass.currentActivityThread().getApplication().getApplicationContext()
context.getPackageManager().getPackageInfo(context.getPackageName(), GET_ACTIVITIES).activities.value.map((activityInfo) => {
console.log(activityInfo.name.value)
})
})
}
// objection的获取所有的Services
function objection_getServices() {
Java.performNow(function () {
var ActivityThreadClass = Java.use("android.app.ActivityThread");
var ArrayMapClass = Java.use("android.util.ArrayMap");
var PackageManagerClass = Java.use("android.content.pm.PackageManager");
var GET_SERVICES = PackageManagerClass.GET_SERVICES.value;
var currentApplication = ActivityThreadClass.currentApplication(); // not using the helper as we need other variables too
var context = currentApplication.getApplicationContext();
var services = [];
currentApplication.mLoadedApk.value.mServices.value.values().toArray().map(function (potentialServices) {
Java.cast(potentialServices, ArrayMapClass).keySet().toArray().map(function (service) {
services.push(service.$className);
});
});
services = services.concat(context.getPackageManager().getPackageInfo(context.getPackageName(), GET_SERVICES).services.value.map(function (activityInfo) {
console.log("find Service => " + activityInfo.name.value)
return activityInfo.name.value;
}));
})
}
// objection的跳转Activity界面
function objection_startActivity(activityName) {
// https://developer.android.com/reference/android/content/Intent.html#FLAG_ACTIVITY_NEW_TASK
Java.performNow(function () {
var FLAG_ACTIVITY_NEW_TASK = 0x10000000; // starts an Android activity
var IntentClass = Java.use("android.content.Intent"); // Get the Activity class's .class
var newActivity = Java.use(activityName);
var newIntent = IntentClass.$new(context, newActivity.class);
newIntent.setFlags(FLAG_ACTIVITY_NEW_TASK);
context.startActivity(newIntent);
})
}
// objection的启动Service
function objection_startService(serviceName) {
// https://developer.android.com/reference/android/content/Intent.html#FLAG_ACTIVITY_NEW_TASK
Java.performNow(function () {
var FLAG_ACTIVITY_NEW_TASK = 0x10000000; // starts an Android activity
var IntentClass = Java.use("android.content.Intent"); // Get the Activity class's .class
var newService = Java.use(serviceName);
console.log(newService.$className)
var newIntent = IntentClass.$new(context, newService.class);
newIntent.setFlags(FLAG_ACTIVITY_NEW_TASK);
context.startService(newIntent);
})
}
/*
sslpinning 仅对系统的checkServerTrusted以及标准ok3的check进行hook,无法对抗混淆的以及其它的
*/
function objection_sslpinning_disable_all() {
sslpinning_disable_system()
sslpinning_disable_okhttp3()
}
function sslpinning_disable_system() {
Java.performNow(function () {
var PlatformClass = Java.use("com.android.org.conscrypt.Platform")
var targetMethodName = "checkServerTrusted"
var overloadsLength = PlatformClass[targetMethodName].overloads.length;
for (var i = 0; i < overloadsLength; ++i) {
PlatformClass[targetMethodName].overloads[i].implementation = function () {
console.log("com.android.org.conscrypt.Platform.checkServerTrusted->i=" + i + " arguments=" + JSON.stringify(arguments))
}
}
})
}
function sslpinning_disable_okhttp3() {
Java.performNow(function () {
var CertificatePinnerClass = Java.use("okhttp3.CertificatePinner")
var targetMethodName = "check"
var overloadsLength = CertificatePinnerClass[targetMethodName].overloads.length;
for (var i = 0; i < overloadsLength; ++i) {
CertificatePinnerClass[targetMethodName].overloads[i].implementation = function () {
console.log("okhttp3.CertificatePinner.check->i=" + i + " arguments=" + JSON.stringify(arguments))
}
}
})
}
/*
hook root检测,但是仍然不全
*/
function objection_root_disable_all() {
root_disable_testKeysCheck()
root_disable_execSuCheck()
root_disable_fileExistsCheck()
}
function root_disable_testKeysCheck() {
Java.performNow(function () {
var JavaString = Java.use("java.lang.String");
JavaString.contains.implementation = function (name) {
//这个太局限了
if (name !== "test-keys") {
return this.contains.call(this, name);
} else {
return false
}
};
})
}
function root_disable_execSuCheck() {
Java.performNow(function () {
var JavaRuntime = Java.use("java.lang.Runtime");
var iOException = Java.use("java.io.IOException");
JavaRuntime.exec.overload("java.lang.String").implementation = function (command) {
if (command.endsWith("su")) {
console.log("called endsWith su")
} // call the original method
if (command.indexOf("su") != -1) {
console.log("called indexOf su")
}
return this.exec.overload("java.lang.String").call(this, command);
};
})
}
function root_disable_fileExistsCheck() {
Java.performNow(function () {
var commonPaths = ["/data/local/bin/su", "/data/local/su", "/data/local/xbin/su", "/dev/com.koushikdutta.superuser.daemon/", "/sbin/su", "/system/app/Superuser.apk", "/system/bin/failsafe/su", "/system/bin/su", "/system/etc/init.d/99SuperSUDaemon", "/system/sd/xbin/su", "/system/xbin/busybox", "/system/xbin/daemonsu", "/system/xbin/su"];
var JavaFile = Java.use("java.io.File");
JavaFile.exists.implementation = function () {
var filename = this.getAbsolutePath();
if (commonPaths.indexOf(filename) >= 0) {
console.log("called JavaFile exists =>" + filename)
}
return this.exists.call(this);
}
})
}
// 获取当前app的包名
function getPackageName() {
var packageName = null;
Java.performNow(function () {
if (is_spawn) {
packageName = get_self_process_name();
} else {
packageName = context.getPackageName()
var packageName1 = context.getBasePackageName()
console.log("context.getBasePackageName()=", packageName1)
}
})
return packageName
}
//对一个jni函数进行demangle
function demangle(name) {
// demangle("_ZN3art3JNI15RegisterNativesEP7_JNIEnvP7_jclassPK15JNINativeMethodi")
// extern "C" char* __cxa_demangle(const char*, char*, size_t*, int*);
var __cxa_demangle = DebugSymbol.fromName("__cxa_demangle").address;
var func_demangle = new NativeFunction(__cxa_demangle, "pointer", ["pointer", "pointer", "pointer", "pointer"])
// var str = Memory.allocUtf8String("_ZN3art3JNI15RegisterNativesEP7_JNIEnvP7_jclassPK15JNINativeMethodi");
var str = Memory.allocUtf8String(name);
var result = func_demangle(new NativePointer(ptr(str)), ptr(0), ptr(0), ptr(0));
// console.log((result).readCString())
return result.readCString()
// console.log(JSON.stringify(Module.enumerateSymbols("libart.so")))
}
//模仿wallbreaker的dumpClass
function LookupClass(classFullName) {
Java.performNow(function () {
var tmpClass = Java.use(classFullName)
var packageName = tmpClass.class.getPackage().getName()
var field_all = tmpClass.class.getDeclaredFields();
var Modifier = Java.use("java.lang.reflect.Modifier");
var user_log_list = []
var classObj = {
"static_fileds": [],
"ins_fields": [],
"contructor_methods": [],
"static_methods": [],
"methods": []
}
for (var i = 0; i < field_all.length; i++) {
var field = field_all[i]
var fieldType = field.getType().getName();
var fieldName = field.getName();
var isStatic = Modifier.isStatic(field.getModifiers())
if (isStatic) {
var fieldValue = tmpClass[fieldName].value;
classObj["static_fileds"].push({
"key": fieldType + " " + fieldName,
// "key": field,
"value": fieldValue
})
} else {
classObj["ins_fields"].push({
"key": fieldType + " " + fieldName,
"value": null
})
}
}
var method_init_all = tmpClass.class.getDeclaredConstructors();
for (var i = 0; i < method_init_all.length; i++) {
var method_init = method_init_all[i]
var method_init_str = method_init.toString().split("throws")[0].trim()
// var method_init_ReturnType = method_init.getReturnType()
var method_init_ParameterTypes = method_init.getParameterTypes()
var method_init_ParameterTypesStr = getParameterTypesToString(method_init_ParameterTypes)
var method_init_str = "$init(" + method_init_ParameterTypesStr + ")"
// var methodName = method.getName()
classObj["contructor_methods"].push(method_init_str)
}
var method_all = tmpClass.class.getDeclaredMethods();
for (var i = 0; i < method_all.length; i++) {
var method = method_all[i]
var methodStr = method.toString().split("throws")[0].trim()
var methodReturnType = method.getReturnType().getName()
var methodName = method.getName()
var methodParameterTypes = method.getParameterTypes()
var method_ParameterTypesStr = getParameterTypesToString(methodParameterTypes)
var method_str = methodReturnType + " " + methodName + " (" + method_ParameterTypesStr + ")"
var isStatic = Modifier.isStatic(method.getModifiers())
if (isStatic) {
// classObj["static_methods"].push("(" + methodReturnType + ") " + methodName+" ("+methodParameterTypes)
classObj["static_methods"].push(method_str)
} else {
// console.log("ins value=",fieldName,ins[fieldName].value)
classObj["methods"].push(method_str)
}
}
//开始打印classObj
var user_log_list = []
var tab = new Array(8).join(" ")
user_log_list.push("package " + packageName + ";")
console.log(classFullName.slice(classFullName.indexOf(packageName)))
user_log_list.push("class " + classFullName.slice(packageName.length + 1) + " {")
user_log_list.push("")
user_log_list.push(tab + "/* static fields */")
var static_fileds = classObj["static_fileds"]
for (var i = 0; i < static_fileds.length; i++) {
var tmpField = static_fileds[i]
var tmpFieldName = tmpField["key"]
var tmpFieldValue = tmpField["value"]
user_log_list.push(tab + tmpFieldName + " => " + tmpFieldValue)
}
user_log_list.push("")
user_log_list.push(tab + "/* instance fields */")
var ins_fields = classObj["ins_fields"]
for (var i = 0; i < ins_fields.length; i++) {
var tmpField = ins_fields[i]
var tmpFieldName = tmpField["key"]
var tmpFieldValue = tmpField["value"]
user_log_list.push(tab + tmpFieldName + " => " + tmpFieldValue)
}
user_log_list.push("")
user_log_list.push(tab + "/* constructor methods */")
var contructor_methods = classObj["contructor_methods"]
for (var i = 0; i < contructor_methods.length; i++) {
var contructor_method = contructor_methods[i]
user_log_list.push(tab + contructor_method)
}
user_log_list.push("")
user_log_list.push(tab + "/* static methods */")
var static_methods = classObj["static_methods"]
for (var i = 0; i < static_methods.length; i++) {
var static_method = static_methods[i]
user_log_list.push(tab + static_method)
}
user_log_list.push("")
user_log_list.push(tab + "/* methods */")
var methods = classObj["methods"]
for (var i = 0; i < methods.length; i++) {
var method = methods[i]
user_log_list.push(tab + method)
}
user_log_list.push("}")
print_java_log(user_log_list, classFullName)
})
}
function getParameterTypesToString(parameterTypes) {
var result = []
for (var i = 0; i < parameterTypes.length; i++) {
var tmpType = parameterTypes[i]
var typeName = tmpType.getName()
result.push(typeName)
}
return result.join(", ")
}
function get_self_process_name() {
var openPtr = Module.getExportByName('libc.so', 'open');
var open = new NativeFunction(openPtr, 'int', ['pointer', 'int']);
var readPtr = Module.getExportByName("libc.so", "read");
var read = new NativeFunction(readPtr, "int", ["int", "pointer", "int"]);
var closePtr = Module.getExportByName('libc.so', 'close');
var close = new NativeFunction(closePtr, 'int', ['int']);
var path = Memory.allocUtf8String("/proc/self/cmdline");
var fd = open(path, 0);
if (fd != -1) {
var buffer = Memory.alloc(0x1000);
var result = read(fd, buffer, 0x1000);
close(fd);
result = ptr(buffer).readCString();
return result;
}
return "-1";
}
function mkdir(path) {
var mkdirPtr = Module.getExportByName('libc.so', 'mkdir');
var mkdir = new NativeFunction(mkdirPtr, 'int', ['pointer', 'int']);
var opendirPtr = Module.getExportByName('libc.so', 'opendir');
var opendir = new NativeFunction(opendirPtr, 'pointer', ['pointer']);
var closedirPtr = Module.getExportByName('libc.so', 'closedir');
var closedir = new NativeFunction(closedirPtr, 'int', ['pointer']);
var cPath = Memory.allocUtf8String(path);
var dir = opendir(cPath);
if (dir != 0) {
closedir(dir);
return 0;
}
mkdir(cPath, 755);
chmod(path);
}
function chmod(path) {
var chmodPtr = Module.getExportByName('libc.so', 'chmod');
var chmod = new NativeFunction(chmodPtr, 'int', ['pointer', 'int']);
var cPath = Memory.allocUtf8String(path);
chmod(cPath, 755);
}
function save_permission() {
var save_permission = false
try {
var dex_path = "/sdcard/lingzhiyi_test.txt";
// var dex_path = "/data/data/"+getPackageName()+"/lingzhiyi_test.txt";
var fd = new File(dex_path, "wb");
fd.write("hello");
fd.flush();
fd.close()
save_permission = true;
} catch (e) {
// console.log(e)
}
return save_permission
}
function dexdump_DexCache() {
Java.performNow(function () {
var dex_count = 1;
Java.choose("java.lang.DexCache", {
onMatch: function (ins) {
var name = "" // 不过滤
// var name = get_self_process_name() // 开启,只在包含当前包名的路劲过滤
if (ins.location.value.indexOf(name) != -1) {
var save_name = ins.location.value.replaceAll("/", "_").replaceAll(".", "_").replaceAll(":", "_").replaceAll("!", "_").replaceAll("-", "_")
var dex_file = ins.dexFile.value
var base = ptr(dex_file).add(Process.pointerSize).readPointer();
var size = ptr(dex_file).add(Process.pointerSize + Process.pointerSize).readUInt();
var magic = ptr(base).readCString();
if (magic.indexOf("dex") == 0) {
var process_name = get_self_process_name();
if (process_name != "-1") {
if (has_save_permission) {
var dex_dir_path = "/sdcard/" + "dumpdex_" + process_name;
mkdir(dex_dir_path);
}
else {
var dex_dir_path = "/data/data/" + process_name; // no save permission
}
var dex_path = dex_dir_path + "/dumpdex_" + save_name + "_DexCache.dex";
var fd = new File(dex_path, "wb");
if (fd && fd != null) {
dex_count++;
var dex_buffer = ptr(base).readByteArray(size);
fd.write(dex_buffer);
fd.flush();
fd.close();
console.log("[dump dex]:", dex_path);
}
}
}
}
},
onComplete: function () { }
})
})
}
function dexdump_Frida() {
Process.enumerateRanges("r--").forEach(range => {
// {"base":"0x70e67000","size":2707456,"protection":"r-x","file":{"path":"/system/framework/arm64/boot.oat","offset":757760,"size":0}}
if (range.file && range.file.path && (range.file.path.startsWith("/system/") || range.file.path.startsWith("/data/dalvik-cache") || range.file.path.startsWith("/dev/kg"))) {
return
} else {
// console.log(JSON.stringify(range))
}
try {
Memory.scanSync(range.base, range.size, "64 65 78 0a 30 ?? ?? 00").forEach(function (match) {
var base = match.address
var size = base.add(0x20).readUInt()
var buffer = ptr(base).readByteArray(size)
var path = range.file.path.replaceAll("/", "_").replaceAll("-", "_").replaceAll("=", "_").replaceAll(".", "_")
if (has_save_permission) {
var savepath = "/sdcard/" + "dumpdex_" + get_self_process_name();
mkdir(savepath);
}
else {
var savepath = "/data/data/" + get_self_process_name(); // no save permission
}
var dex_file_name = savepath + "/dumpdex_" + path + "_frida.dex"
var file = new File(dex_file_name, "wb")
file.write(buffer)
file.flush()
file.close()
console.log("dump=>" + dex_file_name)
})
}
catch (e) {
console.log(e)
}
})
console.log("dumpdex_frida finished~")
}
function readStdString(str) {
const isTiny = (str.readU8() & 1) == 0;
if (isTiny) {
return str.add(1).readUtf8String();
}
return str.add(2 * Process.pointerSize).readPointer().readUtf8String();
}
function callprettymethod_x86(artmethodptr) {
var ArtMethodPrettyMethodaddr = Module.findExportByName("libart.so", "_ZN3art12PrettyMethodEPNS_9ArtMethodEb");
var ArtMethodPrettyMethodfunc = new NativeFunction(ArtMethodPrettyMethodaddr, "pointer", ["pointer", "pointer", "bool"]);
var strptr = Memory.alloc(64);
var ArtMethodName = null;
if (strptr != null) {
ArtMethodPrettyMethodfunc(ptr(strptr), ptr(artmethodptr), 1);
ArtMethodName = readStdString(strptr);
return ArtMethodName;
}
return null;
}
function callPrettyMethod_new(ArtMethodptr) {
var PrettyMethodfunc = new NativeFunction(PrettyMethod_addr, ["pointer", "pointer", "pointer"], ["pointer", "int"]);
var result = PrettyMethodfunc(ArtMethodptr, 1);
var stdstring = Memory.alloc(3 * Process.pointerSize);
ptr(stdstring).writePointer(result[0]);
ptr(stdstring).add(1 * Process.pointerSize).writePointer(result[1]);
ptr(stdstring).add(2 * Process.pointerSize).writePointer(result[2]);
var result = readStdString(stdstring)
// console.log("ArtMethodptr="+ArtMethodptr+"----result="+result)
return result
}
// 同时安卓7的artMethod没有PrettyMethod
function callPrettyMethod_arm32(artmethodptr) {
var ArtMethodPrettyMethodfunc = new NativeFunction(PrettyMethod_addr, "pointer", ["pointer", "pointer", "pointer"]);
var strptr = Memory.alloc(256);
var ArtMethodName = null;
if (strptr != null) {
ArtMethodPrettyMethodfunc(ptr(strptr), ptr(artmethodptr), ptr(1));
ArtMethodName = readStdString(strptr);
return ArtMethodName;
}
return null;
}
var method_name_all = []
// var method_name_all_set = Array.from(new Set(method_name_all)) // 通过该方法去重获取都调用了哪些方法
function ArtMethodInvoke_filter(methodname) {
if (methodname == null) {
return methodname
}
method_name_all.push(methodname)
var method_filter_all = ["android.view", "java.lang.ref", "android.content.res.Configuration", "android.os.BinderProxy", "java.lang.String.intern", "java.util.Locale", "android.os.Binder", "android.graphics", "android.system", "java.lang.ClassNotFoundException", "java.lang.NoSuchFieldError", "android.widget", "dalvik.system.VMStack", "java.lang.System", "java.lang.StringBuilder.append", "java.lang.Object.<init>", "java.net.InetAddress", "android.hardware"]
var filter = false
for (var i = 0; i < method_filter_all.length; i++) {
if (methodname.indexOf(method_filter_all[i]) != -1) {
filter = true
break
}
}
// filter = false
if (!filter) {
// console.log("enter InvokeWithArgArray callded methodname->" + methodname)
return "enter InvokeWithArgArray callded methodname->" + methodname
}
return null;
}
function hook_ArtMethod_Invoke() {
if (Process.arch == "ia32") {
ArtMethodInvoke_addr = DebugSymbol.fromName("_ZN3art9ArtMethod6InvokeEPNS_6ThreadEPjjPNS_6JValueEPKc").address;
}
// void Invoke(Thread* self, uint32_t* args, uint32_t args_size, JValue* result, const char* shorty)
Interceptor.attach(ArtMethodInvoke_addr, {
onEnter: function (args) {
this.user_log_list = []
this.called_method = args[0]
this.vregs_ = args[2]
this.result = args[4]
var keep = 1
var filter_methodname = "SharedPreferences"
// this.user_log_list.push("onEnter ArtMethodInvoke [this.method_args_size]=" + this.method_args_size)
if (Process.arch == "ia32") {
// 模拟器安卓7.0
this.methodname = callprettymethod_x86((this.called_method));
} else {
this.methodname = callPrettyMethod_new((this.called_method));
}
if (is_print_native_stackTrace) {
this.user_log_list.push(('called from:\n' + Thread.backtrace(this.context, Backtracer.ACCURATE).map(DebugSymbol.fromAddress).join('\n') + '\n'))
}
this.flag = (keep && (this.methodname.indexOf(filter_methodname) != -1)) || (!keep)
// try {
if (this.flag) {
this.user_log_list.push("current_called->" + this.methodname)
// print_native_log(this.user_log_list,"ArtInterpreterToInterpreterBridge")
// console.log("enter ArtInterpreterToInterpreterBridge=>access_flags_value:"+access_flags_value_+"---called:"+prettymethod_name+"---number_of_vregs_:"+number_of_vregs_.readUInt())
}
// } catch (e) {
// console.log("ArtMethodInvoke_addr error=======>", e, called_method)
// }
// 在此处进行休眠附加调试
if (this.methodname.indexOf("._ts_getRequestHeader") != -1) {
console.log("正在调用_ts_getRequestHeader函数,休眠60s 尽快ida或者gdb去附加调试")
// sleep(60)
}
}, onLeave: function (retval) {
if (is_print_art_param) {
if (this.flag) {
var access_flags = ptr(this.called_method).add(0x4)
var access_flags_value = access_flags.readU16()
var access_flags_value_ = get_access_flag(access_flags_value)
if (access_flags_value_ != access_flags_value) {
var args_list_str = this.methodname.split("(")[1].split(")")[0]
if (args_list_str.length == 0) {
var args_len = 0
} else {
var args_list_name = args_list_str.split(",")
var args_len = args_list_name.length
}
var origin_len = args_len
var start_index = 0
var is_not_static = 0
if (access_flags_value_.indexOf("static") != -1) {
// 说明是静态方法
this.user_log_list.push("is static")
} else {
// 非静态,是实例方法,第一个参数
start_index += 1
is_not_static = 1
args_len += 1
this.user_log_list.push("is instance")
}
var offset = 0
if (origin_len == 0x0) {
// 说明参数个数为0
// this.user_log_list.push("参数个数为0")
} else {
// this.user_log_list.push("参数个数为"+args_len+" origin_len="+origin_len)
for (; start_index < args_len; start_index++) {
var arg_name = args_list_name[start_index - is_not_static]
var address = ptr(this.vregs_).add(4 * start_index + offset)
var print_name = get_native_value(address, arg_name, start_index - is_not_static)
this.user_log_list.push(print_name)
if (arg_name.indexOf("long") != -1) {
offset += 4
}
}
}
} else {
//todo
}
this.user_log_list.push("called_access_flags_value:" + access_flags_value_.toString(16))
this.user_log_list.push("called:" + this.methodname)
}
}
if (this.flag) {
if (is_print_art_retval) {
this.return_type = this.methodname.split(" ")[0]
if (this.return_type != "void") {
var print_name = get_native_value(this.result, this.return_type, "return")
if (print_name != null) {
this.user_log_list.push(print_name)
}
}
}
print_native_log(this.user_log_list, "onLeave [libart.so => ArtMethodInvoke]=" + ArtMethodInvoke_addr)
}
}
})
}
function hook_ArtMethod_RegisterNative() {
// var ArtMethodRegisterNative_addr = Module.findExportByName("libart.so", "_ZN3art9ArtMethod14RegisterNativeEPKvb");
// console.log("ArtMethodRegisterNative_addr=",ArtMethodRegisterNative_addr)
Interceptor.attach(ArtMethodRegisterNative_addr, {
onEnter: function (args) {
this.artmethod = args[0];
var methodname = callPrettyMethod_new(ptr(this.artmethod));
if (methodname.indexOf("MainActivity.onCreate") != -1) {
console.log("find MainActivity.onCreate ready to sleep 60s")
// sleep(60)
}
// var methodname = (ptr(this.artmethod));
var address = args[1];
this.dex_method_index_ = ptr(this.artmethod).add(12).readU32();
var current_module = Process.getModuleByAddress(address)
var modulename = current_module.name
var base = current_module.base
var offset = address.sub(base)
console.log("go into ArtMethodRegisterNative---" + "artmethodptr:" + ptr(this.artmethod) + "---methodidx:" + this.dex_method_index_ + "--addr:" + address + "----name:" + methodname + "---modulename:" + modulename + "---offset:" + offset);
}, onLeave: function (retval) {
}
})
}
function is_java_func_static(java_func_name) {
if (java_func_name.indexOf("<") != -1) {
return false
}
var result = false
Java.performNow(function () {
var java_func_name_split = java_func_name.split(".")
var classname_array = []
var java_func_short_name = java_func_name_split[java_func_name_split.length - 1]
for (var i = 0; i < java_func_name_split.length - 1; i++) {
classname_array.push(java_func_name_split[i])
}
var classname = classname_array.join(".")
var tmpClass = Java.use(classname)
var Modifier = Java.use("java.lang.reflect.Modifier");
var method_all = tmpClass.class.getDeclaredMethods();
for (var i = 0; i < method_all.length; i++) {
var method = method_all[i]
var methodName = method.getName()
if (methodName == java_func_short_name) {
var isStatic = Modifier.isStatic(method.getModifiers())
result = isStatic
}
}
})
return result
}
function can_hexdump(addr) {
var range = Process.findRangeByAddress(addr)
if (range != null) {
return hexdump(addr) + "\r\n"
} else {
return addr + "\r\n"
}
}
/*
so加载后会执行init,initarray以及JNI_OnLoad,动态注册一般会放在JNI_OnLoad中
*/
function hook_JNI_OnLoad() {
// jint JNI_OnLoad(JavaVM *vm, void *reserved)
// var JNI_Onload_addr = DebugSymbol.fromName("JNI_OnLoad").address;
var JNI_Onload_addr = Module.findExportByName("libmedia_jni.so", "JNI_OnLoad");
// var JNI_Onload_addr = Module.findExportByName(null,"JNI_OnLoad");
console.log("JNI_Onload_addr=", JNI_Onload_addr)
Interceptor.attach(JNI_Onload_addr, {
onEnter: function (args) {
// console.log("enter JNI_Onload_addr")
},
onLeave: function (retval) {
// console.log("leave JNI_Onload_addr")
}
})
}
/*
对动态加载的dex,可以在这里进行hook,或者是更底层
*/
function hook_loadLibrary0() {
Java.performNow(function () {
Java.use("java.lang.Runtime").loadLibrary0.implementation = function (classloader, sopath) {
// hook_InvokeWithArgArray_x86()
var result = this.loadLibrary0(classloader, sopath);
var user_log_list = []
user_log_list.push("[classloader]=" + classloader)
user_log_list.push("[sopath]=" + sopath)
print_log(user_log_list, "java.lang.Runtime.loadLibrary0")
// try{
// if(classloader.findClass("com.taobao.wireless.security.adapter.JNICLibrary")!=-1){
// Java.classFactory.loader = classloader
// // hookOneClass("com.taobao.wireless.security.adapter.JNICLibrary")
// hookOneMethod("com.taobao.wireless.security.adapter.JNICLibrary.doCommandNative")
// }
// }catch(e){
// }
return result;
}
})
}
function get_access_flag(i) {
// var j = parseInt(i)
var result = i
var dict = {
0x1: "public",
0x2: "private",
0x4: "protected",
0x8: "static",
0x9: "public static",
0xa: "private static",
0x10: "final",
0x11: "public final",
0x12: "private final",
0x19: "public final static",
0x1a: "private final static",
0x101: "public native",
0x102: "private native",
0x109: "public static native",
0x10a: "private static native",
0x111: "public final native",
0x112: "private final native",
0x119: "public final static native",// 0x1 0x10 0x8 0x100
0x11a: "private final static native",// 0x2 0x10 0x8 0x100
0x1008: "Synthetic static ",// 0x8 0x1000
}
if (dict[i] != undefined) {
var result = dict[i]
}
return result
}
function hook_ArtInterpreterToInterpreterBridge() {
// var ArtInterpreterToInterpreterBridge_addr = Module.findExportByName("libart.so", "_ZN3art11interpreter33ArtInterpreterToInterpreterBridgeEPNS_6ThreadEPKNS_7DexFile8CodeItemEPNS_11ShadowFrameEPNS_6JValueE")
Interceptor.attach(ArtInterpreterToInterpreterBridge_addr, {
onEnter: function (args) {
// try {
this.keep = 1
var filter_name = "android.app.SharedPreferencesImpl.getString"
this.user_log_list = []
var codeitem = args[1]
// this.user_log_list.push(hexdump(codeitem))
this.callee_frame = args[2]
this.JValue_result = args[3]
if (is_print_native_stackTrace) {
// this.user_log_list.push(('called from:\n' + Thread.backtrace(this.context, Backtracer.ACCURATE).map(DebugSymbol.fromAddress).join('\n') + '\n'))
}
var callee_frame = this.callee_frame
var called_method = ptr(callee_frame).add(Process.pointerSize).readPointer();
var prettymethod_name = callPrettyMethod_new(called_method)
// console.log("ArtInterpreterToInterpreterBridge->"+prettymethod_name)
// return
this.prettymethod_name = prettymethod_name
this.flag = (this.keep && prettymethod_name.indexOf(filter_name) != -1) || (!this.keep)
this.return_type = prettymethod_name.split(" ")[0]
if (this.flag) {
this.user_log_list.push("current_called->" + prettymethod_name)
}
if (is_print_art_param) {
if (this.flag) {
var access_flags = ptr(called_method).add(0x4)
var access_flags_value = access_flags.readU16()
var access_flags_value_ = get_access_flag(access_flags_value)
// console.log(called_method,hexdump(callee_frame),"\r\n",hexdump(called_method))
var number_of_vregs_ = ptr(callee_frame).add(Process.pointerSize * 6);
var vregs_ = ptr(callee_frame).add(Process.pointerSize * 6).add(12)
if (access_flags_value_ != access_flags_value) {
var args_list_str = prettymethod_name.split("(")[1].split(")")[0]
if (args_list_str.length == 0) {
var args_len = 0
} else {
var args_list_name = args_list_str.split(",")
var args_len = args_list_name.length
}
var origin_len = args_len
var start_index = 0
var is_static = 0
if (access_flags_value_.indexOf("static") != -1) {
// 说明是静态方法
this.user_log_list.push("is static~~~")
} else {
// 非静态,是实例方法,第一个参数
start_index += 1
is_static = 1
args_len += 1
this.user_log_list.push("is instance~~~")
}
var offset = 0
if (origin_len == 0x0) {
// 说明参数个数为0
// this.user_log_list.push("参数个数为0")
} else {
// this.user_log_list.push("参数个数为"+args_len+" origin_len="+origin_len)
for (; start_index < args_len; start_index++) {
var arg_name = args_list_name[start_index - is_static]
var address = ptr(vregs_).add(4 * start_index + offset)
var print_name = get_native_value(address, arg_name, start_index - is_static)
this.user_log_list.push(print_name)
if (arg_name.indexOf("long") != -1) {
offset += 4
}
}
}
} else {
//todo
}
this.user_log_list.push("called_access_flags_value:" + access_flags_value_.toString(16))
this.user_log_list.push("called:" + prettymethod_name)
// print_native_log(this.user_log_list, "ArtInterpreterToInterpreterBridge")
// console.log("enter ArtInterpreterToInterpreterBridge=>access_flags_value:"+access_flags_value_+"---called:"+prettymethod_name+"---number_of_vregs_:"+number_of_vregs_.readUInt())
}
}
// } catch (e) {
// console.log("ArtInterpreterToInterpreterBridge error=======>", e, called_method)
// }
},
onLeave: function (retval) {
if (this.flag) {
if (is_print_art_retval) {
if (this.return_type != "void") {
var print_name = get_native_value(this.JValue_result, this.return_type, "return")
if (print_name != null) {
this.user_log_list.push(print_name)
}
}
// if (this.JValue_result != 0x0) {
// this.user_log_list.push("this.JValue_result=")
// this.user_log_list.push(hexdump(this.JValue_result))
// // console.log("this.JValue_result=",hexdump(this.JValue_result))
// }
}
print_native_log(this.user_log_list, "ArtInterpreterToInterpreterBridge")
}
}
})
}
function hook_ArtInterpreterToCompiledCodeBridge() {
Interceptor.attach(ArtInterpreterToCompiledCodeBridge_addr, {
onEnter: function (args) {
// try {
var keep = 1
var filter_name = "android.app.SharedPreferencesImpl"
this.caller_method = args[1]
this.callee_frame = args[2]
this.JValue_result = args[4]
this.user_log_list = []
if (is_print_native_stackTrace) {
// 崩溃的原因是这个
// this.user_log_list.push(('called from:\n' + Thread.backtrace(this.context, Backtracer.ACCURATE).map(DebugSymbol.fromAddress).join('\n') + '\n'))
}
var caller_method = this.caller_method // caller_method可能是0x0
var callee_frame = this.callee_frame
var called_method = ptr(callee_frame).add(Process.pointerSize).readPointer();
var prettymethod_name = callPrettyMethod_new(called_method)
// console.log("ArtInterpreterToCompiledCodeBridge->"+prettymethod_name)
// return 0
if (caller_method != 0x0) {
var prettymethod_name_caller = callPrettyMethod_new(caller_method)
}
this.flag = (keep && ((prettymethod_name.indexOf(filter_name) != -1) || (caller_method != 0x0 && prettymethod_name_caller.indexOf(filter_name) != -1))) || (!keep)
if (this.flag) {
// java_init()
// java_hook_wrapper()
// console.log("args=",args[0],args[1],args[2],args[3],args[4])
this.user_log_list.push("current_called->" + prettymethod_name)
}
this.return_type = prettymethod_name.split(" ")[0]
if (is_print_art_param) {
if (this.flag) {
if (caller_method != 0x0) {
var caller_access_flags = ptr(caller_method).add(0x4)
var caller_access_flags_value = caller_access_flags.readU16()
var caller_access_flags_value_ = get_access_flag(caller_access_flags_value)
}
var called_access_flags = ptr(called_method).add(0x4)
var called_access_flags_value = called_access_flags.readU16()
var called_access_flags_value_ = get_access_flag(called_access_flags_value)
var number_of_vregs_ = ptr(callee_frame).add(Process.pointerSize * 6);
var vregs_ = ptr(callee_frame).add(Process.pointerSize * 6).add(12)
if (called_access_flags_value != called_access_flags_value_) {
var args_list_str = prettymethod_name.split("(")[1].split(")")[0]
if (args_list_str.length == 0) {
var args_len = 0
} else {
var args_list_name = args_list_str.split(",")
var args_len = args_list_name.length
}
var origin_len = args_len
var start_index = 0
var is_not_static = 0
if (called_access_flags_value_.indexOf("static") != -1) {
// 说明是静态方法
this.user_log_list.push("is static!!!!")
} else {
// 非静态,是实例方法,第一个参数
start_index += 1
is_not_static = 1
args_len += 1
this.user_log_list.push("is instance!!!!")
}
var offset = 0
if (origin_len == 0x0) {
// 说明参数个数为0
// this.user_log_list.push("参数个数为0")
} else {
// this.user_log_list.push("参数个数为"+args_len+" origin_len="+origin_len)
for (; start_index < args_len; start_index++) {
var arg_name = args_list_name[start_index - is_not_static]
var address = ptr(vregs_).add(4 * start_index + offset)
var print_name = get_native_value(address, arg_name, start_index - is_not_static)
this.user_log_list.push(print_name)
if (arg_name.indexOf("long") != -1) {
offset += 4
}
}
}
} else {
//todo
}
if (caller_method != 0x0) {
this.user_log_list.push("caller_access_flags_value:" + caller_access_flags_value_.toString(16))
this.user_log_list.push("caller:" + prettymethod_name_caller)
} else {
this.user_log_list.push("caller:" + "0x0")
}
this.user_log_list.push("called_access_flags_value:" + called_access_flags_value_.toString(16))
this.user_log_list.push("called:" + prettymethod_name)
// print_native_log(this.user_log_list, "ArtInterpreterToCompiledCodeBridge")
}
}
// } catch (e) {
// console.log("ArtInterpreterToCompiledCodeBridge error=======>", e, caller_method, called_method)
// }
},
onLeave: function (retval) {
if (this.flag) {
if (is_print_art_retval) {
// if(this.return_type!="void" && this.JValue_result != 0x0){
// console.log(this.return_type)
// console.log(this.JValue_result)
if (this.return_type != "void") {
var print_name = get_native_value(this.JValue_result, this.return_type, "return")
if (print_name != null) {
this.user_log_list.push(print_name)
}
}
// this.user_log_list.push(print_name)
// console.log(print_name)
// if (this.JValue_result != 0x0) {
// this.user_log_list.push("this.JValue_result=")
// this.user_log_list.push(hexdump(this.JValue_result))
// }
// }
}
print_native_log(this.user_log_list, "ArtInterpreterToCompiledCodeBridge")
}
}
})
}
function hook_Art_Interpreter_Invoke() {
// 总共有四种情况的执行方法
/*
1. 机器码->机器码
2. 机器码->解释执行
3. 解释执行->解释执行
4. 解释执行->机器码
*/
// 1. 机器码->机器码
// extern "C" TwoWordReturn artQuickGenericJniTrampoline(Thread* self, ArtMethod** sp)
Interceptor.attach(artQuickGenericJniTrampoline_addr, {
onEnter: function (args) {
// try {
this.keep = 0
var filter_name = "Request"
this.user_log_list = []
// this.callee_frame = args[2]
// this.JValue_result = args[3]
if (is_print_native_stackTrace) {
this.user_log_list.push(('called from:\n' + Thread.backtrace(this.context, Backtracer.ACCURATE).map(DebugSymbol.fromAddress).join('\n') + '\n'))
}
// var callee_frame = this.callee_frame
var called_method = args[1].readPointer()
var prettymethod_name = callPrettyMethod_new(called_method)
// console.log("ArtInterpreterToInterpreterBridge->"+prettymethod_name)
// return
this.prettymethod_name = prettymethod_name
this.flag = (this.keep && prettymethod_name.indexOf(filter_name) != -1) || (!this.keep)
this.return_type = prettymethod_name.split(" ")[0]
if (this.flag) {
this.user_log_list.push("current_called->" + prettymethod_name)
}
if (is_print_art_param) {
return
if (this.flag) {
var access_flags = ptr(called_method).add(0x4)
var access_flags_value = access_flags.readU16()
var access_flags_value_ = get_access_flag(access_flags_value)
// console.log(called_method,hexdump(callee_frame),"\r\n",hexdump(called_method))
var number_of_vregs_ = ptr(callee_frame).add(Process.pointerSize * 6);
var vregs_ = ptr(callee_frame).add(Process.pointerSize * 6).add(12)
if (access_flags_value_ != access_flags_value) {
var args_list_str = prettymethod_name.split("(")[1].split(")")[0]
if (args_list_str.length == 0) {
var args_len = 0
} else {
var args_list_name = args_list_str.split(",")
var args_len = args_list_name.length
}
var origin_len = args_len
var start_index = 0
var is_static = 0
if (access_flags_value_.indexOf("static") != -1) {
// 说明是静态方法
this.user_log_list.push("is static~~~")
} else {
// 非静态,是实例方法,第一个参数
start_index += 1
is_static = 1
args_len += 1
this.user_log_list.push("is instance~~~")
}
var offset = 0
if (origin_len == 0x0) {
// 说明参数个数为0
// this.user_log_list.push("参数个数为0")
} else {
// this.user_log_list.push("参数个数为"+args_len+" origin_len="+origin_len)
for (; start_index < args_len; start_index++) {
var arg_name = args_list_name[start_index - is_static]
var address = ptr(vregs_).add(4 * start_index + offset)
var print_name = get_native_value(address, arg_name, start_index - is_static)
this.user_log_list.push(print_name)
if (arg_name.indexOf("long") != -1) {
offset += 4
}
}
}
} else {
//todo
}
this.user_log_list.push("called_access_flags_value:" + access_flags_value_.toString(16))
this.user_log_list.push("called:" + prettymethod_name)
// print_native_log(this.user_log_list, "ArtInterpreterToInterpreterBridge")
// console.log("enter ArtInterpreterToInterpreterBridge=>access_flags_value:"+access_flags_value_+"---called:"+prettymethod_name+"---number_of_vregs_:"+number_of_vregs_.readUInt())
}
}
// } catch (e) {
// console.log("ArtInterpreterToInterpreterBridge error=======>", e, called_method)
// }
},
onLeave: function (retval) {
if (this.flag) {
print_native_log(this.user_log_list, "artQuickGenericJniTrampoline")
}
}
})
// 2. 机器码->解释执行
// extern "C" uint64_t artQuickToInterpreterBridge(ArtMethod* method, Thread* self, ArtMethod** sp)
Interceptor.attach(artQuickToInterpreterBridge_addr, {
onEnter: function (args) {
// try {
var keep = 0
var filter_name = "get2"
this.caller_method = args[2].readPointer()
// this.callee_frame = args[2]
// this.JValue_result = args[4]
this.user_log_list = []
if (is_print_native_stackTrace) {
// 崩溃的原因是这个
this.user_log_list.push(('called from:\n' + Thread.backtrace(this.context, Backtracer.ACCURATE).map(DebugSymbol.fromAddress).join('\n') + '\n'))
}
var caller_method = this.caller_method // caller_method可能是0x0
// var callee_frame = this.callee_frame
var called_method = args[0]
var prettymethod_name = callPrettyMethod_new(called_method)
// console.log("ArtInterpreterToCompiledCodeBridge->"+prettymethod_name)
// return 0
if (caller_method != 0x0) {
var prettymethod_name_caller = callPrettyMethod_new(caller_method)
}
this.flag = (keep && ((prettymethod_name.indexOf(filter_name) != -1) || (caller_method != 0x0 && prettymethod_name_caller.indexOf(filter_name) != -1))) || (!keep)
if (this.flag) {
// console.log("args=",args[0],args[1],args[2],args[3],args[4])
this.user_log_list.push("current_called->" + prettymethod_name)
}
this.return_type = prettymethod_name.split(" ")[0]
if (is_print_art_param) {
if (this.flag) {
return
if (caller_method != 0x0) {
var caller_access_flags = ptr(caller_method).add(0x4)
var caller_access_flags_value = caller_access_flags.readU16()
var caller_access_flags_value_ = get_access_flag(caller_access_flags_value)
}
var called_access_flags = ptr(called_method).add(0x4)
var called_access_flags_value = called_access_flags.readU16()
var called_access_flags_value_ = get_access_flag(called_access_flags_value)
var number_of_vregs_ = ptr(callee_frame).add(Process.pointerSize * 6);
var vregs_ = ptr(callee_frame).add(Process.pointerSize * 6).add(12)
if (called_access_flags_value != called_access_flags_value_) {
var args_list_str = prettymethod_name.split("(")[1].split(")")[0]
if (args_list_str.length == 0) {
var args_len = 0
} else {
var args_list_name = args_list_str.split(",")
var args_len = args_list_name.length
}
var origin_len = args_len
var start_index = 0
var is_not_static = 0
if (called_access_flags_value_.indexOf("static") != -1) {
// 说明是静态方法
this.user_log_list.push("is static!!!!")
} else {
// 非静态,是实例方法,第一个参数
start_index += 1
is_not_static = 1
args_len += 1
this.user_log_list.push("is instance!!!!")
}
var offset = 0
if (origin_len == 0x0) {
// 说明参数个数为0
// this.user_log_list.push("参数个数为0")
} else {
// this.user_log_list.push("参数个数为"+args_len+" origin_len="+origin_len)
for (; start_index < args_len; start_index++) {
var arg_name = args_list_name[start_index - is_not_static]
var address = ptr(vregs_).add(4 * start_index + offset)
var print_name = get_native_value(address, arg_name, start_index - is_not_static)
this.user_log_list.push(print_name)
if (arg_name.indexOf("long") != -1) {
offset += 4
}
}
}
} else {
//todo
}
if (caller_method != 0x0) {
this.user_log_list.push("caller_access_flags_value:" + caller_access_flags_value_.toString(16))
this.user_log_list.push("caller:" + prettymethod_name_caller)
} else {
this.user_log_list.push("caller:" + "0x0")
}
this.user_log_list.push("called_access_flags_value:" + called_access_flags_value_.toString(16))
this.user_log_list.push("called:" + prettymethod_name)
// print_native_log(this.user_log_list, "ArtInterpreterToCompiledCodeBridge")
}
}
// } catch (e) {
// console.log("ArtInterpreterToCompiledCodeBridge error=======>", e, caller_method, called_method)
// }
},
onLeave: function (retval) {
if (this.flag) {
print_native_log(this.user_log_list, "artQuickToInterpreterBridge")
}
}
})
// return
// 3. 解释执行->解释执行
Interceptor.attach(ArtInterpreterToInterpreterBridge_addr, {
onEnter: function (args) {
// try {
this.keep = 0
var filter_name = "Request"
this.user_log_list = []
this.callee_frame = args[2]
this.JValue_result = args[3]
if (is_print_native_stackTrace) {
this.user_log_list.push(('called from:\n' + Thread.backtrace(this.context, Backtracer.ACCURATE).map(DebugSymbol.fromAddress).join('\n') + '\n'))
}
var callee_frame = this.callee_frame
var called_method = ptr(callee_frame).add(Process.pointerSize).readPointer();
var prettymethod_name = callPrettyMethod_new(called_method)
// console.log("ArtInterpreterToInterpreterBridge->"+prettymethod_name)
// return
this.prettymethod_name = prettymethod_name
this.flag = (this.keep && prettymethod_name.indexOf(filter_name) != -1) || (!this.keep)
this.return_type = prettymethod_name.split(" ")[0]
if (this.flag) {
this.user_log_list.push("current_called->" + prettymethod_name)
}
if (is_print_art_param) {
if (this.flag) {
var access_flags = ptr(called_method).add(0x4)
var access_flags_value = access_flags.readU16()
var access_flags_value_ = get_access_flag(access_flags_value)
// console.log(called_method,hexdump(callee_frame),"\r\n",hexdump(called_method))
var number_of_vregs_ = ptr(callee_frame).add(Process.pointerSize * 6);
var vregs_ = ptr(callee_frame).add(Process.pointerSize * 6).add(12)
if (access_flags_value_ != access_flags_value) {
var args_list_str = prettymethod_name.split("(")[1].split(")")[0]
if (args_list_str.length == 0) {
var args_len = 0
} else {
var args_list_name = args_list_str.split(",")
var args_len = args_list_name.length
}
var origin_len = args_len
var start_index = 0
var is_static = 0
if (access_flags_value_.indexOf("static") != -1) {
// 说明是静态方法
this.user_log_list.push("is static~~~")
} else {
// 非静态,是实例方法,第一个参数
start_index += 1
is_static = 1
args_len += 1
this.user_log_list.push("is instance~~~")
}
var offset = 0
if (origin_len == 0x0) {
// 说明参数个数为0
// this.user_log_list.push("参数个数为0")
} else {
// this.user_log_list.push("参数个数为"+args_len+" origin_len="+origin_len)
for (; start_index < args_len; start_index++) {
var arg_name = args_list_name[start_index - is_static]
var address = ptr(vregs_).add(4 * start_index + offset)
var print_name = get_native_value(address, arg_name, start_index - is_static)
this.user_log_list.push(print_name)
if (arg_name.indexOf("long") != -1) {
offset += 4
}
}
}
} else {
//todo
}
this.user_log_list.push("called_access_flags_value:" + access_flags_value_.toString(16))
this.user_log_list.push("called:" + prettymethod_name)
// print_native_log(this.user_log_list, "ArtInterpreterToInterpreterBridge")
// console.log("enter ArtInterpreterToInterpreterBridge=>access_flags_value:"+access_flags_value_+"---called:"+prettymethod_name+"---number_of_vregs_:"+number_of_vregs_.readUInt())
}
}
// } catch (e) {
// console.log("ArtInterpreterToInterpreterBridge error=======>", e, called_method)
// }
},
onLeave: function (retval) {
if (this.flag) {
if (is_print_art_retval) {
if (this.return_type != "void") {
var print_name = get_native_value(this.JValue_result, this.return_type, "return")
if (print_name != null) {
this.user_log_list.push(print_name)
}
}
// if (this.JValue_result != 0x0) {
// this.user_log_list.push("this.JValue_result=")
// this.user_log_list.push(hexdump(this.JValue_result))
// // console.log("this.JValue_result=",hexdump(this.JValue_result))
// }
}
print_native_log(this.user_log_list, "ArtInterpreterToInterpreterBridge")
}
}
})
// 4. 解释执行->机器码
Interceptor.attach(ArtInterpreterToCompiledCodeBridge_addr, {
onEnter: function (args) {
// try {
var keep = 0
var filter_name = "get2"
this.caller_method = args[1]
this.callee_frame = args[2]
this.JValue_result = args[4]
this.user_log_list = []
if (is_print_native_stackTrace) {
// 崩溃的原因是这个
this.user_log_list.push(('called from:\n' + Thread.backtrace(this.context, Backtracer.ACCURATE).map(DebugSymbol.fromAddress).join('\n') + '\n'))
}
var caller_method = this.caller_method // caller_method可能是0x0
var callee_frame = this.callee_frame
var called_method = ptr(callee_frame).add(Process.pointerSize).readPointer();
var prettymethod_name = callPrettyMethod_new(called_method)
// console.log("ArtInterpreterToCompiledCodeBridge->"+prettymethod_name)
// return 0
if (caller_method != 0x0) {
var prettymethod_name_caller = callPrettyMethod_new(caller_method)
}
this.flag = (keep && ((prettymethod_name.indexOf(filter_name) != -1) || (caller_method != 0x0 && prettymethod_name_caller.indexOf(filter_name) != -1))) || (!keep)
if (this.flag) {
// console.log("args=",args[0],args[1],args[2],args[3],args[4])
this.user_log_list.push("current_called->" + prettymethod_name)
}
this.return_type = prettymethod_name.split(" ")[0]
if (is_print_art_param) {
if (this.flag) {
if (caller_method != 0x0) {
var caller_access_flags = ptr(caller_method).add(0x4)
var caller_access_flags_value = caller_access_flags.readU16()
var caller_access_flags_value_ = get_access_flag(caller_access_flags_value)
}
var called_access_flags = ptr(called_method).add(0x4)
var called_access_flags_value = called_access_flags.readU16()
var called_access_flags_value_ = get_access_flag(called_access_flags_value)
var number_of_vregs_ = ptr(callee_frame).add(Process.pointerSize * 6);
var vregs_ = ptr(callee_frame).add(Process.pointerSize * 6).add(12)
if (called_access_flags_value != called_access_flags_value_) {
var args_list_str = prettymethod_name.split("(")[1].split(")")[0]
if (args_list_str.length == 0) {
var args_len = 0
} else {
var args_list_name = args_list_str.split(",")
var args_len = args_list_name.length
}
var origin_len = args_len
var start_index = 0
var is_not_static = 0
if (called_access_flags_value_.indexOf("static") != -1) {
// 说明是静态方法
this.user_log_list.push("is static!!!!")
} else {
// 非静态,是实例方法,第一个参数
start_index += 1
is_not_static = 1
args_len += 1
this.user_log_list.push("is instance!!!!")
}
var offset = 0
if (origin_len == 0x0) {
// 说明参数个数为0
// this.user_log_list.push("参数个数为0")
} else {
// this.user_log_list.push("参数个数为"+args_len+" origin_len="+origin_len)
for (; start_index < args_len; start_index++) {
var arg_name = args_list_name[start_index - is_not_static]
var address = ptr(vregs_).add(4 * start_index + offset)
var print_name = get_native_value(address, arg_name, start_index - is_not_static)
this.user_log_list.push(print_name)
if (arg_name.indexOf("long") != -1) {
offset += 4
}
}
}
} else {
//todo
}
if (caller_method != 0x0) {
this.user_log_list.push("caller_access_flags_value:" + caller_access_flags_value_.toString(16))
this.user_log_list.push("caller:" + prettymethod_name_caller)
} else {
this.user_log_list.push("caller:" + "0x0")
}
this.user_log_list.push("called_access_flags_value:" + called_access_flags_value_.toString(16))
this.user_log_list.push("called:" + prettymethod_name)
// print_native_log(this.user_log_list, "ArtInterpreterToCompiledCodeBridge")
}
}
// } catch (e) {
// console.log("ArtInterpreterToCompiledCodeBridge error=======>", e, caller_method, called_method)
// }
},
onLeave: function (retval) {
if (this.flag) {
if (is_print_art_retval) {
if (this.return_type != "void") {
var print_name = get_native_value(this.JValue_result, this.return_type, "return")
if (print_name != null) {
this.user_log_list.push(print_name)
}
}
}
print_native_log(this.user_log_list, "ArtInterpreterToCompiledCodeBridge")
}
}
})
// hook_ArtMethod_Invoke()
}
// 初始化java的一些函数和变量
function java_init() {
Java.performNow(function () {
StringClass = Java.use("java.lang.String");
Base64Class = Java.use("android.util.Base64");
frida_major_version = Frida.version.split(".")[0];
android_sdk_version = Java.use("android.os.Build$VERSION").SDK_INT.value;
has_save_permission = save_permission();
console.log("java_init finished~" + new Array(20).join("-"))
})
}
// 初始化native层的一些函数和变量
function native_init() {
var temp_print = 0
module_libart = Process.findModuleByName("libart.so");
var module_libart_symbols = module_libart.enumerateSymbols()
for (var index = 0; index < module_libart_symbols.length; index++) {
var symbol = module_libart_symbols[index];
var symbol_name = symbol.name;
//这个DefineClass的函数签名是Android9的
//_ZN3art11ClassLinker11DefineClassEPNS_6ThreadEPKcmNS_6HandleINS_6mirror11ClassLoaderEEERKNS_7DexFileERKNS9_8ClassDefE
if (symbol_name.indexOf("ClassLinker") >= 0 && symbol_name.indexOf("DefineClass") >= 0 && symbol_name.indexOf("Thread") >= 0 && symbol_name.indexOf("DexFile") >= 0) {
DefineClass_addr = symbol.address;
if (temp_print) {
console.log("DefineClass_addr=", DefineClass_addr)
}
}
// if (symbol.name.indexOf("ClassLinker") >= 0 && symbol.name.indexOf("LoadMethod") >= 0 && symbol.name.indexOf("DexFile") >= 0 && symbol.name.indexOf("ClassDataItemIterator") >= 0 && symbol.name.indexOf("ArtMethod") >= 0) {}
if (symbol.name.indexOf("ClassLinker") >= 0 && symbol.name.indexOf("LoadMethod") >= 0 && symbol.name.indexOf("DexFile") >= 0 && symbol.name.indexOf("ArtMethod") >= 0) {
LoadMethod_addr = symbol.address;
if (temp_print) {
console.log("LoadMethod_addr=", LoadMethod_addr)
}
}
if (symbol.name.indexOf("PrettyMethod") != -1 && symbol.name.indexOf("ArtMethod") != -1 && symbol.name.indexOf("art") != -1) {
PrettyMethod_addr = symbol.address;
if (temp_print) {
console.log("PrettyMethod_addr=", PrettyMethod_addr)
}
}
if (symbol.name.indexOf("RegisterNativeMethod") == -1 && symbol.name.indexOf("ArtMethod") != -1 && symbol.name.indexOf("RegisterNative") != -1) {
ArtMethodRegisterNative_addr = symbol.address;
if (temp_print) {
console.log("ArtMethodRegisterNative_addr=", ArtMethodRegisterNative_addr)
}
}
// _ZN3art9ArtMethod6InvokeEPNS_6ThreadEPjjPNS_6JValueEPKc 安卓8.1.0,安卓7.1.2
if (symbol.name.indexOf("Invoke") != -1 && symbol.name.indexOf("_ZN3art9ArtMethod") != -1 && symbol.name.indexOf("Thread") != -1 && symbol.name.indexOf("JValue") != -1) {
// console.log("func_name="+symbol.name,"demangle_name="+demangle(symbol.name))
ArtMethodInvoke_addr = symbol.address;
if (temp_print) {
console.log("ArtMethodInvoke_addr=", ArtMethodInvoke_addr)
}
}
// _ZN3art3JNI15RegisterNativesEP7_JNIEnvP7_jclassPK15JNINativeMethodi
if (symbol.name.indexOf("RegisterNatives") != -1 && symbol.name.indexOf("_ZN3art3JNI") != -1) {
// console.log("func_name="+symbol.name,"demangle_name="+demangle(symbol.name))
JNIRegisterNatives_addr = symbol.address;
if (temp_print) {
console.log("JNIRegisterNatives_addr=", JNIRegisterNatives_addr)
}
}
if (symbol.name.indexOf("ArtInterpreterToCompiledCodeBridge") != -1) {
// console.log("func_name="+symbol.name,"demangle_name="+demangle(symbol.name))
ArtInterpreterToCompiledCodeBridge_addr = symbol.address;
if (temp_print) {
console.log("ArtInterpreterToCompiledCodeBridge_addr=", ArtInterpreterToCompiledCodeBridge_addr)
}
}
if (symbol.name.indexOf("ArtInterpreterToInterpreterBridge") != -1) {
// console.log("func_name="+symbol.name,"demangle_name="+demangle(symbol.name))
ArtInterpreterToInterpreterBridge_addr = symbol.address;
if (temp_print) {
console.log("ArtInterpreterToInterpreterBridge_addr=", ArtInterpreterToInterpreterBridge_addr)
}
}
if (symbol.name.indexOf("artQuickToInterpreterBridge") != -1) {
// console.log("func_name="+symbol.name,"demangle_name="+demangle(symbol.name))
artQuickToInterpreterBridge_addr = symbol.address;
if (temp_print) {
console.log("artQuickToInterpreterBridge_addr=", artQuickToInterpreterBridge_addr)
}
}
if (symbol.name.indexOf("artQuickGenericJniTrampoline") != -1) {
// console.log("func_name="+symbol.name,"demangle_name="+demangle(symbol.name))
artQuickGenericJniTrampoline_addr = symbol.address;
if (temp_print) {
console.log("artQuickGenericJniTrampoline_addr=", artQuickGenericJniTrampoline_addr)
}
}
}
console.log("native_init finished~" + new Array(20).join("-"))
}
function java_hook_wrapper() {
Java.performNow(function () {
var currentApplication = Java.use("android.app.ActivityThread").currentApplication();
if (currentApplication != null) {
context = currentApplication.getApplicationContext();
hook_java_user()
} else {
Java.use("android.app.ActivityThread").handleBindApplication.implementation = function (appBindData) {
var result = this.handleBindApplication(appBindData)
var currentApplication = Java.use("android.app.ActivityThread").currentApplication();
context = currentApplication.getApplicationContext();
console.log("entered handleBindApplication")
hook_java_user()
return result
}
// Java.use("android.app.Activity").onCreate.overload('android.os.Bundle').implementation = function (bundle) {
// var result = this.onCreate(bundle)
// var currentApplication = Java.use("android.app.ActivityThread").currentApplication();
// context = currentApplication.getApplicationContext();
// if (!is_hooked) {
// hook_java_user()
// is_hooked = true
// }
// return result
// }
// Java.use("android.content.ContextWrapper").attachBaseContext.implementation = function(context_){
// console.log("enter android.content.ContextWrapper.attachBaseContext")
// var result = this.attachBaseContext(context_)
// context = context_
// if(!is_hooked){
// hook_java_user()
// is_hooked=true
// }
// return result;
// }
}
hook_java_system()
})
}
function main() {
java_init();
java_hook_wrapper()
native_init();
native_hook(); // 去这里写native代码
}
//在这里写java的hook代码,不需要再包一层Java.perform了
function java_hook_real() {
// console.log(Java.use("android.app.ActivityThread").class.getClassLoader())
// console.log(Java.enumerateClassLoadersSync())
}
function jstring2Str(jstring) {
var ret;
Java.perform(function () {
var String = Java.use("java.lang.String");
ret = Java.cast(jstring, String);
});
return ret;
}
function jbyteArray2Array(jbyteArray) {
var ret;
Java.perform(function () {
var b = Java.use('[B');
var buffer = Java.cast(jbyteArray, b);
ret = Java.array('byte', buffer);
});
return ret;
}
// 在这里写native的hook代码
function native_hook() {
// hook_ArtMethod_RegisterNative()
// hook_ArtMethod_Invoke()
// hook_ArtInterpreterToInterpreterBridge()
// hook_ArtInterpreterToCompiledCodeBridge()
}
// 在这里写java的hook代码
function hook_java_user() {
dexdump_DexCache()
// hookOneMethod("com.yaotong.crackme.MainActivity.onCreate")
}
function hook_java_system() {
// hookOneMethod("android.app.Application.attach")
// hookOneMethod("java.io.File.$init")
// hookOneClass("android.app.ActivityThread")
// hookOneMethod("android.content.ContextWrapper.attachBaseContext")
// hookOneMethod("android.app.Activity.attachBaseContext")
// hookOneMethod("java.io.File.exists")
// hookOneMethod("java.lang.Runtime.exec")
}
setImmediate(main)
// 普通attach
// frida -UF -l v20220603_hook.js -o out.log
// 普通spawn启动,需要修改包名
// frida -U -f com.lingzhiyi.temp -l v20220603_hook.js -o out.log --no-pause
// frida -U -f com.yaotong.crackme -l v20220603_hook.js -o out.log --no-pause
// frida -U -f com.vnpay.t2p -l v20220603_hook.js -o out.log --no-pause
// 使用ip加端口进行attach
// frida -H 192.168.3.30:27043 -l v20220603_hook.js -o out.log
// 使用ip加端口进行spawn,需要修改包名
// frida -H 192.168.3.30:27043 -f com.lingzhiyi.learnencryptedsp -l v20220603_hook.js -o out.log --no-pause
// 使用gadget模式,使用ip加端口的方式 安卓7直接在sdcard创建包名以加载gadget
// frida -H 192.168.3.32:27043 -n Lingzhiyi -l v20220603_hook.js -o out.log
// frida -H 127.0.0.1:27043 -f com.xingin.xhs --no-pause