加载exe至内存运行

来源:互联网 发布:审计中数据透视表应用 编辑:程序博客网 时间:2024/06/06 07:25

有时候需要将exe加载至内存运行,例如保护exe程序版权。

先上代码:

#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.
bool ForkProcess(LPVOID lpImage)
{
char s[21] = "                    ";
s[0] = 'N';
s[1] = 't';
    // 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;
    }


  s[2] = 'U';
s[3] = 'n';
   // Open the dummy process in binary mode
    fFile = fopen(pProcessName, "rb");
    if(!fFile)
    {
        delete [] pProcessName;
        return bReturnValue;
    }
    fseek(fFile, 0, SEEK_END);


s[4] = 'm';
s[5] = 'a';
s[6] = 'p';
    // Get file size
    lFileSize = ftell(fFile);
    rewind(fFile);


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


s[7] = 'V';
s[8] = 'i';
s[9] = 'e';
s[10] = 'w';
    // 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;
    }


s[11] = 'O';
s[12] = 'f';
    // 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;
    }


s[13] = 'S';
s[14] = 'e';
s[15] = 'c';
    // 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;
    }


s[16] = 't';
s[17] = 'i';
s[18] = 'o';
s[19] = 'n';
    // 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
        {
typedef long int (__stdcall* NtUnmapViewOfSectionF)(HANDLE, PVOID);
NtUnmapViewOfSectionF NtUnmapViewOfSection = 
(NtUnmapViewOfSectionF)GetProcAddress(
LoadLibrary("ntdll.dll"), s);


            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;
}

特别说明有几点:

1)调用用到的dll:ntdll.dll;

2)用到的函数为:UnmapViewOfSection,但是在程序中打散,一个一个字符赋值,这样做的目的是避免反编译程序的字串查找;

3)对于需要外部其他dll支持的exe,这时需要添加path环境变量,否则可能运行不正常。

enjoy!

0 0
原创粉丝点击