模块管理
重要
在早先没有内置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时就保存其执行字节码。
最后是附上模块样例地址