feat: support command template

This commit is contained in:
ReaJason
2025-12-08 01:43:41 +08:00
parent f1d42a9b3c
commit 544706352a
16 changed files with 253 additions and 82 deletions
@@ -1,6 +1,5 @@
import { ScrollTextIcon } from "lucide-react";
import { useTranslation } from "react-i18next";
import CodeViewer from "@/components/code-viewer";
import { Button } from "@/components/ui/button";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { Separator } from "@/components/ui/separator";
@@ -17,7 +16,6 @@ export function JarResult({
generateResult?: MemShellResult;
}>) {
const { t } = useTranslation();
const isPureJar = packMethod === "Jar";
return (
<Card>
<CardHeader>
@@ -62,7 +62,7 @@ export function OptionalClassFormField({
return (
<Fragment>
<div className="pt-2 flex items-center justify-between gap-3">
<div className="flex items-center gap-2 text-sm">
<div className="flex items-center gap-2 text-sm font-medium">
<Shuffle className="h-4 w-4" />
<span>{t("mainConfig.randomClassName")}</span>
</div>
+101 -59
View File
@@ -1,7 +1,14 @@
import { useQuery } from "@tanstack/react-query";
import { ChevronDown, ChevronRight } from "lucide-react";
import { useState } from "react";
import { FormProvider, type UseFormReturn } from "react-hook-form";
import { useTranslation } from "react-i18next";
import { Card, CardContent } from "@/components/ui/card";
import {
Collapsible,
CollapsibleContent,
CollapsibleTrigger,
} from "@/components/ui/collapsible";
import {
FormControl,
FormField,
@@ -31,6 +38,7 @@ export function CommandTabContent({
shellTypes: Array<string>;
}>) {
const { t } = useTranslation(["memshell", "common"]);
const [isAdvancedOpen, setIsAdvancedOpen] = useState(false);
const { data } = useQuery<{
encryptors: Array<string>;
implementationClasses: Array<string>;
@@ -68,68 +76,102 @@ export function CommandTabContent({
</FormFieldItem>
)}
/>
<div className="grid grid-cols-1 md:grid-cols-2 gap-2">
<FormField
control={form.control}
name="encryptor"
render={({ field }) => (
<FormFieldItem>
<FormFieldLabel>{t("common:encryptor")}</FormFieldLabel>
<Select
onValueChange={field.onChange}
value={field.value}
defaultValue="RAW"
>
<FormControl>
<SelectTrigger>
<SelectValue
placeholder={t("common:placeholders.select")}
/>
</SelectTrigger>
</FormControl>
<SelectContent>
{data?.encryptors?.map((v) => (
<SelectItem key={v} value={v}>
{v}
</SelectItem>
))}
</SelectContent>
</Select>
</FormFieldItem>
<Collapsible open={isAdvancedOpen} onOpenChange={setIsAdvancedOpen}>
<CollapsibleTrigger className="flex items-center gap-2 w-full py-2 text-sm font-medium hover:underline">
{isAdvancedOpen ? (
<ChevronDown className="h-4 w-4" />
) : (
<ChevronRight className="h-4 w-4" />
)}
/>
<FormField
control={form.control}
name="implementationClass"
render={({ field }) => (
<FormFieldItem>
<FormFieldLabel>
{t("common:implementationClass")}
</FormFieldLabel>
<Select
onValueChange={field.onChange}
value={field.value}
defaultValue="RuntimeExec"
>
{t("common:advancedConfig")}
</CollapsibleTrigger>
<CollapsibleContent className="space-y-2 pt-2">
<div className="grid grid-cols-1 md:grid-cols-2 gap-2">
<FormField
control={form.control}
name="encryptor"
render={({ field }) => (
<FormFieldItem>
<FormFieldLabel>{t("common:encryptor")}</FormFieldLabel>
<Select
onValueChange={field.onChange}
value={field.value}
defaultValue="RAW"
>
<FormControl>
<SelectTrigger>
<SelectValue
placeholder={t("common:placeholders.select")}
/>
</SelectTrigger>
</FormControl>
<SelectContent>
{data?.encryptors?.map((v) => (
<SelectItem key={v} value={v}>
{v}
</SelectItem>
))}
</SelectContent>
</Select>
</FormFieldItem>
)}
/>
<FormField
control={form.control}
name="implementationClass"
render={({ field }) => (
<FormFieldItem>
<FormFieldLabel>
{t("common:implementationClass")}
</FormFieldLabel>
<Select
onValueChange={field.onChange}
value={field.value}
defaultValue="RuntimeExec"
>
<FormControl>
<SelectTrigger>
<SelectValue
placeholder={t("common:placeholders.select")}
/>
</SelectTrigger>
</FormControl>
<SelectContent>
{data?.implementationClasses?.map((v) => (
<SelectItem key={v} value={v}>
{v}
</SelectItem>
))}
</SelectContent>
</Select>
</FormFieldItem>
)}
/>
</div>
<FormField
control={form.control}
name="commandTemplate"
render={({ field }) => (
<FormFieldItem>
<FormFieldLabel>
{t("common:commandTemplate")} {t("common:optional")}
</FormFieldLabel>
<FormControl>
<SelectTrigger>
<SelectValue
placeholder={t("common:placeholders.select")}
/>
</SelectTrigger>
<Input
{...field}
placeholder={t("common:commandTemplate.placeholder")}
/>
</FormControl>
<SelectContent>
{data?.implementationClasses?.map((v) => (
<SelectItem key={v} value={v}>
{v}
</SelectItem>
))}
</SelectContent>
</Select>
</FormFieldItem>
)}
/>
</div>
<p className="text-xs text-muted-foreground mt-1">
{t("common:commandTemplate.description")}
</p>
</FormFieldItem>
)}
/>
</CollapsibleContent>
</Collapsible>
<OptionalClassFormField form={form} />
</CardContent>
</Card>
+9
View File
@@ -0,0 +1,9 @@
import { Collapsible as CollapsiblePrimitive } from "radix-ui";
const Collapsible = CollapsiblePrimitive.Root;
const CollapsibleTrigger = CollapsiblePrimitive.CollapsibleTrigger;
const CollapsibleContent = CollapsiblePrimitive.CollapsibleContent;
export { Collapsible, CollapsibleTrigger, CollapsibleContent };
+5 -1
View File
@@ -37,5 +37,9 @@
"version.updateAvailableTooltip": "Click to Open Github Release Page ( v{{currentVersion}} -> v{{latestVersion}})",
"shellTool": "Shell Tool",
"lambdaSuffix": "LambdaSuffix",
"probe": "Probe Mode"
"probe": "Probe Mode",
"advancedConfig": "Advanced Config",
"commandTemplate": "Command Template",
"commandTemplate.placeholder": "e.g., sh -c \"{command}\" 2>&1",
"commandTemplate.description": "Use {command} as placeholder"
}
+5 -1
View File
@@ -37,5 +37,9 @@
"version.updateAvailableTooltip": "点击前往 GitHub Release ( v{{currentVersion}} -> v{{latestVersion}})",
"shellTool": "内存马工具",
"lambdaSuffix": "Lambda 类名后缀",
"probe": "回显模式"
"probe": "回显模式",
"advancedConfig": "高级配置",
"commandTemplate": "命令模板",
"commandTemplate.placeholder": "例如:sh -c \"{command}\" 2>&1",
"commandTemplate.description": "使用 {command} 作为占位符"
}
+2 -1
View File
@@ -9,7 +9,7 @@ export interface ShellConfig {
obfuscate?: boolean;
shrink?: boolean;
probe?: boolean;
lambdaSuffix?:boolean;
lambdaSuffix?: boolean;
}
export interface ShellToolConfig {
@@ -17,6 +17,7 @@ export interface ShellToolConfig {
godzillaPass?: string;
godzillaKey?: string;
commandParamName?: string;
commandTemplate?: string;
behinderPass?: string;
antSwordPass?: string;
headerName?: string;
+1
View File
@@ -20,6 +20,7 @@ export const memShellFormSchema = yup.object({
behinderPass: yup.string().optional(),
antSwordPass: yup.string().optional(),
commandParamName: yup.string().optional(),
commandTemplate: yup.string().optional(),
implementationClass: yup.string().optional(),
headerName: yup.string().optional(),
headerValue: yup.string().optional(),
+2 -1
View File
@@ -20,13 +20,14 @@ export function transformToPostData(formValue: MemShellFormSchema) {
byPassJavaModule: formValue.byPassJavaModule,
shrink: formValue.shrink,
lambdaSuffix: formValue.lambdaSuffix,
probe: formValue.probe
probe: formValue.probe,
};
const shellToolConfig: ShellToolConfig = {
shellClassName: formValue.shellClassName,
godzillaPass: formValue.godzillaPass,
godzillaKey: formValue.godzillaKey,
commandParamName: formValue.commandParamName,
commandTemplate: formValue.commandTemplate,
behinderPass: formValue.behinderPass,
antSwordPass: formValue.antSwordPass,
headerName: formValue.headerName,