feat: support AgentAttacher Packer

This commit is contained in:
ReaJason
2025-05-28 01:22:54 +08:00
parent a3704eb7b7
commit 19faf77d5c
24 changed files with 8361 additions and 11 deletions
@@ -5,6 +5,8 @@ import com.reajason.javaweb.behinder.BehinderManager;
import com.reajason.javaweb.godzilla.GodzillaManager;
import com.reajason.javaweb.memshell.*;
import com.reajason.javaweb.memshell.config.*;
import com.reajason.javaweb.memshell.packer.jar.AgentJarPacker;
import com.reajason.javaweb.memshell.packer.jar.AgentJarWithJREAttacherPacker;
import com.reajason.javaweb.memshell.packer.jar.JarPacker;
import com.reajason.javaweb.suo5.Suo5Manager;
import lombok.SneakyThrows;
@@ -16,6 +18,7 @@ import okhttp3.Request;
import okhttp3.Response;
import org.java_websocket.client.WebSocketClient;
import org.java_websocket.handshake.ServerHandshake;
import org.testcontainers.containers.Container;
import org.testcontainers.containers.GenericContainer;
import org.testcontainers.shaded.org.apache.commons.io.FileUtils;
import org.testcontainers.shaded.org.apache.commons.lang3.RandomStringUtils;
@@ -92,13 +95,12 @@ public class ShellAssertionTool {
@SneakyThrows
public static void packerResultAndInject(GenerateResult generateResult, String url, ShellTool shellTool, String shellType, Packers packer, GenericContainer<?> appContainer) {
String content = null;
if (packer.getInstance() instanceof JarPacker) {
if (packer.getInstance() instanceof AgentJarPacker) {
byte[] bytes = ((JarPacker) packer.getInstance()).packBytes(generateResult);
Path tempJar = Files.createTempFile("temp", "jar");
Files.write(tempJar, bytes);
String jarPath = "/" + shellTool + shellType + packer.name() + ".jar";
appContainer.copyFileToContainer(MountableFile.forHostPath(tempJar, 0100666), jarPath);
// Files.copy(tempJar, Paths.get("target.jar"));
FileUtils.deleteQuietly(tempJar.toFile());
String pidInContainer = appContainer.execInContainer("bash", "/fetch_pid.sh").getStdout();
assertDoesNotThrow(() -> Long.parseLong(pidInContainer));
@@ -108,6 +110,27 @@ public class ShellAssertionTool {
containsString("ATTACH_ACK"),
containsString("JVM response code = 0")
));
} else if (packer.getInstance() instanceof AgentJarWithJREAttacherPacker) {
byte[] bytes = ((JarPacker) packer.getInstance()).packBytes(generateResult);
Path tempJar = Files.createTempFile("temp", "jar");
Files.write(tempJar, bytes);
String jarPath = "/" + shellTool + shellType + packer.name() + ".jar";
appContainer.copyFileToContainer(MountableFile.forHostPath(tempJar, 0100666), jarPath);
FileUtils.deleteQuietly(tempJar.toFile());
String pidInContainer = appContainer.execInContainer("bash", "/fetch_pid.sh").getStdout();
assertDoesNotThrow(() -> Long.parseLong(pidInContainer));
Container.ExecResult execResult = appContainer.execInContainer("java", "-jar", jarPath, pidInContainer);
String stdout = execResult.getStdout();
if (stdout.contains("executable file not found")) {
execResult = appContainer.execInContainer("/opt/IBM/WebSphere/AppServer/java/bin/java", "-jar", jarPath, pidInContainer);
}
stdout = execResult.getStdout();
System.out.println(stdout);
System.out.println(execResult.getStderr());
log.info("attach result: {}", stdout);
assertThat(stdout, anyOf(
containsString("ok")
));
} else {
content = packer.getInstance().pack(generateResult);
assertInjectIsOk(url, shellType, shellTool, content, packer, appContainer);
@@ -19,16 +19,30 @@ import static org.junit.jupiter.params.provider.Arguments.arguments;
*/
public class TestCasesProvider {
public static Stream<Arguments> getTestCases(String imageName, Server server, List<String> testShellTypes, List<Packers> testPackers, List<Triple<String, ShellTool, Packers>> unSupportedCases) {
public static Stream<Arguments> getTestCases(String imageName,
Server server,
List<String> testShellTypes,
List<Packers> testPackers,
List<Triple<String, ShellTool, Packers>> unSupportedCases) {
return getTestCases(imageName, server, testShellTypes, testPackers, unSupportedCases, null);
}
public static Stream<Arguments> getTestCases(String imageName, Server server, List<String> testShellTypes, List<Packers> testPackers, List<Triple<String, ShellTool, Packers>> unSupportedCases, List<ShellTool> unSupportedShellTools) {
public static Stream<Arguments> getTestCases(String imageName,
Server server,
List<String> testShellTypes,
List<Packers> testPackers,
List<Triple<String, ShellTool, Packers>> unSupportedCases,
List<ShellTool> unSupportedShellTools) {
Set<ShellTool> supportedShellTools = new TreeSet<>(server.getShell().getSupportedShellTools());
if (unSupportedShellTools != null) {
unSupportedShellTools.forEach(supportedShellTools::remove);
}
Set<String> unSupported = unSupportedCases == null ? Collections.emptySet() : unSupportedCases.stream().map(i -> i.getLeft() + i.getMiddle() + i.getRight()).collect(Collectors.toSet());
Set<String> unSupported = unSupportedCases == null ?
Collections.emptySet() :
unSupportedCases
.stream()
.map(i -> i.getLeft() + i.getMiddle() + i.getRight())
.collect(Collectors.toSet());
return supportedShellTools.stream()
.flatMap(supportedShellTool -> {
List<String> toolSupportedShellTypes = new ArrayList<>();
@@ -41,7 +55,9 @@ public class TestCasesProvider {
return toolSupportedShellTypes.stream().flatMap(supportedShellType -> {
if (supportedShellType.startsWith(ShellType.AGENT)) {
if (!unSupported.contains(supportedShellType + supportedShellTool + Packers.AgentJar)) {
return Stream.of(arguments(imageName, supportedShellType, supportedShellTool, Packers.AgentJar));
return Stream.of(
arguments(imageName, supportedShellType, supportedShellTool, Packers.AgentJar)
);
}
return Stream.empty();
} else {
@@ -58,7 +74,10 @@ public class TestCasesProvider {
});
}
public static Stream<Arguments> getTestCases(String imageName, Server server, List<String> testShellTypes, List<Packers> testPackers) {
public static Stream<Arguments> getTestCases(String imageName,
Server server,
List<String> testShellTypes,
List<Packers> testPackers) {
return getTestCases(imageName, server, testShellTypes, testPackers, null);
}
}