diff --git a/c/meterpreter/source/extensions/stdapi/server/sys/process/process.c b/c/meterpreter/source/extensions/stdapi/server/sys/process/process.c index 45f9b233..513ab899 100644 --- a/c/meterpreter/source/extensions/stdapi/server/sys/process/process.c +++ b/c/meterpreter/source/extensions/stdapi/server/sys/process/process.c @@ -29,6 +29,12 @@ typedef BOOL (WINAPI* INITIALIZEPROCTHREADATTRIBUTELIST) ( PSIZE_T lpSize ); +typedef struct _STARTUPINFOEXA +{ + STARTUPINFOA StartupInfo; + LPPROC_THREAD_ATTRIBUTE_LIST lpAttributeList; +} STARTUPINFOEXA, *LPSTARTUPINFOEXA; + const int PROC_THREAD_ATTRIBUTE_PARENT_PROCESS = 0x00020000; /* @@ -114,16 +120,13 @@ DWORD request_sys_process_execute(Remote *remote, Packet *packet) Tlv inMemoryData; BOOL doInMemory = FALSE; PROCESS_INFORMATION pi; - STARTUPINFOW si; - LPPROC_THREAD_ATTRIBUTE_LIST lpAttributeList; + STARTUPINFOEXA si; HANDLE in[2], out[2]; PCHAR path, arguments, commandLine = NULL; - wchar_t *commandLine_w = NULL; - PCHAR cpDesktop = NULL; - wchar_t *cpDesktop_w = NULL; DWORD flags = 0, createFlags = 0, ppid = 0; BOOL inherit = FALSE; HANDLE token, pToken; + char * cpDesktop = NULL; DWORD session = 0; LPVOID pEnvironment = NULL; LPFNCREATEENVIRONMENTBLOCK lpfnCreateEnvironmentBlock = NULL; @@ -135,9 +138,10 @@ DWORD request_sys_process_execute(Remote *remote, Packet *packet) // Initialize the startup information memset( &pi, 0, sizeof(PROCESS_INFORMATION) ); - memset( &si, 0, sizeof(STARTUPINFOW) ); - si.cb = sizeof(STARTUPINFOW); - lpAttributeList = NULL; + memset( &si, 0, sizeof(STARTUPINFOEXA) ); + + si.StartupInfo.cb = sizeof(STARTUPINFO); + si.lpAttributeList = NULL; // Initialize pipe handles in[0] = NULL; @@ -167,25 +171,23 @@ DWORD request_sys_process_execute(Remote *remote, Packet *packet) if (flags & PROCESS_EXECUTE_FLAG_DESKTOP) { - cpDesktop = (char *)malloc(512); - if (!cpDesktop) + do { - result = ERROR_NOT_ENOUGH_MEMORY; - break; - } - memset(cpDesktop, 0, 512); - met_api->lock.acquire(remote->lock); + cpDesktop = (char *)malloc(512); + if (!cpDesktop) + break; - _snprintf(cpDesktop, 512, "%s\\%s", remote->curr_station_name, remote->curr_desktop_name); + memset(cpDesktop, 0, 512); - met_api->lock.release(remote->lock); + met_api->lock.acquire(remote->lock); - if (!(cpDesktop_w = met_api->string.utf8_to_wchar(cpDesktop))) - { - result = ERROR_NOT_ENOUGH_MEMORY; - break; - } - si.lpDesktop = cpDesktop_w; + _snprintf(cpDesktop, 512, "%s\\%s", remote->curr_station_name, remote->curr_desktop_name); + + met_api->lock.release(remote->lock); + + si.StartupInfo.lpDesktop = cpDesktop; + + } while (0); } // If the remote endpoint provided arguments, combine them with the @@ -211,11 +213,6 @@ DWORD request_sys_process_execute(Remote *remote, Packet *packet) result = ERROR_INVALID_PARAMETER; break; } - if (!(commandLine_w = met_api->string.utf8_to_wchar(commandLine))) - { - result = ERROR_NOT_ENOUGH_MEMORY; - 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 @@ -266,10 +263,10 @@ DWORD request_sys_process_execute(Remote *remote, Packet *packet) } // Initialize the startup info to use the pipe handles - si.dwFlags |= STARTF_USESTDHANDLES; - si.hStdInput = in[0]; - si.hStdOutput = out[1]; - si.hStdError = out[1]; + si.StartupInfo.dwFlags |= STARTF_USESTDHANDLES; + si.StartupInfo.hStdInput = in[0]; + si.StartupInfo.hStdOutput = out[1]; + si.StartupInfo.hStdError = out[1]; inherit = TRUE; createFlags |= CREATE_NEW_CONSOLE; @@ -285,8 +282,8 @@ DWORD request_sys_process_execute(Remote *remote, Packet *packet) // If the hidden flag is set, create the process hidden if (flags & PROCESS_EXECUTE_FLAG_HIDDEN) { - si.dwFlags |= STARTF_USESHOWWINDOW; - si.wShowWindow = SW_HIDE; + si.StartupInfo.dwFlags |= STARTF_USESHOWWINDOW; + si.StartupInfo.wShowWindow = SW_HIDE; createFlags |= CREATE_NO_WINDOW; } @@ -312,8 +309,8 @@ DWORD request_sys_process_execute(Remote *remote, Packet *packet) ) { size_t len = 0; InitializeProcThreadAttributeList(NULL, 1, 0, &len); - lpAttributeList = malloc(len); - if (!InitializeProcThreadAttributeList(lpAttributeList, 1, 0, &len)) { + si.lpAttributeList = malloc(len); + if (!InitializeProcThreadAttributeList(si.lpAttributeList, 1, 0, &len)) { printf("[execute] InitializeProcThreadAttributeList: [%d]\n", GetLastError()); result = GetLastError(); break; @@ -321,7 +318,7 @@ DWORD request_sys_process_execute(Remote *remote, Packet *packet) dprintf("[execute] InitializeProcThreadAttributeList\n"); - if (!UpdateProcThreadAttribute(lpAttributeList, 0, PROC_THREAD_ATTRIBUTE_PARENT_PROCESS, &handle, sizeof(HANDLE), 0, 0)) { + if (!UpdateProcThreadAttribute(si.lpAttributeList, 0, PROC_THREAD_ATTRIBUTE_PARENT_PROCESS, &handle, sizeof(HANDLE), 0, 0)) { printf("[execute] UpdateProcThreadAttribute: [%d]\n", GetLastError()); result = GetLastError(); break; @@ -330,6 +327,7 @@ DWORD request_sys_process_execute(Remote *remote, Packet *packet) dprintf("[execute] UpdateProcThreadAttribute\n"); createFlags |= EXTENDED_STARTUPINFO_PRESENT; + si.StartupInfo.cb = sizeof(STARTUPINFOEXA); FreeLibrary(hKernel32Lib); } @@ -383,10 +381,15 @@ DWORD request_sys_process_execute(Remote *remote, Packet *packet) } // Try to execute the process with duplicated token - if (!CreateProcessAsUserW(pToken, NULL, commandLine_w, NULL, NULL, inherit, createFlags, pEnvironment, NULL, &si, &pi)) + wchar_t *commandLine_w = met_api->string.utf8_to_wchar(commandLine); + if (!CreateProcessAsUserW(pToken, NULL, commandLine_w, NULL, NULL, inherit, createFlags, pEnvironment, NULL, (LPSTARTUPINFOW)&si, &pi)) { LPCREATEPROCESSWITHTOKENW pCreateProcessWithTokenW = NULL; HANDLE hAdvapi32 = NULL; + wchar_t * wcmdline = NULL; + wchar_t * wdesktop = NULL; + size_t size = 0; + free(commandLine_w); result = GetLastError(); // sf: If we hit an ERROR_PRIVILEGE_NOT_HELD failure we can fall back to CreateProcessWithTokenW but this is only @@ -400,12 +403,35 @@ DWORD request_sys_process_execute(Remote *remote, Packet *packet) { break; } + pCreateProcessWithTokenW = (LPCREATEPROCESSWITHTOKENW)GetProcAddress(hAdvapi32, "CreateProcessWithTokenW"); if (!pCreateProcessWithTokenW) { break; } - if (!pCreateProcessWithTokenW(pToken, LOGON_NETCREDENTIALS_ONLY, NULL, commandLine_w, createFlags, pEnvironment, NULL, &si, &pi)) + + // convert the multibyte inputs to wide strings (No CreateProcessWithTokenA available unfortunatly)... + size = mbstowcs(NULL, commandLine, 0); + if (size == (size_t)-1) + { + break; + } + + wcmdline = (wchar_t *)malloc((size + 1) * sizeof(wchar_t)); + mbstowcs(wcmdline, commandLine, size); + + if (si.StartupInfo.lpDesktop) + { + size = mbstowcs(NULL, (char *)si.StartupInfo.lpDesktop, 0); + if (size != (size_t)-1) + { + wdesktop = (wchar_t *)malloc((size + 1) * sizeof(wchar_t)); + mbstowcs(wdesktop, (char *)si.StartupInfo.lpDesktop, size); + si.StartupInfo.lpDesktop = (LPSTR)wdesktop; + } + } + + if (!pCreateProcessWithTokenW(pToken, LOGON_NETCREDENTIALS_ONLY, NULL, wcmdline, createFlags, pEnvironment, NULL, (LPSTARTUPINFOW)&si, &pi)) { result = GetLastError(); dprintf("[execute] failed to create the new process via CreateProcessWithTokenW 0x%.8x", result); @@ -420,6 +446,9 @@ DWORD request_sys_process_execute(Remote *remote, Packet *packet) { FreeLibrary(hAdvapi32); } + + SAFE_FREE(wdesktop); + SAFE_FREE(wcmdline); } else { @@ -456,8 +485,10 @@ DWORD request_sys_process_execute(Remote *remote, Packet *packet) if (session_id(GetCurrentProcessId()) == session || !hWtsapi32) { - if (!CreateProcessW(NULL, commandLine_w, NULL, NULL, inherit, createFlags, NULL, NULL, &si, &pi)) + wchar_t *commandLine_w = met_api->string.utf8_to_wchar(commandLine); + if (!CreateProcessW(NULL, commandLine_w, NULL, NULL, inherit, createFlags, NULL, NULL, (LPSTARTUPINFOW)&si, &pi)) { + free(commandLine_w); BREAK_ON_ERROR("[PROCESS] execute in self session: CreateProcessW failed"); } } @@ -473,8 +504,10 @@ DWORD request_sys_process_execute(Remote *remote, Packet *packet) { BREAK_ON_ERROR("[PROCESS] execute in session: WTSQueryUserToken failed"); } - if (!CreateProcessAsUserW(hToken, NULL, commandLine_w, NULL, NULL, inherit, createFlags, NULL, NULL, &si, &pi)) + wchar_t *commandLine_w = met_api->string.utf8_to_wchar(commandLine); + if (!CreateProcessAsUserW(hToken, NULL, commandLine_w, NULL, NULL, inherit, createFlags, NULL, NULL, (LPSTARTUPINFOW)&si, &pi)) { + free(commandLine_w); BREAK_ON_ERROR("[PROCESS] execute in session: CreateProcessAsUser failed"); } } @@ -501,9 +534,11 @@ DWORD request_sys_process_execute(Remote *remote, Packet *packet) else { // Try to execute the process - if (!CreateProcessW(NULL, commandLine_w, NULL, NULL, inherit, createFlags, NULL, NULL, &si, &pi)) + wchar_t *commandLine_w = met_api->string.utf8_to_wchar(commandLine); + if (!CreateProcessW(NULL, commandLine_w, NULL, NULL, inherit, createFlags, NULL, NULL, (LPSTARTUPINFOW)&si, &pi)) { result = GetLastError(); + free(commandLine_w); break; } } @@ -574,24 +609,14 @@ DWORD request_sys_process_execute(Remote *remote, Packet *packet) free(commandLine); } - if (commandLine_w) - { - free(commandLine_w); - } - if (cpDesktop) { free(cpDesktop); } - if (cpDesktop_w) + if (si.lpAttributeList) { - free(cpDesktop_w); - } - - if (lpAttributeList) - { - free(lpAttributeList); + free(si.lpAttributeList); } met_api->packet.transmit_response(result, remote, response);