您的位置:首页 > 移动开发 > Android开发

android上的简单hook

2016-02-06 20:21 579 查看
cydia substrate目前也支持android了,cydia substrate是一个代码修改平台。它可以修改任何主进程的代码,官方网址:http://www.cydiasubstrate.com/

准备活动

在正式学习之前,需要做如下准备:

1. root你的手机

2. 下载官方的apk,并且安装进手机,点击运行,点击按钮,允许操作。

3. 更新sdk

更新sdk

打开sdkmanager





http://asdk.cydiasubstrate.com/addon.xml

添加完成之后,在extra下回多了一个选项,点击勾选下载



下载完成之后,会在sdk/extra目录下生成我们需要的文件:



API介绍

在正式开始之前,我们先来学习下cydia中重要的api。

MS.hookClassLoad

//该方法实现在指定的类被加载的时候发出通知
void hookClassLoad(String name, MS.ClassLoadHook hook);


参数描述
name包名+类名,使用java的.符号
hookMS.ClassLoadHook的一个实例,当这个类被加载的时候,它的 classLoaded 方法会被执行。
- MS.hookMethod

//该API允许开发者提供一个回调函数替换原来的方法,这个回调函数是一个实现了MS.MethodHook接口的对象,是一个典型的匿名内部类。它包含一个invoked函数
void hookMethod(Class _class, Member member, MS.MethodHook hook, MS.MethodPointer old);


参数描述
_class加载的目标类,为classLoaded传下来的类参数
member通过反射得到的需要hook的方法(或构造函数)。不能够hook字段
hookMS.MethodHook的一个实例,其包含的invoked方法会被调用,用以代替member中的代码

创建android工程

添加jar文件

将SDK中的substrate-api.jar

更改AndroidManifest.xml

添加cydia.permission.SUBSTRATE权限

添加meta标签,name为cydia.permission.SUBSTRATE,value为自己接下来创建的类名.Main

这里由于不需要acitivity,所以讲manifest中额activity相关配置全部删除。如下:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.rectnativetest">

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

<uses-permission android:name="cydia.permission.SUBSTRATE"/>
</manifest>


创建Main.java

接下来就是创建Main.java,并且需要包含一个static void initialize()方法。

// 当插件被加载的时候,该方法中的代码就会运行
static void initialize() {}


获取目标类的实例

这里我们按照官网上给出的栗子,hook类android.content.res.Resources

MS.hookClassLoad("android.content.res.Resources", new MS.ClassLoadHook() {
public void classLoaded(Class<?> resources) {

}
});


通过MS.MethodHook更改源代码

这里更改android.content.res.Resources类的getColor方法的返回值,将其返回红色。

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);
}


运行,安装当前组件,重启手机,效果如下:





可以发现整个手机系统都已经改变为红色的字体了。

Hook登录方法

这里,我自己写了一个简单应用,只有登录功能,逻辑如下:

if (name.equals("zhangsan") && pass.equals("123")) {
return true;
} else {
return false;
}


这里只有用户名为zhangsan以及密码为123,时候,才返回true,即表示登录成功,否则返回false。

同样在Main类的initialize方法里,增加一个hookClassLoad方法,来hook当前登录的activity

MS.hookClassLoad("reacthello.myapplication.MainActivity", new MS.ClassLoadHook() {
public void classLoaded(Class<?> resources) {
Method checkLogin;
try {
checkLogin = resources.getMethod("checkLogin", new Class[]{String.class,String.class});
} catch (NoSuchMethodException e) {
checkLogin = null;
}

if (checkLogin != null) {
final MS.MethodPointer old = new MS.MethodPointer();

MS.hookMethod(resources, checkLogin, new MS.MethodHook() {
public Object invoked(Object resources, Object... args)
throws Throwable
{
return true;
}
}, old);
}
}
});


这里的checklogin是刚才登录逻辑的判断,这里,在hook之后横返回true,也就是无论如何都会登录成功,效果如下:



更改系统Imei的值

现在大家应该都已经知道了可以通过hookClassLoad和hookMethod来更改指定方法运行的代码,以及返回值。现在我们来更改一下手机系统的IMEI值。

首先,需要知道如何通过代码获取IMEI值

android.telephony.TelephonyManager.getDeviceId();


代码:

MS.hookClassLoad("android.telephony.TelephonyManager", new MS.ClassLoadHook() {
public void classLoaded(Class<?> resources) {
Method getDeviceId;
try {
getDeviceId = resources.getMethod("getDeviceId",null);
} catch (NoSuchMethodException e) {
getDeviceId = null;
}

if (getDeviceId != null) {
final MS.MethodPointer old = new MS.MethodPointer();

MS.hookMethod(resources, getDeviceId, new MS.MethodHook() {
public Object invoked(Object resources, Object... args)
throws Throwable
{
String imei = (String)old.invoke(resources, args);
imei = "aaaaaaaaaaaaaaa";
return imei;
}
}, old);
}

}
});


这里更改的android.telephony.TelephonyManager类下的getDeviceId方法。

此时我们通过:

String imei = telephonyManager.getDeviceId();
Toast.makeText(MainActivity.this,"imei is :"+imei,Toast.LENGTH_SHORT).show();


获得的就是aaaaaaaaaa了

实现应用拦截

最后一次尝试一下当我打开一个应用的时候,自动打开一个毫不相干的应用,比如当我每次打开今日头条的时候,系统会跳转到网易新闻,首先我们需要知道“今日头条”和”网易新闻”的主界面的activity,使用如下命令可以获得当前界面的activity:

dumpsys activity | grep mFocusedActivity




在adb shell下可以通过如下代码启动activity

Runtime.getRuntime().exec("am start -n com.netease.newsreader.activity/com.netease.nr.biz.ad.AdActivity");


完整代码:

MS.hookClassLoad("com.ss.android.article.news.activity.MainActivity", new MS.ClassLoadHook() {
public void classLoaded(Class<?> resources) {
Log.d("hookstart","com.ss.android.article.news.activity.MainActivity loaded");
Method onCreate;
try {
onCreate = resources.getMethod("onCreate",Bundle.class);
} catch (NoSuchMethodException e) {
onCreate = null;
}

if (onCreate != null) {
final MS.MethodPointer old = new MS.MethodPointer();

MS.hookMethod(resources, onCreate, new MS.MethodHook() {
public Object invoked(Object resources, Object... args)
throws Throwable
{
Log.d("hang.liu","the ooooooo");
Object object = old.invoke(resources, args);
try {
Log.d("hookstart","onCreate hooked.");
Runtime.getRuntime().exec("am start -n com.netease.newsreader.activity/com.netease.nr.biz.ad.AdActivity");
} catch (Exception e) {
Log.d("hookstart","start activity exception happend...");
}
return object;
}
}, old);
}
}
});


此时效果如下:



ok,可以看到,到目前为止,已经完成了我们想要的效果了。但是还是有很多限制最大的就是手机必须要有root权限,在5.0之后的版本已经不能使用。

源码下载
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: