From:Android Hook 框架 Cydia_substrate 详解:https://www.cnblogs.com/lkislam/p/4859957.html
通过 cydia substrate 对 framework API进行注入:https://www.jianshu.com/p/cc49b30c5b5b
Android 逆向之旅 --- Native层的Hook神器Cydia Substrate使用详解:http://www.520monkey.com/archives/1028
CydiaSubstrate hook
1. Cydia_Substrate 框架简介
Cydia Substrate 和 Xposed:
- Cydia Substrate 可以修改任何主进程的代码,不管是 Java / C / C++ (native代码)编写的。(hook Java层和C++层)
- Xposed 只支持 HOOK app_process 中的 java 函数。( 只能 hook java 层 )
其实 cydia substrate 与 xposed 的 hook 原理是一样的,二者都可以作为 Java Hook 的框架,看使用习惯了。
官网地址:Cydia Substrate
注意:从官网可以看到,Cydia Substrate 支持安卓 2.3 到 4.3 版本。。。手机需要 root
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
使用方法
安装 Cydiastrate 框架 Android 本地服务
首先就是在 Android 设备中安装 Cydia substrate 框架的本地服务应用 substrate.apk。
官方下载地址为:http://www.cydiasubstrate.com/download/com.saurik.substrate.apk
安装完 substrate 后,需要 "Link Substrate Files"(连接本地的 Substrate 服务文件),这一步是需要 Root权限,连接后还需要 重启设备 才能够生效。
下载使用 Cydiasubstrate 库
Cydiasubstrate 官方建议在 Android SDK Manager 中添加它们插件地址的方式进行更新下载。
如:在用户自定义网址中添加http://asdk.cydiasubstrate.com/addon.xml。
通过使用 Android SDK Manager 工具下载完 Cydiasubstrate 框架后,
其存储于目录 ${ANDROID_HOME}\sdk\extras\saurikit\cydia_substrate下。
但是,由于 Android SDK Manager 在国内使用起来存在很多的限制,下载的时候也不是非常稳定,所以还是建议大家直接去官网下载开发库。官方下载地址为:http://asdk.cydiasubstrate.com/zips/cydia_substrate-r2.zip
下载完成后,将得到的所有文件(很多的 jar包 与 so库 ),都拷贝都 Android 项目下的 libs 文件夹中,就可以直接使用了。
其中的 substrate.h 头文件与 lib 文件夹下的 so文件是提供在使用 NDK 进行原生 Hook 程序开发中的函数支持库。
注意:CydiaSubstrate 框架对于 inline Hook 的操作目前还是存在一些 bug,使用的时候可能会出现崩溃的现象,部分使用了国内定制的 ROM 的设备在使用 CydiaSubstrate 框架时会造成设备无法重新启动或无法 Hook 的现象。
CydiaSubstrate怎么用 ?
CydiaSubstrate怎么用,其实很简单,CydiaSubstrate 提供了三个静态的方法工具类,我们只需要学会使用它就好 。
MS.hookClassLoad 拿到指定Class载入时的通知
MS.hookMethod 使用一个Java方法去替换另一个Java方法
MS.moveUnderClassLoader 使用不同的ClassLoder重载对象
具体说明如下:
/*** Hook一个指定的Class* * @param name Class的包名+类名,如android.content.res.Resources* @param hook 成功Hook一个Class后的回调*/
void hookClassLoad(String name, MS.ClassLoadHook hook);/*** Hook一个指定的方法,并替换方法中的代码* * @param _class Hook的calss* @param member Hook class的方法参数* @param hook 成功Hook方法后的回调* @param old Hook前方法,类似C中的方法指针*/
void hookMethod(Class _class, Member member, MS.MethodHook hook, MS.MethodPointer old);/*** Hook一个指定的方法,并替换方法中的代码* * @param _class Hook的calss* @param member Hook class的方法参数* @param alteration*/
void hookMethod(Class _class, Member member, MS.MethodAlteration alteration);/*** 使用一个ClassLoader重载一个对象* * @param loader 使用的ClassLoader* @param object 带重载的对象* @return 重载后的对象*/
<T> T moveUnderClassLoader(ClassLoader loader, T object);
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类实例。
示例 1:接口组件颜色修改为紫罗兰色(hook Java层)
下面以官网的一个实例来说明 cydia substrate 的使用方法。
该实例是实现将多个接口组件颜色修改为紫罗兰色。
步骤 一:
创建一个空的 Android 工程。由于创建的工程将以插件的形式被加载,所以不需要 activity。将 SDK 中的 substrate-api.jar 复制到 project/libs 文件夹中。
步骤 二:
配置 androidmanifest.xml 文件
- (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; }
});
示例 2:duanxinjiankong实例(hook Java层)
在下面的例子中我们实现了短信监听功能,将短信发送人、接收人以及短信内容打印出来:
import java.lang.reflect.Method;
import android.app.PendingIntent;
import android.util.Log;
import com.saurik.substrate.MS;
public class Main { static void initialize() { MS.hookClassLoad("android.telephony.SmsManager", new MS.ClassLoadHook() { @Override public void classLoaded(Class<?> SmsManager) { //code to modify the class when loaded Method sendTextMessage; try { sendTextMessage = SmsManager.getMethod("sendTextMessage", new Class[]{String.class,String.class,String.class,PendingIntent.class,PendingIntent.class}); } catch (NoSuchMethodException e) { sendTextMessage = null; } MS.hookMethod(SmsManager, sendTextMessage, new MS.MethodAlteration() { public Object invoked(Object _this,Object... _args) throws Throwable{ Log.i("SMSHOOK","SEND_SMS"); Log.i("SMSHOOK","destination:"+_args[0]); Log.i("SMSHOOK","source:"+_args[1]); Log.i("SMSHOOK","text:"+_args[2]); return invoke(_this, _args); } }); } }); }
}
运行步骤
- ROOT 的手机一部,没有 ROOT 的,请自行搜索方法。
- 手机端安装 Cydia Substrate。下载地址: http://www.cydiasubstrate.com/download/com.saurik.substrate.apk
- 按照上面的例程,编译代码后安装到手机
- 手机上运行 Substrate,界面上点击"Link Substrate Files",再点击 "Restart System(Soft)"(这些都是Hook 步骤)
- 最后再编写一个 Test.apk,调用 hook 后的 class,检验 hook 结果。
运行后的结果为:
示例 3:广告注入 (hook Java层)
From:https://blog.csdn.net/yzzst/article/details/47318751
使用Cydiasubstrate框架我们能够任意的Hook系统中的Java API,当然其中也用到了很多的反射机制,那么除了系统中给开发者提供的API以外,我们能否也Hook应用程序中的一些方法呢?答案是肯定的。下面我们就以一个实际的例子讲解一下如何Hook一个应用程序。
下面我们针对Android操作系统的浏览器应用,Hook其首页Activity的onCreate方法(其他方法不一定存在,但是onCreate方法一定会有),并在其中注入我们的广告。根据上面对Cydiasubstrate的介绍,我们有了一个简单的思路。
首先,我们根据某广告平台的规定,在我们的AndroidManifest.xml文件中填入一些广告相关的ID。并且在AndroidManifest.xml文件中填写一些使用Cydiasubstrate相关的配置与权限。当然,我们还会声明一个广告的Activity,并设置此Activity为背景透明的Activity,为什么设置透明背景的Activity,如下图:
好了,下面我们就来实操一下。其 AndroidManifest.xml 文件的部分内容如下所示:
<!-- 广告相关的权限 -->
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.GET_TASKS" />
<!-- 加入substrate权限 -->
<uses-permission android:name="cydia.permission.SUBSTRATE" /><applicationandroid:allowBackup="true"android:icon="@drawable/ic_launcher"android:label="@string/app_name"android:theme="@style/AppTheme" ><!-- 广告相关参数 --><meta-dataandroid:name="APP_ID"android:value="c62bd976138fa4f2ec853bb408bb38af" /><meta-dataandroid:name="APP_PID"android:value="DEFAULT" /><!-- 声明substrate的注入口味Main类 --><meta-dataandroid:name="com.saurik.substrate.main"android:value="com.example.hookad.Main" /><!-- 透明无动画的广告Activity --><activityandroid:name="com.example.hookad.MainActivity"android:theme="@android:style/Theme.Translucent.NoTitleBar" ><intent-filter><action android:name="android.intent.action.VIEW" /><category android:name="android.intent.category.DEFAULT" /><!-- 广告的action --><action android:name="com.example.hook.AD" /></intent-filter></activity>
</application>
对于 Cydiasubstrate的主入口 Main 类,依照之前的步骤新建一个包含有 initialize 方法的 Main 类。
这个时候我们希望使用 MS.hookClassLoad 方式找到浏览器主页的 Activity 名称。
这里我们使用 adb shell 下使用 dumpsys activity 命令找到浏览器主页的 Activity 名称为 com.android.browser.BrowserActivity。
使用 MS.hookClassLoad 方法获取了 BrowserActivity 之后再 hook 其 onCreate 方法,在其中启动一个含有广告的 Activity。Main 类的代码如下所示:
public class Main {/*** substrate 初始化后的入口*/static void initialize() {//Hook 浏览器的主Activity,BrowserActivityMS.hookClassLoad("com.android.browser.BrowserActivity", new MS.ClassLoadHook() {public void classLoaded(Class<?> resources) {Log.e("test", "com.android.browser.BrowserActivity");// 获取BrowserActivity的onCreate方法Method onCreate;try {onCreate = resources.getMethod("onCreate", Bundle.class);} catch (NoSuchMethodException e) {onCreate = null;}if (onCreate != null) {final MS.MethodPointer old = new MS.MethodPointer();// hook onCreate方法MS.hookMethod(resources, onCreate, new MS.MethodHook() {public Object invoked(Object object, Object...args) throws Throwable {Log.e("test", "show ad");// 执行Hook前的onCreate方法,保证浏览器正常启动Object result = old.invoke(object, args);// 没有Context// 执行一个shell 启动我们的广告ActivityCMD.run("am start -a com.example.hook.AD");return result;}}, old);}}});}
}
对于启动的广告MainActivity,在其中就是弹出一个插屏广告。当然可也可是其他形式的广告或者浮层,内容比较简单这里不做演示了。对整个项目进行编译,运行。这个时候我们重新启动 Android 自带的浏览器的时候发现,浏览器会弹出一个广告弹框。
从上面的图片我们可以看出来了,之前我们设置插屏广告 MainActivity 为无标题透明(Theme.Translucent.NoTitleBar)就是为了使得弹出来的广告与浏览器融为一体,让用户感觉是浏览器弹出的广告。也是恶意广告程序为了防止自身被卸载掉的一些通用隐藏手段。
这里演示的注入广告是通过 Hook 指定的 Activity 中的 onCreate 方法来启动一个广告 Activity。当然,这里我们演示的 Activity 只是简单的弹出来了一个广告。如果启动的 Activity 带有恶意性,如将 Activity 做得与原 Activity一模一样的钓鱼 Activity,那么对于移动设备用户来说是极具欺骗性的。
示例 4:修改 主题颜色和游戏金币值(hook java层 和 so 层)
From:视频去哪了呢?_哔哩哔哩_bilibili
hook java 层
Main.class 代码:
hook so 层
需要的 jar 包 和 lib
Androidmainfest.xml 添加权限:
添加 libs 文件
添加 .h 文件 和 so 库文件
test.cpp 代码:
IDA 打开 so 库,定位 函数名: