跳至主要內容

模块管理

missking大约 3 分钟

重要

在早先没有内置KernelSu获取root权限时,为了方便在未root环境下注入dex以及so,开发了该功能,而现在有了root环境,此功能就不是那么重要了,可以选择在KernelSu中添加lsposed模块

该功能主要用于在启动过程中快速注入dex以及so,为了便于art hook,内部自动注入了pine的动态库,inline hook可以通过开发模块的时候配置dobby的注入使用。下面是一个简单的模块例子

首先创建新的android项目,修改AndroidManifest.xml文件

<meta-data
    android:name="kdesc"
    android:value="模块样例" />
<meta-data
    android:name="kclass"
    android:value="com.example.mysodemo.myModule" />
<meta-data
    android:name="ksoname"
    android:value="libdobby.so;libmysodemo.so" />

kdesc表示该字段在模块栏目中的描述

kclass表示注入该模块后启动的入口类,该类必须实现接口java.lang.krom.IHook中的onStart函数。模块注入成功后会调用该函数

ksoname表示要注入的动态库列表,在这个例子中,将dobby以及当前例子的动态库都自动注入了。

接着在build.gradle中添加对pine库的引用

implementation 'top.canyie.pine:core:0.2.6'

添加好引用支持后,就可以创建接口了,在java目录下创建package路径java.lang.krom,然后在里面创建接口文件IHook.java

package java.lang.krom;

public interface IHook {
    void onStart(Object app);
}

接口准备完毕,实现它就可以了。下面是com.example.mysodemo.myModule类的实现


public class myModule implements IHook {
    public static String TAG="myModule";
    @Override
    public void onStart(Object app) {
        Log.i(TAG,"onStart my demo");
        PineConfig.debug = true; 
        PineConfig.debuggable = BuildConfig.DEBUG; 

        Log.i(TAG,"start Hook json");
        try {
            Pine.hook(JSONObject.class.getDeclaredMethod("toString"), new MethodHook() {
                @Override public void beforeCall(Pine.CallFrame callFrame) {
                    Log.i(TAG, "enter json toString");
                }

                @Override public void afterCall(Pine.CallFrame callFrame) {
                    Log.i(TAG, "leave json toString "+callFrame.getResult());
                }
            });
        } catch (NoSuchMethodException e) {
            throw new RuntimeException(e);
        }
    }
}

最后安装该模块,再次进入到模块列表页面,就能看到此模块了

模块选择
模块选择

勾选此模块,重新保存配置后,再次打开该应用即可看到下面的日志

myModule                com.aisino.sqzlht                    I  onStart my demo

由于当前系统版本基于android13的基础,所以在模块修改后,重新安装时,需要使用命令adb install -r app-debug.apk即可更新覆盖此模块。

除了IHook接口外,还可以实现另一个接口IDeepDex来完成对深入调用链脱壳的对接,该接口定义如下

package java.lang.krom;

public interface IDeepDex {
    boolean CheckCode(Object[] objs);
}

下面看一个实现的例子如下


public class testModule  implements IHook, IDeepDex {

    public static String TAG="testModule";
    @Override
    public void onStart(Object app) {
        Log.i(TAG,"enter onStart");
    }

    @Override
    public boolean CheckCode(Object[] objs) {
        String codeItem=(String)objs[0];
        int methodIdx=(int)objs[1];
        int offset=(int)objs[2];
        int codeItemLen=(int)objs[3];
        int dexSize=(int)objs[4];
        String methodName=objs[5].toString();
        if(objs.length>6){
            String clsDesc=objs[6].toString();
        }
        System.out.println("myModule checCode "+codeItem);
        return false;
    }
}

在开启深入调用链时,如果有模块实现了IDeepDex接口,则会通过调用其CheckCode函数,交由模块判断其是否应执行到更深处。如没有该模块,则默认为false,统一在invoke时就保存其执行字节码。

最后是附上模块样例地址

MySoDemoopen in new window