1
mirror of https://github.com/rapid7/metasploit-payloads synced 2024-11-20 14:39:22 +01:00

Merge pull request #701 from smashery/new_cmd_exec

New process launch API
This commit is contained in:
adfoster-r7 2024-10-11 00:23:00 +01:00 committed by GitHub
commit 80d73d4d34
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 348 additions and 119 deletions

View File

@ -105,6 +105,167 @@ DWORD request_sys_process_close(Remote *remote, Packet *packet)
return ERROR_SUCCESS;
}
BOOL needs_quoting(PCHAR str)
{
// Initial value is to need quoting, in case it's an empty arg
BOOL bNeedsQuoting = TRUE;
char* pArgIndex = str;
// Check whether we'll need to quote the argument
while (*pArgIndex != '\0')
{
// The arg is not empty
bNeedsQuoting = FALSE;
if (*pArgIndex == '\v' || *pArgIndex == ' ' || *pArgIndex == '\t')
{
bNeedsQuoting = TRUE;
break;
}
++pArgIndex;
}
return bNeedsQuoting;
}
DWORD get_commandline(Packet *packet, DWORD flags, PCHAR* commandLine)
{
// Check new-style arguments first
DWORD dwTlvIndex = 0;
Tlv argTlv;
char* pArgStart;
char* pArgIndex;
BOOL bNeedsQuoting;
size_t commandLineLength = 0;
size_t commandLineWriteIndex = 0;
PCHAR path, arguments = NULL;
DWORD backslashCount;
if (flags & PROCESS_EXECUTE_FLAG_ARG_ARRAY)
{
path = met_api->packet.get_tlv_value_string(packet, TLV_TYPE_PROCESS_UNESCAPED_PATH);
// Calculate the potential size of our command line.
// The path may need quoting, so two extra chars there, plus null terminator.
commandLineLength = strlen(path) + 3;
// Now look at arguments
while (ERROR_SUCCESS == met_api->packet.enum_tlv(packet, dwTlvIndex++, TLV_TYPE_PROCESS_ARGUMENT, &argTlv))
{
commandLineLength += strlen((char*)argTlv.buffer);
commandLineLength += 3; // Two quotes bookending it, plus a space between the arguments
}
// In the worst case, we've got a lot of backslashes just before a quote character, which will need to double in size.
// So, allocate for the worst-case expansion.
commandLineLength *= 2;
if (!(*commandLine = (PCHAR)malloc(commandLineLength)))
{
return ERROR_NOT_ENOUGH_MEMORY;
}
// Append the path to the command line, possibly quoting, but no escaping
bNeedsQuoting = needs_quoting(path);
if (bNeedsQuoting)
{
(*commandLine)[commandLineWriteIndex++] = '"';
}
strncpy_s((*commandLine) + commandLineWriteIndex, commandLineLength - commandLineWriteIndex, path, strlen(path));
commandLineWriteIndex += strlen(path);
if (bNeedsQuoting)
{
(*commandLine)[commandLineWriteIndex++] = '"';
}
dwTlvIndex = 0;
while (ERROR_SUCCESS == met_api->packet.enum_tlv(packet, dwTlvIndex++, TLV_TYPE_PROCESS_ARGUMENT, &argTlv))
{
if (dwTlvIndex != 0)
{
// Add a space between arguments
(*commandLine)[commandLineWriteIndex++] = ' ';
}
pArgStart = (char*)argTlv.buffer;
bNeedsQuoting = needs_quoting(pArgStart);
// Now build up the command line
pArgIndex = pArgStart;
backslashCount = 0;
if (bNeedsQuoting)
{
(*commandLine)[commandLineWriteIndex++] = '"';
}
while (*pArgIndex != '\0')
{
if (*pArgIndex == '\\')
{
++backslashCount;
}
else
{
if (*pArgIndex == '"')
{
// We've encountered a double quote - if there are any backslashes immediately preceding, double them
for (DWORD i = 0; i < backslashCount; ++i)
{
(*commandLine)[commandLineWriteIndex++] = '\\';
}
// Now actually escape the double-quote
(*commandLine)[commandLineWriteIndex++] = '\\';
}
backslashCount = 0;
}
// Now write out whatever the character was
(*commandLine)[commandLineWriteIndex++] = *pArgIndex;
++pArgIndex;
}
if (bNeedsQuoting)
{
// We're about to add another quote - check for backslash doubling again
for (DWORD i = 0; i < backslashCount; ++i)
{
(*commandLine)[commandLineWriteIndex++] = '\\';
}
(*commandLine)[commandLineWriteIndex++] = '"';
}
}
(*commandLine)[commandLineWriteIndex++] = '\0';
dprintf("[PROCESS] Created command line: %s", *commandLine);
}
else
{
path = met_api->packet.get_tlv_value_string(packet, TLV_TYPE_PROCESS_PATH);
arguments = met_api->packet.get_tlv_value_string(packet, TLV_TYPE_PROCESS_ARGUMENTS);
// If the remote endpoint provided arguments, combine them with the
// executable to produce a command line
if (path && arguments)
{
commandLineLength = strlen(path) + strlen(arguments) + 2;
if (!(*commandLine = (PCHAR)malloc(commandLineLength)))
{
return ERROR_NOT_ENOUGH_MEMORY;
}
_snprintf(*commandLine, commandLineLength, "%s %s", path, arguments);
}
else if (path)
{
*commandLine = path;
}
else
{
return ERROR_INVALID_PARAMETER;
}
dprintf("[PROCESS] Using legacy command line: %s", *commandLine);
}
return ERROR_SUCCESS;
}
/*
* Executes a process using the supplied parameters, optionally creating a
* channel through which output is filtered.
@ -122,7 +283,7 @@ DWORD request_sys_process_execute(Remote *remote, Packet *packet)
PROCESS_INFORMATION pi;
STARTUPINFOEXW si;
HANDLE in[2], out[2];
PCHAR path, arguments, commandLine = NULL;
PCHAR commandLine = NULL;
wchar_t* commandLine_w = NULL;
DWORD flags = 0, createFlags = 0, ppid = 0;
BOOL inherit = FALSE;
@ -158,11 +319,16 @@ DWORD request_sys_process_execute(Remote *remote, Packet *packet)
{
break;
}
// Get the execution arguments
arguments = met_api->packet.get_tlv_value_string(packet, TLV_TYPE_PROCESS_ARGUMENTS);
path = met_api->packet.get_tlv_value_string(packet, TLV_TYPE_PROCESS_PATH);
flags = met_api->packet.get_tlv_value_uint(packet, TLV_TYPE_PROCESS_FLAGS);
// Get the execution command line
result = get_commandline(packet, flags, &commandLine);
if (result != ERROR_SUCCESS)
{
break;
}
ppid = met_api->packet.get_tlv_value_uint(packet, TLV_TYPE_PARENT_PID);
if (met_api->packet.get_tlv(packet, TLV_TYPE_VALUE_DATA, &inMemoryData) == ERROR_SUCCESS)
@ -199,30 +365,6 @@ DWORD request_sys_process_execute(Remote *remote, Packet *packet)
} while (0);
}
// If the remote endpoint provided arguments, combine them with the
// executable to produce a command line
if (path && arguments)
{
size_t commandLineLength = strlen(path) + strlen(arguments) + 2;
if (!(commandLine = (PCHAR)malloc(commandLineLength)))
{
result = ERROR_NOT_ENOUGH_MEMORY;
break;
}
_snprintf(commandLine, commandLineLength, "%s %s", path, arguments);
}
else if (path)
{
commandLine = path;
}
else
{
result = ERROR_INVALID_PARAMETER;
break;
}
// If the channelized flag is set, create a pipe for stdin/stdout/stderr
// such that input can be directed to and from the remote endpoint
if (flags & PROCESS_EXECUTE_FLAG_CHANNELIZED)
@ -610,7 +752,7 @@ DWORD request_sys_process_execute(Remote *remote, Packet *packet)
}
// Free the command line if necessary
if (path && arguments && commandLine)
if (commandLine)
{
free(commandLine);
}

View File

@ -53,6 +53,7 @@
#define PROCESS_EXECUTE_FLAG_USE_THREAD_TOKEN (1 << 3)
#define PROCESS_EXECUTE_FLAG_DESKTOP (1 << 4)
#define PROCESS_EXECUTE_FLAG_SESSION (1 << 5)
#define PROCESS_EXECUTE_FLAG_ARG_ARRAY (1 << 8)
#define TLV_TYPE_BASE_ADDRESS MAKE_CUSTOM_TLV( TLV_META_TYPE_QWORD, TLV_TYPE_EXTENSION_STDAPI, 2000 )
#define TLV_TYPE_ALLOCATION_TYPE MAKE_CUSTOM_TLV( TLV_META_TYPE_UINT, TLV_TYPE_EXTENSION_STDAPI, 2001 )
@ -72,6 +73,9 @@
#define TLV_TYPE_PROCESS_ARCH MAKE_CUSTOM_TLV( TLV_META_TYPE_UINT, TLV_TYPE_EXTENSION_STDAPI, 2306 )
#define TLV_TYPE_PARENT_PID MAKE_CUSTOM_TLV( TLV_META_TYPE_UINT, TLV_TYPE_EXTENSION_STDAPI, 2307 )
#define TLV_TYPE_PROCESS_SESSION MAKE_CUSTOM_TLV( TLV_META_TYPE_UINT, TLV_TYPE_EXTENSION_STDAPI, 2308 )
#define TLV_TYPE_PROCESS_ARCH_NAME MAKE_CUSTOM_TLV( TLV_META_TYPE_STRING, TLV_TYPE_EXTENSION_STDAPI, 2309 )
#define TLV_TYPE_PROCESS_ARGUMENT MAKE_CUSTOM_TLV( TLV_META_TYPE_STRING, TLV_TYPE_EXTENSION_STDAPI, 2310 )
#define TLV_TYPE_PROCESS_UNESCAPED_PATH MAKE_CUSTOM_TLV( TLV_META_TYPE_STRING, TLV_TYPE_EXTENSION_STDAPI, 2311 )
// Driver enum stuff
#define TLV_TYPE_DRIVER_ENTRY MAKE_CUSTOM_TLV( TLV_META_TYPE_GROUP, TLV_TYPE_EXTENSION_STDAPI, 2320 )

View File

@ -199,7 +199,7 @@ public class TLVPacket {
ArrayList values = new ArrayList();
ArrayList indices = (ArrayList) valueMap.get(new Integer(type));
if (indices == null) {
throw new IllegalArgumentException("Cannot find type " + type);
return values;
}
for (int i = 0; i < indices.size(); ++i) {

View File

@ -145,21 +145,23 @@ public interface TLVType {
public static final int TLV_TYPE_ENV_GROUP = TLVPacket.TLV_META_TYPE_GROUP | 1102;
// Process
public static final int TLV_TYPE_BASE_ADDRESS = TLVPacket.TLV_META_TYPE_QWORD | 2000;
public static final int TLV_TYPE_ALLOCATION_TYPE = TLVPacket.TLV_META_TYPE_UINT | 2001;
public static final int TLV_TYPE_PROTECTION = TLVPacket.TLV_META_TYPE_UINT | 2002;
public static final int TLV_TYPE_PROCESS_PERMS = TLVPacket.TLV_META_TYPE_UINT | 2003;
public static final int TLV_TYPE_PROCESS_MEMORY = TLVPacket.TLV_META_TYPE_RAW | 2004;
public static final int TLV_TYPE_ALLOC_BASE_ADDRESS = TLVPacket.TLV_META_TYPE_QWORD | 2005;
public static final int TLV_TYPE_MEMORY_STATE = TLVPacket.TLV_META_TYPE_UINT | 2006;
public static final int TLV_TYPE_MEMORY_TYPE = TLVPacket.TLV_META_TYPE_UINT | 2007;
public static final int TLV_TYPE_ALLOC_PROTECTION = TLVPacket.TLV_META_TYPE_UINT | 2008;
public static final int TLV_TYPE_PID = TLVPacket.TLV_META_TYPE_UINT | 2300;
public static final int TLV_TYPE_PROCESS_NAME = TLVPacket.TLV_META_TYPE_STRING | 2301;
public static final int TLV_TYPE_PROCESS_PATH = TLVPacket.TLV_META_TYPE_STRING | 2302;
public static final int TLV_TYPE_PROCESS_GROUP = TLVPacket.TLV_META_TYPE_GROUP | 2303;
public static final int TLV_TYPE_PROCESS_FLAGS = TLVPacket.TLV_META_TYPE_UINT | 2304;
public static final int TLV_TYPE_PROCESS_ARGUMENTS = TLVPacket.TLV_META_TYPE_STRING | 2305;
public static final int TLV_TYPE_BASE_ADDRESS = TLVPacket.TLV_META_TYPE_QWORD | 2000;
public static final int TLV_TYPE_ALLOCATION_TYPE = TLVPacket.TLV_META_TYPE_UINT | 2001;
public static final int TLV_TYPE_PROTECTION = TLVPacket.TLV_META_TYPE_UINT | 2002;
public static final int TLV_TYPE_PROCESS_PERMS = TLVPacket.TLV_META_TYPE_UINT | 2003;
public static final int TLV_TYPE_PROCESS_MEMORY = TLVPacket.TLV_META_TYPE_RAW | 2004;
public static final int TLV_TYPE_ALLOC_BASE_ADDRESS = TLVPacket.TLV_META_TYPE_QWORD | 2005;
public static final int TLV_TYPE_MEMORY_STATE = TLVPacket.TLV_META_TYPE_UINT | 2006;
public static final int TLV_TYPE_MEMORY_TYPE = TLVPacket.TLV_META_TYPE_UINT | 2007;
public static final int TLV_TYPE_ALLOC_PROTECTION = TLVPacket.TLV_META_TYPE_UINT | 2008;
public static final int TLV_TYPE_PID = TLVPacket.TLV_META_TYPE_UINT | 2300;
public static final int TLV_TYPE_PROCESS_NAME = TLVPacket.TLV_META_TYPE_STRING | 2301;
public static final int TLV_TYPE_PROCESS_PATH = TLVPacket.TLV_META_TYPE_STRING | 2302;
public static final int TLV_TYPE_PROCESS_GROUP = TLVPacket.TLV_META_TYPE_GROUP | 2303;
public static final int TLV_TYPE_PROCESS_FLAGS = TLVPacket.TLV_META_TYPE_UINT | 2304;
public static final int TLV_TYPE_PROCESS_ARGUMENTS = TLVPacket.TLV_META_TYPE_STRING | 2305;
public static final int TLV_TYPE_PROCESS_ARGUMENT = TLVPacket.TLV_META_TYPE_STRING | 2310;
public static final int TLV_TYPE_PROCESS_UNESCAPED_PATH = TLVPacket.TLV_META_TYPE_STRING | 2311;
public static final int TLV_TYPE_IMAGE_FILE = TLVPacket.TLV_META_TYPE_STRING | 2400;
public static final int TLV_TYPE_IMAGE_FILE_PATH = TLVPacket.TLV_META_TYPE_STRING | 2401;

View File

@ -7,32 +7,48 @@ import com.metasploit.meterpreter.TLVType;
import com.metasploit.meterpreter.command.Command;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
public class stdapi_sys_process_execute implements Command {
private static final int PROCESS_EXECUTE_FLAG_CHANNELIZED = (1 << 1);
private static final int PROCESS_EXECUTE_FLAG_ARG_ARRAY = (1 << 8);
private static int pid = 0;
public int execute(Meterpreter meterpreter, TLVPacket request, TLVPacket response) throws Exception {
StringBuilder cmdbuf = new StringBuilder();
String cmd = request.getStringValue(TLVType.TLV_TYPE_PROCESS_PATH);
String argsString = request.getStringValue(TLVType.TLV_TYPE_PROCESS_ARGUMENTS, "");
int flags = request.getIntValue(TLVType.TLV_TYPE_PROCESS_FLAGS);
Process proc;
if ((flags & PROCESS_EXECUTE_FLAG_ARG_ARRAY) != 0) {
String cmd = request.getStringValue(TLVType.TLV_TYPE_PROCESS_UNESCAPED_PATH);
if (cmd.length() == 0) {
return ERROR_FAILURE;
}
cmdbuf.append(cmd);
if (argsString.length() > 0) {
cmdbuf.append(" ");
cmdbuf.append(argsString);
List rawArgs = request.getValues(TLVType.TLV_TYPE_PROCESS_ARGUMENT);
ArrayList<String> args = new ArrayList<String>();
for (int i = 0; i < rawArgs.size(); ++i) {
args.add((String) rawArgs.get(i));
}
proc = execute(cmd, args);
} else {
String cmd = request.getStringValue(TLVType.TLV_TYPE_PROCESS_PATH);
if (cmd.length() == 0) {
return ERROR_FAILURE;
}
String argsString = request.getStringValue(TLVType.TLV_TYPE_PROCESS_ARGUMENTS, "");
StringBuilder cmdbuf = new StringBuilder();
cmdbuf.append(cmd);
if (argsString.length() > 0) {
cmdbuf.append(" ");
cmdbuf.append(argsString);
}
proc = execute(cmdbuf.toString());
}
if (cmd.length() == 0) {
return ERROR_FAILURE;
}
Process proc = execute(cmdbuf.toString());
if ((flags & PROCESS_EXECUTE_FLAG_CHANNELIZED) != 0) {
ProcessChannel channel = new ProcessChannel(meterpreter, proc);
synchronized (stdapi_sys_process_execute.class) {
@ -49,6 +65,15 @@ public class stdapi_sys_process_execute implements Command {
return ERROR_SUCCESS;
}
protected Process execute(String cmd, ArrayList<String> args) throws IOException {
ArrayList<String> cmdAndArgs = new ArrayList<String>();
cmdAndArgs.add(cmd);
cmdAndArgs.addAll(args);
ProcessBuilder builder = new ProcessBuilder(cmdAndArgs);
builder.directory(Loader.getCWD());
return builder.start();
}
protected Process execute(String cmdstr) throws IOException {
Process proc = Runtime.getRuntime().exec(cmdstr);
return proc;

View File

@ -71,6 +71,7 @@ define("PROCESS_EXECUTE_FLAG_HIDDEN", (1 << 0));
define("PROCESS_EXECUTE_FLAG_CHANNELIZED", (1 << 1));
define("PROCESS_EXECUTE_FLAG_SUSPENDED", (1 << 2));
define("PROCESS_EXECUTE_FLAG_USE_THREAD_TOKEN", (1 << 3));
define("PROCESS_EXECUTE_FLAG_ARG_ARRAY", (1 << 8));
# Registry
define("TLV_TYPE_HKEY", TLV_META_TYPE_QWORD | 1000);
@ -99,21 +100,23 @@ define("TLV_TYPE_ENV_GROUP", TLV_META_TYPE_GROUP | 1102);
define("DELETE_KEY_FLAG_RECURSIVE", (1 << 0));
# Process
define("TLV_TYPE_BASE_ADDRESS", TLV_META_TYPE_QWORD | 2000);
define("TLV_TYPE_ALLOCATION_TYPE", TLV_META_TYPE_UINT | 2001);
define("TLV_TYPE_PROTECTION", TLV_META_TYPE_UINT | 2002);
define("TLV_TYPE_PROCESS_PERMS", TLV_META_TYPE_UINT | 2003);
define("TLV_TYPE_PROCESS_MEMORY", TLV_META_TYPE_RAW | 2004);
define("TLV_TYPE_ALLOC_BASE_ADDRESS", TLV_META_TYPE_QWORD | 2005);
define("TLV_TYPE_MEMORY_STATE", TLV_META_TYPE_UINT | 2006);
define("TLV_TYPE_MEMORY_TYPE", TLV_META_TYPE_UINT | 2007);
define("TLV_TYPE_ALLOC_PROTECTION", TLV_META_TYPE_UINT | 2008);
define("TLV_TYPE_PID", TLV_META_TYPE_UINT | 2300);
define("TLV_TYPE_PROCESS_NAME", TLV_META_TYPE_STRING | 2301);
define("TLV_TYPE_PROCESS_PATH", TLV_META_TYPE_STRING | 2302);
define("TLV_TYPE_PROCESS_GROUP", TLV_META_TYPE_GROUP | 2303);
define("TLV_TYPE_PROCESS_FLAGS", TLV_META_TYPE_UINT | 2304);
define("TLV_TYPE_PROCESS_ARGUMENTS", TLV_META_TYPE_STRING | 2305);
define("TLV_TYPE_BASE_ADDRESS", TLV_META_TYPE_QWORD | 2000);
define("TLV_TYPE_ALLOCATION_TYPE", TLV_META_TYPE_UINT | 2001);
define("TLV_TYPE_PROTECTION", TLV_META_TYPE_UINT | 2002);
define("TLV_TYPE_PROCESS_PERMS", TLV_META_TYPE_UINT | 2003);
define("TLV_TYPE_PROCESS_MEMORY", TLV_META_TYPE_RAW | 2004);
define("TLV_TYPE_ALLOC_BASE_ADDRESS", TLV_META_TYPE_QWORD | 2005);
define("TLV_TYPE_MEMORY_STATE", TLV_META_TYPE_UINT | 2006);
define("TLV_TYPE_MEMORY_TYPE", TLV_META_TYPE_UINT | 2007);
define("TLV_TYPE_ALLOC_PROTECTION", TLV_META_TYPE_UINT | 2008);
define("TLV_TYPE_PID", TLV_META_TYPE_UINT | 2300);
define("TLV_TYPE_PROCESS_NAME", TLV_META_TYPE_STRING | 2301);
define("TLV_TYPE_PROCESS_PATH", TLV_META_TYPE_STRING | 2302);
define("TLV_TYPE_PROCESS_GROUP", TLV_META_TYPE_GROUP | 2303);
define("TLV_TYPE_PROCESS_FLAGS", TLV_META_TYPE_UINT | 2304);
define("TLV_TYPE_PROCESS_ARGUMENTS", TLV_META_TYPE_STRING | 2305);
define("TLV_TYPE_PROCESS_ARGUMENT", TLV_META_TYPE_STRING | 2310);
define("TLV_TYPE_PROCESS_UNESCAPED_PATH", TLV_META_TYPE_STRING | 2311);
define("TLV_TYPE_IMAGE_FILE", TLV_META_TYPE_STRING | 2400);
define("TLV_TYPE_IMAGE_FILE_PATH", TLV_META_TYPE_STRING | 2401);
@ -898,21 +901,50 @@ function stdapi_sys_process_execute($req, &$pkt) {
global $channel_process_map, $processes;
my_print("doing execute");
$cmd_tlv = packet_get_tlv($req, TLV_TYPE_PROCESS_PATH);
$args_tlv = packet_get_tlv($req, TLV_TYPE_PROCESS_ARGUMENTS);
$flags_tlv = packet_get_tlv($req, TLV_TYPE_PROCESS_FLAGS);
$cmd = $cmd_tlv['value'];
$args = $args_tlv['value'];
$flags = $flags_tlv['value'];
$options = array();
# If there was no command specified, well, a user sending an empty command
# deserves failure.
my_print("Cmd: $cmd $args");
if (0 > strlen($cmd)) {
return ERROR_FAILURE;
# proc_open can take either a string or an array of strings
# We support both, based on the presence of a flag.
# PHP pre-7.4 doesn't support args-as-arrays
if (($flags & PROCESS_EXECUTE_FLAG_ARG_ARRAY) && version_compare(PHP_VERSION, '7.4.0') >= 0) {
$cmd_tlv = packet_get_tlv($req, TLV_TYPE_PROCESS_UNESCAPED_PATH);
$cmd = $cmd_tlv['value'];
# If there was no command specified, well, a user sending an empty command
# deserves failure.
if (0 > strlen($cmd)) {
return ERROR_FAILURE;
}
$args_tlv = packet_get_all_tlvs($req, TLV_TYPE_PROCESS_ARGUMENT);
$real_cmd = array();
array_push($real_cmd, $cmd);
foreach ($args_tlv as $arg_tlv) {
$arg = $arg_tlv['value'];
array_push($real_cmd, $arg);
}
if (is_windows()) {
$options['bypass_shell'] = true;
}
} else {
$cmd_tlv = packet_get_tlv($req, TLV_TYPE_PROCESS_PATH);
$cmd = $cmd_tlv['value'];
# If there was no command specified, well, a user sending an empty command
# deserves failure.
if (0 > strlen($cmd)) {
return ERROR_FAILURE;
}
$args_tlv = packet_get_tlv($req, TLV_TYPE_PROCESS_ARGUMENTS);
$args = $args_tlv['value'];
$real_cmd = $cmd ." ". $args;
my_print("Cmd: $real_cmd");
}
$real_cmd = $cmd ." ". $args;
$pipe_desc = array(array('pipe','r'), array('pipe','w'));
if (is_windows()) {
@ -924,7 +956,7 @@ function stdapi_sys_process_execute($req, &$pkt) {
# Now that we've got the command built, run it. If it worked, we'll send
# back a handle identifier.
$handle = proc_open($real_cmd, $pipe_desc, $pipes);
$handle = proc_open($real_cmd, $pipe_desc, $pipes, null, null, $options);
if (!is_resource($handle)) {
return ERROR_FAILURE;
}

View File

@ -638,23 +638,25 @@ DELETE_KEY_FLAG_RECURSIVE = (1 << 0)
##
# Process
##
TLV_TYPE_BASE_ADDRESS = TLV_META_TYPE_QWORD | 2000
TLV_TYPE_ALLOCATION_TYPE = TLV_META_TYPE_UINT | 2001
TLV_TYPE_PROTECTION = TLV_META_TYPE_UINT | 2002
TLV_TYPE_PROCESS_PERMS = TLV_META_TYPE_UINT | 2003
TLV_TYPE_PROCESS_MEMORY = TLV_META_TYPE_RAW | 2004
TLV_TYPE_ALLOC_BASE_ADDRESS = TLV_META_TYPE_QWORD | 2005
TLV_TYPE_MEMORY_STATE = TLV_META_TYPE_UINT | 2006
TLV_TYPE_MEMORY_TYPE = TLV_META_TYPE_UINT | 2007
TLV_TYPE_ALLOC_PROTECTION = TLV_META_TYPE_UINT | 2008
TLV_TYPE_PID = TLV_META_TYPE_UINT | 2300
TLV_TYPE_PROCESS_NAME = TLV_META_TYPE_STRING | 2301
TLV_TYPE_PROCESS_PATH = TLV_META_TYPE_STRING | 2302
TLV_TYPE_PROCESS_GROUP = TLV_META_TYPE_GROUP | 2303
TLV_TYPE_PROCESS_FLAGS = TLV_META_TYPE_UINT | 2304
TLV_TYPE_PROCESS_ARGUMENTS = TLV_META_TYPE_STRING | 2305
TLV_TYPE_PROCESS_ARCH = TLV_META_TYPE_UINT | 2306
TLV_TYPE_PARENT_PID = TLV_META_TYPE_UINT | 2307
TLV_TYPE_BASE_ADDRESS = TLV_META_TYPE_QWORD | 2000
TLV_TYPE_ALLOCATION_TYPE = TLV_META_TYPE_UINT | 2001
TLV_TYPE_PROTECTION = TLV_META_TYPE_UINT | 2002
TLV_TYPE_PROCESS_PERMS = TLV_META_TYPE_UINT | 2003
TLV_TYPE_PROCESS_MEMORY = TLV_META_TYPE_RAW | 2004
TLV_TYPE_ALLOC_BASE_ADDRESS = TLV_META_TYPE_QWORD | 2005
TLV_TYPE_MEMORY_STATE = TLV_META_TYPE_UINT | 2006
TLV_TYPE_MEMORY_TYPE = TLV_META_TYPE_UINT | 2007
TLV_TYPE_ALLOC_PROTECTION = TLV_META_TYPE_UINT | 2008
TLV_TYPE_PID = TLV_META_TYPE_UINT | 2300
TLV_TYPE_PROCESS_NAME = TLV_META_TYPE_STRING | 2301
TLV_TYPE_PROCESS_PATH = TLV_META_TYPE_STRING | 2302
TLV_TYPE_PROCESS_GROUP = TLV_META_TYPE_GROUP | 2303
TLV_TYPE_PROCESS_FLAGS = TLV_META_TYPE_UINT | 2304
TLV_TYPE_PROCESS_ARGUMENTS = TLV_META_TYPE_STRING | 2305
TLV_TYPE_PROCESS_ARCH = TLV_META_TYPE_UINT | 2306
TLV_TYPE_PARENT_PID = TLV_META_TYPE_UINT | 2307
TLV_TYPE_PROCESS_ARGUMENT = TLV_META_TYPE_STRING | 2310
TLV_TYPE_PROCESS_UNESCAPED_PATH = TLV_META_TYPE_STRING | 2311
TLV_TYPE_IMAGE_FILE = TLV_META_TYPE_STRING | 2400
TLV_TYPE_IMAGE_FILE_PATH = TLV_META_TYPE_STRING | 2401
@ -724,6 +726,7 @@ PROCESS_EXECUTE_FLAG_SUSPENDED = (1 << 2)
PROCESS_EXECUTE_FLAG_USE_THREAD_TOKEN = (1 << 3)
PROCESS_EXECUTE_FLAG_SUBSHELL = (1 << 6)
PROCESS_EXECUTE_FLAG_PTY = (1 << 7)
PROCESS_EXECUTE_FLAG_ARG_ARRAY = (1 << 8)
PROCESS_ARCH_UNKNOWN = 0
PROCESS_ARCH_X86 = 1
@ -1408,22 +1411,43 @@ def stdapi_sys_process_close(request, response):
@register_function
def stdapi_sys_process_execute(request, response):
cmd = packet_get_tlv(request, TLV_TYPE_PROCESS_PATH)['value']
raw_args = packet_get_tlv(request, TLV_TYPE_PROCESS_ARGUMENTS)
if raw_args:
raw_args = raw_args['value']
else:
raw_args = ""
flags = packet_get_tlv(request, TLV_TYPE_PROCESS_FLAGS)['value']
if len(cmd) == 0:
return ERROR_FAILURE, response
if os.path.isfile('/bin/sh') and (flags & PROCESS_EXECUTE_FLAG_SUBSHELL):
if raw_args:
cmd = cmd + ' ' + raw_args
args = ['/bin/sh', '-c', cmd]
if flags & PROCESS_EXECUTE_FLAG_ARG_ARRAY:
cmd = packet_get_tlv(request, TLV_TYPE_PROCESS_UNESCAPED_PATH)['value']
if len(cmd) == 0:
return ERROR_FAILURE, response
command = [cmd]
for arg in packet_enum_tlvs(request, TLV_TYPE_PROCESS_ARGUMENT):
command.append(arg['value'])
else:
args = [cmd]
args.extend(shlex.split(raw_args))
cmd = packet_get_tlv(request, TLV_TYPE_PROCESS_PATH)['value']
if len(cmd) == 0:
return ERROR_FAILURE, response
# Legacy argument style
arg_string = packet_get_tlv(request, TLV_TYPE_PROCESS_ARGUMENTS)
if arg_string:
arg_string = arg_string['value']
else:
arg_string = ""
cmd_string = cmd + ' ' + arg_string
if sys.platform == 'win32':
command = cmd_string
else:
if arg_string == '':
# Everything was just provided in a single argument. Need to split it out.
command = shlex.split(cmd)
else:
# In case we're not using a subshell:
command = [cmd]
command.extend(shlex.split(arg_string))
if (flags & PROCESS_EXECUTE_FLAG_SUBSHELL) and os.path.isfile('/bin/sh'):
command = ['/bin/sh', '-c', cmd_string]
if (flags & PROCESS_EXECUTE_FLAG_CHANNELIZED):
if has_pty and (flags & PROCESS_EXECUTE_FLAG_PTY):
@ -1434,17 +1458,17 @@ def stdapi_sys_process_execute(request, response):
termios.tcsetattr(master, termios.TCSADRAIN, settings)
except:
pass
proc_h = STDProcess(args, stdin=slave, stdout=slave, stderr=slave, bufsize=0, preexec_fn=os.setsid)
proc_h = STDProcess(command, stdin=slave, stdout=slave, stderr=slave, bufsize=0, preexec_fn=os.setsid)
proc_h.stdin = os.fdopen(master, 'wb')
proc_h.stdout = os.fdopen(master, 'rb')
proc_h.stderr = open(os.devnull, 'rb')
proc_h.ptyfd = slave
else:
proc_h = STDProcess(args, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
proc_h = STDProcess(command, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
proc_h.echo_protection = True
proc_h.start()
else:
proc_h = subprocess.Popen(args, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
proc_h = subprocess.Popen(command, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
proc_h_id = meterpreter.add_process(proc_h)
response += tlv_pack(TLV_TYPE_PID, proc_h.pid)