正如标题所说,我想使用 xposed 记录应用程序中调用的所有方法,从它开始直到我停止它。我只想记录类名、方法名,不想挂钩所有方法。我尝试这段代码,但得到错误 getMethod not found。
findAndHookMethod("java.lang.Class", lpparam.classLoader, "getMethod", String.class, Object.class, new XC_MethodHook()
提前致谢!
正如标题所说,我想使用 xposed 记录应用程序中调用的所有方法,从它开始直到我停止它。我只想记录类名、方法名,不想挂钩所有方法。我尝试这段代码,但得到错误 getMethod not found。
findAndHookMethod("java.lang.Class", lpparam.classLoader, "getMethod", String.class, Object.class, new XC_MethodHook()
提前致谢!
没有像您似乎正在搜索的那样的单一解决方案。
挂钩所有方法将记录应用程序从开始到停止调用的方法(有点 - 见下文),但如果(出于某种原因)您不想挂钩所有方法,我能想到的唯一解决方案是修改 java VM 本身(我不建议这样做。)
(某种)有效的解决方案
我所做的是首先使用 apktool 反编译我的 apk 并获取所有类中所有方法的名称。然后我使用 xposed 挂钩到每个类的每个方法,并将当前函数名称打印到 dlog。
为什么它只起作用
每当它挂钩方法时,Xposed 都会产生开销。对于 xposed 应用程序的一般用法,它并不多。但是,当您开始挂钩应用程序的每个方法时,开销很快就会变得非常大 - 以至于上述方法适用于小型应用程序,但对于任何大型应用程序,它很快就会导致应用程序挂起然后崩溃。
一种同样有效的替代方案
FRIDA是一种将 JavaScript 注入原生应用程序的方法。在这里,他们向您展示了如何记录所有函数调用。虽然在上面的链接中,他们将所有函数调用记录在一段 python 代码中,但相同的代码也适用于 Android。
有一种方法可以记录所有 Java 方法。修改 XposedBridge。
Xposed hook java方法通过XposedBridge.java的方法“handleHookedMethod(Member method, int originalMethodId, Object additionalInfoObj, thisObject, Object[] args)”
Log.v(TAG, "className " + method.getClass().getName() + ",methodName " + method.getName());
如前所述,由于其开销,Xposed 在这种情况下不是可行的方法。
最简单的解决方案就是使用Google 提供的dmtracedump。大多数 x86 Android 映像和模拟器都带有可调试标志 (ro.debuggable),因此您甚至可以将其用于闭源应用程序。
此外,众所周知, Emma等其他工具也可以与 Android 一起使用,但这些工具可能需要修改源代码。
我找到了解决方案。
请参阅下面的代码片段。
package com.kyunggi.logcalls;
import android.content.pm.*;
import android.util.*;
import dalvik.system.*;
import de.robv.android.xposed.*;
import de.robv.android.xposed.callbacks.XC_LoadPackage.*;
import java.io.*;
import java.lang.reflect.*;
import java.util.*;
import static de.robv.android.xposed.XposedHelpers.findAndHookMethod;
import android.app.*;
public class Main implements IXposedHookLoadPackage {
private String TAG = "LogCall";
public void handleLoadPackage(final LoadPackageParam lpparam) throws Throwable {
if (!lpparam.packageName.equals("com.android.bluetooth")) {
Log.i(TAG, "Not: " + lpparam.packageName);
return;
}
Log.i(TAG, "Yes " + lpparam.packageName);
//Modified https://d3adend.org/blog/?p=589
ApplicationInfo applicationInfo = AndroidAppHelper.currentApplicationInfo();
if (applicationInfo.processName.equals("com.android.bluetooth")) {
Set<String> classes = new HashSet<>();
DexFile dex;
try {
dex = new DexFile(applicationInfo.sourceDir);
Enumeration entries = dex.entries();
while (entries.hasMoreElements()) {
String entry = (String) entries.nextElement();
classes.add(entry);
}
dex.close();
} catch (IOException e) {
Log.e("HookDetection", e.toString());
}
for (String className : classes) {
boolean obex = false;
if (className.startsWith("com.android.bluetooth") || (obex = className.startsWith("javax.obex"))) {
try {
final Class clazz = lpparam.classLoader.loadClass(className);
for (final Method method : clazz.getDeclaredMethods()) {
if (obex) {
if (!Modifier.isPublic(method.getModifiers())) {
continue; //on javax.obex package, hook only public APIs
}
}
XposedBridge.hookMethod(method, new XC_MethodHook() {
final String methodNam = method.getName();
final String classNam = clazz.getName();
final StringBuilder sb = new StringBuilder("[");
final String logstr = "className " + classNam + ",methodName " + methodNam;
@Override
protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
//Method method=(Method)param.args[0];
sb.setLength(0);
sb.append(logstr);
//Log.v(TAG,logstr);
for (Object o : param.args) {
String typnam = "";
String value = "null";
if (o != null) {
typnam = o.getClass().getName();
value = o.toString();
}
sb.append(typnam).append(" ").append(value).append(", ");
}
sb.append("]");
Log.v(TAG, sb.toString());
}
});
}
} catch (ClassNotFoundException e) {
Log.wtf("HookDetection", e.toString());
}
}
}
}
// ClassLoader rootcl=lpparam.classLoader.getSystemClassLoader();
//findAndHookMethod("de.robv.android.xposed.XposedBridge", rootcl, "handleHookedMethod", Member.class, int.class, Object.class, Object.class, Object[].class, );
}
}