一、Xposed原理:
应用通过meta-data标签声明自己是一个Xposed模块,通过assets目录下的xposed-init文件声明入口类
Xposed分为三个部分:Xposed-Installer、Xposed、XposedBridge.jar
Xposed-Installer:将app_process拷贝到/system/app/目录下,将XposedBridge.jar拷贝到/data/data/package下,初始化/data/data/package/modules.list和enabled_modules.list
for (PackageInfo pkg : PackageManager.getInstalledPackage(PackageManager.GET_META_DATA)) {
ApplicationInfo app = pkg.applicationInfo;
if (app.metaData.containsKey("xposedmodule")) {
}
}
app_process是Android的zygote进程,Android系统所有进程都由zygote进程fork出来的,首先说一下系统自带的app_process的作用(创建虚拟机实例、注册Java核心类及JNI方法、注册Android核心类和JNI方法、创建Socket通讯接口、启动SystemServer进程、启动Looper循环监听Socket接口),替换后的app_process在原有基础上加载xposed.so、XposedBridge.jar并注册相关Jni方法,关键步骤是Native Hook了ActivityThread的关键方法(handleBindApplication),在应用加载时会调用各个Xposed应用的入口方法
二、反编译工具:
Smali、Baksmali、apktool(基于Smali和Baksmali)
dex2jar、jadx、jd-gui,这三个工具是用来查看java源码的
Smali语法:数据类型(Z、J、[、L)、函数定义(函数名+方法签名)(foo(IILjava/lang/String;)Z
方法调用(invoke-static、invoke-virtual(protected或public函数)、invoke-interface、invoke-direct(private函数)、invoke-super)
三、辅助工作:
打印Log:
XposedHelpers.findAndHookMethod("com.tencent.mars.xlog.Xlog", classLoader, "getLogLevel", new XC_MethodHook() {
@Override
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
super.afterHookedMethod(param);
param.setResult(0);
}
});
XposedHelpers.findAndHookMethod("com.tencent.mars.xlog.Xlog", classLoader, "setConsoleLogOpen", boolean.class, new XC_MethodHook() {
@Override
protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
super.beforeHookedMethod(param);
param.args[0] = true;
}
});
打印ClickListener:
XposedHelpers.findAndHookMethod(View.class, "performClick", new XC_MethodHook() {
@Override
protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
try{
Field mListenerInfoField= View.class.getDeclaredField("mListenerInfo");
mListenerInfoField.setAccessible(true);
Object mListenerInfo=mListenerInfoField.get(param.thisObject);
Field mOnClickListenerField=mListenerInfo.getClass().getDeclaredField("mOnClickListener");
mOnClickListenerField.setAccessible(true);
Object mOnClickListener=mOnClickListenerField.get(mListenerInfo);
Log.d("DebugTools","clicked "+param.thisObject+" / "+mOnClickListener);
}catch (Exception e){
Log.e("DebugTools",e.toString());
}
}
});
绕过应用签名校验:(安装正常微信,拿到签名字符串,替换应用校验逻辑)
AndResGuard资源混淆,apkTool无法回编译:修改资源名称(if、do等)
锁屏问题:
public static synchronized boolean isGrantRootPermission() {
Process process = null;
DataOutputStream os = null;
try {
process = Runtime.getRuntime().exec("su");
os = new DataOutputStream(process.getOutputStream());
os.writeBytes("dumpsys deviceidle disable all\n");
os.writeBytes("settings put global low_power_trigger_level 0\n");
os.writeBytes("settings put global low_power 0\n");
os.writeBytes("exit\n");
os.flush();
int exitValue = process.waitFor();
if (exitValue == 0) {
MessageCollect.recordLogic(TAG,"have granted root permission");
return true;
} else {
MessageCollect.recordLogic(TAG,"granted root permission failed");
return false;
}
} catch (Exception e) {
return false;
} finally {
try {
if (os != null) {
os.close();
}
process.destroy();
} catch (Exception e) {
e.printStackTrace();
}
}
}
应用保活:监控功能需要应用始终存活
心跳上传:用于监控微信助手存活状态(微信版本、网络连接等)
四、应用架构:微信助手有两个版本(Root版本和免Root版本),需要最大限度考虑代码复用。首先,第一层是工具类,第二层是Xposed和Legend模块,第三层封装了一层通用层,屏蔽了Xposed和Legend的差异,第四层是微信相关代码,采用独立模块,通过广播解耦,具体功能有(添加好友、创建群聊、删除好友、踢群、加群、上传群聊二维码、自动下载高清大图、发送图片、发送文本消息、清理黑粉(静默、非静默)、实时上传微信消息),第五层是应用层(root版本、非root版本),主要是功能定制,调用第四层的相关实现,其中应用层入口分别为xposed_init指定和smali代码嵌入
.method protected attachBaseContext(Landroid/content/Context;)V
.locals 1
.prologue
.line 146
invoke-super {p0, p1}, Landroid/app/Application;->attachBaseContext(Landroid/content/Context;)V
invoke-static {p0}, Lcom/lede/wdplugins/entrance/TinkerHookEntrance;->wechatHook(Landroid/content/Context;)V
.line 147
new-instance v0, Lcom/tencent/tinker/loader/TinkerUncaughtHandler;
invoke-direct {v0, p0}, Lcom/tencent/tinker/loader/TinkerUncaughtHandler;-><init>(Landroid/content/Context;)V
invoke-static {v0}, Ljava/lang/Thread;->setDefaultUncaughtExceptionHandler(Ljava/lang/Thread$UncaughtExceptionHandler;)V
.line 148
invoke-direct {p0, p1}, Lcom/tencent/tinker/loader/app/TinkerApplication;->onBaseContextAttached(Landroid/content/Context;)V
.line 149
return-void
.end method
后话:一代助手是通过辅助功能来实现的,效率太低