Skip to content

Latest commit

 

History

History
150 lines (109 loc) · 4.27 KB

File metadata and controls

150 lines (109 loc) · 4.27 KB

打包、Manifest、LibrarySet 与 ClassLoader

本仓编译依赖固定在 deps/api/VERSION。先执行 ./scripts/install-api-deps.sh;该脚本会校验 SHA256SUMS 并安装下面的 Maven 坐标。不要把 deps/api/*.jar 复制进任何插件模块。

最小 POM

<properties>
  <maven.compiler.source>8</maven.compiler.source>
  <maven.compiler.target>8</maven.compiler.target>
  <chains.api.version>2.0.0-beta7</chains.api.version>
</properties>

<dependency>
  <groupId>org.vulhub</groupId>
  <artifactId>java-chains-plugin-api</artifactId>
  <version>${chains.api.version}</version>
  <scope>provided</scope>
</dependency>

只有确实使用公开 allowlisted helper 时才增加 java-chains-common,同样使用 provided。本仓同时分发该二进制,方便 IDE/编译,但这不表示 common 的所有实现包都对插件开放。

不要依赖或打包 java-chains-corejava-chains-serverjava-chains-nodesjava-chains-all

Manifest

文件位置:src/main/resources/META-INF/chains-plugin.json

{
  "id": "demo",
  "version": "1.0.0",
  "apiVersion": "2.0.0-beta7",
  "libraries": []
}

version 是插件版本;apiVersion 是目标宿主 API 版本。

LibrarySet 四段闭环

1. 编译期

本地第三方 jar 可使用 system scope:

<dependency>
  <groupId>local.demo</groupId>
  <artifactId>demo-victim</artifactId>
  <version>1.0</version>
  <scope>system</scope>
  <systemPath>${project.basedir}/libs/demo-victim.jar</systemPath>
</dependency>

这只解决编译。

2. 打包期

<resource>
  <directory>${project.basedir}/libs</directory>
  <includes><include>demo-victim.jar</include></includes>
  <targetPath>libraries/demo-victim</targetPath>
</resource>

3. Manifest 声明

"libraries": [{
  "id": "demo-victim",
  "version": "1.0",
  "isolation": "private",
  "entries": ["libraries/demo-victim/demo-victim.jar"]
}]

4. 节点绑定

@GadgetMeta(id = "DemoLibraryGadget", libraries = {"demo-victim"}, ...)

四步缺一不可。

间接运行时依赖

victim jar 能编译不等于它在隔离 ClassLoader 中能独立执行。它可能在触发路径上引用未重定位的日志、代理、表达式或工具库。

  • 把触发路径真正需要的间接 jar 作为独立文件放入同一 libraries/<setId>/,并加入 manifest entries
  • 不要把这些类 shade 进插件主 jar,也不要依赖它们恰好存在于宿主。
  • jdeps --missing-deps 可以帮助发现候选缺口,但大型 victim jar 常含很多本链不会走到的可选代码,不能把全部 not found 都打包。
  • 最终判据是临时宿主 Reload 后,在真实插件 ClassLoader 中执行一次安全 generate;每次 NoClassDefFoundError 都回到实际触发路径确认是必需还是可选分支。

隔离策略

  • private:优先使用当前 PluginUnit 自带 jar,通常是首选。
  • shared:表达共享依赖意图;仍需验证目标宿主的解析顺序。

不要创建万能 shared classpath,也不要假设宿主应用的 Jackson、codec、Spring 等第三方库可见。

执行期 ClassLoader

插件使用 ChildFirst 上下文和受限父加载器。执行 Gadget 时 TCCL 指向当前插件 ClassLoader。

Class<?> type = PluginClasses.forName("com.vendor.Victim");
ClassLoader loader = PluginClasses.contextLoader();

常见失败:

  • jar 只在 libs/,未打进 libraries/<id>/
  • manifest id 与注解 id 不一致。
  • entries 指向不存在的归档路径。
  • 代理接口与实现来自不同 loader。
  • plugin-api 被 shade,导致同名 Class 不相等。

产物检查

./scripts/install-api-deps.sh
mvn clean verify
./build.sh
jar tf target/chains-plugin-*.jar

应包含:manifest、插件类、nodes YAML、可选 preset、可选 LibrarySet。

不得包含:

org/vulhub/javachains/api/
org/vulhub/javachains/core/
org/vulhub/javachains/server/
BOOT-INF/
third-libs/
com/ar3h/

插件自己的 org/vulhub/javachains/plugins/ 包必须保留。

升级 API

  1. 读取目标宿主的公开 plugin-api 版本。
  2. 同步 POM 依赖和 manifest apiVersion
  3. 插件行为变化时另行提升插件 version
  4. 运行 clean verify、ClassLoader 测试和真实宿主冒烟。