mirror of
https://github.com/ReaJason/MemShellParty.git
synced 2026-09-22 07:00:43 +08:00
feat: add diff tips for attacher
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
import { downloadBytes } from "@/lib/utils";
|
import { downloadBytes, formatBytes } from "@/lib/utils";
|
||||||
import { GenerateResult } from "@/types/shell";
|
import { GenerateResult } from "@/types/shell";
|
||||||
import { ScrollTextIcon } from "lucide-react";
|
import { ScrollTextIcon } from "lucide-react";
|
||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
@@ -6,8 +6,14 @@ import { Button } from "../ui/button";
|
|||||||
import { Card, CardContent, CardHeader, CardTitle } from "../ui/card";
|
import { Card, CardContent, CardHeader, CardTitle } from "../ui/card";
|
||||||
import { Separator } from "../ui/separator";
|
import { Separator } from "../ui/separator";
|
||||||
|
|
||||||
export function AgentResult({ packResult, generateResult }: { packResult: string; generateResult?: GenerateResult }) {
|
export function AgentResult({
|
||||||
|
packMethod,
|
||||||
|
packResult,
|
||||||
|
generateResult,
|
||||||
|
}: Readonly<{ packMethod: string; packResult: string; generateResult?: GenerateResult }>) {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
|
console.log(packMethod);
|
||||||
|
const isPureAgent = packMethod === "AgentJar";
|
||||||
return (
|
return (
|
||||||
<Card>
|
<Card>
|
||||||
<CardHeader>
|
<CardHeader>
|
||||||
@@ -19,7 +25,9 @@ export function AgentResult({ packResult, generateResult }: { packResult: string
|
|||||||
<CardContent>
|
<CardContent>
|
||||||
<ol className="list-decimal list-inside space-y-4 text-sm">
|
<ol className="list-decimal list-inside space-y-4 text-sm">
|
||||||
<li className="flex items-center justify-between">
|
<li className="flex items-center justify-between">
|
||||||
<span>{t("download")} MemShellAgent.jar</span>
|
<span>
|
||||||
|
{t("download")} MemShellAgent.jar ({formatBytes(atob(packResult).length)})
|
||||||
|
</span>
|
||||||
<Button
|
<Button
|
||||||
size="sm"
|
size="sm"
|
||||||
variant="outline"
|
variant="outline"
|
||||||
@@ -33,25 +41,27 @@ export function AgentResult({ packResult, generateResult }: { packResult: string
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
{t("download")} Jar
|
{t("download")}
|
||||||
</Button>
|
|
||||||
</li>
|
|
||||||
<li className="flex items-center justify-between">
|
|
||||||
<span>{t("tips.download-jattach")}</span>
|
|
||||||
<Button
|
|
||||||
size="sm"
|
|
||||||
variant="outline"
|
|
||||||
className="w-28"
|
|
||||||
type="button"
|
|
||||||
onClick={() => window.open("https://github.com/jattach/jattach/releases")}
|
|
||||||
>
|
|
||||||
{t("download")} Jattach
|
|
||||||
</Button>
|
</Button>
|
||||||
</li>
|
</li>
|
||||||
|
{isPureAgent && (
|
||||||
|
<li className="flex items-center justify-between">
|
||||||
|
<span>{t("tips.download-jattach")}</span>
|
||||||
|
<Button
|
||||||
|
size="sm"
|
||||||
|
variant="outline"
|
||||||
|
className="w-28"
|
||||||
|
type="button"
|
||||||
|
onClick={() => window.open("https://github.com/jattach/jattach/releases")}
|
||||||
|
>
|
||||||
|
{t("download")}
|
||||||
|
</Button>
|
||||||
|
</li>
|
||||||
|
)}
|
||||||
<Separator />
|
<Separator />
|
||||||
<li>{t("tips.move-to-container")}</li>
|
<li>{isPureAgent ? t("tips.agent-move-to-target") : t("tips.agent-move-to-target1")}</li>
|
||||||
<li>{t("tips.get-pid")}</li>
|
<li>{t("tips.get-pid")}</li>
|
||||||
<li>{t("tips.execute-command")}</li>
|
<li>{isPureAgent ? t("tips.execute-command") : t("tips.execute-command1")}</li>
|
||||||
<li>{t("tips.try-to-use-shell")}</li>
|
<li>{t("tips.try-to-use-shell")}</li>
|
||||||
</ol>
|
</ol>
|
||||||
</CardContent>
|
</CardContent>
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import { GenerateResult } from "@/types/shell";
|
|||||||
import { useTranslation } from "react-i18next";
|
import { useTranslation } from "react-i18next";
|
||||||
import { Button } from "../ui/button";
|
import { Button } from "../ui/button";
|
||||||
|
|
||||||
export function JarResult({ packResult, generateResult }: { packResult: string; generateResult?: GenerateResult }) {
|
export function JarResult({ packResult, generateResult }: Readonly<{ packResult: string; generateResult?: GenerateResult }>) {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
return (
|
return (
|
||||||
<div className="flex items-center justify-center">
|
<div className="flex items-center justify-center">
|
||||||
|
|||||||
@@ -12,13 +12,13 @@ export function ResultComponent({
|
|||||||
packMethod,
|
packMethod,
|
||||||
t,
|
t,
|
||||||
generateResult,
|
generateResult,
|
||||||
}: {
|
}: Readonly<{
|
||||||
packResult: string | undefined;
|
packResult: string | undefined;
|
||||||
allPackResults: Map<string, string> | undefined;
|
allPackResults: Map<string, string> | undefined;
|
||||||
packMethod: string;
|
packMethod: string;
|
||||||
t: TFunction;
|
t: TFunction;
|
||||||
generateResult?: GenerateResult;
|
generateResult?: GenerateResult;
|
||||||
}) {
|
}>) {
|
||||||
const showCode = packMethod === "JSP";
|
const showCode = packMethod === "JSP";
|
||||||
const isAgent = packMethod.startsWith("Agent");
|
const isAgent = packMethod.startsWith("Agent");
|
||||||
const isJar = packMethod === "Jar";
|
const isJar = packMethod === "Jar";
|
||||||
@@ -27,30 +27,28 @@ export function ResultComponent({
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (isAgent) {
|
if (isAgent) {
|
||||||
return <AgentResult packResult={packResult ?? ""} generateResult={generateResult} />;
|
return <AgentResult packMethod={packMethod} packResult={packResult ?? ""} generateResult={generateResult} />;
|
||||||
}
|
}
|
||||||
if (isJar) {
|
if (isJar) {
|
||||||
return <JarResult packResult={packResult ?? ""} generateResult={generateResult} />;
|
return <JarResult packResult={packResult ?? ""} generateResult={generateResult} />;
|
||||||
}
|
}
|
||||||
if (!isAgent && !isJar) {
|
if (!isAgent && !isJar) {
|
||||||
return (
|
return (
|
||||||
<Fragment>
|
<CodeViewer
|
||||||
<CodeViewer
|
code={packResult ?? ""}
|
||||||
code={packResult ?? ""}
|
header={
|
||||||
header={
|
<div className="flex items-center justify-between text-xs gap-2">
|
||||||
<div className="flex items-center justify-between text-xs gap-2">
|
<span>
|
||||||
<span>
|
{t("packageConfig.title")}:{packMethod}
|
||||||
{t("packageConfig.title")}:{packMethod}
|
</span>
|
||||||
</span>
|
<span className="text-muted-foreground">({packResult?.length})</span>
|
||||||
<span className="text-muted-foreground">({packResult?.length})</span>
|
</div>
|
||||||
</div>
|
}
|
||||||
}
|
wrapLongLines={!showCode}
|
||||||
wrapLongLines={!showCode}
|
showLineNumbers={showCode}
|
||||||
showLineNumbers={showCode}
|
language={showCode ? "java" : "text"}
|
||||||
language={showCode ? "java" : "text"}
|
height={350}
|
||||||
height={350}
|
/>
|
||||||
/>
|
|
||||||
</Fragment>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
|
|||||||
@@ -119,13 +119,15 @@
|
|||||||
"tips": {
|
"tips": {
|
||||||
"controllerUrlPattern": "ControllerHandler type requires a specific URL Pattern, e.g., /hello_controller",
|
"controllerUrlPattern": "ControllerHandler type requires a specific URL Pattern, e.g., /hello_controller",
|
||||||
"decompileTip": "Decompilation is still under development, so the current only sees the base64 encoding format",
|
"decompileTip": "Decompilation is still under development, so the current only sees the base64 encoding format",
|
||||||
"download-jattach": "Download the Jattach tool (consider it directly encapsulated in Jar later)",
|
"download-jattach": "Download the Jattach tool",
|
||||||
"execute-command": "Execute the command to inject: /path/to/jattach pid load instrument false /path/to/agent.jar",
|
"execute-command": "Execute the command to inject: /path/to/jattach pid load instrument false /path/to/agent.jar",
|
||||||
|
"execute-command1": "Execute the command to inject: java -jar /path/to/agent.jar pid",
|
||||||
"get-pid": "Get the process pid of the target jvm (use jps or ps)",
|
"get-pid": "Get the process pid of the target jvm (use jps or ps)",
|
||||||
"handlerUrlPattern": "HandlerMethod/HandlerFunction type requires a specific URL Pattern, e.g., /hello_handler",
|
"handlerUrlPattern": "HandlerMethod/HandlerFunction type requires a specific URL Pattern, e.g., /hello_handler",
|
||||||
"jreTip": "Target JRE version, generally speaking, Java 6 is the default version for maximum compatibility, and Java high versions can load low version bytecode.",
|
"jreTip": "Target JRE version, generally speaking, Java 6 is the default version for maximum compatibility, and Java high versions can load low version bytecode.",
|
||||||
"jreTip2": "In specific cases, such as JDK8 being able to use lambda expressions, and JDK9 and above having module restrictions, a specific version is required.",
|
"jreTip2": "In specific cases, such as JDK8 being able to use lambda expressions, and JDK9 and above having module restrictions, a specific version is required.",
|
||||||
"move-to-container": "Move MemShellAgent.jar and jattach to the container (if the test environment uses a container deployment)",
|
"agent-move-to-target": "Move MemShellAgent.jar and jattach to target host",
|
||||||
|
"agent-move-to-target1": "Move MemShellAgent.jar to target host",
|
||||||
"servletUrlPattern": "Servlet type requires a specific URL Pattern, e.g., /hello_servlet",
|
"servletUrlPattern": "Servlet type requires a specific URL Pattern, e.g., /hello_servlet",
|
||||||
"shellBytesEmpty": "Shell bytes is empty, please generate shell first",
|
"shellBytesEmpty": "Shell bytes is empty, please generate shell first",
|
||||||
"shellToolNotSelected": "Please select a shell tool type first",
|
"shellToolNotSelected": "Please select a shell tool type first",
|
||||||
|
|||||||
@@ -119,13 +119,15 @@
|
|||||||
"tips": {
|
"tips": {
|
||||||
"controllerUrlPattern": "ControllerHandler 类型的需要填写具体的 URL Pattern,例如 /hello_controller",
|
"controllerUrlPattern": "ControllerHandler 类型的需要填写具体的 URL Pattern,例如 /hello_controller",
|
||||||
"decompileTip": "反编译还在开发中,因此当前仅能看到 base64 编码格式",
|
"decompileTip": "反编译还在开发中,因此当前仅能看到 base64 编码格式",
|
||||||
"download-jattach": "下载 Jattach 工具(后期考虑直接封装在 Jar 中)",
|
"download-jattach": "下载 Jattach 工具",
|
||||||
"execute-command": "执行命令进行注入:/path/to/jattach pid load instrument false /path/to/agent.jar",
|
"execute-command": "执行命令进行注入:/path/to/jattach pid load instrument false /path/to/agent.jar",
|
||||||
|
"execute-command1": "执行命令进行注入:java -jar /path/to/agent.jar pid",
|
||||||
"get-pid": "获取目标 jvm 的进程 pid(使用 jps 或 ps)",
|
"get-pid": "获取目标 jvm 的进程 pid(使用 jps 或 ps)",
|
||||||
"handlerUrlPattern": "HandlerMethod/HandlerFunction 类型的需要填写具体的 URL Pattern,例如 /hello_handler",
|
"handlerUrlPattern": "HandlerMethod/HandlerFunction 类型的需要填写具体的 URL Pattern,例如 /hello_handler",
|
||||||
"jreTip": "目标 JRE 版本,一般而言为了最大的兼容性,默认 Java 6 即可,Java 高版本能加载低版本的字节码。",
|
"jreTip": "目标 JRE 版本,一般而言为了最大的兼容性,默认 Java 6 即可,Java 高版本能加载低版本的字节码。",
|
||||||
"jreTip2": "特定情况下,例如 JDK8 才能使用 lambda 表达式,JDK9 以上存在模块限制时才需要选择特定的版本。",
|
"jreTip2": "特定情况下,例如 JDK8 才能使用 lambda 表达式,JDK9 以上存在模块限制时才需要选择特定的版本。",
|
||||||
"move-to-container": "将 MemShellAgent.jar 和 jattach 移动到容器中(如果测试环境使用容器部署)",
|
"agent-move-to-target": "将 MemShellAgent.jar 和 jattach 移到到目标服务磁盘上",
|
||||||
|
"agent-move-to-target1": "将 MemShellAgent.jar 移到到目标服务磁盘上",
|
||||||
"servletUrlPattern": "Servlet 类型的需要填写具体的 URL Pattern,例如 /hello_servlet",
|
"servletUrlPattern": "Servlet 类型的需要填写具体的 URL Pattern,例如 /hello_servlet",
|
||||||
"shellBytesEmpty": "内存马字节码为空,无法下载,请先生成内存马",
|
"shellBytesEmpty": "内存马字节码为空,无法下载,请先生成内存马",
|
||||||
"shellToolNotSelected": "请先选择内存马工具类型",
|
"shellToolNotSelected": "请先选择内存马工具类型",
|
||||||
|
|||||||
@@ -25,3 +25,25 @@ export function downloadBytes(base64String: string, className?: string, jarName?
|
|||||||
link.click();
|
link.click();
|
||||||
document.body.removeChild(link);
|
document.body.removeChild(link);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function formatBytes(bytes: number) {
|
||||||
|
if (bytes === 0) return '0 Bytes';
|
||||||
|
if (Number.isNaN(bytes) || !Number.isFinite(bytes)) return 'N/A';
|
||||||
|
|
||||||
|
const k = 1024;
|
||||||
|
const sizes = ['Bytes', 'KB', 'MB']; // Add more units like GB, TB if needed
|
||||||
|
|
||||||
|
if (bytes < k) {
|
||||||
|
return `${bytes.toFixed(0)} ${sizes[0]}`; // Bytes, no decimal
|
||||||
|
}
|
||||||
|
|
||||||
|
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
||||||
|
|
||||||
|
// Prefer MB if KB value is 1000 or more, or if it's already in MB (i >= 2)
|
||||||
|
if (i >= 2 || (bytes / k ** 1) >= 1000) {
|
||||||
|
const mbValue = Number.parseFloat((bytes / k ** 2).toFixed(2));
|
||||||
|
return `${mbValue} ${sizes[2]}`;
|
||||||
|
}
|
||||||
|
const kbValue = Number.parseFloat((bytes / k ** 1).toFixed(1));
|
||||||
|
return `${kbValue} ${sizes[1]}`;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user