feat: support appendLambdaSuffix

This commit is contained in:
ReaJason
2025-12-08 01:43:41 +08:00
parent 79c3e0d929
commit 653665e479
13 changed files with 78 additions and 4 deletions
@@ -46,6 +46,11 @@ public class MemShellGenerator {
injectorConfig.setInjectorClassName(CommonUtil.generateInjectorClassName()); injectorConfig.setInjectorClassName(CommonUtil.generateInjectorClassName());
} }
if (shellConfig.isLambdaSuffix()) {
shellToolConfig.setShellClassName(CommonUtil.appendLambdaSuffix(shellToolConfig.getShellClassName()));
injectorConfig.setInjectorClassName(CommonUtil.appendLambdaSuffix(injectorConfig.getInjectorClassName()));
}
byte[] shellBytes = ShellToolFactory.generateBytes(shellConfig, shellToolConfig); byte[] shellBytes = ShellToolFactory.generateBytes(shellConfig, shellToolConfig);
injectorConfig.setInjectorClass(injectorClass); injectorConfig.setInjectorClass(injectorClass);
@@ -61,6 +61,12 @@ public class ShellConfig {
@Builder.Default @Builder.Default
private boolean shrink = false; private boolean shrink = false;
/**
* 追加 Lambda 类名后缀
*/
@Builder.Default
private boolean lambdaSuffix = false;
public boolean isDebugOff() { public boolean isDebugOff() {
return !debug; return !debug;
} }
@@ -15,6 +15,9 @@ public class ProbeShellGenerator {
if (StringUtils.isBlank(probeConfig.getShellClassName())) { if (StringUtils.isBlank(probeConfig.getShellClassName())) {
probeConfig.setShellClassName(CommonUtil.generateInjectorClassName()); probeConfig.setShellClassName(CommonUtil.generateInjectorClassName());
} }
if (probeConfig.isLambdaSuffix()) {
probeConfig.setShellClassName(CommonUtil.appendLambdaSuffix(probeConfig.getShellClassName()));
}
byte[] bytes = probeConfig.getProbeMethod().generateBytes(probeConfig, contentConfig); byte[] bytes = probeConfig.getProbeMethod().generateBytes(probeConfig, contentConfig);
return ProbeShellResult.builder() return ProbeShellResult.builder()
.shellClassName(probeConfig.getShellClassName()) .shellClassName(probeConfig.getShellClassName())
@@ -53,6 +53,12 @@ public class ProbeConfig {
@Builder.Default @Builder.Default
private boolean staticInitialize = false; private boolean staticInitialize = false;
/**
* 追加 Lambda 类名后缀
*/
@Builder.Default
private boolean lambdaSuffix = false;
public boolean isDebugOff() { public boolean isDebugOff() {
return !debug; return !debug;
} }
@@ -101,6 +101,13 @@ public class CommonUtil {
return getRandomPackageName() + "." + INJECTOR_CLASS_NAMES[new Random().nextInt(INJECTOR_CLASS_NAMES.length)]; return getRandomPackageName() + "." + INJECTOR_CLASS_NAMES[new Random().nextInt(INJECTOR_CLASS_NAMES.length)];
} }
public static String appendLambdaSuffix(String className) {
if (className.contains("$Lambda$")) {
return className;
}
return className + "$Proxy0$$Lambda$1";
}
public static String generateShellClassName(String server, String shellType) { public static String generateShellClassName(String server, String shellType) {
String packageName; String packageName;
switch (server) { switch (server) {
@@ -358,7 +358,7 @@ export default function MainConfigCard({
)} )}
/> />
</div> </div>
<div className="flex gap-4 mt-4 flex-col sm:flex-row xl:grid xl:grid-cols-2 2xl:flex 2xl:flex-row"> <div className="flex gap-4 mt-4 flex-col sm:flex-row xl:grid xl:grid-cols-2 2xl:grid 2xl:grid-cols-3">
<FormField <FormField
control={form.control} control={form.control}
name="debug" name="debug"
@@ -391,6 +391,24 @@ export default function MainConfigCard({
</FormItem> </FormItem>
)} )}
/> />
<FormField
control={form.control}
name="lambdaSuffix"
render={({ field }) => (
<FormItem className="flex items-center space-x-2 space-y-0">
<FormControl>
<Switch
id="lambdaSuffix"
checked={field.value}
onCheckedChange={field.onChange}
/>
</FormControl>
<Label htmlFor="lambdaSuffix">
{t("common:lambdaSuffix")}
</Label>
</FormItem>
)}
/>
<FormField <FormField
control={form.control} control={form.control}
name="shrink" name="shrink"
@@ -279,7 +279,7 @@ export default function MainConfigCard({ form, servers }: MainConfigCardProps) {
const SwitchGroup = useMemo( const SwitchGroup = useMemo(
() => ( () => (
<div className="flex gap-4 mt-4 flex-col sm:flex-row"> <div className="flex gap-4 mt-4 flex-col sm:flex-row xl:grid xl:grid-cols-2 2xl:grid 2xl:grid-cols-3">
<FormField <FormField
control={form.control} control={form.control}
name="debug" name="debug"
@@ -312,6 +312,22 @@ export default function MainConfigCard({ form, servers }: MainConfigCardProps) {
</FormItem> </FormItem>
)} )}
/> />
<FormField
control={form.control}
name="lambdaSuffix"
render={({ field }) => (
<FormItem className="flex items-center space-x-2 space-y-0">
<FormControl>
<Switch
id="lambdaSuffix"
checked={field.value}
onCheckedChange={field.onChange}
/>
</FormControl>
<Label htmlFor="lambdaSuffix">{t("common:lambdaSuffix")}</Label>
</FormItem>
)}
/>
<FormField <FormField
control={form.control} control={form.control}
name="shrink" name="shrink"
+3 -1
View File
@@ -35,5 +35,7 @@
"usage": "Usage", "usage": "Usage",
"version.updateAvailable": "Update Available", "version.updateAvailable": "Update Available",
"version.updateAvailableTooltip": "Click to Open Github Release Page ( v{{currentVersion}} -> v{{latestVersion}})", "version.updateAvailableTooltip": "Click to Open Github Release Page ( v{{currentVersion}} -> v{{latestVersion}})",
"shellTool": "Shell Tool" "shellTool": "Shell Tool",
"lambdaSuffix": "LambdaSuffix",
"probe": "Probe Mode"
} }
+3 -1
View File
@@ -35,5 +35,7 @@
"usage": "使用指南", "usage": "使用指南",
"version.updateAvailable": "有可用升级", "version.updateAvailable": "有可用升级",
"version.updateAvailableTooltip": "点击前往 GitHub Release ( v{{currentVersion}} -> v{{latestVersion}})", "version.updateAvailableTooltip": "点击前往 GitHub Release ( v{{currentVersion}} -> v{{latestVersion}})",
"shellTool": "内存马工具" "shellTool": "内存马工具",
"lambdaSuffix": "Lambda 类名后缀",
"probe": "回显模式"
} }
+2
View File
@@ -8,6 +8,8 @@ export interface ShellConfig {
byPassJavaModule?: boolean; byPassJavaModule?: boolean;
obfuscate?: boolean; obfuscate?: boolean;
shrink?: boolean; shrink?: boolean;
probe?: boolean;
lambdaSuffix?:boolean;
} }
export interface ShellToolConfig { export interface ShellToolConfig {
+1
View File
@@ -17,6 +17,7 @@ export interface ProbeConfig {
byPassJavaModule?: boolean; byPassJavaModule?: boolean;
shrink?: boolean; shrink?: boolean;
staticInitialize?: boolean; staticInitialize?: boolean;
lambdaSuffix?: boolean;
} }
export interface ProbeContentConfig { export interface ProbeContentConfig {
+3
View File
@@ -26,6 +26,8 @@ export const memShellFormSchema = yup.object({
injectorClassName: yup.string().optional(), injectorClassName: yup.string().optional(),
packingMethod: yup.string().required().min(1), packingMethod: yup.string().required().min(1),
shrink: yup.boolean().optional(), shrink: yup.boolean().optional(),
lambdaSuffix: yup.boolean().optional(),
probe: yup.boolean().optional(),
shellClassBase64: yup.string().optional(), shellClassBase64: yup.string().optional(),
encryptor: yup.string().optional(), encryptor: yup.string().optional(),
}); });
@@ -165,6 +167,7 @@ export const probeShellFormSchema = yup.object().shape({
byPassJavaModule: yup.boolean().optional(), byPassJavaModule: yup.boolean().optional(),
shrink: yup.boolean().optional(), shrink: yup.boolean().optional(),
staticInitialize: yup.boolean().optional(), staticInitialize: yup.boolean().optional(),
lambdaSuffix: yup.boolean().optional(),
}); });
type ProbeValidationResult = ResolverResult<ProbeShellFormSchema>; type ProbeValidationResult = ResolverResult<ProbeShellFormSchema>;
+3
View File
@@ -19,6 +19,8 @@ export function transformToPostData(formValue: MemShellFormSchema) {
targetJreVersion: formValue.targetJdkVersion, targetJreVersion: formValue.targetJdkVersion,
byPassJavaModule: formValue.byPassJavaModule, byPassJavaModule: formValue.byPassJavaModule,
shrink: formValue.shrink, shrink: formValue.shrink,
lambdaSuffix: formValue.lambdaSuffix,
probe: formValue.probe
}; };
const shellToolConfig: ShellToolConfig = { const shellToolConfig: ShellToolConfig = {
shellClassName: formValue.shellClassName, shellClassName: formValue.shellClassName,
@@ -56,6 +58,7 @@ export function transformToProbePostData(formValue: ProbeShellFormSchema) {
debug: formValue.debug, debug: formValue.debug,
byPassJavaModule: formValue.byPassJavaModule, byPassJavaModule: formValue.byPassJavaModule,
staticInitialize: formValue.staticInitialize, staticInitialize: formValue.staticInitialize,
lambdaSuffix: formValue.lambdaSuffix,
}; };
const probeContentConfig: ProbeContentConfig = { const probeContentConfig: ProbeContentConfig = {
host: formValue.host, host: formValue.host,