动态加载EXE文件到内存执行

PE(dll、exe)文件内存加载(手动映射)小记 前言 PE文件即Windos操作系统下的可执行文件的文件结构名称,其中包含但不限于.dll .exe .sys .ocx等等。内存加载PE顾名思义就是通过内存,而非文件。这里的内存指代的是直接加载源。 这个技术其实很早之前就有了,网上也有很多开源可参考的代码,但是仅做一个伸手党那是绝对不行的,首先这些历史悠久的代码存在或多或少的bug,或莫名的崩溃咯,或32和64不兼容咯,各种问题皆是。当然,这些前辈先贤的代码一定是具有非常大的参考和开拓意义的。 技术用途 ... 阅读详情
//*******************************************************************************************************
// loadEXE.cpp : Defines the entry point for the console application.
//
// Proof-Of-Concept Code
// Copyright (c) 2004
// All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, provided that the above
// copyright notice(s) and this permission notice appear in all copies of
// the Software and that both the above copyright notice(s) and this
// permission notice appear in supporting documentation.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
// OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
// HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL
// INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING
// FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
// NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
// WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
//
// Usage:
// loadEXE <EXE filename>
//
// This will execute calc.exe in suspended mode and replace its image with
// the new EXE's image.  The thread is then resumed, thus causing the new EXE to
// execute within the process space of svchost.exe.
//
//*******************************************************************************************************

#include 
<stdio.h>
#include 
<windows.h>
#include 
<tlhelp32.h>
#include 
<psapi.h>

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(FILE *fp, MZHeader *outMZ, PE_Header *outPE, PE_ExtHeader *outpeXH,
                SectionHeader 
**outSecHdr)
{
    fseek(fp, 
0, SEEK_END);
    
long fileSize = ftell(fp);
    fseek(fp, 
0, SEEK_SET);

    
if(fileSize < sizeof(MZHeader))
    
{
        printf(
"File size too small ");        
        
return false;
    }


    
// read MZ Header
    MZHeader mzH;
    fread(
&mzH, sizeof(MZHeader), 1, fp);

    
if(mzH.signature != 0x5a4d)        // MZ
    {
        printf(
"File does not have MZ header ");
        
return false;
    }


    
//printf("Offset to PE Header = %X ", mzH.offsetToPE);

    
if((unsigned long)fileSize < mzH.offsetToPE + sizeof(PE_Header))
    
{
        printf(
"File size too small ");        
        
return false;
    }


    
// read PE Header
    fseek(fp, mzH.offsetToPE, SEEK_SET);
    PE_Header peH;
    fread(
&peH, sizeof(PE_Header), 1, fp);

    
//printf("Size of option header = %d ", peH.sizeOfOptionHeader);
    
//printf("Number of sections = %d ", peH.numSections);

    
if(peH.sizeOfOptionHeader != sizeof(PE_ExtHeader))
    
{
        printf(
"Unexpected option header size. ");

        
return false;
    }


    
// read PE Ext Header
    PE_ExtHeader peXH;

    fread(
&peXH, sizeof(PE_ExtHeader), 1, fp);

    
//printf("Import table address = %X ", peXH.importTableAddress);
    
//printf("Import table size = %X ", peXH.importTableSize);
    
//printf("Import address table address = %X ", peXH.importAddressTableAddress);
    
//printf("Import address table size = %X ", peXH.importAddressTableSize);


    
// read the sections
    SectionHeader *secHdr = new SectionHeader[peH.numSections];

    fread(secHdr, 
sizeof(SectionHeader) * peH.numSections, 1, fp);

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

        }

    }


    
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(FILE *fp, MZHeader *inMZ, PE_Header *inPE, PE_ExtHeader *inpeXH,
            SectionHeader 
*inSecHdr, LPVOID ptrLoc)
{
    
char *outPtr = (char *)ptrLoc;

    fseek(fp, 
0, SEEK_SET);
    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 = fread(outPtr, 1, headerSize, fp);
    
//printf("HeaderSize = %d ", headerSize);
    if(readSize != headerSize)
    
{
        printf(
"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;

            fseek(fp, inSecHdr[i].pointerToRawData, SEEK_SET);
            readSize 
= fread(outPtr, 1, toRead, fp);

            
if(readSize != toRead)
            
{
                printf(
"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)
        
{
            
//printf("Addr = %X ", fixBlk->pageRVA);
            
//printf("Size = %X ", fixBlk->blockSize);

            
int numEntries = (fixBlk->blockSize - sizeof(FixupBlock)) >> 1;
            
//printf("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;

                
//printf("Val = %X ", *offsetPtr);
                
//printf("Type = %X ", relocType);

                
if(relocType == 3)
                    
*codeLoc = ((DWORD)*codeLoc) + delta;
                
else
                
{
                    printf(
"Unknown relocation type = %d ", relocType);
                }

                offsetPtr
++;
            }


            fixBlk 
= (FixupBlock *)offsetPtr;
        }

    }
    
}



#define TARGETPROC "calc.exe"
CHAR    szDefDir[] 
= "I:/MyProject/tools/Xptools";
//CHAR    szDeft[] = "E:/WINDOWS/system32/notepad.exe";
//CHAR    szDeft[] = "I:/MyProject/tools/Xptools/XPtools.exe";
//CHAR    szDeft[] = "I:/MyProject/Test/Calcu/debug/Calcu.exe";
CHAR    szDeft[] = "I:/MyProject/PCBTest/Bin/PCBTest.exe";

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, TARGETPROC,
        NULL, NULL, 
0, CREATE_SUSPENDED, NULL, 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 
+= 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.
//
//**********************************************************************************************************

void doFork(MZHeader *inMZ, PE_Header *inPE, PE_ExtHeader *inpeXH,
            SectionHeader 
*inSecHdr, LPVOID ptrLoc, DWORD imageSize)
{
    STARTUPINFO si 
= {0};
    PROCESS_INFORMATION pi;
    CONTEXT ctx;
    PROCINFO childInfo;

    
if(createChild(&pi, &ctx, &childInfo)) 
    
{        
        printf(
"Original EXE loaded (PID = %d). ", pi.dwProcessId);
        printf(
"Original Base Addr = %X, Size = %X ", childInfo.baseAddr, childInfo.imageSize);

        LPVOID v 
= (LPVOID)NULL;

        
if(inpeXH->imageBase == childInfo.baseAddr && imageSize <= childInfo.imageSize)
        
{
            
// if new EXE has same baseaddr and is its size is <= to the original EXE, just
            
// overwrite it in memory
            v = (LPVOID)childInfo.baseAddr;
            DWORD oldProtect;
            VirtualProtectEx(pi.hProcess, (LPVOID)childInfo.baseAddr, childInfo.imageSize, PAGE_EXECUTE_READWRITE, 
&oldProtect);            

            printf(
"Using Existing Mem for New EXE at %X ", (unsigned long)v);
        }

        
else
        
{
            
// get address of ZwUnmapViewOfSection
            PTRZwUnmapViewOfSection pZwUnmapViewOfSection = (PTRZwUnmapViewOfSection)GetProcAddress(GetModuleHandle("ntdll.dll"), "ZwUnmapViewOfSection");

            
// try to unmap the original EXE image
            if(pZwUnmapViewOfSection(pi.hProcess, (LPVOID)childInfo.baseAddr) == 0)
            
{
                
// allocate memory for the new EXE image at the prefered imagebase.
                v = VirtualAllocEx(pi.hProcess, (LPVOID)inpeXH->imageBase, imageSize, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
                
if(v)
                    printf(
"Unmapped and Allocated Mem for New EXE at %X ", (unsigned long)v);
            }

        }


        
if(!v && hasRelocationTable(inpeXH))
        
{
            
// if unmap failed but EXE is relocatable, then we try to load the EXE at another
            
// location
            v = VirtualAllocEx(pi.hProcess, (void *)NULL, imageSize, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
            
if(v)
            
{
                printf(
"Allocated Mem for New EXE at %X. EXE will be relocated. ", (unsigned long)v);

                
// we've got to do the relocation ourself if we load the image at another
                
// memory location                
                doRelocation(inMZ, inPE, inpeXH, inSecHdr, ptrLoc, (DWORD)v);
            }

        }


        printf(
"EIP = %X ", ctx.Eip);
        printf(
"EAX = %X ", ctx.Eax);
        printf(
"EBX = %X ", ctx.Ebx);        // EBX points to PEB
        printf("ECX = %X ", ctx.Ecx);
        printf(
"EDX = %X ", ctx.Edx);

        
if(v)
        
{            
            printf(
"New EXE Image Size = %X ", imageSize);

            
// patch the EXE base addr in PEB (PEB + 8 holds process base addr)
            DWORD *pebInfo = (DWORD *)ctx.Ebx;
            DWORD wrote;                        
            WriteProcessMemory(pi.hProcess, 
&pebInfo[2], &v, sizeof(DWORD), &wrote);

            
// patch the base addr in the PE header of the EXE that we load ourselves
            PE_ExtHeader *peXH = (PE_ExtHeader *)((DWORD)inMZ->offsetToPE + sizeof(PE_Header) + (DWORD)ptrLoc);
            peXH
->imageBase = (DWORD)v;

            
if(WriteProcessMemory(pi.hProcess, v, ptrLoc, imageSize, NULL))
            
{    
                printf(
"New EXE image injected into process. ");

                ctx.ContextFlags
=CONTEXT_FULL;                
                
//ctx.Eip = (DWORD)v + ((DWORD)dllLoaderWritePtr - (DWORD)ptrLoc);
                //ctx.Eip = 0x007B9640;

                
if((DWORD)v == childInfo.baseAddr)
                
{
                    ctx.Eax 
= (DWORD)inpeXH->imageBase + inpeXH->addressOfEntryPoint;        // eax holds new entry point
                }

                
else
                
{
                    
// in this case, the DLL was not loaded at the baseaddr, i.e. manual relocation was
                    
// performed.
                    ctx.Eax = (DWORD)v + inpeXH->addressOfEntryPoint;        // eax holds new entry point
                }


                printf(
"********> EIP = %X ", ctx.Eip);
                printf(
"********> EAX = %X ", ctx.Eax);

                SetThreadContext(pi.hThread,
&ctx);

                ResumeThread(pi.hThread);
                printf(
"Process resumed (PID = %d). ", pi.dwProcessId);
            }

            
else
            
{
                printf(
"WriteProcessMemory failed ");
                TerminateProcess(pi.hProcess, 
0);
            }

        }

        
else
        
{
            printf(
"Load failed.  Consider making this EXE relocatable. ");
            TerminateProcess(pi.hProcess, 
0);
        }

    }

    
else
    
{
        printf(
"Cannot load %s ", TARGETPROC);
    }

}





int main(int argc, char* argv[])
{
    POINT        pt;
    GetCursorPos(
&pt);

    FILE 
*fp;
    
if(argc != 2)
    
{
        printf(
" Usage: %s <EXE filename> ", argv[0]);
        printf(
"No Input EXE, use: %s ", szDeft);
        fp 
= fopen(szDeft, "rb");
    }

    
else
        fp 
= fopen(argv[1], "rb");
    
if(fp)
    
{
        MZHeader mzH;
        PE_Header peH;
        PE_ExtHeader peXH;
        SectionHeader 
*secHdr;

        
if(readPEInfo(fp, &mzH, &peH, &peXH, &secHdr))
        
{
            
int imageSize = calcTotalImageSize(&mzH, &peH, &peXH, secHdr);
            
//printf("Image Size = %X ", imageSize);

            LPVOID ptrLoc 
= VirtualAlloc(NULL, imageSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
            
if(ptrLoc)
            
{
                
//printf("Memory allocated at %X ", ptrLoc);
                loadPE(fp, &mzH, &peH, &peXH, secHdr, ptrLoc);                                                

                doFork(
&mzH, &peH, &peXH, secHdr, ptrLoc, imageSize);                                
            }

            
else
                printf(
"Allocation failed ");
        }


        fclose(fp);
    }

    
else
        printf(
" Cannot open the EXE file! ");

    
return 0;
}
 
加载exe至内存运行 有时候需要将exe加载至内存运行,例如保护exe程序版权。 先上代码: #ifdef WIN32     #include #else     #error Process Forking Requires a Windows Operating System #endif #include ///////////////////////////////////////// 阅读详情

相关推荐

动态链接库——DLL文件

引入库文件包含被DLL导出的函数的名称和位置,DLL包含实际的函数和数据,应用程序使用LIB文件链接到所需要使用的DLL文件,库中的函数和数据并不复制到可执行文件中,因此在应用程序的可执行文件中,存放的不是被调用的函数代码,而是DLL中所要调用的函数的内存地址,这样当一个或多个应用程序运行是再把程序代码和被调用的函数代码链接起来,从而节省了内存资源。dll通常包含的是多个程序都能用到的代码和数据,一般大型软件都有一个exe和一堆dll文件。将库中的代码先加载到内存中,再链接到可执行文件中。

qq_43199575的博客 691

从内存中加载并启动一个exe

windows似乎只提供了一种启动进程的方法:即必须从一个可执行文件中加载并启动。而下面这段代码就是提供一种可以直接从内存中启动一个exe的变通办法。用途嘛, 也许可以用来保护你的exe,你可以对要保护的 exe 进行任意切分、加密、存储,只要运行时能将exe的内容正确拼接到一块内存中,就可以直接从内存中启动,而不必不安全地去生成一个临时文件再从临时文件启动进程。另外这段代码也提供了一种自己写ex

xuplus的专栏 1591

深入解析Windows中EXE可执行文件的运行原理与生命周期

简单来说,就是把文件的一部分“挂”到虚拟地址空间上,形成一个“视图”(View)。当你访问这个地址时,CPU触发缺页异常,操作系统才真正从磁盘读取对应页面。这就叫按需分页(Demand Paging),也叫懒加载(Lazy Loading)。一切准备就绪,加载器最后一项任务就是:跳转到 AddressOfEntryPoint!但这不是直接跳到main,而是先进入CRT启动代码:// 初始化堆_ioinit();// 初始化stdio。

weixin_29363791的博客 684

动态加载EXE文件到内存执行(测试可以编译成功)

//******************************************************************************************************* // loadEXE.cpp : Defines the entry point for the console application. // // Proof-Of-Concep

多媒体编程、网络编程、系统编程、网络安全编程、驱动编程 2418

VS工程实现实现EXE文件内存中模拟DLL方式加载执行

提供一套可直接编译运行的Visual Studio 2013+工程,包含mainexe(原始EXE)和dllexe(改造版)两个项目,演示如何让EXE绕过磁盘落地和标准启动流程,在内存中被LoadLibrary直接加载执行。核心改动包括:入口函数重定向为DllMain风格、手动处理PE重定位表、修复导入地址表(IAT)、调整PE头标志位以兼容DLL加载机制。源码含exemain.cpp(传统WinMain入口)、dllmain.cpp(导出DllMain并模拟EXE逻辑)、stdafx.h/.cpp基础支持

peace的博客 198

C#开发EXE外壳程序实战详解

C# EXE外壳是一种基于.NET平台的程序封装技术,通过构建一个可执行文件(.exe)作为“外壳”,在运行时加载并执行目标程序或附加逻辑。该技术广泛应用于软件保护、启动器开发、资源嵌入、权限控制以及合法的程序集成场景中。其核心思想是将原始目标程序以二进制形式嵌入外壳程序内部,运行时动态解密、加载并执行,从而实现对外部程序的透明调度与增强功能扩展。相比传统批处理或简单脚本启动器,C# EXE外壳具备更强的控制力和安全性——得益于.NET丰富的反射机制、程序集加载策略(如。

weixin_31163455的博客 1234

dll 与 exe 的区别

    在windows中dll与exe都是基于pe格式的,exe是通常的可执行文件,有程序的执行入口(例如Main() )包含数据和代码 。而dll则是动态链接库文件,也可能是纯资源文件,只包含数据,不包含代码,它通常是为了被其他多个程序重用而建,为软件开发提供复用性。

990

深入解析Windows下EXE可执行文件的完整生命周期与运行机制

解决方案包括:- 使用局部静态变量(C++11 起线程安全)- 将所有跨单元依赖改为惰性初始化- 使用。

weixin_42153793的博客 1147

静态库lib和动态库dll

静态库lib和动态库dll 有两种库(Lib,所谓的库,其实就对cpp源文件文件进行打包),一种是静态库,一种是动态库。 静态库 文件:会使用到.h和.lib文件这两种文件 编译器链接可执行文件时,链接器会从.lib文件中复制这些函数和数据,并且最终合并成一个可执行exe文件。 使用方法 在使用该库的源文件中包含该库的.h文件 在使用该库的源文件中写下以下语句 #pragma comment(lib, "库名.lib") 动态库 文件:会使用到.h和.lib和.dll这三种文件(其中.h和.lib文件

m0_37971774的博客 548

实现exe从资源中加载到内存中运行

这是网上的一段代码稍微修改了下,实现在windows下将程序加载到资源,运行时从资源加载到内存,并运行

RunPE-In-Memory:在内存中运行Exe文件(PE模块)(如Application Loader)

RunPE-In-Memory:在内存中运行Exe文件(PE模块)(如Application Loader)

动态链接库与静态链接库的区别

这篇文章讲得很好: https://www.cnblogs.com/tracylee/archive/2012/10/15/2723816.html 这是总结一下, 静态链接库直接被包含在最终生成的可执行文件中, 动态链接库(DLL)文件夹与可执行文件独立, 可执行文件可以动态地使用与卸载DLL 使用DLL可以节省内存, 而且由于DLL与EXE独立, DLL文件可以单独维护, 提高程序...

/dev/null 144

动态加载EXE文件到内存执行1

动态加载EXE文件到内存执行 //***************************************************************

EXE和DLL之间的区别是什么?

现在的Windows中,exe 和 dll 都是基于PE格式,exe 是通常的可执行文件,包含数据和代码,而 dll 是动态链接文件,也有可能是纯资源文件,只包含数据,不含程序代码。ddl 的目的之一就是提供能被许多不同的应用程序所使用的函数和资源。dll 中的函数和资源为软件开发提供了复用。它们是在运行时由磁盘物理映像载入被调用者的内存空间或共享内存空间执行。

ojlovecd的专栏 3999

ROS-订阅与处理激光雷达scan话题

激光雷达通常有四个性能衡量指标:测距分辨率、扫描频率(有时也用扫描周期)、角度分辨率及可视范围。测距分辨率衡量在一个给定的距离下测距的精确程度,通常与距离真实值相差在5-20mm;扫描频率衡量激光雷达完成一次完整扫描的快慢,通常在10Hz及以上;角度分辨率直接决定激光雷达一次完整扫描能返回多少个样本点;可视范围指激光雷达完整扫描的广角,可视范围之外即为盲区。

weixin_42438635的博客 4478

从零构建SOEM主站:基于STM32的EtherCAT伺服控制实战指南

本文详细介绍了如何从零构建基于STM32的SOEM主站系统,实现EtherCAT伺服电机的高精度控制。通过硬件选型、SOEM协议栈移植、PDO/SDO配置优化等实战步骤,帮助开发者掌握工业自动化中的关键运动控制技术,特别适用于23位编码器伺服电机的应用场景。

weixin_29186249的博客 666

从源文件到可执行文件

用某种编程语言编写的程序就称为 源代码,保存源代码的文件称为 源文件。因为源文件是简单的文本文件,所以用Windows 自带的记事本等文本编辑器就可以编写。源代码是无法直接运行的。这是因为,CPU 能直接解析并运行的不是源代码而是本地代码的程序。作为计算机大脑的Pentium 等CPU,也只能解释已经转换成本地代码的程序内容。本地(native)这个术语有“母语的”意思。对CPU 来说,母语就是机器语言,而转换成机器语言的程序就是本地代码。用任何编程语言编写的源代码,最后都要翻译成本地代码,否则CPU 就不

zhenpixiaoyang的博客 2518

避坑指南:Unity新版InputSystem在移动端的5个常见问题及解决方案

本文针对Unity新版InputSystem在移动端开发中的常见问题,提供了5个关键解决方案,包括虚拟摇杆灵敏度调节、多点触控冲突处理、按钮反馈延迟优化、手势识别与陀螺仪数据融合以及Android/iOS平台差异处理。这些实战经验帮助开发者高效解决触控适配难题,提升移动游戏体验。

soda5的博客 405
上一篇: CodeCrypt 1.0 SourceCode
下一篇: 一段仿真PE加载器行为的程序
iiprogram
博客等级 码龄25年 1068粉丝 1515原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值