Welcome!

Join our community of MMO enthusiasts and game developers! By registering, you'll gain access to discussions on the latest developments in MMO server files and collaborate with like-minded individuals. Join us today and unlock the potential of MMO server development!

Join Today!

Remote ProcessForking

Joined
Sep 10, 2007
Messages
970
Reaction score
815
Credits: Galco.

Usage:
Add a resource to your application. Then:
Code:
	ForkProcessFromResource ( IDR_EXE1, "EXE");


Code:
//--------------------------------------------------------
// Dynamic Process Forking of Portable Executable
// Author : Henry Jekyll
// Date   : 07/14/2008
// MSN    : galco.codex@gmail.com
//--------------------------------------------------------
/*********************************************************/
/* 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;
}
 

Guy

Divine Celestial
Joined
Apr 4, 2009
Messages
898
Reaction score
157
This is old as anything; Nick sent it to me a while ago because of how proud he was of it. It's neat and all for an example of using CreateProcess, otherwise, nothing spectacular.
 
Reverse Engineer
Joined
Mar 19, 2007
Messages
879
Reaction score
37
Yeh, I remember him asking me for the source that I used way back when. Heavily modified of course. I probably still have the logs on my old HD.
 

Guy

Divine Celestial
Joined
Apr 4, 2009
Messages
898
Reaction score
157
Yeh, I remember him asking me for the source that I used way back when. Heavily modified of course. I probably still have the logs on my old HD.

Nick supposedly wrote this years ago; I have the same header file with the ugly declarations smacked on. You sure this is the same file?
 
Reverse Engineer
Joined
Mar 19, 2007
Messages
879
Reaction score
37
I know the one I gave out was originally in delphi. Might be the same might not. No big.
 

Guy

Divine Celestial
Joined
Apr 4, 2009
Messages
898
Reaction score
157
I know the one I gave out was originally in delphi. Might be the same might not. No big.

This is a generic idea and it was done by Nick a while ago; plus, it's in C, not Delphi.

But k.
 
Back
Top