文章仅限于个人学习使用
样本
YmlsYmlsaSAgNy4zOS4w
工具=>ida frida(未去任何特征) so文件arm64-v8a
1.数据加密
看看是哪个so文件有检测
function hook_dlopen1(soName = 'libmsaoaidsec.so') {
Interceptor.attach(Module.findExportByName(null, "android_dlopen_ext"),
{
onEnter: function (args) {
var pathptr = args[0];
if (pathptr !== undefined && pathptr != null) {
var path = ptr(pathptr).readCString();
console.log(path)
}
}
}
);
}
/data/app/~~BSX3pQx54amgGap_bJlDRg==/tv.danmaku.bili-gpokD3YitZKGKPiflQDaDQ==/oat/arm64/base.odex
libframework-connectivity-jni.so
libforcedarkimpl.so
/data/app/~~BSX3pQx54amgGap_bJlDRg==/tv.danmaku.bili-gpokD3YitZKGKPiflQDaDQ==/lib/arm64/libblkv.so
/data/app/~~BSX3pQx54amgGap_bJlDRg==/tv.danmaku.bili-gpokD3YitZKGKPiflQDaDQ==/lib/arm64/libbili_core.so
/data/app/~~BSX3pQx54amgGap_bJlDRg==/tv.danmaku.bili-gpokD3YitZKGKPiflQDaDQ==/lib/arm64/libmsaoaidsec.so
Process terminated
在加载完成libmsaoaidsec.so后闪退
2.检测点
按照检测思路,一般会用pthread_create起线程
https://github.com/darvincisec/DetectFrida
function hook_pthread_createx() {
var libcModule = Process.findModuleByName('libc.so');
if (libcModule) {
var pthread_create = new NativeFunction(
libcModule.findExportByName('pthread_create'),
'int', ['pointer', 'pointer', 'pointer', 'pointer']
);
Interceptor.attach(pthread_create, {
onEnter: function (args) {
var libmsaoaidsecModule = Process.findModuleByName('libmsaoaidsec.so');
if (libmsaoaidsecModule) {
// 在进入 pthread_create 之前
console.log("pthread_create called with arguments:");
console.log("attr:", args[0]);
console.log("attr:", (args[0] - libmsaoaidsecModule.base).toString(16));
console.log("start_routine:", args[1]);
console.log("arg:", args[2]);
console.log("function at=>0x"+(args[2] - libmsaoaidsecModule.base).toString(16));
console.log("pid:", args[3]);
console.log('----------------------------------------\n')
}
},
onLeave: function (retval) {
// 在离开 pthread_create 之后
console.log("pthread_create returned:", retval);
if (retval.toInt32() === 0) {
console.log("Thread created successfully!");
} else {
console.log("Thread creation failed!");
}
}
});
}
}
结果是在0x1aee4和0x1a574
3.nop检测点
0x1aee4
0x1a574
两个函数往上翻找都会有个getpid
然后可以用两种方式去patch地址
3-1.ida patch
直接nop掉0x1A858和0x1B8B4,apply patch后push到手机即可
3-2 frida patch
frida patch后效果如下
function hook_RegisterNatives() {
var symbols = Module.enumerateSymbolsSync("libart.so");
var addrRegisterNatives = null;
for (var i = 0; i < symbols.length; i++) {
var symbol = symbols[i];
if (symbol.name.indexOf("art") >= 0 &&
symbol.name.indexOf("JNI") >= 0 &&
symbol.name.indexOf("RegisterNatives") >= 0 &&
symbol.name.indexOf("CheckJNI") < 0) {
addrRegisterNatives = symbol.address;
console.log("RegisterNatives is at ", symbol.address, symbol.name);
if (addrRegisterNatives != null) {
Interceptor.attach(addrRegisterNatives, {
onEnter: function (args) {
var env = args[0];
var java_class = args[1];
var class_name = Java.vm.tryGetEnv().getClassName(java_class);
console.log("\n[RegisterNatives] method_count:", args[3]);
var methods_ptr = ptr(args[2]);
var method_count = parseInt(args[3]);
for (var i = 0; i < method_count; i++) {
var name_ptr = Memory.readPointer(methods_ptr.add(i * Process.pointerSize * 3));
var sig_ptr = Memory.readPointer(methods_ptr.add(i * Process.pointerSize * 3 + Process.pointerSize));
var fnPtr_ptr = Memory.readPointer(methods_ptr.add(i * Process.pointerSize * 3 + Process.pointerSize * 2));
var name = Memory.readCString(name_ptr);
var sig = Memory.readCString(sig_ptr);
var find_module = Process.findModuleByAddress(fnPtr_ptr);
console.log("[RegisterNatives] java_class:", class_name, "name:", name, "sig:", sig, "fnPtr:", fnPtr_ptr, "module_name:", find_module.name, "module_base:", find_module.base, "offset:", ptr(fnPtr_ptr).sub(find_module.base));
// }
}
}
});
}
}
}
}
function print_arg(addr) {
try {
var module = Process.findRangeByAddress(addr);
if (module != null) return "\n" + hexdump(addr) + "\n";
return ptr(addr) + "\n";
} catch (e) {
return addr + "\n";
}
}
function hook_native_addr() {
var funcPtr = Module.findBaseAddress("libbili.so").add(0x8d14);
var paramsNum = 0x3;
var module = Process.findModuleByAddress(funcPtr);
try {
Interceptor.attach(funcPtr, {
onEnter: function (args) {
this.logs = "";
this.params = [];
// @ts-ignore
this.logs = this.logs.concat("So: " + module.name + " Method: sub_8D14 offset: " + ptr(funcPtr).sub(module.base) + "\n");
for (let i = 0; i < paramsNum; i++) {
this.params.push(args[i]);
this.logs = this.logs.concat("this.args" + i + " onEnter: " + print_arg(args[i]));
}
}, onLeave: function (retval) {
this.logs = this.logs.concat("retval onLeave: " + print_arg(retval) + "\n");
console.log(this.logs);
}
});
} catch (e) {
console.log(e);
}
}
function hook_dlopen1(soName = 'libmsaoaidsec.so') {
// hook_RegisterNatives()
Interceptor.attach(Module.findExportByName(null, "android_dlopen_ext"),
{
onEnter: function (args) {
var pathptr = args[0];
if (pathptr !== undefined && pathptr != null) {
var path = ptr(pathptr).readCString();
if (path.indexOf(soName) >= 0) {
// hook_pthread_createx()
hook_libc_getpid()
}
}
}
}
);
}
function enumerateLoadedModules() {
// 使用 Process.enumerateModules() 方法来获取当前加载的所有模块(包括共享库)
var modules = Process.enumerateModules();
// 遍历所有模块并打印它们的信息
for (var i = 0; i < modules.length; i++) {
var module = modules[i];
console.log('Module Name:', module.name);
console.log('Base Address:', module.base);
console.log('Size:', module.size);
}
}
function hook_pthread_createx() {
var libcModule = Process.findModuleByName('libc.so');
if (libcModule) {
var pthread_create = new NativeFunction(
libcModule.findExportByName('pthread_create'),
'int', ['pointer', 'pointer', 'pointer', 'pointer']
);
Interceptor.attach(pthread_create, {
onEnter: function (args) {
var libmsaoaidsecModule = Process.findModuleByName('libmsaoaidsec.so');
if (libmsaoaidsecModule) {
// 在进入 pthread_create 之前
console.log("pthread_create called with arguments:");
console.log("attr:", args[0]);
console.log("attr:", (args[0] - libmsaoaidsecModule.base).toString(16));
console.log("start_routine:", args[1]);
console.log("arg:", args[2]);
console.log("function at=>0x"+(args[2] - libmsaoaidsecModule.base).toString(16));
console.log("pid:", args[3]);
console.log('----------------------------------------\n')
}
},
onLeave: function (retval) {
// 在离开 pthread_create 之后
console.log("pthread_create returned:", retval);
if (retval.toInt32() === 0) {
console.log("Thread created successfully!");
} else {
console.log("Thread creation failed!");
}
}
});
}
}
function nop(targetModule, addr) {
// 定义要 NOP 的函数地址和指令长度
var targetFunctionAddress = targetModule.base.add(addr); // 0x1A858 是函数的偏移地址
var instructionLength = 4; // 假设函数中的指令长度为 4 字节
// 在目标函数地址写入 NOP 指令
Memory.protect(targetFunctionAddress, instructionLength, 'rwx');
for (var i = 0; i < instructionLength; i++) {
Memory.writeU8(targetFunctionAddress.add(i), 0x90); // 0x90 是 NOP 指令
}
console.log('NOPed function at address 0x', (addr).toString(16));
}
function hook_libc_getpid() {
// 寻找并 hook 目标库
var f = false
var libcModule = Process.findModuleByName('libc.so');
if (libcModule) {
var getpid = libcModule.findExportByName('getpid');
Interceptor.attach(getpid, {
onEnter: function (args) {
var targetModule = Process.getModuleByName('libmsaoaidsec.so');
if (targetModule && !f) {
nop(targetModule, 0x1A858)
nop(targetModule, 0x1B8B4)
f = true
}
},
onLeave: function (retval) {
}
});
}
}
setImmediate(hook_dlopen1, "libmsaoaidsec.so")
提示
ARMv7-A ARMv7-R:大多数指令仍然是4个字节长,但ARMv7-A引入了Thumb-2指令集,其中包括16位和32位指令。Thumb-2指令集的指令可以是2或4个字节长。
ARMv8-A:ARMv8-A引入了64位的A64指令集,其中指令通常是4个字节长。此外,ARMv8-A还支持A32和T32指令集,其中A32指令通常是4个字节长,而T32指令可以是2或4个字节长。
参考
https://bbs.kanxue.com/thread-277034.htm