碎碎念-记一下LSPatch的原理

基本原理

LSPatch会替换掉清单中的appcomponentFactory,并在内部执行其自身的代码。
这是属性是安卓8加入的,所以lspatch的最低版本就是安卓8。
appcomponmentFactory的作用是减少instrumentation的工作量
众所周知,一个安卓程序,第一段被执行的代码就位于instrumentation,instrumentation负责整个程序的内部协作。
instrumentation尤为重量,所以在安卓8,谷歌提供了appcomponentFactory。前者关注程序所有的协作,而后者只关注四大组件的创建。

步骤解析

第一步就是拷贝LSPatch的源码

https://github.com/LSPosed/LSPatch

LSPAppComponentFactoryStub

有了上述的介绍,读者们应该清楚LSPatch第一段执行的代码就位于LSPAppComponentFactoryStub,
而他的代码在源码中位于meta-loader中。
大致流程如下

public class LSPAppComponentFactoryStub extends AppComponentFactory {
   

    private static final String TAG = "LSPatch-MetaLoader";
    private static final Map<String, String> archToLib = new HashMap<String, String>(4);

    public static byte[] dex;

    static {
   
        try {
   
            archToLib.put("arm", "armeabi-v7a");
            archToLib.put("arm64", "arm64-v8a");
            archToLib.put("x86", "x86");
            archToLib.put("x86_64", "x86_64");

            ...
            String libName = archToLib.get(arch);
            // 获取是哪个架构的

            boolean useManager = false;
            String soPath;

            // 读patch的config
            try (var is = cl.getResourceAsStream(Constants.CONFIG_ASSET_PATH);
                ...
            }

            if (useManager) {
   
                // 如果使用管理器(本地模式)
                Log.i(TAG, "Bootstrap loader from manager");
                var ipm = IPackageManager.Stub.asInterface(ServiceManager.getService("package"));
                ApplicationInfo manager = ipm.getApplicationInfo(Constants.MANAGER_PACKAGE_NAME, 0, Process.myUid() / 100000);
                try (var zip = new ZipFile(new File(manager.sourceDir));
                     // 从管理器的apk中拿到assets/lspatch/loader.dex
                     var is = zip.getInputStream(zip.getEntry(Constants.LOADER_DEX_ASSET_PATH));
                     var os = new ByteArrayOutputStream()) {
   
                    transfer(is, os);
                    dex = os.toByteArray();
                }
                soPath = manager.sourceDir + "!/assets/lspatch/so/" + libName + "/liblspatch.so";
            } else {
   
                Log.i(TAG, "Bootstrap loader from embedment");
                try (var is = cl.getResourceAsStream(Constants.LOADER_DEX_ASSET_PATH);
                     // 从被patch的apk中拿到assets/lspatch/loader.dex
                     var os = new ByteArrayOutputStream()) {
   
                    transfer(is, os);
                    dex = os.toByteArray();
                }
                soPath = cl.getResource(
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

有头发的琦玉

打点钱,我会再努力的

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值