如何xposed hook 带“壳“的app

本文转载自:https://www.cnblogs.com/xiaobaiyey/p/6442417.html

前段时间做了个游戏内购xposed 插件,但是当前的游戏部分都加壳了,并且最新的游戏支付sdk也进行加密了,这样就尴尬了

于是到网上搜索了下:看到"非虫"大大在看雪上发的部分代码如何hook 360加固的应用:原帖貌似被删了,在网上找了部分代码

链接地址:利用xposed hook被360加固的apk - 简书

大概原理:拿到壳的ClassLoader 然后再根据壳的ClassLoader 拿到对应的Class 然后在hook

if (loadPackageParam.packageName.equals("com.package.name")) {
    XposedHelpers.findAndHookMethod("com.qihoo.util.StubAppxxxxxxxx", loadPackageParam.classLoader,
            "getNewAppInstance", Context.class, new XC_MethodHook() {
                @Override
                protected void afterHookedMethod(MethodHookParam param) throws Throwable {
                    super.afterHookedMethod(param);
                    Context context = (Context) param.args[0];
                    ClassLoader classLoader =context.getClassLoader();
                    XposedHelpers.findAndHookMethod("com.amap.api.location.AMapLocation", classLoader, "getLongitude", new XC_MethodHook(){
                        @Override
                        protected void afterHookedMethod(MethodHookParam param) throws Throwable {
                            super.afterHookedMethod(param);
                            param.setResult(123.123123);
                        }
                    });
                    XposedHelpers.findAndHookMethod("com.amap.api.location.AMapLocation", classLoader, "getLatitude", new XC_MethodHook(){
                        @Override
                        protected void afterHookedMethod(MethodHookParam param) throws Throwable {
                            super.afterHookedMethod(param);
                            param.setResult(33.333333);
                        }
                    });
                }
            });
}

 

根据这个原理 查看xposed源码 XposedHelpers.findAndHookMethod方法

public static Unhook findAndHookMethod(String className, ClassLoader classLoader, String methodName, Object... parameterTypesAndCallback) {
    return findAndHookMethod(findClass(className, classLoader), methodName, parameterTypesAndCallback);
}

在查看:其中findclass方法

public static Class<?> findClass(String className, ClassLoader classLoader) {
    if(classLoader == null) {
        classLoader = XposedBridge.BOOTCLASSLOADER;
    }
 
    try {
        return ClassUtils.getClass(classLoader, className, false);
    } catch (ClassNotFoundException var3) {
        throw new XposedHelpers.ClassNotFoundError(var3);
    }
}

  也就是通过ClassLoader 加载Class  然后在进行hook,想到一个办法就是

  在类加载的时候进行hook

  对于加固的应用 xposed 拿到的Classloader 不一定能加载到Class

  于是根据android 源码 加载Class用到的一个是BootClassLoader(系统启动的时候创建的),另一个是PathClassLoader(应用启动时创建的),所以只用看PathClassLoader的源

public class PathClassLoader extends BaseDexClassLoader

接着看BaseDexClassLoader

public class BaseDexClassLoader extends ClassLoader {

    private final DexPathList pathList;



    /**

     * Constructs an instance.

     *

     * @param dexPath the list of jar/apk files containing classes and

     * resources, delimited by {@code File.pathSeparator}, which

     * defaults to {@code ":"} on Android

     * @param optimizedDirectory directory where optimized dex files

     * should be written; may be {@code null}

     * @param libraryPath the list of directories containing native

     * libraries, delimited by {@code File.pathSeparator}; may be

     * {@code null}

     * @param parent the parent class loader

     */

    public BaseDexClassLoader(String dexPath, File optimizedDirectory,

            String libraryPath, ClassLoader parent) {

        super(parent);

        this.pathList = new DexPathList(this, dexPath, libraryPath, optimizedDirectory);

    }



    @Override

    protected Class<?> findClass(String name) throws ClassNotFoundException {

        List<Throwable> suppressedExceptions = new ArrayList<Throwable>();

        Class c = pathList.findClass(name, suppressedExceptions);

        if (c == null) {

            ClassNotFoundException cnfe = new ClassNotFoundException("Didn't find class \"" + name + "\" on path: " + pathList);

            for (Throwable t : suppressedExceptions) {

                cnfe.addSuppressed(t);

            }

            throw cnfe;

        }

        return c;

    }

//......

}

  于是一路分析下去:

  得到:BaseDexClassLoader.findClass(String name)

   ----->DexPathList.findClass(String name, List<Throwable> suppressed)

  ----->DexFile.loadClassBinaryName(String name, ClassLoader loader, List<Throwable> suppressed)

  ---->DexFile.defineClass(String name, ClassLoader loader, Object cookie,List<Throwable> suppressed)

  ---->defineClassNative(name, loader, cookie);

  defineClassNative(name, loader, cookie);方法为native方法 xposed 无法hook 

  最后如果给想在类加载完成时进行hook那么就要在DexFile.defineClass(String name, ClassLoader loader, Object cookie,List<Throwable> suppressed)这个方法上做文章:

  使用xposed hook dalvik.system.DexFile.defineClass方法在然后在hook 后方法里进行过滤拿到想要的Class

public void hookDefineClass() {

    try {

        /*get DexFile Class*/

        Class clazz = loadPackageParam.classLoader.loadClass("dalvik.system.DexFile");

        Method[] methods = clazz.getDeclaredMethods();

        for (int i = 0; i < methods.length; i++) {

            String name = methods[i].getName();

            if (name.equalsIgnoreCase("defineClass")) {

                hookhelper.hookMethod(methods[i], new MethodHookCallBack() {

                    @Override

                    public void beforeHookedMethod(HookParam param) throws IOException, ClassNotFoundException {

                    }



                    @Override

                    public void afterHookedMethod(HookParam param) throws IOException, ClassNotFoundException, NoSuchFieldException, IllegalAccessException, JSONException {

                        //ClassName

        String ClassName = (String) param.args[0];;

        if(ClassName.equalsIgnoreCase("xxxx")){

          //here do something

          //get Class

          Class clazz = (Class) param.getResult();

          // do something you want

          XposedHelpers.findAndHookMethod(Class<?> clazz, String methodName, Object... parameterTypesAndCallback)

        }

                         

                    }

                });

            }

        }

    } catch (ClassNotFoundException e) {

        e.printStackTrace();

    }

}

  一个例子(由于使用自己封装的xposed方法):

  UnicomPay.java(联通支付sdk)

package com.xiaobai.viptools.xposedpay;



import com.xiaobai.viptools.impl.PayOrderHook;

import com.xiaobai.viptools.xposed.HookParam;

import com.xiaobai.viptools.xposed.MethodHookCallBack;



import java.io.IOException;

import java.lang.reflect.Method;



import de.robv.android.xposed.XposedBridge;

import de.robv.android.xposed.callbacks.XC_LoadPackage;



/**

 *

 * Created by xiaobai on 2017/2/3.

 */



public class UnicomPay implements PayOrderHook {

    private XC_LoadPackage.LoadPackageParam lpparam;



    public UnicomPay(XC_LoadPackage.LoadPackageParam loadPackageParam) {

        this.lpparam = loadPackageParam;

    }



    @Override

    public void Hookpay(Class clazz) throws ClassNotFoundException {

        Method[] methods=clazz.getMethods();

        for (int i = 0; i <methods.length; i++) {

            String name=methods[i].getName();

            if (name.equalsIgnoreCase("pay")){

                Method paymethod=methods[i];

                HookPayMethond(paymethod);

            }

        }

    }



    private void HookPayMethond(Method method){

        hookhelper.hookMethod(method, new MethodHookCallBack() {

            @Override

            public void beforeHookedMethod(HookParam param) throws IOException {

                XposedBridge.log("paymethod arg size:"+param.args.length);

                Class clazz= param.args[param.args.length-1].getClass();

                HookPayresult(clazz);

            }



            @Override

            public void afterHookedMethod(HookParam param) throws IOException, ClassNotFoundException, NoSuchFieldException, IllegalAccessException {



            }

        });



    }

    private void  HookPayresult(Class clazz){

        Method[] methods=clazz.getMethods();

        for (int i = 0; i < methods.length; i++) {

            if (methods[i].getName().equalsIgnoreCase("PayResult")){

                hookhelper.hookMethod(methods[i], new MethodHookCallBack() {

                    @Override

                    public void beforeHookedMethod(HookParam param) throws IOException {

                        XposedBridge.log("arg[1]:code "+param.args[1]);

                        param.args[1]=1;

                        XposedBridge.log("payhook success");

                    }

                    @Override

                    public void afterHookedMethod(HookParam param) throws IOException, ClassNotFoundException, NoSuchFieldException, IllegalAccessException {



                    }

                });

            }

        }

    }

}

  HookPayMethod.java

package com.xiaobai.viptools.XposedModule;



import android.content.Context;





import com.xiaobai.viptools.helper.JsonHelper;

import com.xiaobai.viptools.impl.HookHelperInterface;

import com.xiaobai.viptools.util.ContextHolder;

import com.xiaobai.viptools.xposed.HookHelperFacktory;

import com.xiaobai.viptools.xposed.HookParam;

import com.xiaobai.viptools.xposed.MethodHookCallBack;







import de.robv.android.xposed.callbacks.XC_LoadPackage;



/**

 * Created by xiaobai on 2017/2/3.

 */



public class HookPayMethod {

    private XC_LoadPackage.LoadPackageParam loadPackageParam;

    private HookHelperInterface hookhelper = HookHelperFacktory.getHookHelper();



    public HookPayMethod(XC_LoadPackage.LoadPackageParam loadPackageParam) {

        this.loadPackageParam = loadPackageParam;

    }



    /*针对加壳app hook defineclass 过滤app*/

    public void hookDefineClass() {

        try {

            /*获取DexFile Class*/

            Class clazz = loadPackageParam.classLoader.loadClass("dalvik.system.DexFile");

            Method[] methods = clazz.getDeclaredMethods();

            for (int i = 0; i < methods.length; i++) {

                String name = methods[i].getName();

                if (name.equalsIgnoreCase("defineClass")) {

                    hookhelper.hookMethod(methods[i], new MethodHookCallBack() {

                        @Override

                        public void beforeHookedMethod(HookParam param) throws IOException, ClassNotFoundException {

                        }



                        @Override

                        public void afterHookedMethod(HookParam param) throws IOException, ClassNotFoundException, NoSuchFieldException, IllegalAccessException, JSONException {

                            selectPayMethod(param);

                        }

                    });

                }

            }

        } catch (ClassNotFoundException e) {

            e.printStackTrace();

        }

    }





    private void selectPayMethodDebug(HookParam param) throws ClassNotFoundException {

        String ClassName = (String) param.args[0];

        // System.out.println(ClassName);

        if (unicompay && ClassName.equalsIgnoreCase("com.unicom.dcLoader.Utils")) {

            Class PayClass = (Class) param.getResult();

            UnicomPay unicomPay = new UnicomPay(loadPackageParam);

            unicomPay.Hookpay(PayClass);

        }

    }



}

对付简单的加固应该没问题

猜你喜欢

转载自blog.csdn.net/chali1314/article/details/129154999