Created
July 16, 2021 15:23
-
-
Save SeeFlowerX/373101e86529ae04807f634b87ac4c7c to your computer and use it in GitHub Desktop.
libpoxy_star.so分析hook脚本
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
let jni_struct_array = [ | |
"reserved0", "reserved1", "reserved2", "reserved3", "GetVersion", "DefineClass", "FindClass", "FromReflectedMethod", "FromReflectedField", "ToReflectedMethod", "GetSuperclass", "IsAssignableFrom", "ToReflectedField", "Throw", "ThrowNew", | |
"ExceptionOccurred", "ExceptionDescribe", "ExceptionClear", "FatalError", "PushLocalFrame", "PopLocalFrame", "NewGlobalRef", "DeleteGlobalRef", "DeleteLocalRef", "IsSameObject", "NewLocalRef", "EnsureLocalCapacity", "AllocObject", "NewObject", | |
"NewObjectV", "NewObjectA", "GetObjectClass", "IsInstanceOf", "GetMethodID", "CallObjectMethod", "CallObjectMethodV", "CallObjectMethodA", "CallBooleanMethod", "CallBooleanMethodV", "CallBooleanMethodA", "CallByteMethod", "CallByteMethodV", | |
"CallByteMethodA", "CallCharMethod", "CallCharMethodV", "CallCharMethodA", "CallShortMethod", "CallShortMethodV", "CallShortMethodA", "CallIntMethod", "CallIntMethodV", "CallIntMethodA", "CallLongMethod", "CallLongMethodV", "CallLongMethodA", | |
"CallFloatMethod", "CallFloatMethodV", "CallFloatMethodA", "CallDoubleMethod", "CallDoubleMethodV", "CallDoubleMethodA", "CallVoidMethod", "CallVoidMethodV", "CallVoidMethodA", "CallNonvirtualObjectMethod", "CallNonvirtualObjectMethodV", | |
"CallNonvirtualObjectMethodA", "CallNonvirtualBooleanMethod", "CallNonvirtualBooleanMethodV", "CallNonvirtualBooleanMethodA", "CallNonvirtualByteMethod", "CallNonvirtualByteMethodV", "CallNonvirtualByteMethodA", "CallNonvirtualCharMethod", | |
"CallNonvirtualCharMethodV", "CallNonvirtualCharMethodA", "CallNonvirtualShortMethod", "CallNonvirtualShortMethodV", "CallNonvirtualShortMethodA", "CallNonvirtualIntMethod", "CallNonvirtualIntMethodV", "CallNonvirtualIntMethodA", | |
"CallNonvirtualLongMethod", "CallNonvirtualLongMethodV", "CallNonvirtualLongMethodA", "CallNonvirtualFloatMethod", "CallNonvirtualFloatMethodV", "CallNonvirtualFloatMethodA", "CallNonvirtualDoubleMethod", "CallNonvirtualDoubleMethodV", | |
"CallNonvirtualDoubleMethodA", "CallNonvirtualVoidMethod", "CallNonvirtualVoidMethodV", "CallNonvirtualVoidMethodA", "GetFieldID", "GetObjectField", "GetBooleanField", "GetByteField", "GetCharField", "GetShortField", "GetIntField", | |
"GetLongField", "GetFloatField", "GetDoubleField", "SetObjectField", "SetBooleanField", "SetByteField", "SetCharField", "SetShortField", "SetIntField", "SetLongField", "SetFloatField", "SetDoubleField", "GetStaticMethodID", | |
"CallStaticObjectMethod", "CallStaticObjectMethodV", "CallStaticObjectMethodA", "CallStaticBooleanMethod", "CallStaticBooleanMethodV", "CallStaticBooleanMethodA", "CallStaticByteMethod", "CallStaticByteMethodV", "CallStaticByteMethodA", | |
"CallStaticCharMethod", "CallStaticCharMethodV", "CallStaticCharMethodA", "CallStaticShortMethod", "CallStaticShortMethodV", "CallStaticShortMethodA", "CallStaticIntMethod", "CallStaticIntMethodV", "CallStaticIntMethodA", "CallStaticLongMethod", | |
"CallStaticLongMethodV", "CallStaticLongMethodA", "CallStaticFloatMethod", "CallStaticFloatMethodV", "CallStaticFloatMethodA", "CallStaticDoubleMethod", "CallStaticDoubleMethodV", "CallStaticDoubleMethodA", "CallStaticVoidMethod", | |
"CallStaticVoidMethodV", "CallStaticVoidMethodA", "GetStaticFieldID", "GetStaticObjectField", "GetStaticBooleanField", "GetStaticByteField", "GetStaticCharField", "GetStaticShortField", "GetStaticIntField", "GetStaticLongField", | |
"GetStaticFloatField", "GetStaticDoubleField", "SetStaticObjectField", "SetStaticBooleanField", "SetStaticByteField", "SetStaticCharField", "SetStaticShortField", "SetStaticIntField", "SetStaticLongField", "SetStaticFloatField", | |
"SetStaticDoubleField", "NewString", "GetStringLength", "GetStringChars", "ReleaseStringChars", "NewStringUTF", "GetStringUTFLength", "GetStringUTFChars", "ReleaseStringUTFChars", "GetArrayLength", "NewObjectArray", "GetObjectArrayElement", | |
"SetObjectArrayElement", "NewBooleanArray", "NewByteArray", "NewCharArray", "NewShortArray", "NewIntArray", "NewLongArray", "NewFloatArray", "NewDoubleArray", "GetBooleanArrayElements", "GetByteArrayElements", "GetCharArrayElements", | |
"GetShortArrayElements", "GetIntArrayElements", "GetLongArrayElements", "GetFloatArrayElements", "GetDoubleArrayElements", "ReleaseBooleanArrayElements", "ReleaseByteArrayElements", "ReleaseCharArrayElements", "ReleaseShortArrayElements", | |
"ReleaseIntArrayElements", "ReleaseLongArrayElements", "ReleaseFloatArrayElements", "ReleaseDoubleArrayElements", "GetBooleanArrayRegion", "GetByteArrayRegion", "GetCharArrayRegion", "GetShortArrayRegion", "GetIntArrayRegion", | |
"GetLongArrayRegion", "GetFloatArrayRegion", "GetDoubleArrayRegion", "SetBooleanArrayRegion", "SetByteArrayRegion", "SetCharArrayRegion", "SetShortArrayRegion", "SetIntArrayRegion", "SetLongArrayRegion", "SetFloatArrayRegion", | |
"SetDoubleArrayRegion", "RegisterNatives", "UnregisterNatives", "MonitorEnter", "MonitorExit", "GetJavaVM", "GetStringRegion", "GetStringUTFRegion", "GetPrimitiveArrayCritical", "ReleasePrimitiveArrayCritical", "GetStringCritical", | |
"ReleaseStringCritical", "NewWeakGlobalRef", "DeleteWeakGlobalRef", "ExceptionCheck", "NewDirectByteBuffer", "GetDirectBufferAddress", "GetDirectBufferCapacity", "GetObjectRefType" | |
] | |
function getJNIFunctionAdress(func_name){ | |
// 通过函数名获取到对应的jni函数地址 | |
let jnienv_addr = Java.vm.getEnv().handle.readPointer() | |
let offset = jni_struct_array.indexOf(func_name) * Process.pointerSize; | |
return Memory.readPointer(jnienv_addr.add(offset)) | |
} | |
function hook_jni(func_name){ | |
let listener = null; | |
switch (func_name){ | |
case "SetByteArrayRegion": | |
listener = Interceptor.attach(getJNIFunctionAdress(func_name), { | |
onEnter: function(args){ | |
console.log(`env->${func_name} called from ${Thread.backtrace(this.context, Backtracer.ACCURATE).map(DebugSymbol.fromAddress).join("\n")}`); | |
this.arg_array = args[1]; | |
}, | |
onLeave: function(retval){ | |
jbhexdump(this.arg_array); | |
console.log("SetByteArrayRegion onLeave"); | |
} | |
}) | |
default: | |
listener = Interceptor.attach(getJNIFunctionAdress(func_name), { | |
onEnter: function(args){ | |
console.log(`env->${func_name} called from ${Thread.backtrace(this.context, Backtracer.ACCURATE).map(DebugSymbol.fromAddress).join("\n")}`); | |
} | |
}) | |
} | |
return listener; | |
} | |
function jhexdump(array) { | |
if(!array) return; | |
console.log("---------jhexdump start---------"); | |
var ptr = Memory.alloc(array.length); | |
for(var i = 0; i < array.length; ++i) | |
Memory.writeS8(ptr.add(i), array[i]); | |
console.log(hexdump(ptr, {offset: 0, length: array.length, header: false, ansi: false})); | |
console.log("---------jhexdump end---------"); | |
} | |
function jbhexdump(array) { | |
console.log("---------jbhexdump start---------"); | |
let env = Java.vm.getEnv(); | |
let size = env.getArrayLength(array); | |
let data = env.getByteArrayElements(array); | |
console.log(hexdump(data, {offset: 0, length: size, header: false, ansi: false})); | |
env.releaseByteArrayElements(array, data, 0); | |
console.log("---------jbhexdump end---------"); | |
} | |
function dumpByteArray(obj){ | |
console.log("---------dumpByteArray start---------"); | |
let obj_ptr = ptr(obj.$h).readPointer(); | |
let buf_ptr = obj_ptr.add(Process.pointerSize * 3); | |
let size = obj_ptr.add(Process.pointerSize * 2).readU32(); | |
console.log(hexdump(buf_ptr, {offset: 0, length: size, header: false, ansi: false})); | |
console.log("---------dumpByteArray end---------"); | |
} | |
function getByte_LogArgs(){ | |
Java.perform(function(){ | |
let gson = Java.use('com.google.gson.Gson'); | |
let ByteDataCls = Java.use("com.tencent.starprotocol.ByteData"); | |
ByteDataCls.getByte.overload("android.content.Context", "long", "long", "long", "long", "java.lang.Object", "java.lang.Object", "java.lang.Object", "java.lang.Object").implementation = function(context, num1, num2, num3, num4, obj1, obj2, obj3, obj4){ | |
console.log(context, num1, num2, num3, num4); | |
console.log("obj1", obj1.$className, gson.$new().toJson(obj1)) | |
console.log("obj2", obj2.$className, gson.$new().toJson(obj2)) | |
console.log("obj3", obj3.$className, gson.$new().toJson(obj3)) | |
console.log("obj4", obj4.$className, gson.$new().toJson(obj4)) | |
dumpByteArray(obj4); | |
let resp = this.getByte(context, num1, num2, num3, num4, obj1, obj2, obj3, obj4) | |
jhexdump(resp); | |
return resp | |
} | |
}) | |
} | |
function freeze_funcs(){ | |
let lrand48_addr = Module.findExportByName("libc.so", "lrand48"); | |
Interceptor.attach(lrand48_addr, {onLeave: function(retval){retval.replace(7)}}); | |
let tm_s = 1626403551; | |
let tm_us = 151606; | |
let gettimeofday_addr = Module.findExportByName("libc.so", "gettimeofday"); | |
Interceptor.attach(gettimeofday_addr, { | |
onEnter: function(args) { | |
this.tm_ptr = args[0]; | |
}, | |
onLeave:function(retval){ | |
this.tm_ptr.writeLong(tm_s); | |
this.tm_ptr.add(0x4).writeLong(tm_us); | |
} | |
}); | |
} | |
function call_getByte(){ | |
Java.perform(function(){ | |
let LongCls = Java.use("java.lang.Long"); | |
let StringCls = Java.use("java.lang.String"); | |
let ReflectArrayCls = Java.use('java.lang.reflect.Array') | |
let ByteDataCls = Java.use("com.tencent.starprotocol.ByteData"); | |
let ctx = Java.use('android.app.ActivityThread').currentApplication().getApplicationContext(); | |
let num_1 = LongCls.$new(1).longValue(); | |
let num_2 = LongCls.$new(0).longValue(); | |
let num_3 = LongCls.$new(0).longValue(); | |
let num_4 = LongCls.$new(0).longValue(); | |
let obj1 = ReflectArrayCls.newInstance(StringCls.class, 9); | |
ReflectArrayCls.set(obj1, 0, "dl_10303"); | |
ReflectArrayCls.set(obj1, 1, "1"); | |
ReflectArrayCls.set(obj1, 2, "66666666666666666666666666666666"); | |
ReflectArrayCls.set(obj1, 3, "getCKey"); | |
ReflectArrayCls.set(obj1, 4, "888888888888888888888888888888888888"); | |
ReflectArrayCls.set(obj1, 5, "1626403551515"); | |
ReflectArrayCls.set(obj1, 6, ""); | |
ReflectArrayCls.set(obj1, 7, "8.3.95.26016"); | |
ReflectArrayCls.set(obj1, 8, "com.tencent.qqlive"); | |
let obj2 = StringCls.$new(""); | |
let obj3 = StringCls.$new("66666666666666666666666666666666"); | |
let obj4 = Java.array('B', [49,54,50,54,52,48,51,53,53,49,44,110,48,48,51,57,101,121,49,109,109,100,44,110,117,108,108]); | |
let ByteDataIns = ByteDataCls.getInstance() | |
let byte = ByteDataIns.getByte(ctx, num_1, num_2, num_3, num_4, obj1, obj2, obj3, obj4); | |
jhexdump(byte); | |
Interceptor.detachAll(); | |
}) | |
} | |
function inline_hook(){ | |
let hook_flag = false; | |
let base_addr = Module.getBaseAddress("libpoxy_star.so"); | |
Interceptor.attach(base_addr.add(0xD9AC).add(1), { | |
onEnter: function(args){ | |
hook_flag = true; | |
this.hook_jni_interceptor = hook_jni("SetByteArrayRegion"); | |
}, | |
onLeave: function (retval) { | |
hook_flag = false; | |
this.hook_jni_interceptor.detach(); | |
console.log(`onLeave sub_D9AC`); | |
jbhexdump(retval); | |
} | |
}); | |
Interceptor.attach(base_addr.add(0xAAE88).add(1), { | |
onEnter: function (args) { | |
if(hook_flag){ | |
console.log(`call sub_AAE88`); | |
this.arg_0 = args[0]; | |
console.log("sub_AAE88 arg_0", hexdump(args[0].readPointer())); | |
} | |
}, | |
onLeave: function (retval) { | |
console.log("sub_AAE88 onLeave arg_0", hexdump(this.arg_0.readPointer())); | |
} | |
}); | |
Interceptor.attach(base_addr.add(0xABDBC).add(1), { | |
onEnter: function (args) { | |
if(hook_flag){ | |
console.log(`call sub_ABDBC`); | |
this.arg_0 = args[0]; | |
console.log("sub_ABDBC arg_0", hexdump(args[0].readPointer())); | |
} | |
}, | |
onLeave: function (retval) { | |
console.log("sub_ABDBC onLeave arg_0", hexdump(this.arg_0.readPointer())); | |
} | |
}); | |
Interceptor.attach(base_addr.add(0xAC214).add(1), { | |
onEnter: function (args) { | |
console.log(`call sub_AC214`); | |
console.log("input", args[1], args[2], args[3], args[4]); | |
} | |
}); | |
Interceptor.attach(base_addr.add(0xAD1D0).add(1), { | |
onEnter: function (args) { | |
console.log(`call sub_AD1D0`); | |
console.log("input", args[0], args[1], args[3]); | |
console.log(hexdump(args[2].readByteArray(args[3].toUInt32()))); | |
} | |
}); | |
Interceptor.attach(base_addr.add(0x139A4).add(1), { | |
onLeave: function (retval) { | |
console.log("sub_139A4 retval", retval.readPointer()); | |
} | |
}); | |
Interceptor.attach(base_addr.add(0x82648).add(1), { | |
onEnter: function (args) { | |
console.log(`call sub_82648`); | |
console.log("arg_1", hexdump(args[1].readByteArray(args[2].toUInt32()))) | |
console.log("arg_2", args[2].toUInt32()) | |
} | |
}); | |
Interceptor.attach(base_addr.add(0x84890).add(1), { | |
onEnter: function (args) { | |
this.arg_1 = args[1]; | |
}, | |
onLeave: function (retval) { | |
console.log(`sub_84890 onLeave`); | |
console.log("arg_1", hexdump(this.arg_1)) | |
} | |
}); | |
Interceptor.attach(base_addr.add(0x85A40).add(1), { | |
onEnter: function (args) { | |
console.log(`call sub_85A40`); | |
console.log("sub_85A40 arg_1", hexdump(args[1].readByteArray(args[2].toUInt32()))); | |
console.log("sub_85A40 arg_2", args[2]); | |
console.log("sub_85A40 arg_3", hexdump(args[3].readByteArray(args[4].toUInt32()))); | |
console.log("sub_85A40 arg_4", args[4]); | |
} | |
}); | |
Interceptor.attach(base_addr.add(0x68E44).add(1), { | |
onEnter: function (args) { | |
console.log(`call sub_68E44`); | |
console.log("sub_68E44 arg_1", hexdump(args[1].readByteArray(args[2].toUInt32()))); | |
console.log("sub_68E44 arg_2", args[2]); | |
} | |
}); | |
Interceptor.attach(base_addr.add(0x6D628).add(1), { | |
onEnter: function (args) { | |
this.arg_0 = args[0]; | |
}, | |
onLeave: function (retval) { | |
console.log("sub_6D628 retval", hexdump(this.arg_0)); | |
} | |
}); | |
Interceptor.attach(base_addr.add(0xA605C).add(1), { | |
onEnter: function (args) { | |
console.log(`call sub_A605C`); | |
this.arg_6 = args[6]; | |
console.log("sub_A605C arg_1", hexdump(args[1].readByteArray(args[2].toUInt32()))); | |
console.log("sub_A605C arg_2", args[2]); | |
console.log("sub_A605C arg_3", args[3]); | |
console.log("sub_A605C arg_4", args[4]); | |
console.log("sub_A605C arg_5", args[5]); | |
console.log("sub_A605C arg_6", hexdump(args[6])); | |
console.log("sub_A605C arg_7", hexdump(args[7].readByteArray(args[8].toUInt32()))); | |
console.log("sub_A605C arg_8", args[8]); | |
}, | |
onLeave: function (retval) { | |
console.log("sub_A605C retval", hexdump(this.arg_6)); | |
} | |
}); | |
Interceptor.attach(base_addr.add(0x9C1F0).add(1), { | |
onEnter: function (args) { | |
console.log(`call sub_9C1F0`); | |
this.arg_3 = args[3]; | |
console.log("sub_9C1F0 arg_1", hexdump(args[1].readByteArray(args[2].toUInt32()))); | |
console.log("sub_9C1F0 arg_2", args[2]); | |
console.log("sub_9C1F0 arg_3", hexdump(args[3])); | |
}, | |
onLeave: function (retval) { | |
console.log("sub_9C1F0 retval", hexdump(this.arg_3)); | |
} | |
}); | |
Interceptor.attach(base_addr.add(0x9B980).add(1), { | |
onEnter: function (args) { | |
console.log(`call sub_9B980`); | |
this.arg_0 = args[0]; | |
console.log("sub_9B980 arg_0", hexdump(args[0])); | |
console.log("sub_9B980 arg_1", hexdump(args[1].readByteArray(args[2].toUInt32()))); | |
console.log("sub_9B980 arg_2", args[2]); | |
}, | |
onLeave: function (retval) { | |
console.log("sub_9B980 retval", hexdump(this.arg_0)); | |
} | |
}); | |
Interceptor.attach(base_addr.add(0x86CD4).add(1), { | |
onEnter: function (args) { | |
console.log(`call sub_86CD4`); | |
console.log("sub_86CD4 args[1]", args[1]) | |
console.log("sub_86CD4 args[1]", hexdump(args[1])) | |
console.log("sub_86CD4 args[2]", args[2]) | |
console.log("sub_86CD4 args[3]", hexdump(args[3])) | |
console.log("sub_86CD4 args[4]", args[4]) | |
console.log("sub_86CD4 args[5]", args[5]) | |
}, | |
onLeave: function (retval) { | |
} | |
}); | |
Interceptor.attach(base_addr.add(0x87DD8).add(1), { | |
onEnter: function (args) { | |
console.log(`call sub_87DD8`); | |
this.arg_2 = args[2]; | |
console.log("sub_87DD8 args[0]", hexdump(args[0])) | |
console.log("sub_87DD8 args[1]", hexdump(args[1])) | |
console.log("sub_87DD8 args[2]", hexdump(args[2])) | |
}, | |
onLeave: function (retval) { | |
console.log("sub_87DD8 retval", hexdump(this.arg_2)); | |
} | |
}); | |
Interceptor.attach(base_addr.add(0x89BF4).add(1), { | |
onEnter: function (args) { | |
console.log(`call sub_89BF4`); | |
this.arg_1 = args[1]; | |
console.log("sub_89BF4 args[1]", hexdump(args[1].readByteArray(args[2].toUInt32()))) | |
console.log("sub_89BF4 args[2]", args[2]) | |
}, | |
onLeave: function (retval) { | |
console.log("sub_89BF4 retval", hexdump(this.arg_1)); | |
} | |
}); | |
} | |
freeze_funcs(); | |
inline_hook(); | |
call_getByte(); | |
// setTimeout(() => { | |
// getByte_LogArgs(); | |
// }, 500); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment