/*
*
*/
function dumpAddr(address, length) {
length = length || 1024;
console.log(hexdump(address, {
offset: 0,
length: length,
header: true,
ansi: true
}));
}
//5. 打印堆栈
function showStacks() {
Java.perform(function () {
console.log(Java.use(“android.util.Log”).getStackTraceString(Java.use(“java.lang.Exception”).$new()));
});
}
function hook_dy_so2() {
hook_dy();
var time = 1000;
var base_addr = Module.findBaseAddress("libmetasec_ml.so");
if (base_addr == null) {
//console.log("base_addr is null");
setTimeout(hook_dy_so2, time);
} else {
var modLibil2cpp = Process.getModuleByName("libmetasec_ml.so")
console.log("hook_dy_so2 base_addr:", base_addr, modLibil2cpp.base, modLibil2cpp.size.toString(16));
//var func_addr = base_addr.add(0x0c6b93);
var iSignOffset = 0xXXXXX; //17.9版本 Q 1 52 409 3145
iSignOffset = 0xXXXXX; //19.3版本 Q 1 52 409 3145
iSignOffset = 0xXXXXX; //19.5版本 Q 1 52 409 3145
iSignOffset = 0xXXXXX; //19.6版本 Q 1 52 409 3145
var func_addr = base_addr.add(iSignOffset);
console.log(" hook_dy_so2: my_make_XGorgon be found 2", base_addr.toString(16), func_addr.toString(16))
var src_func = new NativePointer(ptr(func_addr));
Interceptor.attach(src_func, {
//onEnter: function(args)顾名思义就是进入该函数前要执行的代码,其中args是传入的参数,一般so层函数第一个参数都是JniEnv,第二个参数是jclass,从第三个参数开始才是我们java层传入的参数
onEnter: function (args) {
//对于调用者直接是native里面的函数,用下面方式打印参数
console.log("args0",args[0].readCString());
console.log("args1", args[1].readCString());
if (args[1] != null) {
console.log("args2", args[2].readCString());
}
//console.log("\nBacktrace:\n" + Thread.backtrace(this.context, Backtracer.ACCURATE).map(DebugSymbol.fromAddress).join("\n"));
},
onLeave: function (retval) { //onLeave: function(retval)是该函数执行结束要执行的代码,其中retval参数即是返回值
console.log("return:" + retval, retval.readCString()); //打印返回值
//retval.replace(0); //替换返回值为0
}
});
}
//打印请求数据
//hook_sscronet();
}
function hook_dy() {
//Java.use()与Java.choose()最大的区别,就是在于前者会新建一个对象,后者会选择内存中已有的实例。
//com.topgamesinc.thirdpart
//public void purchaseItem(String uin,String serverId, String itemId,String itemName,String itemPrice, final String specialItemId)
Java.perform(function () {
if (Java.available) {
//hook弹出检测到root环境的提示框
//第一个参数:MainActivity.this,当前的上下文环境
//第二个参数:要显示的字符串,就是你想在屏幕上显示的内容
//第三个参数:显示的时间长短,就是这个字符串在屏幕上显示的时长。Toast默认的有两个LENGTH_LONG(长)和LENGTH_SHORT(短) 。
var javaString = Java.use('java.lang.String')
var CharSequence = Java.use('java.lang.CharSequence');
var MainActivity = Java.use('android.widget.Toast');
if (MainActivity != null) {
MainActivity.makeText.overload('android.content.Context', 'java.lang.CharSequence', 'int').implementation = function (a, b, c) {
console.log("call Toast makeText: ", b);
//console.log("call Toast makeText: ", Java.cast(b, javaString));
showStacks();
//var hookContent = javaString.$new('hook')
var bRet = this.makeText(a, b, c);
return bRet;
}
}
//com.ttnet.org.chromium.net.impl nativeCreateRequestAdapter function ( j, str, i, i2, z, z2, z3, z4, i3, z5, i4)
//N.MnXVOzVo Object obj, long j, String str, int i, int i2, boolean z, boolean z2, boolean z3, boolean z4, int i3, boolean z5, int i4
MainActivity = Java.use('J.N');
if (MainActivity != null) {
MainActivity.MnXVOzVo.implementation = function (obj, j, str, i, i2, z, z2, z3, z4, i3, z5, i4) {
console.log("\r\n call nativeCreateRequestAdapter: " + str);
//return 0; //这里返回0,只是让流程不继续,不实际发送请求到服务器,不然多次测试会时不时出安全验证,影响分析
return this.MnXVOzVo(obj,j, str, i, i2, z, z2, z3, z4, i3, z5, i4);
}
}
//com.ttnet.org.chromium.net.CronetEngine.Builder
var bHaveFlag = false;
MainActivity = Java.use('org.chromium.CronetClient');
if (MainActivity != null) {
MainActivity.openConnection.implementation = function (context, str, z, str2, executor) {
//需要查询url请求记录,就打开下面日志
console.log("\r\n call openConnection: ", str);
//这样可以拿到url
//call openConnection: https://aweme.snssdk.com/aweme/v1/commit/item/digg/?aweme_id=7032113629130394911&type=1&channel_id=0&city=440100&activity=0&item_type=0&is_commerce=0&iid=1012008136226883&device_id=3061490899750333&ac=wifi&channel=tengxun_1128_64&aid=1128&app_name=aweme&version_code=180700&version_name=18.7.0&device_platform=android&os=android&ssmix=a&device_type=MI+8&device_brand=Xiaomi&language=zh&os_api=29&os_version=10&manifest_version_code=180701&resolution=1080*2028&dpi=440&update_version_code=18709900&_rticket=1638775989823&package=com.ss.android.ugc.aweme&cpu_support64=true&host_abi=arm64-v8a&is_guest_mode=0&app_type=normal&minor_status=0&appTheme=light&need_personal_recommend=1&is_android_pad=0&ts=1638775988&cdid=5e37d2e0-27b8-4c1b-bbaf-1da2107b2fe2
//Found instance: org.chromium.CronetClient@515f501
//var sCronetEngine = this.build();
//var haveObj = Java.choose('org.chromium.CronetClient');
if (!bHaveFlag) {
Java.choose("org.chromium.CronetClient", {
onMatch: function (instance) { //该类有多少个实例,该回调就会被触发多少次
console.log("Found instance: " + instance);
//instance.getCronetEngine().startNetLogToFile("/data/local/tmp/cronet_log.json", true);
bHaveFlag = true;
},
onComplete: function () { }
});
}
return this.openConnection(context, str, z, str2, executor);
}
}
//hook 设备注册激活相关
//hookAllOverloads("com.ss.android.deviceregister.DeviceRegisterManager", "getSigHash"); //
hookAllOverloads("com.bytedance.common.utility.DigestUtils", "md5Hex");
hookAllOverloads("com.ss.bduploader.BDAuthHelper","setStringValue");
MainActivity = Java.use('com.alipay.sdk.util.f');
if (MainActivity != null) {
MainActivity.LIZIZ.overload('java.lang.String', 'java.lang.String').implementation = function (str1 ,str2) {
console.log("\r\n call com.alipay.sdk.util.f.LIZIZ: ", str1,str2);
//showStacks();
//return 0; //这里返回0,只是让流程不继续,不实际发送请求到服务器,不然多次测试会时不时出安全验证,影响分析
//dumpAddr(hexTemp,0x80);
return this.LIZIZ(str1,str2);
}
}
MainActivity = Java.use('com.bytedance.retrofit2.mime.DigestUtil');
if (MainActivity != null) {
MainActivity.md5Hex.overload('[B').implementation = function (byteArray) {
var result = this.md5Hex(byteArray);
// 2. 使用 javascript JSON.stringify() 打印 [B
var result1 = JSON.stringify(byteArray);
var strByte = byteToString(byteArray);
console.log('byteArray,byte src :', result1);
console.log(strByte);
console.log('byteArray,md5str: ', result);
return result;
}
}
MainActivity = Java.use('android.os.Debug');
if (MainActivity != null) {
MainActivity.isDebuggerConnected.implementation = function () {
console.log("call isDebuggerConnected");
//console.log(p0);
showStacks();
//java.lang.Exception
//at android.os.Debug.isDebuggerConnected(Native Method)
//at com.inca.security.IiIIiiiiIi.IiIIIiiIII(hc: 449)
//at com.inca.security.IiIIiiiiIi.run(hc: 319)
var bRet = this.isDebuggerConnected();
//bRet = true;
console.log("isDebuggerConnected bRet: ", bRet);
return bRet;
}
}
//void android.os.Process.killProcess(int)
MainActivity = Java.use('android.os.Process');
if (MainActivity != null) {
MainActivity.killProcess.implementation = function (pid) {
console.log("call killProcess");
//console.log(p0);
showStacks();
var bRet = this.killProcess(pid);
return bRet;
}
}
//com.kugou.common.utils.bv
}
});
}
//byte数组转字符串
//https://www.cnblogs.com/haishikugua/archive/2020/05/08/12850341.html
function byteToString(arr) {
if (typeof arr === ‘string’) {
return arr;
}
var str = ‘’,
_arr = arr;
for (var i = 0; i < _arr.length; i++) {
var one = _arr[i].toString(2),
v = one.match(/^1+?(?=0)/);
if (v && one.length == 8) {
var bytesLength = v[0].length;
var store = _arr[i].toString(2).slice(7 - bytesLength);
for (var st = 1; st < bytesLength; st++) {
store += _arr[st + i].toString(2).slice(2);
}
str += String.fromCharCode(parseInt(store, 2));
i += bytesLength - 1;
} else {
str += String.fromCharCode(_arr[i]);
}
}
return str;
}
function get_func_addr(module, offset) {
var base_addr = Module.findBaseAddress(module);
console.log("base_addr: " + base_addr);
console.log(hexdump(ptr(base_addr), {
length: 16,
header: true,
ansi: true
}))
var func_addr = base_addr.add(offset);
if (Process.arch == 'arm')
return func_addr.add(1); //如果是32位地址+1
else
return func_addr;
}
//setImmediate(hook_dy_so2,3); // hook_dy_so2
VX:Ays971124 (进群学习)