本文主要是介绍xposed代码分析,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
代码流程
主要流程有四个:
加载jar包
使用了xposed框架,那么runtimeStart的参数如下,
if (zygote) {
isXposedLoaded = xposed::initialize(true, startSystemServer, NULL, argc, argv);
runtimeStart(runtime, isXposedLoaded ? XPOSED_CLASS_DOTS_ZYGOTE : "com.android.internal.os.ZygoteInit", args, zygote);
原始的zygote中,runtimeStart的参数如下,
if (zygote) {
runtime.start("com.android.internal.os.ZygoteInit", args, zygote);
XPOSED_CLASS_DOTS_ZYGOTE宏定义如下,
#define XPOSED_CLASS_DOTS_ZYGOTE "de.robv.android.xposed.XposedBridge"
runtimeStart打开虚拟机执行de.robv.android.xposed.XposedBridge中的main方法,
初始化相关模块后再调用ZygoteInit.main,执行com.android.internal.os.ZygoteInit中的main方法
赋值callback函数
bool onVmCreated(JNIEnv*) {
// TODO: Handle CLASS_MIUI_RESOURCES?
ArtMethod::xposed_callback_class = classXposedBridge;
ArtMethod::xposed_callback_method = methodXposedBridgeHandleHookedMethod;
return true;
}
methodXposedBridgeHandleHookedMethod = env->GetStaticMethodID(classXposedBridge, "handleHookedMethod",
"(Ljava/lang/reflect/Member;ILjava/lang/Object;Ljava/lang/Object;[Ljava/lang/Object;)Ljava/lang/Object;");
所有被hook过的方法,回调函数都是handleHookedMethod
Hook指定函数
一般的hook指定函数的方法
findAndHookMethod(ActivityThread.class, "systemMain", new XC_MethodHook() {
在ART中保存hook函数相关信息到XposedHookInfo结构体中
// Save extra information in a separate structure, stored instead of the native method
XposedHookInfo* hook_info = reinterpret_cast<XposedHookInfo*>(linear_alloc->Alloc(soa.Self(), sizeof(XposedHookInfo)));
hook_info->reflected_method = soa.Vm()->AddGlobalRef(soa.Self(), reflected_method);
hook_info->additional_info = soa.Env()->NewGlobalRef(additional_info);
hook_info->original_method = backup_method;
SetEntryPointFromJniPtrSize(reinterpret_cast<uint8_t*>(hook_info), sizeof(void*));
设置标志位,表明此方法被hook了
// Adjust access flags.
const uint32_t kRemoveFlags = kAccNative | kAccSynchronized | kAccAbstract | kAccDefault | kAccDefaultConflict;
SetAccessFlags((GetAccessFlags() & ~kRemoveFlags) | kAccXposedHookedMethod);
调用hook过的函数
当某个函数被调用时,会调用ART中的函数artQuickProxyInvokeHandler,
大致调用流程为art_method.Invoke()--> art_quick_invoke_stub-->
EntryPointFromQuickCompiledCode(art_quick_proxy_invoke_handler) --> artQuickProxyInvokeHandler--->InvokeXposedHandleHookedMethod
在artQuickProxyInvokeHandler中如果此函数被hook过,
const bool is_xposed = proxy_method->IsXposedHookedMethod();
if (is_xposed) {
jmethodID proxy_methodid = soa.EncodeMethod(proxy_method);
self->EndAssertNoThreadSuspension(old_cause);
JValue result = InvokeXposedHandleHookedMethod(soa, shorty, rcvr_jobj, proxy_methodid, args);
local_ref_visitor.FixupReferences();
return result.GetJ();
}
InvokeXposedHandleHookedMethod函数主要内容如下,
const XposedHookInfo* hook_info = soa.DecodeMethod(method)->GetXposedHookInfo();
// Call XposedBridge.handleHookedMethod(Member method, int originalMethodId, Object additionalInfoObj,
// Object thisObject, Object[] args)
jvalue invocation_args[5];
invocation_args[0].l = hook_info->reflected_method;
invocation_args[1].i = 1;
invocation_args[2].l = hook_info->additional_info;
invocation_args[3].l = rcvr_jobj;
invocation_args[4].l = args_jobj;
jobject result =
soa.Env()->CallStaticObjectMethodA(ArtMethod::xposed_callback_class,
ArtMethod::xposed_callback_method,
invocation_args);
handleHookedMethod函数主要内容如下,
// call "before method" callbacks
int beforeIdx = 0;
do {
try {
((XC_MethodHook) callbacksSnapshot[beforeIdx]).beforeHookedMethod(param);
} catch (Throwable t) {
XposedBridge.log(t);
// reset result (ignoring what the unexpectedly exiting callback did)
param.setResult(null);
param.returnEarly = false;
continue;
}
if (param.returnEarly) {
// skip remaining "before" callbacks and corresponding "after" callbacks
beforeIdx++;
break;
}
} while (++beforeIdx < callbacksLength);
// call original method if not requested otherwise
if (!param.returnEarly) {
try {
param.setResult(invokeOriginalMethodNative(method, originalMethodId,
additionalInfo.parameterTypes, additionalInfo.returnType, param.thisObject, param.args));
} catch (InvocationTargetException e) {
param.setThrowable(e.getCause());
}
}
// call "after method" callbacks
int afterIdx = beforeIdx - 1;
do {
Object lastResult = param.getResult();
Throwable lastThrowable = param.getThrowable();
try {
((XC_MethodHook) callbacksSnapshot[afterIdx]).afterHookedMethod(param);
} catch (Throwable t) {
XposedBridge.log(t);
// reset to last result (ignoring what the unexpectedly exiting callback did)
if (lastThrowable == null)
param.setResult(lastResult);
else
param.setThrowable(lastThrowable);
}
} while (--afterIdx >= 0);
hook示例代码
待hook的APP代码
public class MainActivity extends AppCompatActivity {
private Button button;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.layout_main);
button = (Button) findViewById(R.id.testButton);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(MainActivity.this, toastMessage(), Toast.LENGTH_SHORT).show();
}
});
}
public String toastMessage() {
return "我未被劫持";
}
}
Hook方法
新建一个类,并实现IXposedHookLoadPackage接口,并实现接口中的handleLoadPackage方法
public class HookToast implements IXposedHookLoadPackage {
@Override
public void handleLoadPackage(XC_LoadPackage.LoadPackageParam loadPackageParam) throws Throwable {
if (loadPackageParam.packageName.equals("com.mrglaucus.xposedmoduledemo")) {
Class clazz = loadPackageParam.classLoader.loadClass("com.mrglaucus.xposedmoduledemo.MainActivity");
XposedHelpers.findAndHookMethod(clazz, "toastMessage", new XC_MethodHook() {
@Override
protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
super.beforeHookedMethod(param);
}
@Override
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
param.setResult("你已被劫持");
}
});
}
}
}
这篇关于xposed代码分析的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!