Cydia Substrate是一个代码修改平台。它可以修改任何主进程的代码,不管是用Java还是C/C++(native代码)编写的。而Xposed只支持 HOOK app_process中的java函数,因此Cydia Substrate是一款强大而实用的HOOK工具。
官网地址:http://www.cydiasubstrate.com/
Demo地址:https://github.com/zencodex/cydia-android-hook
官方教程:http://www.cydiasubstrate.com/id/20cf4700-6379-4a14-9bc2-853fde8cc9d1
SDK下载地址:http://asdk.cydiasubstrate.com/zips/cydia_substrate-r2.zip
Substrate几个重要API介绍
MS.hookClassLoad
函数原型:void hookClassLoad(String name, MS.ClassLoadHook hook);
该方法实现在指定的类被加载的时候发出通知。因为一个类可以在任何时候被加载,所以Substrate提供了一个方法用来检测用户感兴趣的类何时被加载。
参数 |
描述 |
name |
包名+类名,使用java的.符号 |
hook |
MS.ClassLoadHook的一个实例,当这个类被加载的时候,它的 classLoaded 方法会被执行。 |
MS.hookMethod
该API允许开发者提供一个回调函数替换原来的方法,这个回调函数是一个实现了MS.MethodHook接口的对象,是一个典型的匿名内部类。它包含一个invoked函数。
函数原型:
void hookMethod(Class _class, Member member, MS.MethodHook hook, MS.MethodPointer old); void hookMethod(Class _class, Member member, MS.MethodAlteration alteration);
参数描述
(一)
参数 |
描述 |
|
加载的目标类,为classLoaded传下来的类参数 |
|
通过反射得到的需要hook的方法(或构造函数). 注意:不能HOOK字段 (在编译的时候会进行检测). |
|
|
(二)
参数 |
描述 |
|
加载的目标类,为classLoaded传下来的类参数 |
|
通过反射得到的需要hook的方法(或构造函数). 注意:不能HOOK字段 (在编译的时候会进行检测). |
|
An instance of |
建议开发者使用第二种方式,这种方式使用起来简单并且很少出错,不需要一个单独的MS.MethodPointer类实例。
使用方法
下面以官网的一个实例来说明cydia substrate的使用方法。该实例是实现将多个接口组件颜色修改为紫罗兰色。
需要安装:http://www.cydiasubstrate.com/download/com.saurik.substrate.apk
步骤一:创建一个空的Android工程。由于创建的工程将以插件的形式被加载,所以不需要activity。将SDK中的substrate-api.jar复制到project/libs文件夹中。
步骤二:配置Manifest文件
(1)需要指定权限:cydia.permission.SUBSTRATE
(2)添加meta标签,name为cydia.permission.SUBSTRATE,value为下一步中创建的类名.Main
- <manifest xmlns:android="http://schemas.android.com/apk/res/android">
- <application>
- <meta-data android:name="com.saurik.substrate.main"
- android:value=".Main"/>
- </application>
- <uses-permission android:name="cydia.permission.SUBSTRATE"/>
- </manifest>
步骤二:创建一个类,类名为Main。类中包含一个static方法initialize,当插件被加载的时候,该方法中的代码就会运行,完成一些必要的初始化工作。
- import com.saurik.substrate.MS;
- public class Main {
- static void initialize() {
- // ... code to run when extension is loaded
- }
- }
步骤三:为了实现HOOK,达到修改目标类中的代码的目的,我们需要得到目标类的一个实例,如示例中的resources。
- public class Main {
- static void initialize() {
- MS.hookClassLoad("android.content.res.Resources", new MS.ClassLoadHook() {
- public void classLoaded(Class<?> resources) {
- // ... code to modify the class when loaded
- }
- });
- }
- }
步骤四:通过MS.MethodHook实例实现原代码的修改。
为了调用原来代码中的方法,我们需要创建一个MS.MethodPointer类的实例,它可以在任何时候运行原来的代码。
在这里我们通过对原代码中resources对象原始代码的调用和修改,将所有绿色修改成了紫罗兰色。
- 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);
- }
- }
安装运行,重启系统后发现很多字体颜色都变了。如下图所示:
示例中MS.hookMethod的代码可以改成:
- MS.hookMethod(resources, getColor, new MS.MethodAlteration<Resources, Integer>() {
- public Integer invoked(Resources resources, Object... args)
- throws Throwable
- {
- int color = invoke(resources, args);
- return color & ~0x0000ff00 | 0x00ffee00;
- }
- });
短信监控实例
在下面的例子中我们实现了短信监听功能,将短信发送人、接收人以及短信内容打印出来:
- 1 import java.lang.reflect.Method;
- 2 import android.app.PendingIntent;
- 3 import android.util.Log;
- 4 import com.saurik.substrate.MS;
- 5
- 6
- 7 public class Main {
- 8
- 9 static void initialize() {
- 10
- 11 MS.hookClassLoad("android.telephony.SmsManager", new MS.ClassLoadHook() {
- 12
- 13
- 14 @Override
- 15
- 16 public void classLoaded(Class<?> SmsManager) {
- 17
- 18 //code to modify the class when loaded
- 19
- 20 Method sendTextMessage;
- 21
- 22 try {
- 23
- 24 sendTextMessage = SmsManager.getMethod("sendTextMessage",
- 25
- 26 new Class[]{String.class,String.class,String.class,PendingIntent.class,PendingIntent.class});
- 27
- 28
- 29 } catch (NoSuchMethodException e) {
- 30
- 31 sendTextMessage = null;
- 32
- 33 }
- 34
- 35 MS.hookMethod(SmsManager, sendTextMessage, new MS.MethodAlteration() {
- 36
- 37 public Object invoked(Object _this,Object... _args) throws Throwable{
- 38
- 39 Log.i("SMSHOOK","SEND_SMS");
- 40
- 41 Log.i("SMSHOOK","destination:"+_args[0]);
- 42
- 43 Log.i("SMSHOOK","source:"+_args[1]);
- 44
- 45 Log.i("SMSHOOK","text:"+_args[2]);
- 46
- 47 return invoke(_this, _args);
- 48
- 49 }
- 50
- 51 });
- 52
- 53
- 54 }
- 55
- 56 });
- 57
- 58 }
- 59
- 60 }
运行后的结果为: