我有一个可执行文件A.exe,我现在编写另外一个执行程序B.exe,我将A.exe这个文件以数据的方式放到B工程的资源里,当B.exe执行时将资源里的A.exe数据读取出来放在内存里,然后直接执行这个A.exe,当然,我们可以将内存里的这段数据写到硬盘上产生一个临时的可执行文件,然后再执行它是一定没问题的,但我不希望这段数据写到硬盘,而是要直接在内存中执行,有办法实现吗?我想过用用内存虚拟磁盘的办法,但那太复杂,而且我的A.exe文件写到虚拟磁盘上同样存在安全隐患。请大侠帮忙看看

解决方案 »

  1.   

    CreateFileMapping、MapViewOfFile将B进行映射,然后获取B的入口函数执行。
      

  2.   

    http://www.cppblog.com/eday/archive/2007/01/19/17801.html
    http://hi.baidu.com/dnpf/blog/item/9789247f784c2f0c28388aa3.html
      

  3.   


    我拷贝了网页里的代码测试了一下,启动不了exe程序。
      

  4.   

    搞定,代码贴出来与大家共勉:#include "StdAfx.h"
    #include "RunExeInMem.h"TCHAR g_szHostExeFileName[MAX_PATH] = {0};
    TCHAR g_szDefDir[MAX_PATH] = {0};struct PE_Header 
    {
    unsigned long signature;
    unsigned short machine;
    unsigned short numSections;
    unsigned long timeDateStamp;
    unsigned long pointerToSymbolTable;
    unsigned long numOfSymbols;
    unsigned short sizeOfOptionHeader;
    unsigned short characteristics;
    };struct PE_ExtHeader
    {
    unsigned short magic;
    unsigned char majorLinkerVersion;
    unsigned char minorLinkerVersion;
    unsigned long sizeOfCode;
    unsigned long sizeOfInitializedData;
    unsigned long sizeOfUninitializedData;
    unsigned long addressOfEntryPoint;
    unsigned long baseOfCode;
    unsigned long baseOfData;
    unsigned long imageBase;
    unsigned long sectionAlignment;
    unsigned long fileAlignment;
    unsigned short majorOSVersion;
    unsigned short minorOSVersion;
    unsigned short majorImageVersion;
    unsigned short minorImageVersion;
    unsigned short majorSubsystemVersion;
    unsigned short minorSubsystemVersion;
    unsigned long reserved1;
    unsigned long sizeOfImage;
    unsigned long sizeOfHeaders;
    unsigned long checksum;
    unsigned short subsystem;
    unsigned short DLLCharacteristics;
    unsigned long sizeOfStackReserve;
    unsigned long sizeOfStackCommit;
    unsigned long sizeOfHeapReserve;
    unsigned long sizeOfHeapCommit;
    unsigned long loaderFlags;
    unsigned long numberOfRVAAndSizes;
    unsigned long exportTableAddress;
    unsigned long exportTableSize;
    unsigned long importTableAddress;
    unsigned long importTableSize;
    unsigned long resourceTableAddress;
    unsigned long resourceTableSize;
    unsigned long exceptionTableAddress;
    unsigned long exceptionTableSize;
    unsigned long certFilePointer;
    unsigned long certTableSize;
    unsigned long relocationTableAddress;
    unsigned long relocationTableSize;
    unsigned long debugDataAddress;
    unsigned long debugDataSize;
    unsigned long archDataAddress;
    unsigned long archDataSize;
    unsigned long globalPtrAddress;
    unsigned long globalPtrSize;
    unsigned long TLSTableAddress;
    unsigned long TLSTableSize;
    unsigned long loadConfigTableAddress;
    unsigned long loadConfigTableSize;
    unsigned long boundImportTableAddress;
    unsigned long boundImportTableSize;
    unsigned long importAddressTableAddress;
    unsigned long importAddressTableSize;
    unsigned long delayImportDescAddress;
    unsigned long delayImportDescSize;
    unsigned long COMHeaderAddress;
    unsigned long COMHeaderSize;
    unsigned long reserved2;
    unsigned long reserved3;
    };
    struct SectionHeader
    {
    unsigned char sectionName[8];
    unsigned long virtualSize;
    unsigned long virtualAddress;
    unsigned long sizeOfRawData;
    unsigned long pointerToRawData;
    unsigned long pointerToRelocations;
    unsigned long pointerToLineNumbers;
    unsigned short numberOfRelocations;
    unsigned short numberOfLineNumbers;
    unsigned long characteristics;
    };struct MZHeader
    {
    unsigned short signature;
    unsigned short partPag;
    unsigned short pageCnt;
    unsigned short reloCnt;
    unsigned short hdrSize;
    unsigned short minMem;
    unsigned short maxMem;
    unsigned short reloSS;
    unsigned short exeSP;
    unsigned short chksum;
    unsigned short exeIP;
    unsigned short reloCS;
    unsigned short tablOff;
    unsigned short overlay;
    unsigned char reserved[32];
    unsigned long offsetToPE;
    };
    struct ImportDirEntry
    {
    DWORD importLookupTable;
    DWORD timeDateStamp;
    DWORD fowarderChain;
    DWORD nameRVA;
    DWORD importAddressTable;
    };
    //**********************************************************************************************************
    //
    // This function reads the MZ, PE, PE extended and Section Headers from an EXE file.
    //
    //**********************************************************************************************************BOOL readPEInfo( BYTE *pFileData, int nFileSize, MZHeader *outMZ, PE_Header *outPE, PE_ExtHeader *outpeXH,
    SectionHeader **outSecHdr)
    {
    if(nFileSize < sizeof(MZHeader))
    {
    HwDbgLog ( L_DEBUG, _T("File size too small ") );
    return FALSE;
    } BYTE *pFilePos = pFileData;
    // read MZ Header
    MZHeader mzH;
    memcpy ( &mzH, pFilePos, sizeof(MZHeader) );
    pFilePos += sizeof(MZHeader); if(mzH.signature != 0x5a4d)        // MZ
    {
    Log( L_WARNING, _T("File does not have MZ header ") );
    return FALSE;
    } HwDbgLog ( L_DEBUG, _T("Offset to PE Header = %X"), mzH.offsetToPE ); if((unsigned long)nFileSize < mzH.offsetToPE + sizeof(PE_Header))
    {
    Log ( L_WARNING, _T("File size too small ") );       
    return FALSE;
    } // read PE Header
    pFilePos = pFileData + mzH.offsetToPE;
    PE_Header peH;
    memcpy ( &peH, pFilePos, sizeof(PE_Header) );
    pFilePos += sizeof(PE_Header); HwDbgLog ( L_DEBUG, _T("Size of option header = %d"), peH.sizeOfOptionHeader );
    HwDbgLog ( L_DEBUG, _T("Number of sections = %d"), peH.numSections );
    if ( peH.sizeOfOptionHeader != sizeof(PE_ExtHeader) )
    {
    HwDbgLog ( L_DEBUG, _T("Unexpected option header size. ") );
    return FALSE;
    } // read PE Ext Header
    PE_ExtHeader peXH;
    memcpy ( &peXH, pFilePos, sizeof(PE_ExtHeader) );
    pFilePos += sizeof(PE_ExtHeader); HwDbgLog ( L_DEBUG, _T("Import table address = %X "), peXH.importTableAddress );
    HwDbgLog ( L_DEBUG, _T("Import table size = %X "), peXH.importTableSize );
    HwDbgLog ( L_DEBUG, _T("Import address table address = %X "), peXH.importAddressTableAddress );
    HwDbgLog ( L_DEBUG, _T("Import address table size = %X "), peXH.importAddressTableSize );
    // read the sections
    SectionHeader *secHdr = new SectionHeader[peH.numSections];
    memcpy ( secHdr, pFilePos, sizeof(SectionHeader) * peH.numSections );
    pFilePos += sizeof(SectionHeader) * peH.numSections; *outMZ = mzH;
    *outPE = peH;
    *outpeXH = peXH;
    *outSecHdr = secHdr; return TRUE;
    }
    //**********************************************************************************************************
    //
    // This function calculates the size required to load an EXE into memory with proper alignment.
    //
    //**********************************************************************************************************int calcTotalImageSize(MZHeader *inMZ, PE_Header *inPE, PE_ExtHeader *inpeXH,
       SectionHeader *inSecHdr)
    {
    int result = 0;
    int alignment = inpeXH->sectionAlignment; if(inpeXH->sizeOfHeaders % alignment == 0)
    result += inpeXH->sizeOfHeaders;
    else
    {
    int val = inpeXH->sizeOfHeaders / alignment;
    val++;
    result += (val * alignment);
    }
    for(int i = 0; i < inPE->numSections; i++)
    {
    if(inSecHdr[i].virtualSize)
    {
    if(inSecHdr[i].virtualSize % alignment == 0)
    result += inSecHdr[i].virtualSize;
    else
    {
    int val = inSecHdr[i].virtualSize / alignment;
    val++;
    result += (val * alignment);
    }
    }
    }
      

  5.   

    return result;
    }
    //**********************************************************************************************************
    //
    // This function calculates the aligned size of a section
    //
    //**********************************************************************************************************unsigned long getAlignedSize(unsigned long curSize, unsigned long alignment)
    {    
    if(curSize % alignment == 0)
    return curSize;
    else
    {
    int val = curSize / alignment;
    val++;
    return (val * alignment);
    }
    }
    //**********************************************************************************************************
    //
    // This function loads a PE file into memory with proper alignment.
    // Enough memory must be allocated at ptrLoc.
    //
    //**********************************************************************************************************BOOL loadPE ( BYTE *pFileData, int nFileSize, MZHeader *inMZ, PE_Header *inPE, PE_ExtHeader *inpeXH,
    SectionHeader *inSecHdr, LPVOID ptrLoc)
    {
    BYTE *pFilePos = pFileData;
    char *outPtr = (char *)ptrLoc; unsigned long headerSize = inpeXH->sizeOfHeaders; // certain PE files have sectionHeaderSize value > size of PE file itself.  
    // this loop handles this situation by find the section that is nearest to the
    // PE header. for(int i = 0; i < inPE->numSections; i++)
    {
    if(inSecHdr[i].pointerToRawData < headerSize)
    headerSize = inSecHdr[i].pointerToRawData;
    } // read the PE header
    unsigned long readSize = (unsigned long)__min(headerSize, (unsigned long)nFileSize);
    memcpy ( outPtr, pFilePos, readSize );
    pFilePos += readSize;
    HwDbgLog ( L_DEBUG, _T("HeaderSize = %d "), headerSize);
    if(readSize != headerSize)
    {
    Log ( L_WARNING, _T("Error reading headers (%d %d)"), readSize, headerSize);
    return FALSE;
    } outPtr += getAlignedSize(inpeXH->sizeOfHeaders, inpeXH->sectionAlignment); // read the sections
    for(i = 0; i < inPE->numSections; i++)
    {
    if(inSecHdr[i].sizeOfRawData > 0)
    {
    unsigned long toRead = inSecHdr[i].sizeOfRawData;
    if(toRead > inSecHdr[i].virtualSize)
    toRead = inSecHdr[i].virtualSize; pFilePos = pFileData + inSecHdr[i].pointerToRawData;
    readSize = __min ( toRead, nFileSize-inSecHdr[i].pointerToRawData );
    memcpy ( outPtr, pFilePos, readSize );
    if ( readSize != toRead )
    {
    Log ( L_WARNING, _T("Error reading section %d"), i );
    return FALSE;
    }
    outPtr += getAlignedSize(inSecHdr[i].virtualSize, inpeXH->sectionAlignment);
    }
    else
    {
    // this handles the case where the PE file has an empty section. E.g. UPX0 section
    // in UPXed files.
    if ( inSecHdr[i].virtualSize )
    outPtr += getAlignedSize(inSecHdr[i].virtualSize, inpeXH->sectionAlignment);
    }
    } return TRUE;
    }struct FixupBlock
    {
    unsigned long pageRVA;
    unsigned long blockSize;
    };
    //**********************************************************************************************************
    //
    // This function loads a PE file into memory with proper alignment.
    // Enough memory must be allocated at ptrLoc.
    //
    //**********************************************************************************************************void doRelocation(MZHeader *inMZ, PE_Header *inPE, PE_ExtHeader *inpeXH,
      SectionHeader *inSecHdr, LPVOID ptrLoc, DWORD newBase)
    {
    if(inpeXH->relocationTableAddress && inpeXH->relocationTableSize)
    {
    FixupBlock *fixBlk = (FixupBlock *)((char *)ptrLoc + inpeXH->relocationTableAddress);
    long delta = newBase - inpeXH->imageBase; while(fixBlk->blockSize)
    {
    HwDbgLog ( L_DEBUG, _T("Addr = %X"), fixBlk->pageRVA);
    HwDbgLog ( L_DEBUG, _T("Size = %X"), fixBlk->blockSize); int numEntries = (fixBlk->blockSize - sizeof(FixupBlock)) >> 1;
    HwDbgLog ( L_DEBUG, _T("Num Entries = %d"), numEntries); unsigned short *offsetPtr = (unsigned short *)(fixBlk + 1); for(int i = 0; i < numEntries; i++)
    {
    DWORD *codeLoc = (DWORD *)((char *)ptrLoc + fixBlk->pageRVA + (*offsetPtr & 0x0FFF)); int relocType = (*offsetPtr & 0xF000) >> 12; HwDbgLog ( L_DEBUG, _T("Val = %X"), *offsetPtr);
    HwDbgLog ( L_DEBUG, _T("Type = %X"), relocType); if(relocType == 3)
    *codeLoc = ((DWORD)*codeLoc) + delta;
    else
    {
    Log ( L_WARNING, _T("Unknown relocation type = %d"), relocType );
    }
    offsetPtr++;
    }
    fixBlk = (FixupBlock *)offsetPtr;
    }
    }    
    }typedef struct _PROCINFO
    {
    DWORD baseAddr;
    DWORD imageSize;
    } PROCINFO;//**********************************************************************************************************
    //
    // Creates the original EXE in suspended mode and returns its info in the PROCINFO structure.
    //
    //**********************************************************************************************************
    BOOL createChild(PPROCESS_INFORMATION pi, PCONTEXT ctx, PROCINFO *outChildProcInfo)
    {
    STARTUPINFO si = {0}; if ( CreateProcess ( NULL, g_szHostExeFileName,
    NULL, NULL, 0, CREATE_SUSPENDED, NULL, g_szDefDir, &si, pi))        
    {
    ctx->ContextFlags=CONTEXT_FULL;
    GetThreadContext(pi->hThread, ctx); DWORD *pebInfo = (DWORD*)ctx->Ebx;
    DWORD read;
    ReadProcessMemory(pi->hProcess, &pebInfo[2], (LPVOID)&(outChildProcInfo->baseAddr), sizeof(DWORD), &read); DWORD curAddr = outChildProcInfo->baseAddr;
    MEMORY_BASIC_INFORMATION memInfo;
    while(VirtualQueryEx(pi->hProcess, (LPVOID)curAddr, &memInfo, sizeof(memInfo)))
    {
    if(memInfo.State == MEM_FREE)
    break;
    curAddr += (DWORD)memInfo.RegionSize;
    }
    outChildProcInfo->imageSize = (DWORD)curAddr - (DWORD)outChildProcInfo->baseAddr; return TRUE;
    }
    return FALSE;
    }
    //**********************************************************************************************************
    //
    // Returns TRUE if the PE file has a relocation table
    //
    //**********************************************************************************************************BOOL hasRelocationTable(PE_ExtHeader *inpeXH)
    {
    if(inpeXH->relocationTableAddress && inpeXH->relocationTableSize)
    {
    return TRUE;
    }
    return FALSE;
    }
    typedef DWORD (WINAPI *PTRZwUnmapViewOfSection)(IN HANDLE ProcessHandle, IN PVOID BaseAddress);
    //**********************************************************************************************************
    //
    // To replace the original EXE with another one we do the following.
    // 1) Create the original EXE process in suspended mode.
    // 2) Unmap the image of the original EXE.
    // 3) Allocate memory at the baseaddress of the new EXE.
    // 4) Load the new EXE image into the allocated memory.  
    // 5) Windows will do the necessary imports and load the required DLLs for us when we resume the suspended 
    //    thread.
    //
    // When the original EXE process is created in suspend mode, GetThreadContext returns these useful
    // register values.
    // EAX - process entry point
    // EBX - points to PEB
    //
    // So before resuming the suspended thread, we need to set EAX of the context to the entry point of the
    // new EXE.
    //
    //**********************************************************************************************************