use clap::{Args, Parser, Subcommand};
use crate::enums::list_features::ListFeatures;
use crate::enums::php::{PhpCms, PhpVersion, TemplateVariant};
#[derive(Parser, Debug, Default)]
#[command(author, version, long_about)]
pub struct CliArguments {
#[arg(short, long, global = true, action = clap::ArgAction::Count, default_value = "0", display_order = 0)]
pub debug: u8,
#[command(subcommand)]
pub command: CliCommand,
}
#[derive(Subcommand, Debug, PartialEq, Default)]
pub enum CliCommand {
#[default]
Clone,
FeatureList(CliFeatureListArguments),
Generate(CliGenerateArguments),
}
#[derive(Debug, Args, PartialEq, Default)]
pub struct CliFeatureListArguments {
pub template: ListFeatures,
}
#[derive(Debug, Args, PartialEq, Default)]
pub struct CliGenerateArguments {
#[command(flatten)]
pub obfuscation: CliGenerateObfuscation,
#[command(flatten)]
pub security: CliGenerateSecurity,
#[command(subcommand)]
pub template: CliGenerateCommand,
#[arg(short, long, global = true, display_order = 0)]
pub output: Option<String>,
}
#[derive(Subcommand, Debug, PartialEq)]
#[command(subcommand_value_name = "TEMPLATE")]
pub enum CliGenerateCommand {
Php(CliGeneratePhpTemplate),
}
impl Default for CliGenerateCommand {
fn default() -> Self {
CliGenerateCommand::Php(CliGeneratePhpTemplate::default())
}
}
#[derive(Debug, Args, PartialEq, Default)]
pub struct CliGeneratePhpTemplate {
#[arg(short, long, default_value = "53", display_order = 0, value_enum)]
pub template_version: PhpVersion,
#[arg(long, default_value = "base", display_order = 0, value_enum)]
pub variant: TemplateVariant,
#[arg(long, display_order = 2, value_enum)]
pub cms: Option<PhpCms>,
#[arg(
short,
long,
action = clap::ArgAction::Append,
display_order = 2,
long_help = r#"Define the CMS options to use for the template.
This will pass additional options to the CMS template to customize the generated webshell.
The options are passed as a key-value pair separated by an equal sign, multiple options can
be passed by repeating the flag multiple times.
Each option is useful to disguise the webshell during installation or into the plugin
details views (if self hiding is not available or enabled).
Note that the options are specific to the CMS template and may not be available in all
templates.
WordPress plugin options:
- __PLUGIN_NAME__: Identifies the plugin in the CMS
- __PLUGIN_DESCRIPTION__: Description of the plugin
- __PLUGIN_VERSION__: Version of the plugin
- __PLUGIN_AUTHOR__: Author of the plugin
Joomla plugin options:
- __PLUGIN_NAME__: Identifies the plugin in the CMS
- __PLUGIN_DESCRIPTION__: Description of the plugin
- __CREATION_DATE__: Creation date of the plugin
- __PLUGIN_VERSION__: Version of the plugin
Drupal plugin options:
Currently no options are available
Note:
- Options are not validated and are passed as-is to the template
- Options are not sanitized and may break the generated code if not correctly formatted, try
not to use special characters please
- Options are not required and can be omitted if not needed, in that case random values will be used
Example: `--cms-option key1=value1 --cms-option key2=value`"#
)]
pub cms_option: Vec<String>,
#[arg(long = "no-plugin", overrides_with = "_no_plugin", default_value = "true", action = clap::ArgAction::SetFalse, display_order = 1)]
pub plugin: bool,
#[arg(short = 'p', long = "plugin", overrides_with = "plugin", display_order = 1)]
pub _no_plugin: bool,
#[arg(short, long, default_value = "false", display_order = 1)]
pub standalone: bool,
#[arg(
short = 'F',
long,
default_value = r"\w",
display_order = 1,
long_help = r#"Prefix to use for the functions.
This will prefix all the functions with a generated string, required to avoid conflicts with other
plugins in WordPress and other CMS.
The pattern follows a regex-like syntax:
- `\d` - Random digit
- `\w` - Random word character (uppercase or lowercase letter)
- `\s` - Random special character
- `.` - Random character
- `\\` - Escape sequence
Additionally the pattern can contain repetition fragments enclosed in curly braces:
- `{m}` - Repeat the previous character m times (ONLY IF it is a pattern character)
Any other character is treated as a literal character.
Note: It is strongly un-suggested to provide special characters in the format as the possibility to
break the code is high."#
)]
pub functions_prefix: String,
#[arg(
short,
long,
action = clap::ArgAction::Append,
display_order = 2,
default_value = "all",
long_help = r#"Features to include in the generated webshell.
This will include optional features in the generated webshell, each additional feature will add more code increasing its overall size,
complexity, detectability and functionality.
Note that the features are specific to the template and may not be available in all templates or cms.
To see the available features for the selected template, use the `feature-list [template-language]` command.
Additionally a special feature `all` can be used to include all the available features for the selected template.
"#
)]
pub features: Vec<String>,
#[arg(
short,
long,
action = clap::ArgAction::Append,
display_order = 2,
long_help = r#"Features to exclude from the generated webshell.
This will exclude optional features from the generated webshell, each excluded feature will reduce the overall size,
complexity, detectability and functionality of the webshell.
Note that the features are specific to the template and may not be available in all templates or cms.
This flag is particularly useful when the `all` feature is used to include all the available features but some of them
need to be excluded.
"#
)]
pub exclude_features: Vec<String>,
}
#[derive(Debug, Args, PartialEq, Default)]
pub struct CliGenerateObfuscation {
#[arg(long, global = true, default_value = "false", display_order = 0)]
pub obfuscate: bool,
#[arg(long, global = true, default_value = "false", display_order = 0)]
pub minify: bool,
#[arg(long, global = true, default_value = "false", display_order = 0)]
pub remove_icons: bool,
#[arg(
long,
global = true,
default_value = r"\w{3}",
display_order = 3,
long_help = r#"Format used to generate variable names if obfuscation is enabled.
The pattern follows a regex-like syntax:
- `\d` - Random digit
- `\w` - Random word character (uppercase or lowercase letter)
- `\s` - Random special character
- `.` - Random character
- `\\` - Escape sequence
Additionally the pattern can contain repetition fragments enclosed in curly braces:
- `{m}` - Repeat the previous character m times (ONLY IF it is a pattern character)
Any other character is treated as a literal character.
Note: It is strongly un-suggested to provide special characters in the format as the possibility to
break the code is high."#
)]
pub obfuscation_variable_format: String,
#[arg(
long,
global = true,
default_value = r"\w{3}",
display_order = 3,
long_help = r#"Format used to generate function names if obfuscation is enabled.
The pattern follows a regex-like syntax:
- `\d` - Random digit
- `\w` - Random word character (uppercase or lowercase letter)
- `\s` - Random special character
- `.` - Random character
- `\\` - Escape sequence
Additionally the pattern can contain repetition fragments enclosed in curly braces:
- `{m}` - Repeat the previous character m times (ONLY IF it is a pattern character)
Any other character is treated as a literal character.
Note: It is strongly un-suggested to provide special characters in the format as the possibility to
break the code is high."#
)]
pub obfuscation_function_format: String,
}
#[derive(Debug, Args, PartialEq, Default)]
pub struct CliGenerateSecurity {
#[arg(long, global = true, display_order = 4)]
pub password: Option<String>,
#[arg(long, global = true, default_value = "32", display_order = 4)]
pub password_length: u32,
#[arg(long, global = true, display_order = 4)]
pub username: Option<String>,
#[arg(long, global = true, default_value = "16", display_order = 4)]
pub username_length: u32,
#[arg(long, global = true, display_order = 4)]
pub salt: Option<String>,
#[arg(long, global = true, default_value = "64", display_order = 4)]
pub salt_length: u32,
}