OLLVM混淆函数名:std::string_
查找JNI_OnLoad
加载Android ARM库:
修改类型:
双击查看v6 = off_33D60里的off_33D60:
print_dex(0x37070)是sign1。
查看交叉引用:
是std::string_::
形式的函数,改了函数的名字,这是OLLVM的另一种加密函数,在.init_array段里面:
OLLVM字符串使用前混淆:运行时解密
Ctrl+S打开.init_array:
查看sub_6CEC函数:
都赋值为0,未解密。
接下来的两个函数,都不是解密函数。
do
{
byte_3E1BA[v5] = byte_22E80[v5
+ 280
+ -28
* ((unsigned __int64)((v5 >> 2) * (unsigned __int128)0x4924924924924925uLL >> 64) >> 1)] ^ byte_22E80[v5 + 308];
++v5;
}
通过十六进制打印虚拟地址(0x3E1BA)的内容,可知在使用字符串之前解密。
Frida Hook:
function hook_libart() {
var module_libart = Process.findModuleByName("libart.so");
console.log(module_libart);
var addr_RegisterNatives = null;
var addr_GetStringUTFChars = null;
var addr_NewStringUTF = null;
var addr_FindClass = null;
//枚举模块的符号
var symbols = module_libart.enumerateSymbols();
for (var i = 0; i < symbols.length; i++) {
var name = symbols[i].name;
if (name.indexOf("CheckJNI") == -1 && name.indexOf("JNI") > 0) {
if (name.indexOf("RegisterNatives") > 0) {
console.log(name);
addr_RegisterNatives = symbols[i].address;
} else if (name.indexOf("GetStringUTFChars") > 0) {
console.log(name);
addr_GetStringUTFChars = symbols[i].address;
} else if (name.indexOf("NewStringUTF") > 0) {
console.log(name);
addr_NewStringUTF = symbols[i].address;
} else if (name.indexOf("FindClass") > 0) {
console.log(name);
addr_FindClass = symbols[i].address;
}
}
}
if (addr_RegisterNatives) {
Interceptor.attach(addr_RegisterNatives, {
onEnter: function (args) {
var java_class = Java.vm.tryGetEnv().getClassName(args[1]);
var methods = args[2];
var method_count = parseInt(args[3]);
console.log("addr_RegisterNatives java_class:", java_class, "method_count:", method_count);
for (var i = 0; i < method_count; i++) {
console.log(methods.add(i * Process.pointerSize * 3).readPointer().readCString());
console.log(methods.add(i * Process.pointerSize * 3 + Process.pointerSize).readPointer().readCString());
var fnPtr = methods.add(i * Process.pointerSize * 3 + Process.pointerSize * 2).readPointer();
var module_so = Process.findModuleByAddress(fnPtr);
console.log(module_so.name + "!" + fnPtr.sub(module_so.base));
}
}, onLeave: function (retval) {
}
})
}
if (addr_GetStringUTFChars) {
Interceptor.attach(addr_GetStringUTFChars, {
onLeave : function(retval) {
console.log("[GetStringUTFChars] : ", ptr(retval).readCString());
}
})
}
if (addr_NewStringUTF) {
Interceptor.attach(addr_NewStringUTF, {
onEnter : function(args) {
console.log("[NewStringUTF] : ", ptr(args[1]).readCString());
}
})
}
if (addr_FindClass) {
Interceptor.attach(addr_FindClass, {
onEnter : function(args) {
console.log("[FindClass] : ", ptr(args[1]).readCString());
}
})
}
}
function print_hex(addr) {
var base_hello_jni = Module.findBaseAddress("libhello-jni.so");
console.log(hexdump(base_hello_jni.add(addr)));
}
function hook_native() {
var base_hello_jni = Module.findBaseAddress("libhello-jni.so");
console.log(base_hello_jni);
if (base_hello_jni == null) {
return ;
}
Interceptor.attach(base_hello_jni.add(0x81D0), {
onEnter : function(args) {
this.arg0 = args[0]; //把参数保存到局部变量里面
this.arg1 = args[1];
}, onLeave : function(retval) {
console.log("0x81D0:\r\n", hexdump(this.arg0), "\r\n", hexdump(this.arg1));
}
});
Interceptor.attach(base_hello_jni.add(0x809C), {
onEnter : function(args) {
this.arg0 = args[0]; //把参数保存到局部变量里面
this.arg1 = args[1];
this.arg2 = args[2];
}, onLeave : function(retval) {
console.log("0x809C:\r\n", hexdump(this.arg1, {length : parseInt(this.arg2)}));
}
});
//inline hook
Interceptor.attach(base_hello_jni.add(0x731C), {
onEnter : function(args) {
console.log("0x731C", this.context.x13, this.context.x14);
}, onLeave : function(retval) {
}
});
}
function hook_android_dlopen_ext() {
Interceptor.attach(Module.findExportByName(null, "android_dlopen_ext"), {
onEnter: function (args) {
this.name = args[0].readCString();
console.log("android_dlopen_ext:", this.name);
}, onLeave: function (retval) {
if (this.name.indexOf("libhello-jni.so") > 0) {
hook_native();
}
}
})
}
function main() {
// hook_libart();
hook_android_dlopen_ext();
hook_native();
}
setImmediate(main);