记录 Xposed 在应用程序中调用的所有方法

Log all methods called in an app by Xposed

如标题所述,我想使用 xposed 记录应用程序中调用的所有方法,从它开始直到我停止它。我只想记录 Class 名称,方法名称,不想挂钩所有方法。 我尝试了这段代码,但收到错误 getMethod not found.

findAndHookMethod("java.lang.Class", lpparam.classLoader, "getMethod", String.class, Object.class, new XC_MethodHook()

提前致谢!

没有像您正在搜索的那样的单行解决方案。

挂钩所有方法将允许记录应用程序从开始到停止调用了哪些方法(有点 - 见下文),但如果(出于某种原因)你不想挂钩所有方法,唯一的解决方案我能想到的是修改 java 虚拟机本身(我不推荐。)

一个(有点)有效的解决方案

我做的是首先使用apktool 反编译我的apk 并获取所有classes 中的所有方法的名称。 然后我使用 xposed 挂钩每个 class 的每个方法并将当前函数名称打印到 dlog。

为什么它只能起作用

Xposed 在挂钩方法时会产生开销。对于 xposed 应用程序的一般用途,它并不多。但是当你开始挂钩一个应用程序的每一个方法时,开销很快就会变得大得离谱——以至于尽管上述方法适用于小型应用程序,但对于任何大型应用程序来说,它很快就会导致应用程序挂起然后崩溃。

也有一定效果的替代方案

FRIDA is a way to inject javascript to native apps. Here 他们向您展示了如何记录所有函数调用。在上面 link 中,他们将所有函数调用记录在一段 python 代码中,相同的代码也适用于 Android.

如前所述,由于其开销,Xposed 在这种情况下不是可行的方法。

最简单的解决方案就是使用 Google 提供的 dmtracedump。大多数 x86 Android 图像和模拟器都带有可调试标志 (ro.debuggable),因此您甚至可以将其用于闭源应用程序。

此外,其他工具(例如 Emma 也可用于 Android,但这些工具可能需要修改源代码。

有一种方法可以记录所有 Java methods.Modify 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());

我找到了解决方案。

请参阅下面的代码片段。

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, );
    }
}