ida静态分析
示例app是网上找的一个杀毒软件,做安全的app防护应该是OK的。
直接找到JNI_OnLoad
类名没处理,直接是明文。
jint JNI_OnLoad(JavaVM *vm, void *reserved)
{
jint v2; // w19
__int64 v4; // [xsp+0h] [xbp-30h] BYREF
qword_25148 = vm;
if ( (*vm)->GetEnv(vm, &v4, 65540LL) )
return -1;
v2 = -1;
if ( (sub_6454)(v4, "com/avl/engine/security/NativeUtils", off_24058, 13LL) )
{
sub_BABC();
if ( (sub_6454)(v4, "com/avl/engine/security/AVLA", off_24190, 32LL) )
return 65540;
else
return -1;
}
return v2;
}
sub_6454 里面可以看到RegisterNatives 实现动态注册
bool __fastcall sub_6454(JNIEnv *a1, const char *a2, const JNINativeMethod *a3, jint a4)
{
void *v8; // x22
jint v9; // w20
v8 = ((*a1)->FindClass)(a1);
if ( (*a1)->ExceptionOccurred(a1) )
{
(*a1)->ExceptionDescribe(a1);
(*a1)->ExceptionClear(a1);
}
if ( v8 )
{
v9 = (*a1)->RegisterNatives(a1, v8, a3, a4);
(*a1)->DeleteLocalRef(a1, v8);
return v9 >= 0;
}
else
{
__android_log_print(6, "@AVLSDK Error", "class %s not found!", a2);
return 0LL;
}
}
sub_6454 的三个参数就是函数的JNINativeMethod结构体,里面就是动态注册函数的方法名,方法签名和对应的实现的函数地址。
typedef struct {
const char* name;
const char* signature;
void* fnPtr;
} JNINativeMethod;
前面JNI_OnLoad里面调了两次sub_6454 ,第四个参数是注册的方法数量,也就是NativeUtils类注册了13个方法,AVLA类注册了32个方法。
分别是
(sub_6454)(v4, “com/avl/engine/security/NativeUtils”, off_24058, 13LL)
(sub_6454)(v4, “com/avl/engine/security/AVLA”, off_24190, 32LL)
看一下off_24058 ,这里就是13个动态注册的函数
同样的 off_24190 是32个动态注册的函数,这里截图只截取部分。
在方法名、方法签名等没有处理的情况下,通过静态分析也能很清楚的看到动态注册的对应函数。
如果方法名、方法签名做了处理,比如加密,ida静态就没办法清楚的呈现了。
这个时候就需要动态分析,上frida hook。
frida hook RegisterNatives
frida hook register的脚步网上很多,我这里用的这个
https://github.com/lasting-yang/frida_hook_libart
脚本如下:
function find_RegisterNatives(params) {
let symbols = Module.enumerateSymbolsSync("libart.so");
let addrRegisterNatives = null;
for (let i = 0; i < symbols.length; i++) {
let symbol = symbols[i];
//_ZN3art3JNI15RegisterNativesEP7_JNIEnvP7_jclassPK15JNINativeMethodi
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);
hook_RegisterNatives(addrRegisterNatives)
}
}
}
function hook_RegisterNatives(addrRegisterNatives) {
if (addrRegisterNatives != null) {
Interceptor.attach(addrRegisterNatives, {
onEnter: function (args) {
console.log("[RegisterNatives]");
let java_class = args[1];
let class_name = Java.vm.tryGetEnv().getClassName(java_class);
console.log("java_class ===> " + class_name);
console.log("method_count ===> " + args[3]);
let methods_ptr = ptr(args[2]);
let method_count = parseInt(args[3]);
for (let i = 0; i < method_count; i++) {
let name_ptr = Memory.readPointer(methods_ptr.add(i * Process.pointerSize * 3));
let sig_ptr = Memory.readPointer(methods_ptr.add(i * Process.pointerSize * 3 + Process.pointerSize));
let fnPtr_ptr = Memory.readPointer(methods_ptr.add(i * Process.pointerSize * 3 + Process.pointerSize * 2));
let name = Memory.readCString(name_ptr);
let sig = Memory.readCString(sig_ptr);
let symbol = DebugSymbol.fromAddress(fnPtr_ptr)
console.log("[RegisterNatives] ===>", "name:", name, "sig:", sig, "fnPtr:", fnPtr_ptr, " fnOffset:", symbol, " callee:", DebugSymbol.fromAddress(this.returnAddress));
}
}
});
}
}
setImmediate(find_RegisterNatives);
运行打印效果:
[Pixel 3a::com.antiy.avl ]-> [RegisterNatives]
java_class ===> com.avl.engine.security.NativeUtils
method_count ===> 0xd
[RegisterNatives] ===> name: getLocalUID sig: ()Ljava/lang/String; fnPtr: 0x7c8be18fdc fnOffset: 0x7c8be18fdc libavlasys.so!0xdfdc callee: 0x7c8be114dc libavlasys.so!0x64dc
[RegisterNatives] ===> name: getCpuPlatform sig: ()Ljava/lang/String; fnPtr: 0x7c8be190f0 fnOffset: 0x7c8be190f0 libavlasys.so!0xe0f0 callee: 0x7c8be114dc libavlasys.so!0x64dc
[RegisterNatives] ===> name: unzipAvllib sig: (Ljava/lang/String;Ljava/lang/String;)I fnPtr: 0x7c8be194a4 fnOffset: 0x7c8be194a4 libavlasys.so!0xe4a4 callee: 0x7c8be114dc libavlasys.so!0x64dc
[RegisterNatives] ===> name: getFileMD5 sig: (Ljava/lang/String;I)Ljava/lang/String; fnPtr: 0x7c8be1a1c8 fnOffset: 0x7c8be1a1c8 libavlasys.so!0xf1c8 callee: 0x7c8be114dc libavlasys.so!0x64dc
[RegisterNatives] ===> name: getStringMD5 sig: (Ljava/lang/String;I)Ljava/lang/String; fnPtr: 0x7c8be1a26c fnOffset: 0x7c8be1a26c libavlasys.so!0xf26c callee: 0x7c8be114dc libavlasys.so!0x64dc
[RegisterNatives] ===> name: unzipFile sig: (Ljava/lang/String;Ljava/lang/String;Ljava/util/List;)I fnPtr: 0x7c8be1994c fnOffset: 0x7c8be1994c libavlasys.so!0xe94c callee: 0x7c8be114dc libavlasys.so!0x64dc
[RegisterNatives] ===> name: unzipAssetsFile sig: (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/util/List;)I fnPtr: 0x7c8be195fc fnOffset: 0x7c8be195fc libavlasys.so!0xe5fc callee: 0x7c8be114dc libavlasys.so!0x64dc
[RegisterNatives] ===> name: unzipAssetsFileEfficient sig: (Landroid/content/res/AssetManager;Ljava/lang/String;Ljava/lang/String;Ljava/util/List;)I fnPtr: 0x7c8be1972c fnOffset: 0x7c8be1972c libavlasys.so!0xe72c callee: 0x7c8be114dc libavlasys.so!0x64dc
[RegisterNatives] ===> name: readAssetsFile sig: (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String; fnPtr: 0x7c8be19a34 fnOffset: 0x7c8be19a34 libavlasys.so!0xea34 callee: 0x7c8be114dc libavlasys.so!0x64dc
[RegisterNatives] ===> name: readAssetsFileEfficient sig: (Landroid/content/res/AssetManager;Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String; fnPtr: 0x7c8be19c0c fnOffset: 0x7c8be19c0c libavlasys.so!0xec0c callee: 0x7c8be114dc libavlasys.so!0x64dc
[RegisterNatives] ===> name: searchFile sig: (Ljava/lang/String;Lcom/avl/engine/security/FileSearcher;)I fnPtr: 0x7c8be1261c fnOffset: 0x7c8be1261c libavlasys.so!0x761c callee: 0x7c8be114dc libavlasys.so!0x64dc
[RegisterNatives] ===> name: searchFile sig: ([Ljava/lang/String;Lcom/avl/engine/security/FileSearcher;)I fnPtr: 0x7c8be126b0 fnOffset: 0x7c8be126b0 libavlasys.so!0x76b0 callee: 0x7c8be114dc libavlasys.so!0x64dc
[RegisterNatives] ===> name: getMetaInfEntryNames sig: (Ljava/lang/String;)[[B fnPtr: 0x7c8be14220 fnOffset: 0x7c8be14220 libavlasys.so!0x9220 callee: 0x7c8be114dc libavlasys.so!0x64dc
[RegisterNatives]
java_class ===> com.avl.engine.security.AVLA
method_count ===> 0x20
[RegisterNatives] ===> name: checkKey sig: ()I fnPtr: 0x7c8be19104 fnOffset: 0x7c8be19104 libavlasys.so!0xe104 callee: 0x7c8be114dc libavlasys.so!0x64dc
[RegisterNatives] ===> name: setAVLSdkPath sig: (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;I)I fnPtr: 0x7c8be19108 fnOffset: 0x7c8be19108 libavlasys.so!0xe108 callee: 0x7c8be114dc libavlasys.so!0x64dc
[RegisterNatives] ===> name: installPackage sig: (Ljava/lang/String;ILjava/lang/String;Ljava/lang/String;)I fnPtr: 0x7c8be192e8 fnOffset: 0x7c8be192e8 libavlasys.so!0xe2e8 callee: 0x7c8be114dc libavlasys.so!0x64dc
[RegisterNatives] ===> name: scanEx sig: (Ljava/lang/String;[IJ)[Ljava/lang/String; fnPtr: 0x7c8be18a5c fnOffset: 0x7c8be18a5c libavlasys.so!0xda5c callee: 0x7c8be114dc libavlasys.so!0x64dc
[RegisterNatives] ===> name: scan sig: (Ljava/lang/String;[I)Ljava/lang/String; fnPtr: 0x7c8be18900 fnOffset: 0x7c8be18900 libavlasys.so!0xd900 callee: 0x7c8be114dc libavlasys.so!0x64dc
[RegisterNatives] ===> name: arbitrateVirusName sig: (Ljava/lang/String;)I fnPtr: 0x7c8be18b6c fnOffset: 0x7c8be18b6c libavlasys.so!0xdb6c callee: 0x7c8be114dc libavlasys.so!0x64dc
[RegisterNatives] ===> name: getVirusDescription sig: (Ljava/lang/String;I)Ljava/lang/String; fnPtr: 0x7c8be18ba4 fnOffset: 0x7c8be18ba4 libavlasys.so!0xdba4 callee: 0x7c8be114dc libavlasys.so!0x64dc
[RegisterNatives] ===> name: getEngineVersion sig: ()Ljava/lang/String; fnPtr: 0x7c8be193ec fnOffset: 0x7c8be193ec libavlasys.so!0xe3ec callee: 0x7c8be114dc libavlasys.so!0x64dc
[RegisterNatives] ===> name: getSigLibVersion sig: ()Ljava/lang/String; fnPtr: 0x7c8be19448 fnOffset: 0x7c8be19448 libavlasys.so!0xe448 callee: 0x7c8be114dc libavlasys.so!0x64dc
[RegisterNatives] ===> name: getEngConfVersion sig: (Ljava/lang/String;)Ljava/lang/String; fnPtr: 0x7c8be1a3e8 fnOffset: 0x7c8be1a3e8 libavlasys.so!0xf3e8 callee: 0x7c8be114dc libavlasys.so!0x64dc
[RegisterNatives] ===> name: getCertHash sig: (Ljava/lang/String;)Ljava/lang/String; fnPtr: 0x7c8be19e40 fnOffset: 0x7c8be19e40 libavlasys.so!0xee40 callee: 0x7c8be114dc libavlasys.so!0x64dc
[RegisterNatives] ===> name: getCertFullHash sig: (Ljava/lang/String;)Ljava/lang/String; fnPtr: 0x7c8be19ee4 fnOffset: 0x7c8be19ee4 libavlasys.so!0xeee4 callee: 0x7c8be114dc libavlasys.so!0x64dc
[RegisterNatives] ===> name: getAPKInfo sig: (Ljava/lang/String;)Ljava/lang/String; fnPtr: 0x7c8be19f88 fnOffset: 0x7c8be19f88 libavlasys.so!0xef88 callee: 0x7c8be114dc libavlasys.so!0x64dc
[RegisterNatives] ===> name: computeToken sig: (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)I fnPtr: 0x7c8be1a0d8 fnOffset: 0x7c8be1a0d8 libavlasys.so!0xf0d8 callee: 0x7c8be114dc libavlasys.so!0x64dc
[RegisterNatives] ===> name: initEngine sig: ()I fnPtr: 0x7c8be1a310 fnOffset: 0x7c8be1a310 libavlasys.so!0xf310 callee: 0x7c8be114dc libavlasys.so!0x64dc
[RegisterNatives] ===> name: releaseEngine sig: ()I fnPtr: 0x7c8be1a314 fnOffset: 0x7c8be1a314 libavlasys.so!0xf314 callee: 0x7c8be114dc libavlasys.so!0x64dc
[RegisterNatives] ===> name: setScanLimit sig: (III)I fnPtr: 0x7c8be1a318 fnOffset: 0x7c8be1a318 libavlasys.so!0xf318 callee: 0x7c8be114dc libavlasys.so!0x64dc
[RegisterNatives] ===> name: setDEXScanLimit sig: (IIII)I fnPtr: 0x7c8be1a328 fnOffset: 0x7c8be1a328 libavlasys.so!0xf328 callee: 0x7c8be114dc libavlasys.so!0x64dc
[RegisterNatives] ===> name: setOpcDEXScanLimit sig: (II)I fnPtr: 0x7c8be1a33c fnOffset: 0x7c8be1a33c libavlasys.so!0xf33c callee: 0x7c8be114dc libavlasys.so!0x64dc
[RegisterNatives] ===> name: setMapleScanLimit sig: (I)I fnPtr: 0x7c8be1a348 fnOffset: 0x7c8be1a348 libavlasys.so!0xf348 callee: 0x7c8be114dc libavlasys.so!0x64dc
[RegisterNatives] ===> name: setScanLimitEx sig: (III)I fnPtr: 0x7c8be1a350 fnOffset: 0x7c8be1a350 libavlasys.so!0xf350 callee: 0x7c8be114dc libavlasys.so!0x64dc
[RegisterNatives] ===> name: setAIES sig: (II)I fnPtr: 0x7c8be1a360 fnOffset: 0x7c8be1a360 libavlasys.so!0xf360 callee: 0x7c8be114dc libavlasys.so!0x64dc
[RegisterNatives] ===> name: setAIER sig: (DDD)I fnPtr: 0x7c8be1a36c fnOffset: 0x7c8be1a36c libavlasys.so!0xf36c callee: 0x7c8be114dc libavlasys.so!0x64dc
[RegisterNatives] ===> name: gsi sig: (Ljava/lang/String;)Ljava/lang/String; fnPtr: 0x7c8be16764 fnOffset: 0x7c8be16764 libavlasys.so!0xb764 callee: 0x7c8be114dc libavlasys.so!0x64dc
[RegisterNatives] ===> name: icf sig: (Ljava/lang/String;I)I fnPtr: 0x7c8be18c50 fnOffset: 0x7c8be18c50 libavlasys.so!0xdc50 callee: 0x7c8be114dc libavlasys.so!0x64dc
[RegisterNatives] ===> name: gcv sig: (Ljava/lang/String;I)Ljava/lang/String; fnPtr: 0x7c8be18d5c fnOffset: 0x7c8be18d5c libavlasys.so!0xdd5c callee: 0x7c8be114dc libavlasys.so!0x64dc
[RegisterNatives] ===> name: fcf sig: (I)V fnPtr: 0x7c8be18f44 fnOffset: 0x7c8be18f44 libavlasys.so!0xdf44 callee: 0x7c8be114dc libavlasys.so!0x64dc
[RegisterNatives] ===> name: feedbackInit sig: (Ljava/lang/String;)I fnPtr: 0x7c8be1a370 fnOffset: 0x7c8be1a370 libavlasys.so!0xf370 callee: 0x7c8be114dc libavlasys.so!0x64dc
[RegisterNatives] ===> name: feedbackRelease sig: ()V fnPtr: 0x7c8be1a3e4 fnOffset: 0x7c8be1a3e4 libavlasys.so!0xf3e4 callee: 0x7c8be114dc libavlasys.so!0x64dc
[RegisterNatives] ===> name: signBlockHash sig: (Ljava/lang/String;)Ljava/lang/String; fnPtr: 0x7c8be1a54c fnOffset: 0x7c8be1a54c libavlasys.so!0xf54c callee: 0x7c8be114dc libavlasys.so!0x64dc
[RegisterNatives] ===> name: keySetHash sig: (Ljava/lang/String;)Ljava/lang/String; fnPtr: 0x7c8be1a5f4 fnOffset: 0x7c8be1a5f4 libavlasys.so!0xf5f4 callee: 0x7c8be114dc libavlasys.so!0x64dc
[RegisterNatives] ===> name: signBlockAndKeySetHash sig: (Ljava/lang/String;)Ljava/lang/String; fnPtr: 0x7c8be1a6a8 fnOffset: 0x7c8be1a6a8 libavlasys.so!0xf6a8 callee: 0x7c8be114dc libavlasys.so!0x64dc