feat: support fumadocs

This commit is contained in:
ReaJason
2025-12-08 01:43:41 +08:00
parent 8b71ca9911
commit ca1d567ce7
140 changed files with 4788 additions and 1438 deletions
+134
View File
@@ -0,0 +1,134 @@
export interface ShellConfig {
server: string;
serverVersion: string;
shellTool: string;
shellType: string;
targetJreVersion?: string;
debug?: boolean;
byPassJavaModule?: boolean;
obfuscate?: boolean;
shrink?: boolean;
}
export interface ShellToolConfig {
shellClassName?: string;
godzillaPass?: string;
godzillaKey?: string;
commandParamName?: string;
behinderPass?: string;
antSwordPass?: string;
headerName?: string;
headerValue?: string;
shellClassBase64?: string;
encryptor?: string;
implementationClass?: string;
}
export interface CommandShellToolConfig {
shellClassName?: string;
paramName?: string;
}
export interface GodzillaShellToolConfig {
shellClassName?: string;
pass?: string;
key?: string;
headerName?: string;
headerValue?: string;
}
export interface BehinderShellToolConfig {
shellClassName?: string;
pass?: string;
headerName?: string;
headerValue?: string;
}
export interface Suo5ShellToolConfig {
shellClassName?: string;
headerName?: string;
headerValue?: string;
}
export interface AntSwordShellToolConfig {
shellClassName?: string;
pass?: string;
headerName?: string;
headerValue?: string;
}
export interface NeoreGeorgShellToolConfig {
shellClassName?: string;
headerName?: string;
headerValue?: string;
}
export interface InjectorConfig {
injectorClassName?: string;
classInheritance?: string;
urlPattern?: string;
staticInitialize?: boolean;
}
export interface ConfigResponseType {
servers: ServerConfig;
core: MainConfig;
packers: PackerConfig;
}
export interface ServerConfig {
[serverName: string]: Array<string>;
}
export interface MainConfig {
[serverName: string]: {
[toolName: string]: string[];
};
}
export type PackerConfig = Array<string>;
export interface MemShellGenerateResponse {
memShellResult: MemShellResult;
packResult?: string;
allPackResults?: Map<string, string>;
}
export interface APIErrorResponse {
error: string;
}
export interface MemShellResult {
shellClassName: string;
shellSize: number;
shellBytesBase64Str: string;
injectorClassName: string;
injectorSize: number;
injectorBytesBase64Str: string;
shellConfig: ShellConfig;
shellToolConfig:
| CommandShellToolConfig
| GodzillaShellToolConfig
| BehinderShellToolConfig
| AntSwordShellToolConfig;
injectorConfig: InjectorConfig;
}
export const JDKVersion = [
{ name: "Java6", value: "50" },
{ name: "Java8", value: "52" },
{ name: "Java9", value: "53" },
{ name: "Java11", value: "55" },
{ name: "Java17", value: "61" },
{ name: "Java21", value: "65" },
];
export enum ShellToolType {
Behinder = "Behinder",
Godzilla = "Godzilla",
Command = "Command",
AntSword = "AntSword",
Suo5 = "Suo5",
NeoreGeorg = "NeoreGeorg",
Custom = "Custom",
}
+70
View File
@@ -0,0 +1,70 @@
export type ProbeMethod = "ResponseBody" | "DNSLog" | "Sleep";
export type ProbeContent =
| "BasicInfo"
| "Server"
| "OS"
| "JDK"
| "Bytecode"
| "Command";
export interface ProbeConfig {
probeMethod: string;
probeContent: string;
shellClassName?: string;
targetJreVersion?: string;
debug?: boolean;
byPassJavaModule?: boolean;
shrink?: boolean;
staticInitialize?: boolean;
}
export interface ProbeContentConfig {
host?: string;
seconds?: number;
sleepServer?: string;
server?: string;
reqParamName?: string;
}
export interface DNSLogConfig {
host: string;
}
export interface SleepConfig {
server: string;
sleepServer: string;
}
export interface ResponseBodyConfig {
server: string;
reqParamName: string;
}
export interface PayloadFormValues {
probeMethod: ProbeMethod;
probeContent?: ProbeContent;
debug?: boolean;
byPassJavaModule?: boolean;
shrink?: boolean;
host?: string;
server?: string;
reqParamName?: string;
sleepServer?: string;
seconds?: number;
packingMethod: string;
}
export interface ProbeShellGenerateResponse {
probeShellResult: ProbeShellResult;
packResult?: string;
allPackResults?: Map<string, string>;
}
export interface ProbeShellResult {
shellClassName: string;
shellSize: number;
shellBytesBase64Str: string;
probeConfig: ProbeConfig;
probeContentConfig: DNSLogConfig | ResponseBodyConfig | SleepConfig;
}
+237
View File
@@ -0,0 +1,237 @@
import type { TFunction } from "i18next";
import { useCallback } from "react";
import type { FieldErrors, ResolverResult } from "react-hook-form";
import * as yup from "yup";
import { ShellToolType } from "./memshell";
export const memShellFormSchema = yup.object({
server: yup.string().required().min(1),
serverVersion: yup.string().required().min(1),
targetJdkVersion: yup.string().optional(),
debug: yup.boolean().optional(),
byPassJavaModule: yup.boolean().optional(),
staticInitialize: yup.boolean().optional(),
shellClassName: yup.string().optional(),
shellTool: yup.string().required().min(1),
shellType: yup.string().required().min(1),
urlPattern: yup.string().optional(),
godzillaPass: yup.string().optional(),
godzillaKey: yup.string().optional(),
behinderPass: yup.string().optional(),
antSwordPass: yup.string().optional(),
commandParamName: yup.string().optional(),
implementationClass: yup.string().optional(),
headerName: yup.string().optional(),
headerValue: yup.string().optional(),
injectorClassName: yup.string().optional(),
packingMethod: yup.string().required().min(1),
shrink: yup.boolean().optional(),
shellClassBase64: yup.string().optional(),
encryptor: yup.string().optional(),
});
type ValidationResult = ResolverResult<MemShellFormSchema>;
const urlPatternIsNeeded = (shellType: string) => {
if (shellType.startsWith("Agent")) {
return false;
}
return (
shellType.endsWith("Servlet") ||
shellType.endsWith("ControllerHandler") ||
shellType === "HandlerMethod" ||
shellType === "HandlerFunction" ||
shellType.endsWith("WebSocket")
);
};
const isInvalidUrl = (urlPattern: string | undefined) =>
urlPattern === "/" ||
urlPattern === "/*" ||
!urlPattern?.startsWith("/") ||
!urlPattern;
export const useYupValidationResolver = (
validationSchema: yup.ObjectSchema<any>,
t: TFunction,
) =>
useCallback(
async (
data: MemShellFormSchema,
_context: any,
): Promise<ValidationResult> => {
try {
const values = (await validationSchema.validate(data, {
abortEarly: false,
})) as MemShellFormSchema;
const urlPattern: keyof MemShellFormSchema = "urlPattern";
const shellClassBase64: keyof MemShellFormSchema = "shellClassBase64";
const serverVersion: keyof MemShellFormSchema = "serverVersion";
const errors = {} as any;
if (
urlPatternIsNeeded(values?.shellType) &&
isInvalidUrl(values?.urlPattern)
) {
errors[urlPattern] = {
type: "custom",
message: t("memshell:tips.specificUrlPattern"),
};
}
if (
values.shellTool === ShellToolType.Custom &&
!values.shellClassBase64
) {
errors[shellClassBase64] = {
type: "custom",
message: t("memshell:tips.customShellClass"),
};
}
if (
values.server === "TongWeb" &&
values.shellType === "Valve" &&
values.serverVersion === "unknown"
) {
errors[serverVersion] = {
type: "custom",
message: t("memshell:tips.serverVersion"),
};
}
if (
values.server === "Jetty" &&
(values.shellType === "Handler" ||
values.shellType === "JakartaHandler") &&
values.serverVersion === "unknown"
) {
errors[serverVersion] = {
type: "custom",
message: t("memshell:tips.serverVersion"),
};
}
return {
values,
errors,
};
} catch (errors) {
if (errors instanceof yup.ValidationError) {
return {
values: {},
errors: errors.inner.reduce(
(allErrors, currentError) => {
allErrors[currentError.path as keyof MemShellFormSchema] = {
type: currentError.type ?? "validation",
message: currentError.message,
};
return allErrors;
},
{} as FieldErrors<MemShellFormSchema>,
),
};
}
return {
values: {},
errors: {
server: {
type: "unknown",
message: "An unexpected validation error occurred",
},
},
};
}
},
[validationSchema, t],
);
export type MemShellFormSchema = yup.InferType<typeof memShellFormSchema>;
export type ProbeShellFormSchema = yup.InferType<typeof probeShellFormSchema>;
export const probeShellFormSchema = yup.object().shape({
probeMethod: yup.string().required(),
probeContent: yup.string().required(),
shellClassName: yup.string().optional(),
host: yup.string().optional(),
server: yup.string().optional(),
reqParamName: yup.string().optional(),
seconds: yup.number().optional(),
sleepServer: yup.string().optional(),
packingMethod: yup.string().required(),
targetJdkVersion: yup.string().optional(),
debug: yup.boolean().optional(),
byPassJavaModule: yup.boolean().optional(),
shrink: yup.boolean().optional(),
staticInitialize: yup.boolean().optional(),
});
type ProbeValidationResult = ResolverResult<ProbeShellFormSchema>;
export const useYupValidationProbeResolver = (
validationSchema: yup.ObjectSchema<any>,
t: TFunction,
) =>
useCallback(
async (
data: ProbeShellFormSchema,
_context: any,
): Promise<ProbeValidationResult> => {
try {
const values = (await validationSchema.validate(data, {
abortEarly: false,
})) as ProbeShellFormSchema;
const host: keyof ProbeShellFormSchema = "host";
const reqParamName: keyof ProbeShellFormSchema = "reqParamName";
const errors = {} as any;
if (values.probeMethod === "DNSLog" && !values.host) {
errors[host] = {
type: "custom",
message: t("probeshell:tips.dnslog.host.required"),
};
}
if (values.probeMethod === "ResponseBody" && !values.reqParamName) {
errors[reqParamName] = {
type: "custom",
message: t("probeshell:tips.response.reqParamName.required"),
};
}
return {
values,
errors,
};
} catch (errors) {
if (errors instanceof yup.ValidationError) {
return {
values: {},
errors: errors.inner.reduce(
(allErrors, currentError) => {
allErrors[currentError.path as keyof ProbeShellFormSchema] = {
type: currentError.type ?? "validation",
message: currentError.message,
};
console.log(allErrors);
return allErrors;
},
{} as FieldErrors<ProbeShellFormSchema>,
),
};
}
return {
values: {},
errors: {
server: {
type: "unknown",
message: "An unexpected validation error occurred",
},
},
};
}
},
[validationSchema, t],
);