原理
我们可以用Java开发app,或者结合使用Java和C|C++开发app,NativeActivity则为单独使用C|C++开发app提供支持。
从开发者的角度看,我们是在单独用C++开发app,但从底层看还是离不开Java。
在android源码中,已经使用java开发好了一个中间类,我们使用C++开发的Native库之所以能运行,就是因为被这个中间类使用JNI的方式调用了。
这个中间类就是NativeActivity类。
NativeActivity类
NativeActivity本质是一个java类,位于android源码的android-sdk\sources\android-22\android\app\文件中。继承自Activity类,是android自带的诸多activity类中的一种。
所有使用NativeActivity开发的app,它的中,activity标记的android:name属性值都为"",表明这个app的activity对应的类就是android源码提供的NativeActivity类:
<activity android:name="" ... ...>
... ...
</activity>
而这个NativeActivity类的核心功能,就是在特定事件发生时,调用我们使用C++开发的Native库里的回调函数。
比如在函数中,调用C++开发的Native库的onStartNative函数:
protected void onStart() {
();
onStartNative(mNativeHandle);
}
所以我们用C++开发的Native库,需要导出这些Native函数,app的activity才能正确运行。
开发
这就牵涉到我们使用C++开发app的两种方式:
-
native_activity.h
-
android_native_app_glue.h
native_activity.h
该文件位于NDK的\toolchains\llvm\prebuilt\windows-x86_64\sysroot\usr\include\android目录下。
其中定义了一个ANativeActivity类,这个类中又包含一个ANativeActivityCallbacks结构的指针:
typedef struct ANativeActivity {
struct ANativeActivityCallbacks* callbacks;
... ...
}
这个ANativeActivityCallbacks结构里面就是Native库需要导出的所有函数:
typedef struct ANativeActivityCallbacks {
void (*onStart)(ANativeActivity* activity);
void (*onResume)(ANativeActivity* activity);
void* (*onSaveInstanceState)(ANativeActivity* activity, size_t* outSize);
void (*onPause)(ANativeActivity* activity);
void (*onStop)(ANativeActivity* activity);
void (*onDestroy)(ANativeActivity* activity);
void (*onWindowFocusChanged)(ANativeActivity* activity, int hasFocus);
void (*onNativeWindowCreated)(ANativeActivity* activity, ANativeWindow* window);
void (*onNativeWindowResized)(ANativeActivity* activity, ANativeWindow* window);
void (*onNativeWindowRedrawNeeded)(ANativeActivity* activity, ANativeWindow* window);
void (*onNativeWindowDestroyed)(ANativeActivity* activity, ANativeWindow* window);
void (*onInputQueueCreated)(ANativeActivity* activity, AInputQueue* queue);
void (*onInputQueueDestroyed)(ANativeActivity* activity, AInputQueue* queue);
void (*onContentRectChanged)(ANativeActivity* activity, const ARect* rect);
void (*onConfigurationChanged)(ANativeActivity* activity);
void (*onLowMemory)(ANativeActivity* activity);
} ANativeActivityCallbacks;
使用native_activity.h开发app的核心工作,就是要实现ANativeActivityCallbacks的各个接口函数,native_activity.h本身是不包含这些函数体的实现的。
android_native_app_glue.h
android_native_app_glue.h则是对native_activity.h的封装。
该文件位于NDK的\sources\android\native_app_glue目录下。
它定义了一个android_app类,在其中包含ANativeActivity类的指针成员:
struct android_app {
... ...
ANativeActivity* activity;
... ...
}
最重要的,android_app类给所有需要导出的Native函数都提供了默认的实现代码:
void ANativeActivity_onCreate(ANativeActivity* activity, void* savedState, size_t savedStateSize) {
LOGV("Creating: %p", activity);
activity->callbacks->onConfigurationChanged = onConfigurationChanged;
activity->callbacks->onContentRectChanged = onContentRectChanged;
activity->callbacks->onDestroy = onDestroy;
activity->callbacks->onInputQueueCreated = onInputQueueCreated;
activity->callbacks->onInputQueueDestroyed = onInputQueueDestroyed;
activity->callbacks->onLowMemory = onLowMemory;
activity->callbacks->onNativeWindowCreated = onNativeWindowCreated;
activity->callbacks->onNativeWindowDestroyed = onNativeWindowDestroyed;
activity->callbacks->onNativeWindowRedrawNeeded = onNativeWindowRedrawNeeded;
activity->callbacks->onNativeWindowResized = onNativeWindowResized;
activity->callbacks->onPause = onPause;
activity->callbacks->onResume = onResume;
activity->callbacks->onSaveInstanceState = onSaveInstanceState;
activity->callbacks->onStart = onStart;
activity->callbacks->onStop = onStop;
activity->callbacks->onWindowFocusChanged = onWindowFocusChanged;
activity->instance = android_app_create(activity, savedState, savedStateSize);
}
这使得开发人员不需要自己去实现所有Native库需要导出的回调函数,只实现需要加入自定义功能的回调函数即可。
而且ANativeActivity_onCreate函数最后调用的android_app_create函数会创建一个线程:
static struct android_app* android_app_create(ANativeActivity* activity, void* savedState, size_t savedStateSize) {
... ...
pthread_create(&android_app->thread, &attr, android_app_entry, android_app);
... ...
}
这个线程的线程函数android_app_entry会进一步调用一个名字为android_main的函数:
static void* android_app_entry(void* param) {
... ...
android_main(android_app);
... ...
}
这个android_main函数来自外部库,需要由我们的C++代码实现:
extern void android_main(struct android_app* app);
这里,这个android_main就是我们使用C++开发app时的主函数。我们在这个android_main()函数里面的任务就是进行消息循环,做各种任务。
逆向分析
所以,当我们逆向分析一个NativeActivity开发的app时,发现Native库里导出了android_main函数,表明这是使用android_native_app_glue.h开发的。基本就可以确定android_main就是Native库的主函数,从这里入手分析即可。(如CTF题目 easy-dex)
如果在Native库里没有找到android_main函数,就表明这个NativeActivity是使用native_activity.h开发的,这时就会看到导出了ANativeActivityCallbacks结构里的诸多回调函数,这些回调函数对应app运行过程中的不同事件,我们就需要在这些回调函数中找逆向分析的入手点。
———————————————————————————————————————————
欢迎关注我的微博:大雄_RE。专注软件逆向,分享最新的好文章、好工具,追踪行业大佬的研究成果。