android下的Hook框架有很多,比较出名的就是Xposed和Cydia Substrate,当然都各有不足,Xposed只能Hook Java层,面对native层就显得无力了;Substrate和Java层和native层都可以Hook,但作者好像很久没更新了,只能在dalvik上Hook,在android5.0及以上版本就不能用了,而且兼容性也不是很好,在几款模拟器上都没配置成功。
当然还有其它一些和新出的hook框架也是不错的,就不一一介绍了,下面给出Hook 框架的项目地址
Xposed:https://github.com/rovo89/Xposed
Cydia Substrate官网:http://www.cydiasubstrate.com/
Android Inline Hook:https://github.com/ele7enxxh/Android-Inline-Hook
StormHook:Android侵入式Java Hook框架:https://github.com/woxihuannisja/StormHook
免RootHook框架:https://github.com/asLody/legend
基于VirtualApp和YAHFA的免RootHook框架:https://github.com/rk700/VirtualHook
开发工具:Android studio3.0.1
运行环境:Genymotion模拟器,系统安卓4.4.4
Xposed版本:v2.7
XposedBridgeApi版本:v54
注意:Android 5.0以下Xposed版本用v2.7,Android5.0用v3.+
二个app,一个点击按钮获取imei,另一个完成Hook系统imie操作
添加权限:
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
layout:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:gravity="center"
tools:context="com.banyan.imei.MainActivity">
<TextView
android:id="@+id/textView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="20dp"
android:text="获取到的imei值为:" />
<Button
android:layout_marginTop="18dp"
android:id="@+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="获取imei"/>
LinearLayout>
Activity:
package com.banyan.imei;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.telephony.TelephonyManager;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
private Button button1;
private TextView textView1;
private TelephonyManager tm;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
button1 = findViewById(R.id.button1);
textView1 = findViewById(R.id.textView1);
tm = (TelephonyManager) this.getSystemService(TELEPHONY_SERVICE);
button1.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
//获取imei
String imei = tm.getDeviceId();
//设置文本框的内容为获取的imei
textView1.setText("获取到的imei值为:");
textView1.setText(textView1.getText() + imei);
}
});
}
}
运行效果如下:
因为是模拟器,这imei有点奇怪^_^
好,下面我们来完成Hook imei操作。。
使用Xposed hook的必要配置
<meta-data android:name="xposedmodule" android:value="ture"/>
<meta-data android:name="xposeddescription" android:value="Hook imei测试" />
<meta-data android:name="xposedminversion" android:value="54" />
新建个lib文件夹,拷贝XposedBridgeApi-54.jar到此目录,然后右键点击lib文件夹中的jar文件选择-> add as Library,这个有个坑,添加完之后还要更改一下配置,不然编译的时候会把XposedBridgeApi也编译进去,会导致很多问题,所以要配置一下使之编译的时候不参加编译。
Ctrl+Shift+Alt+s快捷键来到Project Structure界面,更改 jar的implementation 为compileOnly:
新建assetc文件夹,在文件夹下新建xposed_init文件,然后向文件添加入口类信息。如下图:
新建MianHook,代码如下:
package com.banyan.hook;
import android.telephony.TelephonyManager;
import de.robv.android.xposed.IXposedHookLoadPackage;
import de.robv.android.xposed.XC_MethodHook;
import de.robv.android.xposed.XposedHelpers;
import de.robv.android.xposed.callbacks.XC_LoadPackage;
/**
* Created by banyan on 2018/1/1.
*/
//实现IXposedHookLoadPackage接口
public class MainHook implements IXposedHookLoadPackage{
//执行接口的handleLoadPackage方法
@Override
public void handleLoadPackage(XC_LoadPackage.LoadPackageParam loadPackageParam) throws Throwable {
/***
* 用XposedHelpers类的findAndHookMethod方法查找需要hook的方法并进行hook
* 第一个参数:需要Hook的类
* 第二个参数:需要Hook的方法
* 第三个参数:hook到了方法后要进行的操作
* */
XposedHelpers.findAndHookMethod(TelephonyManager.class, "getDeviceId", new XC_MethodHook() {
/***
* 在被Hook的方法执行之前要进行的操作
* 比如改变参数之类的
*/
@Override
protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
super.beforeHookedMethod(param);
}
/***
* 在被Hook的方法执行后要进行的操作
* 比如改变返回值之类的
*/
@Override
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
String primary = (String) param.getResult();
//改变被Hook的方法getDeviceId()的返回值
param.setResult("我是etDeviceId方法,我被Hook了,返回值由" + primary + "改成了:88888888888888");
}
});
}
}
Hook是种优雅的利器^-^。。