绕过App签名方案

2,317 阅读1分钟

方案:使用动态代理,替换 PackageManager 里的签名信息

替换掉ActivityThread里面的 sPackageManager 字段

替换 ApplicationPackageManager里面的 mPM对象

获取PackageManager相关代码:

public static void hookPMS(Context context, String packageName, String sign) {
        try {
            SignatureFake.setSign(sign);
            // 获取全局的ActivityThread对象
            Object currentActivityThread = Reflect.onClass("android.app.ActivityThread")
                    .call("currentActivityThread").get();
            Object sPackageManager = Reflect.onClass("android.app.ActivityThread").field("sPackageManager").get();

            Class<?> iPackageManagerInterface = Reflect.onClass("android.content.pm.IPackageManager").type();

            Object proxy = Proxy.newProxyInstance(
                    iPackageManagerInterface.getClassLoader(),
                    new Class<?>[]{iPackageManagerInterface},
                    new PmsHookBinderInvocationHandler(sPackageManager, packageName, 0));
            // 1. 替换掉ActivityThread里面的 sPackageManager 字段
            Reflect.on(currentActivityThread).set("sPackageManager",proxy);
            // 2. 替换 ApplicationPackageManager里面的 mPM对象
            PackageManager pm = context.getPackageManager();
            Reflect.on(pm).set("mPM", proxy);
        } catch (Exception e) {
            Log.d(TAG, "hook pms error:" + Log.getStackTraceString(e));
        }
    }

InvocationHandler 回调


    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

        //查看是否是getPackageInfo方法
        if("getPackageInfo".equals(method.getName())){
            if(DEBUG)
            {
                Log.d(TAG,"hook method:" + method.getName());
            }

            String pkgName = (String)args[0];
            Integer flag = (Integer)args[1];
            if(DEBUG)
            {
                Log.d(TAG, "hook pkgName:" + pkgName + " appPkgName:" + appPkgName + ",flaf:" + flag);
            }

            //是否是获取我们需要hook apk的签名
            if((flag & PackageManager.GET_SIGNATURES) == PackageManager.GET_SIGNATURES && appPkgName.compareToIgnoreCase(pkgName) == 0){
                //将构造方法中传进来的新的签名覆盖掉原来的签名
                PackageInfo info = (PackageInfo) method.invoke(base, args);
                info.signatures = SignatureFake.getSignature(info.signatures);
                return info;
            }
        }
        return method.invoke(base, args);
    }

代码: github.com/bineanzhou/…