反编译常见问题札记——二次打包签名Hook篇代码块

207 阅读1分钟

应用签名获取方式(替换目标pkg)

PackageManager manager = context.getPackageManager();
PackageInfo packageInfo = manager.getPackageInfo("target package name", PackageManager.GET_SIGNATURES);
Signature[] signatures = packageInfo.signatures;
String str = signatures[0].toCharsString();

如何变更签名(二次打包签名绕过)

Class<?> activityThreadClass = Class.forName("android.app.ActivityThread");
            Method currentActicityThreadMethod = activityThreadClass.getDeclaredMethod("currentActivityThread");

            ActivityThread currentActivityThread = (ActivityThread) currentActicityThreadMethod.invoke(null);

            Field sPackageManagerField = activityThreadClass.getDeclaredField("sPackageManager");
            sPackageManagerField.setAccessible(true);
            Object sPackageManager = sPackageManagerField.get(currentActivityThread);

            Class<?> iPackageManagerInterface = Class.forName("android.content.pm.IPackageManager");
        	//代理替换
            Object proxy = Proxy.newProxyInstance(iPackageManagerInterface.getClass().getClassLoader(), new Class[]{iPackageManagerInterface}, new HookSign(sPackageManager));

            sPackageManagerField.set(currentActivityThread, proxy);

            PackageManager pm = context.getPackageManager();
            Field mPMField = pm.getClass().getDeclaredField("mPM");
            mPMField.setAccessible(true);
            mPMField.set(pm, proxy);

如何防止二次打包?

  1. 签名校验?貌似对上述方案不靠谱
  2. 代理check?听起来有点靠谱
  3. 其它方式,欢迎留言一起讨论!

检测系统Api是否被Hook过?

/**
* Returns true if and only if the specified class was dynamically
* generated to be a proxy class using the {@code getProxyClass}
* method or the {@code newProxyInstance} method.
*
* <p>The reliability of this method is important for the ability
* to use it to make security decisions, so its implementation should
* not just test if the class in question extends {@code Proxy}.
*
* @param   cl the class to test
* @return  {@code true} if the class is a proxy class and
*          {@code false} otherwise
* @throws  NullPointerException if {@code cl} is {@code null}
*/
public static boolean isProxyClass(Class<?> cl) {
    return Proxy.class.isAssignableFrom(cl) && proxyClassCache.containsValue(cl);
}


//具体业务检测代码:
PackageManager manager = context.getPackageManager();
Field mPM = manager.getClass().getDeclaredField("mPM");
mPM.setAccessible(true);
if (Proxy.isProxyClass(mPM.get(manager).getClass())) {
    //发现核心api被代理,此处可以做事情!
}