前一段时间给Saurik发了几封邮件,想让Substrate for Android开源,以更好地支持Android 5.0,可惜Saurik一直没回我。Substrate文档较少,又没有开源社区支持,再加上Frida出来了,估计以后用Substrate的会更少。这里分享一下Substrate的各种方法,供参考。

Substrate hook步骤:

  1. 在Manifest里进行权限的声明

<permission
        android:name="cydia.permission.SUBSTRATE"
        android:label="modify code from other packages"
        android:permissionGroup="android.permission-group.DEVELOPMENT_TOOLS"
        android:protectionLevel="dangerous" />
<uses-permission android:name="cydia.permission.SUBSTRATE" />
  1. Java hook:

(1) 声明meta data, 指向Java hook的入口类:


<meta-data android:name="com.saurik.substrate.main" android:value=".Main" />

(2) 在Main类里实现static void initialize() {}函数, 在模块安装后, Cydia会自动调用initialize函数. 可以在这里进行hook的编写, 当然也可以手动调用hook函数. 如修该系统自体:


static void hookColor() {
		MS.hookClassLoad("android.content.res.Resources",
				new MS.ClassLoadHook() {
					public void classLoaded(Class<?> resources) {
						Method getColor;
						try {
							getColor = resources.getMethod("getColor",
									Integer.TYPE);
						} catch (NoSuchMethodException e) {
							getColor = null;
						}
						if (getColor != null) {
							final MS.MethodPointer old = new MS.MethodPointer();
							MS.hookMethod(resources, getColor,
									new MS.MethodHook() {
										public Object invoked(Object resources,
												Object... args)
												throws Throwable {
											int color = (Integer) old.invoke(
													resources, args);
											return color & ~0x0000ff00
													| 0x00ff0000;
										}
									}, old);
						}
					}
				});
	}
3. C hook: (1) 把libsubstrate.so和libsubstrate-dvm.so拷贝到工程JNI目录. 前者是c函数hook依赖库,后者是dvm函数hook依赖库. 在Android. mk里加入以下代码, 以把依赖库编译模块安装包里. ``` include $(CLEAR_VARS) LOCAL_MODULE:= substrate LOCAL_SRC_FILES := libsubstrate.so include $(PREBUILT_SHARED_LIBRARY) ``` 在hook模块的编译脚本里链接libsubstrate.so: ``` LOCAL_LDLIBS += -L$(LOCAL_PATH) -lsubstrate ``` (2) 初始化设置: a. 定义要hook的模块, 如果是so ``` MSConfig(MSFilterLibrary, "/system/lib/libdvm.so") ```
如果是exe ``` MSConfig(MSFilterExecutable, "/system/bin/app_process") ``` b. 初始化入口: ``` MSInitialize { //TODO:模块安装后, Cydia会自动调用这里的代码,你可以在这里进行hook,也可以以后手动hook hook(); } ``` (3) 进行hook, 以hook libdvm.so里的dvmCallMethodV为例: ``` void hook() { MSImageRef image = MSGetImageByName("/system/lib/libdvm.so"); if (image != NULL) { void * symbole = MSFindSymbol(image, "_Z14dvmCallMethodVP6ThreadPK6MethodP6ObjectbP6JValueSt9__va_list"); if (symbole == NULL) { LOGE("error find _Z21dvmDexFileOpenPartialPKviPP6DvmDex "); } else { MSHookFunction(symbole, (void*) &MydvmCallMethodV, (void **) &OriDvmCallMethodV); LOGD("hook dvmCallMethodV ok"); } } else { LOGE("error find libdvm"); } } ``` 4. JNI hook 与C hook基本类似, 主要区别: (1) 把C函数hook链接的so改为libsubstrate-dvm.so (2) 在C代码里进行hook: ``` MSConfig(MSFilterExecutable, "/system/bin/app_process") static jint (*_Resources$getColor)(JNIEnv *jni, jobject _this, ...); static jint $Resources$getColor(JNIEnv *jni, jobject _this, jint rid) { jint color = _Resources$getColor(jni, _this, rid); return color & ~0x0000ff00 | 0x00ff0000; } static void OnResources(JNIEnv *jni, jclass resources, void *data) { jmethodID method = jni->GetMethodID(resources, "getColor", "(I)I"); if (method != NULL) MSJavaHookMethod(jni, resources, method, &$Resources$getColor, &_Resources$getColor); } MSInitialize { MSJavaHookClassLoad(NULL, "android/content/res/Resources", &OnResources); } ```