本文主要是介绍Android反编译与Xposed所必须了解的事情(二),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
一、Xposed使用步骤
- Gradle引用依赖
- Manifest中添加meta内容识别
- 添加assets文件夹,创建xposed_init文件,用于hook文件识别
- 编写hook代码,hook对应的类和方法
二、流程解析
接上篇内容,依旧以打开LOG为目的,之前我们已经找到了对应的自定义log类,下面只需要打开log开关。
- 添加Gradle依赖
compileOnly 'de.robv.android.xposed:api:82'
- Manifest添加meta内容识别
<meta-dataandroid:name="xposedmodule"android:value="true"/><meta-dataandroid:name="xposeddescription"android:value="描述"/><!-- 支持的xposed的最低版本 --><meta-dataandroid:name="xposedminversion"android:value="82"/>
- 添加xposed_init文件,并放到assets文件夹下
对应的是XposedInstaller会回调类。
com.alzzz.xxxx.xposed.Hook
- hook对应的package和对应的类
1、实现IXposedHookLoadPackage接口,实现handleLoadPackage类
2、判断包名,是否是想要hook的apk(非必须)
3、找到Hook时机(这次是在Application的attach方法进行hook的)
4、找到对应的类,通过反射修改对应字段
三、代码实现
1、Hook.java
主要工作:hook在Application的attach方法,读取文件中的json配置,看是否开启了log开关,开了就进行hook
public class Hook implements IXposedHookLoadPackage {private static final String CLASS_NAME = "com.xxx.xxxx";private IConfig mConfig = new IConfig();private Context mApplicationContext;private ClassLoader mClassLoader;@Overridepublic void handleLoadPackage(XC_LoadPackage.LoadPackageParam lpparam) throws Throwable {if (CLASS_NAME.equalsIgnoreCase(lpparam.packageName)){//初始化配置initConfig();setupHookComponent();}}/*** 组建context和appliction组件*/private void setupHookComponent() {XposedHelpers.findAndHookMethod(Application.class, "attach",Context.class,new XC_MethodHook() {@Overrideprotected void afterHookedMethod(MethodHookParam param) throws Throwable {super.afterHookedMethod(param);mApplicationContext = (Context) param.args[0];mClassLoader = mApplicationContext.getClassLoader();LOGGER.d("mClassLoader = "+mClassLoader);startHook();}});}/*** 开始hook*/private void startHook() {if (mConfig.isLogHook()){//开启了log hook开关LOGGER.d("starting log hook");IFishHook logHook = new FishLogHook(mApplicationContext, mClassLoader);logHook.startHook();}}/*** 初始化设置,必须在最前*/private void initConfig() {mConfig = new IConfig();try {String content = FileUtils.getFileContent(FileUtils.PATH_FILE_DIR, FileUtils.FILE_NAME_CONFIG);if (!TextUtils.isEmpty(content)){JSONObject jsonObject = new JSONObject(content);mConfig.decode(jsonObject);LOGGER.d(content);}} catch (IOException e) {e.printStackTrace();} catch (JSONException e) {e.printStackTrace();}}
}
2、FishLogHook
主要功能:反射打开LOG开关
public class FishLogHook implements IFishHook {private Context mApplicationContext;private ClassLoader mClassLoader;Class<?> instanceClazz;boolean hasHooked = false;public FishLogHook(Context mApplicationContext, ClassLoader mClassLoader) {this.mApplicationContext = mApplicationContext;this.mClassLoader = mClassLoader;}@Overridepublic void startHook() {if (instanceClazz == null) {try {instanceClazz = Class.forName("com.xxx.xxxx.xframework.util.Log", true, mClassLoader);} catch (ClassNotFoundException e) {e.printStackTrace();LOGGER.e(e.getMessage());}}doLogProxy();}private void doLogProxy() {if (instanceClazz != null){try {LOGGER.d("Loghook ===> start log proxy");Field field = instanceClazz.getDeclaredField("enable");field.setAccessible(true);LOGGER.d("Loghook ===> field = "+field.get(null));field.set(null, true);LOGGER.d("Loghook ===> field = "+field.get(null));} catch (NoSuchFieldException e) {e.printStackTrace();} catch (IllegalAccessException e) {e.printStackTrace();}}}
}
至此就打开了LOG开关了,这里需要注意两个事:
1、在Android 7.0以后XSharedPreference已经不好用了,因为SharedPreference的Mode类型只能是Private的了,在其他的应用内是打不开的,所以我采用了文件的方式,通过将config的内容存在文件中进行配置的管理。
2、如果想要加载外部的类或方法,需要拿到真正可以用的ClassLoader,这个比较关键。
由此,可以考虑一下是否可以直接把OkHttp的Log拦截器打开呢?是否可以Hook住网络请求,默认不验证签名呢?更换View功能是不是也可以?想想热更新相关,是不是可以替某些用三方热更的Apk,热更一些dex进去呢?这当然都可以。而且代码量也不多,只需要读懂想要hook的App的代码就行了。
这篇关于Android反编译与Xposed所必须了解的事情(二)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!