本文详细记录一下使用IDA导入头文件的方法,以jni.h为例。

0x00 简介

在分析Android中的so时,常见的一个需求是要分析动态注册时JNI_Onload函数,但是IDA的识别效果不是很好,部分函数如RegisterNatives、FindClass、GetEnv没有识别出来。这时就需要导入jni.h这个头文件了。原生的JNI_Onload函数在IDA中F5的效果如下:
image-20190509110238140

0x01 获取jni.h

jni.h源码位于Android NDK目录下,路径:<ndk-bundle>/sysroot/usr/include/jni.h 。在导入之前需要注释相应的头文件,否则IDA会找不到。复制一份到你需要的位置保存。

0x02 导入头文件

点击IDA中File->Load file -> Parse C header file,或者按快捷键Ctrl+F9可以打开导入窗口
image-20190509110335216

选择刚才的jni.h导入后,可以看到IDA的导入成功窗口,注意一定要看log是否有其他报错:
image-20190509110805702

0x03 导入结构体

这里给出一个JNI_Onload的动态注册的例子:

#include <jni.h>
static JNINativeMethod nativeMethod[]={
        {
                "helloworld",
                "(Ljava/lang/String;)Ljava/lang/String;", 
                (void*)jnihelloworld                                                     
        },
};

JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *jvm, void *reserved) {
    JNIEnv *env = NULL;
    jint result = JNI_FALSE;
    check();
    if (jvm->GetEnv((void**) &env, JNI_VERSION_1_6) != JNI_OK) { 
        return result;
    }
    if (env == NULL) {
        return result;
    }
    jclass clazz = env->FindClass("<your package name>");  // change to yourself
    if (clazz == NULL) {
        return result;
    }
    if (env->RegisterNatives(clazz, nativeMethod, sizeof(nativeMethod) / sizeof(nativeMethod[0])) < 0) {
        return result;
    }
    result = JNI_VERSION_1_6;
    return result;
}

在IDA中目前是无法识别JNIEnv *中的函数的,因此需要导入JNIEnv结构体。

点击IDA的Structures窗口,在空白处按I,会出现Create structure/union窗口,点击Add standard structure就可以导入结构体了。
image-20190509111459986

选择_JNIEnv结构体,点击OK。
image-20190509111543395

导入完成后,就可以看到Structures中多了一个_JNIEnv结构体:
image-20190509112306693

0x04 修复参数类型

回到JNI_Onload函数,点env(由v4重命名而来),按y修改参数的类型为JNIEnv *,之后就可以识别出env中的函数了。同理还可以导入JavaVM *,最终F5效果如下:
image-20190509113307234

0xFF 参考

  1. https://bbs.pediy.com/thread-217701.htm