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:
commit
80d73d4d34
@ -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);
|
||||
}
|
||||
|
@ -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 )
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user