内存缓冲区中的CreateProcess()在Windows 7上不起作用

时间:2014-02-05 22:33:34

标签: c++ windows winapi

我正在寻找一段时间来了解如何将exe读入内存并直接从内存中执行。然后我通过了这个非常有用的答案CreateProcess from memory buffer

幸运的是,我发现了一些实现上述想法的代码。经过一些调整,我得到了它的工作。

#include <Windows.h>
#include <stdlib.h>
#include <stdio.h>

void RunFromMemory(unsigned char* pImage,char* pPath)
{
    DWORD dwWritten = 0;
    DWORD dwHeader = 0; 
    DWORD dwImageSize = 0;
    DWORD dwSectionCount = 0;
    DWORD dwSectionSize = 0;
    DWORD firstSection = 0;
    DWORD previousProtection = 0;
    DWORD jmpSize = 0;

    IMAGE_NT_HEADERS INH;
    IMAGE_DOS_HEADER IDH;
    IMAGE_SECTION_HEADER Sections[1000];

    PROCESS_INFORMATION peProcessInformation;
    STARTUPINFO peStartUpInformation;
    CONTEXT pContext;
    SECURITY_ATTRIBUTES secAttrib;

    char* pMemory;
    char* pFile;
    memcpy(&IDH,pImage,sizeof(IDH));
    memcpy(&INH,(void*)((DWORD)pImage+IDH.e_lfanew),sizeof(INH));

    dwImageSize = INH.OptionalHeader.SizeOfImage;
    pMemory = (char*)malloc(dwImageSize);
    memset(pMemory,0,dwImageSize);
    pFile = pMemory;

    dwHeader = INH.OptionalHeader.SizeOfHeaders;
    firstSection = (DWORD)(((DWORD)pImage+IDH.e_lfanew) + sizeof(IMAGE_NT_HEADERS));
    memcpy(Sections,(char*)(firstSection),sizeof(IMAGE_SECTION_HEADER)*INH.FileHeader.NumberOfSections);

    memcpy(pFile,pImage,dwHeader);

    if((INH.OptionalHeader.SizeOfHeaders % INH.OptionalHeader.SectionAlignment)==0)
    {
        jmpSize = INH.OptionalHeader.SizeOfHeaders;
    }
    else
    {
        jmpSize = INH.OptionalHeader.SizeOfHeaders / INH.OptionalHeader.SectionAlignment;
        jmpSize += 1;
        jmpSize *= INH.OptionalHeader.SectionAlignment;
    }

    pFile = (char*)((DWORD)pFile + jmpSize);

    for(dwSectionCount = 0; dwSectionCount < INH.FileHeader.NumberOfSections; dwSectionCount++)
    {
        jmpSize = 0;
        dwSectionSize = Sections[dwSectionCount].SizeOfRawData;
        memcpy(pFile,(char*)(pImage + Sections[dwSectionCount].PointerToRawData),dwSectionSize);

        if((Sections[dwSectionCount].Misc.VirtualSize % INH.OptionalHeader.SectionAlignment)==0)
        {
            jmpSize = Sections[dwSectionCount].Misc.VirtualSize;
        }
        else
        {
            jmpSize = Sections[dwSectionCount].Misc.VirtualSize / INH.OptionalHeader.SectionAlignment;
            jmpSize += 1;
            jmpSize *= INH.OptionalHeader.SectionAlignment;
        }
        pFile = (char*)((DWORD)pFile + jmpSize);
    }


    memset(&peStartUpInformation,0,sizeof(STARTUPINFO));
    memset(&peProcessInformation,0,sizeof(PROCESS_INFORMATION));
    memset(&pContext,0,sizeof(CONTEXT));

    peStartUpInformation.cb = sizeof(peStartUpInformation);
    if(CreateProcess(NULL,pPath,NULL,NULL,false,CREATE_SUSPENDED, NULL,NULL,&peStartUpInformation,&peProcessInformation))
    {

        pContext.ContextFlags = CONTEXT_FULL;
        GetThreadContext(peProcessInformation.hThread,&pContext);
        VirtualProtectEx(peProcessInformation.hProcess,(void*)((DWORD)INH.OptionalHeader.ImageBase),dwImageSize,PAGE_EXECUTE_READWRITE,&previousProtection);
        WriteProcessMemory(peProcessInformation.hProcess,(void*)((DWORD)INH.OptionalHeader.ImageBase),pMemory,dwImageSize,&dwWritten);
        WriteProcessMemory(peProcessInformation.hProcess,(void*)((DWORD)pContext.Ebx + 8),&INH.OptionalHeader.ImageBase,4,&dwWritten);
        pContext.Eax = INH.OptionalHeader.ImageBase + INH.OptionalHeader.AddressOfEntryPoint;
        SetThreadContext(peProcessInformation.hThread,&pContext);
        VirtualProtectEx(peProcessInformation.hProcess,(void*)((DWORD)INH.OptionalHeader.ImageBase),dwImageSize,previousProtection,0);
        ResumeThread(peProcessInformation.hThread);

    }
    else{
        // for debugging
        DWORD er = GetLastError();
        DWORD x = er;
    }
    free(pMemory);
}

int main()
{
    //*********** open file to encrypt ************
    char exe_path[] = "C:\\prog.exe";
    FILE *inFile = fopen(exe_path, "rb");
    fseek(inFile , 0 , SEEK_END);
    unsigned long dwSize = ftell(inFile);
    rewind(inFile);
    unsigned char *lpMemory = (unsigned char*) malloc (sizeof(unsigned char)*dwSize);
    fread(lpMemory,1,dwSize,inFile);
    fclose (inFile);
    //**********************************************


    //********* execute ***********
    RunFromMemory(lpMemory,exe_path);


    return 0;
}

我将一个名为prog.exe的示例程序放入我的C驱动器中,此代码将其读入内存并执行它。此代码在Windows XP上运行良好,但我无法在Windows 7上启动此错误消息。

The application was unable to start correctly (0xc000000c). Click OK to close the application.

我不明白为什么它可以在Windows XP上正常工作但在Windows 7上无法正常工作.Windows 7是否对PE格式或标题应用了一些更改?

提前致谢。如果有人想测试它,请不要忘记将示例文件放在C:\prog.exe或根据需要更改代码中的路径。

1 个答案:

答案 0 :(得分:0)

这是一个重大的黑客,你应该真的避免这样做。如果您想要启动一个新进程,那么使其无问题的唯一保证方法是启动驻留在文件系统中的可执行文件。其他任何东西都是黑客,你不能依赖它在未来工作。