2

As title said, I want to use xposed to log all methods called in an app from it start till I stop it. I only want to log Class name, Method name, don't want to hook all method. I try this code, but get error getMethod not found.

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

Thanks in advance!

LieuLiau
  • 25
  • 1
  • 6
  • Hooking *all* the methods called by an app is pretty much impossible. What if you were to hook the method used to print the logs? If all you want is to see a static list of methods in the app, you can just use `apktool` to decompile the APK file. – Andrew Sun Mar 11 '17 at 19:04
  • 1
    I don't want to hook all methods. I just want to log what methods were called by app from it start till I stop it. – LieuLiau Mar 12 '17 at 01:22
  • It is possible by modifing AOSP, still relevant ? – whoopdedoo Dec 02 '19 at 22:22

4 Answers4

4

There is no one line solution like what you seem to be searching.

Hooking all methods will let log what methods were called by app from it start till stop (sort of - see below), but if (for some reason) you don't want to hook all methods, the only solution I can think of is modifying the java VM itself (NOT something I would recommend.)

A solution that (sort of) works

What I did was first use apktool to decompile my apk and get the names of all the methods in all the classes. Then I used xposed to hook into every single method of every class and print to the dlog the current function name.

Why it only sort of works

Xposed has an overhead whenever it hook a methods. For general usage of xposed apps, it isnt much. But when you start hooking each and every methods of an app, the overhead very quickly becomes ridiculously large - So much so that while the above methods works for small apps, for any large app it very quickly causes the app to hang and then crash.

An alternative that also sort-of works

FRIDA is a way to inject javascript to native apps. Here they show you how to log all function calls. While in the above link they log all function calls in a piece of python code, the same code also works for Android.

Akhil Kedia
  • 136
  • 5
2

There is a way to log all Java methods.Modify XposedBridge.

Xposed hook java method through XposedBridge.java's method "handleHookedMethod(Member method, int originalMethodId, Object additionalInfoObj, thisObject, Object[] args)"

Log.v(TAG, "className " + method.getClass().getName() + ",methodName " + method.getName());
illusion
  • 21
  • 1
1

As mentioned before Xposed is not the way to go in this situation due to its overhead.

The simplest solution is just to use dmtracedump as provided by Google. Most x86 Android images and emulator come with the debuggable flag on (ro.debuggable) so you can even use it for closed source apps.

Additionally other tools such as Emma are known to work with Android as well, but these might need modifications to the source code.

4knahs
  • 629
  • 4
  • 14
  • Yes, I know this traceview, but problem is sometimes app force close before my stoptracing call, so no trace file is written. – LieuLiau Mar 18 '17 at 05:41
  • Is this your app or a closed source app? If all you want is the name of the methods/classes that ran, then Emma code coverage can be retrieved over time... – 4knahs Mar 23 '17 at 15:34
  • It's a closed source app. Can Emma use for that? – LieuLiau Mar 28 '17 at 03:40
  • I have only tried using Emma with opensource apps as it requires adding a class to the app. It might work for closed source apps if added with xposed but i never tried. Have you looked at startMethodTracingSampling and startNativeTracing? The first allows setting a sampling interval and the later runs at the emulator level and writes the output to stdout. So both of these might provide you with intermediate results. – 4knahs Mar 28 '17 at 10:49
1

I found a solution.

See this code snippet below.

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, );
    }
}
kangear
  • 2,493
  • 2
  • 31
  • 44
KYHSGeekCode
  • 1,068
  • 2
  • 12
  • 30