Skip to content

Commit d58c1cb

Browse files
committed
feat: support probe shell generation
1 parent dbf120e commit d58c1cb

File tree

304 files changed

+59083
-1453
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

304 files changed

+59083
-1453
lines changed

.github/workflows/test.yaml

Lines changed: 56 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ jobs:
6161
exit 1
6262
fi
6363
64-
integration-test:
64+
memshell-integration-test:
6565
strategy:
6666
fail-fast: false
6767
matrix:
@@ -114,7 +114,60 @@ jobs:
114114
run: ./gradlew ${{ matrix.cases.depend_tasks }}
115115

116116
- name: Integration Test with gradle
117-
run: ./gradlew :integration-test:test --tests '*.${{ matrix.cases.middleware }}.*' --info
117+
run: ./gradlew :integration-test:test --tests '*.memshell.${{ matrix.cases.middleware }}.*' --info
118118

119119
- name: Export Integration Test Summary
120-
run: cat integration-test/build/test-results/report.md >> $GITHUB_STEP_SUMMARY
120+
run: cat integration-test/build/test-results/report.md >> $GITHUB_STEP_SUMMARY
121+
122+
detection-integration-test:
123+
strategy:
124+
fail-fast: false
125+
matrix:
126+
cases:
127+
- middleware: "tomcat"
128+
depend_tasks: ":vul:vul-webapp:war :vul:vul-webapp-expression:war :vul:vul-webapp-deserialize:war :vul:vul-webapp-jakarta:war"
129+
- middleware: "jetty"
130+
depend_tasks: ":vul:vul-webapp:war :vul:vul-webapp-jakarta:war"
131+
- middleware: "jbossas"
132+
depend_tasks: ":vul:vul-webapp:war"
133+
- middleware: "jbosseap"
134+
depend_tasks: ":vul:vul-webapp:war"
135+
- middleware: "wildfly"
136+
depend_tasks: ":vul:vul-webapp:war :vul:vul-webapp-jakarta:war"
137+
- middleware: "glassfish"
138+
depend_tasks: ":vul:vul-webapp:war :vul:vul-webapp-jakarta:war"
139+
- middleware: "resin"
140+
depend_tasks: ":vul:vul-webapp:war"
141+
- middleware: "payara"
142+
depend_tasks: ":vul:vul-webapp:war :vul:vul-webapp-jakarta:war"
143+
- middleware: "websphere"
144+
depend_tasks: ":vul:vul-webapp:war"
145+
- middleware: "websphere7"
146+
depend_tasks: ":vul:vul-webapp:war"
147+
- middleware: "weblogic"
148+
depend_tasks: ":vul:vul-webapp:war"
149+
- middleware: "springwebmvc"
150+
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"
151+
- middleware: "springwebflux"
152+
depend_tasks: ":vul:vul-springboot2-webflux:bootJar :vul:vul-springboot3-webflux:bootJar"
153+
runs-on: ubuntu-latest
154+
name: ${{ matrix.cases.middleware }}
155+
needs: [ unit-test ]
156+
steps:
157+
- name: Checkout
158+
uses: actions/checkout@v4
159+
160+
- name: Setup Java
161+
uses: actions/setup-java@v4
162+
with:
163+
distribution: 'temurin'
164+
java-version: 17
165+
166+
- name: Setup Gradle
167+
uses: gradle/actions/setup-gradle@v4
168+
169+
- name: Prepare for Integration Test
170+
run: ./gradlew ${{ matrix.cases.depend_tasks }}
171+
172+
- name: Integration Test with gradle
173+
run: ./gradlew :integration-test:test --tests '*.probe.${{ matrix.cases.middleware }}.*' --info

asserts/http_post_server.py

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import http.server
2+
import socketserver
3+
4+
PORT = 8000
5+
TARGET_PATH = "/api/v1/data"
6+
7+
8+
class SimpleHTTPRequestHandler(http.server.BaseHTTPRequestHandler):
9+
def do_POST(self):
10+
if self.path == TARGET_PATH:
11+
try:
12+
content_length = int(self.headers['Content-Length'])
13+
post_data_bytes = self.rfile.read(content_length)
14+
post_data_str = post_data_bytes.decode('utf-8')
15+
print("-----------------------------\n")
16+
print(f"Client IP: {self.client_address}")
17+
print(f"Request Header:\n{self.headers}")
18+
print(f"Request Body:\n{post_data_str}")
19+
print("-----------------------------\n")
20+
self.send_response(200)
21+
self.send_header('Content-type', 'application/json')
22+
self.end_headers()
23+
response_message = '{"status": "success"}'
24+
self.wfile.write(response_message.encode('utf-8'))
25+
except Exception as e:
26+
print(f"Parse POST failed: {e}")
27+
self.send_response(500)
28+
else:
29+
print("Make sure use " + TARGET_PATH + " rather than " + self.path)
30+
self.send_response(404)
31+
32+
33+
with socketserver.TCPServer(("", PORT), SimpleHTTPRequestHandler) as httpd:
34+
print(f"POST request at http://localhost:{PORT}{TARGET_PATH} Listening ")
35+
httpd.serve_forever()

boot/src/main/java/com/reajason/javaweb/boot/controller/GeneratorController.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import com.reajason.javaweb.boot.dto.GenerateRequest;
44
import com.reajason.javaweb.boot.dto.GenerateResponse;
55
import com.reajason.javaweb.memshell.MemShellGenerator;
6-
import com.reajason.javaweb.memshell.config.GenerateResult;
6+
import com.reajason.javaweb.memshell.MemShellResult;
77
import com.reajason.javaweb.memshell.config.InjectorConfig;
88
import com.reajason.javaweb.memshell.config.ShellConfig;
99
import com.reajason.javaweb.memshell.config.ShellToolConfig;
@@ -27,7 +27,7 @@ public GenerateResponse generate(@RequestBody GenerateRequest request) {
2727
ShellConfig shellConfig = request.getShellConfig();
2828
ShellToolConfig shellToolConfig = request.parseShellToolConfig();
2929
InjectorConfig injectorConfig = request.getInjectorConfig();
30-
GenerateResult generateResult = MemShellGenerator.generate(shellConfig, injectorConfig, shellToolConfig);
30+
MemShellResult generateResult = MemShellGenerator.generate(shellConfig, injectorConfig, shellToolConfig);
3131
Packer packer = request.getPacker().getInstance();
3232
if (packer instanceof JarPacker) {
3333
return new GenerateResponse(generateResult, Base64.getEncoder().encodeToString(((JarPacker) packer).packBytes(generateResult.toJarPackerConfig())));
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
package com.reajason.javaweb.boot.controller;
2+
3+
import com.reajason.javaweb.boot.dto.ProbeGenerateRequest;
4+
import com.reajason.javaweb.boot.dto.ProbeGenerateResponse;
5+
import com.reajason.javaweb.packer.AggregatePacker;
6+
import com.reajason.javaweb.packer.Packer;
7+
import com.reajason.javaweb.probe.ProbeGenerator;
8+
import com.reajason.javaweb.probe.ProbeResult;
9+
import com.reajason.javaweb.probe.config.ProbeConfig;
10+
import com.reajason.javaweb.probe.config.ProbeContentConfig;
11+
import org.springframework.web.bind.annotation.*;
12+
13+
/**
14+
* @author ReaJason
15+
* @since 2025/8/10
16+
*/
17+
@RestController
18+
@RequestMapping("/probe/generate")
19+
@CrossOrigin("*")
20+
public class ProbeGeneratorController {
21+
@PostMapping
22+
public ProbeGenerateResponse generate(@RequestBody ProbeGenerateRequest request) {
23+
ProbeConfig probeConfig = request.getProbeConfig();
24+
ProbeContentConfig probeContentConfig = request.parseProbeContentConfig();
25+
ProbeResult generateResult = ProbeGenerator.generate(probeConfig, probeContentConfig);
26+
Packer packer = request.getPacker().getInstance();
27+
if (packer instanceof AggregatePacker) {
28+
return new ProbeGenerateResponse(generateResult, ((AggregatePacker) packer).packAll(generateResult.toClassPackerConfig()));
29+
} else {
30+
return new ProbeGenerateResponse(generateResult, packer.pack(generateResult.toClassPackerConfig()));
31+
}
32+
}
33+
}

boot/src/main/java/com/reajason/javaweb/boot/dto/GenerateResponse.java

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
package com.reajason.javaweb.boot.dto;
22

3-
import com.reajason.javaweb.memshell.config.GenerateResult;
3+
import com.reajason.javaweb.memshell.MemShellResult;
44
import lombok.Data;
55
import lombok.NoArgsConstructor;
66

@@ -13,16 +13,16 @@
1313
@Data
1414
@NoArgsConstructor
1515
public class GenerateResponse {
16-
private GenerateResult generateResult;
16+
private MemShellResult generateResult;
1717
private String packResult;
1818
private Map<String, String> allPackResults;
1919

20-
public GenerateResponse(GenerateResult generateResult, String packResult) {
20+
public GenerateResponse(MemShellResult generateResult, String packResult) {
2121
this.generateResult = generateResult;
2222
this.packResult = packResult;
2323
}
2424

25-
public GenerateResponse(GenerateResult generateResult, Map<String, String> allPackResults) {
25+
public GenerateResponse(MemShellResult generateResult, Map<String, String> allPackResults) {
2626
this.allPackResults = allPackResults;
2727
this.generateResult = generateResult;
2828
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
package com.reajason.javaweb.boot.dto;
2+
3+
import com.reajason.javaweb.packer.Packers;
4+
import com.reajason.javaweb.probe.config.*;
5+
import lombok.Data;
6+
7+
/**
8+
* @author ReaJason
9+
* @since 2025/8/10
10+
*/
11+
@Data
12+
public class ProbeGenerateRequest {
13+
private ProbeConfig probeConfig;
14+
private ProbeContentConfigDTO probeContentConfig;
15+
private Packers packer;
16+
17+
@Data
18+
static class ProbeContentConfigDTO {
19+
private String host;
20+
private int seconds;
21+
private String server;
22+
private String sleepServer;
23+
private String reqParamName;
24+
private String reqHeaderName;
25+
}
26+
27+
public ProbeContentConfig parseProbeContentConfig() {
28+
return switch (probeConfig.getProbeMethod()) {
29+
case DNSLog -> DnsLogConfig.builder()
30+
.host(probeContentConfig.host)
31+
.build();
32+
case Sleep -> SleepConfig.builder()
33+
.seconds(probeContentConfig.seconds)
34+
.server(probeContentConfig.sleepServer)
35+
.build();
36+
case ResponseBody -> ResponseBodyConfig.builder()
37+
.reqParamName(probeContentConfig.reqParamName)
38+
.reqHeaderName(probeContentConfig.reqHeaderName)
39+
.server(probeContentConfig.server)
40+
.build();
41+
default -> throw new UnsupportedOperationException("unknown probe method: " + probeConfig.getProbeMethod());
42+
};
43+
}
44+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
package com.reajason.javaweb.boot.dto;
2+
3+
import com.reajason.javaweb.probe.ProbeResult;
4+
import lombok.Data;
5+
import lombok.NoArgsConstructor;
6+
7+
import java.util.Map;
8+
9+
/**
10+
* @author ReaJason
11+
* @since 2025/8/10
12+
*/
13+
@Data
14+
@NoArgsConstructor
15+
public class ProbeGenerateResponse {
16+
private ProbeResult probeResult;
17+
private String packResult;
18+
private Map<String, String> allPackResults;
19+
20+
public ProbeGenerateResponse(ProbeResult probeResult, String packResult) {
21+
this.probeResult = probeResult;
22+
this.packResult = packResult;
23+
}
24+
25+
public ProbeGenerateResponse(ProbeResult probeResult, Map<String, String> allPackResults) {
26+
this.allPackResults = allPackResults;
27+
this.probeResult = probeResult;
28+
}
29+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package com.reajason.javaweb;
2+
3+
/**
4+
* @author ReaJason
5+
* @since 2025/8/5
6+
*/
7+
public class Constants {
8+
public static class Server {
9+
public static final String TOMCAT = "Tomcat";
10+
public static final String JETTY = "Jetty";
11+
public static final String UNDERTOW = "Undertow";
12+
public static final String JBOSS = "JBoss";
13+
public static final String RESIN = "Resin";
14+
public static final String WEBLOGIC = "WebLogic";
15+
public static final String WEBSPHERE = "WebSphere";
16+
public static final String GLASSFISH = "GlassFish";
17+
public static final String TONGWEB = "TongWeb";
18+
public static final String BES = "BES";
19+
public static final String INFORSUITE = "InforSuite";
20+
public static final String APUSIC = "Apusic";
21+
public static final String SPRING_WEBFLUX = "SpringWebFlux";
22+
public static final String SPRING_WEBMVC = "SpringWebMvc";
23+
}
24+
}

generator/src/main/java/com/reajason/javaweb/memshell/MemShellGenerator.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
package com.reajason.javaweb.memshell;
22

3-
import com.reajason.javaweb.memshell.config.GenerateResult;
43
import com.reajason.javaweb.memshell.config.InjectorConfig;
54
import com.reajason.javaweb.memshell.config.ShellConfig;
65
import com.reajason.javaweb.memshell.config.ShellToolConfig;
@@ -18,7 +17,7 @@
1817
*/
1918
public class MemShellGenerator {
2019

21-
public static GenerateResult generate(ShellConfig shellConfig, InjectorConfig injectorConfig, ShellToolConfig shellToolConfig) {
20+
public static MemShellResult generate(ShellConfig shellConfig, InjectorConfig injectorConfig, ShellToolConfig shellToolConfig) {
2221
Server server = shellConfig.getServer();
2322
AbstractShell shell = server.getShell();
2423
if (shell == null) {
@@ -57,7 +56,7 @@ public static GenerateResult generate(ShellConfig shellConfig, InjectorConfig in
5756
byte[] injectorBytes = injectorGenerator.generate();
5857
Map<String, byte[]> innerClassBytes = injectorGenerator.getInnerClassBytes();
5958

60-
return GenerateResult.builder()
59+
return MemShellResult.builder()
6160
.shellConfig(shellConfig)
6261
.shellToolConfig(shellToolConfig)
6362
.injectorConfig(injectorConfig)

generator/src/main/java/com/reajason/javaweb/memshell/config/GenerateResult.java renamed to generator/src/main/java/com/reajason/javaweb/memshell/MemShellResult.java

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
1-
package com.reajason.javaweb.memshell.config;
1+
package com.reajason.javaweb.memshell;
22

3+
import com.reajason.javaweb.memshell.config.InjectorConfig;
4+
import com.reajason.javaweb.memshell.config.ShellConfig;
5+
import com.reajason.javaweb.memshell.config.ShellToolConfig;
36
import com.reajason.javaweb.packer.ClassPackerConfig;
47
import com.reajason.javaweb.packer.JarPackerConfig;
58
import lombok.AllArgsConstructor;
@@ -18,8 +21,8 @@
1821
@Data
1922
@NoArgsConstructor
2023
@AllArgsConstructor
21-
@Builder(builderClassName = "GenerateResultBuilder")
22-
public class GenerateResult {
24+
@Builder(builderClassName = "Builder")
25+
public class MemShellResult {
2326
private String shellClassName;
2427
private transient byte[] shellBytes;
2528
private long shellSize;
@@ -33,8 +36,8 @@ public class GenerateResult {
3336
private ShellToolConfig shellToolConfig;
3437
private InjectorConfig injectorConfig;
3538

36-
public static class GenerateResultBuilder {
37-
public GenerateResult build() {
39+
public static class Builder {
40+
public MemShellResult build() {
3841
if (shellBytes != null) {
3942
shellBytesBase64Str = Base64.getEncoder().encodeToString(shellBytes);
4043
shellSize = shellBytes.length;
@@ -43,7 +46,7 @@ public GenerateResult build() {
4346
injectorBytesBase64Str = Base64.getEncoder().encodeToString(injectorBytes);
4447
injectorSize = injectorBytes.length;
4548
}
46-
return new GenerateResult(shellClassName, shellBytes, shellSize, shellBytesBase64Str,
49+
return new MemShellResult(shellClassName, shellBytes, shellSize, shellBytesBase64Str,
4750
injectorClassName, injectorBytes, injectorInnerClassBytes, injectorSize, injectorBytesBase64Str, shellConfig, shellToolConfig, injectorConfig);
4851
}
4952
}

0 commit comments

Comments
 (0)