简介
Cydia Substrate是一个很强大的工具,他提供了很便利的方法帮助你去hook so和java中的方法。
在本例中,出于学习的目的,我使用Cydia Substrate来hook每个进程的dvmLoadNativeCode函数,以达到监控加载so顺序的功能。
Cydia Substrate相关链接
Hook模块编译指南
1. 创建一个android程序,如果没什么特殊需要,可以不创建activity(这个不是必须)。
2. 将SDK下载到本地。目录结构是这样的:
3. 在android工程中新建jni文件夹,然后加入相关的头文件substrate.h和库文件,例如我的工程只支持arm,那么就加入cydia_substrate\lib\armeabi下的两个so。目录结构如下:
4. 在AndroidManifest.xml中注册cydia的自定义权限cydia.permission.SUBSTRATE。
另外,设置
android:hasCode 为 "false"
android:installLocation 为 "internalOnly".
如下所示
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
android:installLocation="internalOnly"
>
<application android:hasCode="false">
</application>
<uses-permission android:name="cydia.permission.SUBSTRATE"/>
</manifest>
#include <jni.h>
#include "substrate.h"
#include <android/log.h>
#include <unistd.h>
#include <stdio.h>
#include <fcntl.h>
#include <sys/types.h>
#include <string.h>
#include <sys/stat.h>
#define TAG "HOOKTEST"
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, TAG, __VA_ARGS__)
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, TAG, __VA_ARGS__)
MSConfig(MSFilterLibrary, "libdvm.so"); // 要hook的so库,后缀名即可。
bool (*_dvmLoadNativeCode)(char* pathName, void* classLoader, char** detail);
bool fake_dvmLoadNativeCode(char* soPath, void* classLoader, char** detail)
{
LOGD("fake_dvmLoadNativeCode soPath:%s", soPath);
return _dvmLoadNativeCode(soPath,classLoader,detail);
}
//Substrate entry point
MSInitialize{
LOGD("Substrate initialized.");
MSImageRef image;
image = MSGetImageByName("/system/lib/libdvm.so"); // 此处要绝对路径
if (image != NULL)
{
LOGD("dvm image: 0x%08X", (void*)image);
void * dvmload = MSFindSymbol(image, "_Z17dvmLoadNativeCodePKcP6ObjectPPc");
if(dvmload == NULL)
{
LOGD("error find dvmLoadNativeCode.");
}
else
{
MSHookFunction(dvmload,(void*)&fake_dvmLoadNativeCode,(void **)&_dvmLoadNativeCode);
LOGD("hook dvmLoadNativeCode sucess.");
}
}
else{
LOGD("can not find libdvm.");
}
}
6. 编写Android.mk
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := substrate
LOCAL_SRC_FILES := libsubstrate.so
include $(PREBUILT_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := substrate-dvm
LOCAL_SRC_FILES := libsubstrate-dvm.so
include $(PREBUILT_SHARED_LIBRARY)
include $(CLEAR_VARS)
# 注意:此处substrate规定模块名必须以.cy结尾
LOCAL_MODULE := test.cy
LOCAL_SRC_FILES := test.cpp
LOCAL_LDLIBS := -llog
LOCAL_ARM_MODE := arm
LOCAL_LDLIBS += -L$(LOCAL_PATH) -lsubstrate-dvm -lsubstrate
include $(BUILD_SHARED_LIBRARY)
7. ndk-build之后会在android工程中生成libs目录,结构如下:
8. build android工程即可生成hook模块的apk安装包。
使用指南
1. 下载
Cydia Substrate框架apk
并安装到手机上。
2. 安装在上面编译出来的
hook模块apk。此时,
Cydia Substrate框架apk会提示你有新的模块可以使用
。
3. 打开框架apk,点击“Link Substrate Files”,之后点击“Restart System”就可以使用了。
4. Hook native demo运行之后,会打印每个程序加载so的情况,如下图:
总结
本例就当是给大家使用
Cydia Substrate框架的抛砖引玉了,希望各路大神能写出更多更好的插件来方便后来人。
如果看了本篇文章还有不明白的,欢迎留言探讨交流。
源码
https://github.com/mohuihui/CydiaSubstrateAndroidNativeHOOK