精华内容
下载资源
问答
  • 用c++ 许多代码都得自己写, 这里是我自己修改的一个内存载入的一个封装库 , c++ 的程序员可以直接拿来用 特点如下: 直接在内存载入,无磁盘占用 支持加壳保护的dll , 平时用的最多的vmp ,其它壳子还请自己测试...

    用c++ 许多代码都得自己写, 这里是我自己修改的一个内存载入的一个封装库 , c++ 的程序员可以直接拿来用

     

    特点如下:

    直接在内存中载入,无磁盘占用

    支持加壳保护的dll , 平时用的最多的vmp ,其它壳子还请自己测试

    无模块载入, 因为重写了loadlibary ,如需要请自己注册

    支持注入到目标进程,前提请先使用相应权限打开目标

     

    对原代码的修改如下:

    使用内联汇编将原 c/c++的库调用 代替, 使得 注入代码可行

    支持直接使用资源加载和注入

    支持加载exe ,请自行 hook 某些函数 ,确保exe 正确运行

    加入inline 注入方式

    代码少量加花, 确保编译器最大优化无误

     

    注入的示例代码

    if (l.softGo(shell) )
    {
    	if( remoteInject( l.PI.hProcess  ,GetModuleHandleW(NULL) , IDR_DLL1, L"dll" )  )
    		LYOTRACELN(" 注入成功 " ) ;
    	else
    		LYOTRACELN(" 注入失败 " );
    	l.run();
    }
    

     

     

    down here

    转载于:https://www.cnblogs.com/lyo1005/p/4784129.html

    展开全文
  • 载入内存,让程序运行起来

    千次阅读 2016-09-22 23:42:45
    转载于:C语言中文网高级部分。 ... 那么,QQ是怎么运行起来的...双击QQ图标,操作系统就会知道你要运行这个软件,它会在硬盘中找到你安装的QQ软件,将数据(安装的软件本质上就是很多数据的集合)复制到内存。对!就是复

    转载于:C语言中文网高级部分。

    如果你的电脑上安装了QQ,你希望和好友聊天,会双击QQ图标,打开QQ软件,输入账号和密码,然后登录就可以了。

    那么,QQ是怎么运行起来的呢?

    首先,有一点你要明确,你安装的QQ软件是保存在硬盘中的。

    双击QQ图标,操作系统就会知道你要运行这个软件,它会在硬盘中找到你安装的QQ软件,将数据(安装的软件本质上就是很多数据的集合)复制到内存。对!就是复制到内存!QQ不是在硬盘中运行的,而是在内存中运行的。

    为什么呢?因为内存的读写速度比硬盘快很多。

    对于读写速度,内存 > 固态硬盘 > 机械硬盘。机械硬盘是靠电机带动盘片转动来读写数据的,而内存条通过电路来读写数据,电机的转速肯定没有电的传输速度(几乎是光速)快。虽然固态硬盘也是通过电路来读写数据,但是因为与内存的控制方式不一样,速度也不及内存。

    所以,不管是运行QQ还是编辑Word文档,都是先将硬盘上的数据复制到内存,才能让CPU来处理,这个过程就叫作载入内存(Load into Memory)。完成这个过程需要一个特殊的程序(软件),这个程序就叫做加载器(Loader)。

    CPU直接与内存打交道,它会读取内存中的数据进行处理,并将结果保存到内存。如果需要保存到硬盘,才会将内存中的数据复制到硬盘。

    例如,打开Word文档,输入一些文字,虽然我们看到的不一样了,但是硬盘中的文档没有改变,新增的文字暂时保存到了内存,Ctrl+S才会保存到硬盘。因为内存断电后会丢失数据,所以如果你编辑完Word文档忘记保存就关机了,那么你将永远无法找回这些内容。

    虚拟内存

    如果我们运行的程序较多,占用的空间就会超过内存(内存条)容量。例如计算机的内存容量为2G,却运行着10个程序,这10个程序共占用3G的空间,也就意味着需要从硬盘复制 3G 的数据到内存,这显然是不可能的。

    操作系统(Operating System,简称 OS)为我们解决了这个问题:当程序运行需要的空间大于内存容量时,会将内存中暂时不用的数据再写回硬盘;需要这些数据时再从硬盘中读取,并将另外一部分不用的数据写入硬盘。这样,硬盘中就会有一部分空间用来存放内存中暂时不用的数据。这一部分空间就叫做虚拟内存(Virtual Memory)。

    3G - 2G = 1G,上面的情况需要在硬盘上分配 1G 的虚拟内存。

    硬盘的读写速度比内存慢很多,反复交换数据会消耗很多时间,所以如果你的内存太小,会严重影响计算机的运行速度,甚至会出现”卡死“现象,即使CPU强劲,也不会有大的改观。如果经济条件允许,建议将内存升级为 4G,在 win7、win8 下运行软件就会比较流畅了。


    总结:CPU直接从内存中读取数据,处理完成后将结果再写入内存。

    图1:CPU、内存、硬盘和主板的关系

    展开全文
  • 加载exe内存运行

    千次阅读 2016-08-25 21:36:10
    有时候需要将exe加载至内存运行,例如保护exe程序版权。 先上代码: #ifdef WIN32  #include #else  #error Process Forking Requires a Windows Operating System #endif #include /////////////////...

    有时候需要将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!

    展开全文
  • 直接载入内存中的DLL

    万次阅读 2014-09-09 17:29:44
     你可能不希望在发布程序时附带上一个外部的 DLL,因为可能会有些用户在无意中把 DLL 删除了而造成 EXE 不能正确运行,也有可能该 DLL 会被别人拿去使用,也有可能,此 DLL 会成为破解者破解你的程序的突破口。...
    http://www.cppblog.com/mybios/archive/2006/11/21/15483.html
    作者:任明汉
    
    下载源代码
    
    前言
    
      你可能不希望在发布程序时附带上一个外部的 DLL,因为可能会有些用户在无意中把 DLL 删除了而造成 EXE 不能正确运行,也有可能该 DLL 会被别人拿去使用,也有可能,此 DLL 会成为破解者破解你的程序的突破口。无论出于何种原因,如果你想把一个 DLL 合并到一个 EXE 中的话,本文向你介绍这种方法。
    Win32 程序调用 DLL 的机制
    
       Win32 EXE 在调用一个外部 DLL 中的函数时,首先要调用 LoadLibary 函数来载入此 DLL 到程序的进程地址空间。 如果 LoadLibary 载入此 DLL 成功,将返回一个该 DLL 的句柄。 这个句柄实际上就是该 DLL 在内存中的起始地址。 在载入 DLL 成功后,还必须调用 GetProcAddress 函数来获取要调用的函数的地址。然后再根据该地址来调用这个函数。
    根据上述原理,我们可以把一个 DLL 作为资源文件放到 EXE 文件中,在程序运行时,分配一块内存,然后将此资源复制到该分配的内存中,并根据该内存地址计算得到相关的导出函数地址,然后,当我们需要调用某一函数时,可以用该函数在内存中的地址来调用它。
    程序实现。
      首先,把要合并的 DLL 作为资源加入到项目的资源文件中,然后在程序运行时,从资源中载入该资源,以得到该 DLL 在内存中的位置:
    
    LPVOID sRawDll; // 资源文件在内存中的地址 
    HRSRC hRes; 
    HMODULE hLibrary; 
    HGLOBAL hResourceLoaded; 
    char lib_name[MAX_PATH]; 
    GetModuleFileName(hInstance, lib_name, MAX_PATH ); // 得到运行程序的名字 
    hLibrary = LoadLibrary(lib_name);                  // 就象载入一个 DLL 一样载入运行程序到内存中 
    
    if (NULL != hLibrary) 
    {
    	// 得到指定的资源文件在内存中的位置 
    	hRes = FindResource(hLibrary, MAKEINTRESOURCE(IDR_DATA1), RT_RCDATA); 
    	if (NULL != hRes) 
    	{
    		// 将资源文件载入内存 
    		hResourceLoaded = LoadResource(hLibrary, hRes); 
    		if (NULL != hResourceLoaded) 
    		{
    			// 得到资源文件大小 
    			SizeofResource(hLibrary, hRes); 
    
    			// 锁定资源以得到它在内存中的地址 
    			sRawDll = (LPVOID)LockResource(hResourceLoaded); 
    		}
    	}
    	else return 1; 
    	FreeLibrary(hLibrary);
    }
    else return 1; 
    
    然后,从资源中载入 DLL 到内存函数 LoadPbDllFromMemory 将载入 DLL 到内存中, 该函数有两个参数,第一个参数是指向 DLL 资源在内存中的地址的指针,也就是前面代码中的 LockResource 函数的返回值。第二个参数是一个空的指针,如果函数 LoadPbDllFromMemory 运行成功,该指针将指向重新组合后的内存中的 DLL 的起始地址。该函数还有一个功能就是如果运行成功,它将手动地用 DLL_PROCESS_ATTACH 参数调用 DLL 的入口函数 DllMain 来初始化该 DLL。除此之外,它还会手动地载入合并的 DLL 的入口表中导入的 DLL 并调整它们在内存中的相对地址。以下是该函数代码:
    
    DWORD LoadPbDllFromMemory(LPVOID lpRawDll, LPVOID lpImageDll) 
    {
    	SYSTEM_INFO sSysInfo; 
    	PIMAGE_DOS_HEADER dosHeader; 
    	PIMAGE_NT_HEADERS pNTHeader; 
    	PIMAGE_SECTION_HEADER section; 
    	PIMAGE_IMPORT_DESCRIPTOR pImportDesc; 
    	PIMAGE_IMPORT_BY_NAME pOrdinalName; 
    	PIMAGE_BASE_RELOCATION baseReloc; 
    	PDWORD lpLink; 
    	unsigned char Protection[4096]; 
    	HINSTANCE hDll; 
    	WORD i; 
    	DWORD ImagePages,fOldProtect,j,MaxLen,HdrLen,Addr1,Addr2,Pg,Pg1,Pg2; 
    	char * sDllName; 
    
    	if(NULL == lpRawDll) return 1 ; 
    
    	dosHeader = (PIMAGE_DOS_HEADER)lpRawDll; 
    
    	// Is this the MZ header? 
    	if ((TRUE == IsBadReadPtr(dosHeader,sizeof (IMAGE_DOS_HEADER))) ||
    				 (IMAGE_DOS_SIGNATURE != dosHeader->e_magic)) 
    		return 2; 
    
    	// Get the PE header. 
    	pNTHeader = MakePtr(PIMAGE_NT_HEADERS,dosHeader,dosHeader->e_lfanew); 
    
    	// Is this a real PE image? 
    	if((TRUE == IsBadReadPtr(pNTHeader,sizeof ( IMAGE_NT_HEADERS))) || 
    				( IMAGE_NT_SIGNATURE != pNTHeader->Signature)) 
    		return 3 ; 
    
    	if(( pNTHeader->FileHeader.SizeOfOptionalHeader != 
    			sizeof(pNTHeader->OptionalHeader)) || 
    		(pNTHeader->OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR32_MAGIC)) 
    		return 4; 
    
    	if (pNTHeader->FileHeader.NumberOfSections < 1) return 5; 
    
    	section = IMAGE_FIRST_SECTION( pNTHeader ); 
    	int HeaderSize = sizeof(IMAGE_SECTION_HEADER); 
    
    	// 节头长度 
    	HdrLen = (DWORD)section - (DWORD)dosHeader + 
    			HeaderSize * pNTHeader->FileHeader.NumberOfSections; 
    
    	// 找出最大的节的长度,此节一般是代码所在的节(.text 节) 
    	MaxLen = HdrLen; 
    	int ii=0; 
    
    	for (i = 0;i<(DWORD)pNTHeader->FileHeader.NumberOfSections;i++)// find MaxLen 
    	{
    		if(MaxLen < section[i].VirtualAddress + section[i].SizeOfRawData) 
    		{
    			MaxLen = section[i].VirtualAddress + section[i].SizeOfRawData; 
    		}
    		if(strcmp((const char *)section[i].Name,".rsrc") == 0) ii=i; 
    	}
    
    	GetSystemInfo(&sSysInfo);
    	ImagePages = MaxLen / sSysInfo.dwPageSize; 
    	if (MaxLen % sSysInfo.dwPageSize) ImagePages++; 
    
    	// 分配所需的内存 
    	DWORD NeededMemory = ImagePages * sSysInfo.dwPageSize; 
    	lpImageDll = VirtualAlloc(NULL, NeededMemory, MEM_COMMIT, PAGE_EXECUTE_READWRITE); 
    
    	if (lpImageDll == NULL) return 6; // 分配内存失败 
    
    	MoveMemory( lpImageDll, lpRawDll, HdrLen ); // 复制节头 
    
    	DWORD OrgAddr = 0; 
    	DWORD NewAddr = 0; 
    	DWORD Size = 0; 
    
    	// 复制 .text 节数据 
    	for (i = 0;i<pNTHeader->FileHeader.NumberOfSections;i++) 
    	{
    		OrgAddr = (DWORD)lpImageDll + (DWORD)section[i].VirtualAddress; 
    		NewAddr = (DWORD)lpRawDll + (DWORD)section[i].PointerToRawData; 
    		Size = (DWORD)section[i].SizeOfRawData; 
    		MoveMemory((void *)OrgAddr, (void *)NewAddr, Size ); 
    	}
    
    	// 把指针指向新的 DLL 映像 
    	dosHeader = (PIMAGE_DOS_HEADER) lpImageDll; // Switch to new image 
    	pNTHeader = (PIMAGE_NT_HEADERS) ((DWORD)dosHeader + dosHeader->e_lfanew); 
    	section = (PIMAGE_SECTION_HEADER) ((DWORD)pNTHeader + sizeof(IMAGE_NT_HEADERS)); 
    	pImageBase = (PBYTE)dosHeader; 
    
    	if((ii!=0) && (IsNT()==TRUE)) 
    	{
    		section[ii].VirtualAddress = section[ii].VirtualAddress + (DWORD)lpRawDll; 
    		section[ii].PointerToRawData = section[ii].PointerToRawData + (DWORD)lpRawDll; 
    	}
    
    	DWORD importsStartRVA; 
    
    	// Look up where the imports section is (normally in the .idata section) 
    	// but not necessarily so. Therefore, grab the RVA from the data dir. 
    	importsStartRVA = GetImgDirEntryRVA(pNTHeader,IMAGE_DIRECTORY_ENTRY_IMPORT); 
    	if ( !importsStartRVA ) 
    	{
    		VirtualFree(dosHeader,0, MEM_RELEASE); 
    		return 7; 
    	}
    
    	pImportDesc = (PIMAGE_IMPORT_DESCRIPTOR) pNTHeader->
    		OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress; 
    
    	if(pImportDesc!= 0) 
    		pImportDesc = (PIMAGE_IMPORT_DESCRIPTOR) ((DWORD)pImportDesc + (DWORD)dosHeader); 
    	else 
    	{
    		VirtualFree(dosHeader,0, MEM_RELEASE); 
    		return 8; 
    	}
    
    	while (1) // 处理各入口表中的 DLL 
    	{
    		// 检查是否遇到了空的 IMAGE_IMPORT_DESCRIPTOR 
    		if ((pImportDesc->TimeDateStamp==0 ) && (pImportDesc->Name==0)) break; 
    
    		// 从磁盘载入必须的 Dll, 
    		// 注意,载入的 DLL 是合并的 DLL 的入口表中的 DLL, 
    		// 不是合并到 EXE 中的 DLL 
    		sDllName = (char *) (pImportDesc->Name + (DWORD)pImageBase); 
    		hDll = GetModuleHandle(sDllName); 
    
    		if (hDll == 0 ) hDll = LoadLibrary(sDllName); 
    
    		if (hDll == 0 ) 
    		{
    			MessageBox(NULL, "Can''t find required Dll",
    					"Error in LoadPbDllFromMemory()",0); 
    			VirtualFree(dosHeader,0, MEM_RELEASE); 
    			return 9; 
    		}
    
    		DWORD *lpFuncNameRef = (DWORD *) (pImportDesc->OriginalFirstThunk +
    								 (DWORD)dosHeader); 
    		DWORD *lpFuncAddr = (DWORD *) (pImportDesc->FirstThunk +
    								 (DWORD)dosHeader); 
    
    		while( *lpFuncNameRef != 0) 
    		{
    			pOrdinalName = (PIMAGE_IMPORT_BY_NAME) (*lpFuncNameRef +
    						 (DWORD)dosHeader); 
    			DWORD pIMAGE_ORDINAL_FLAG = 0x80000000; 
    
    			if (*lpFuncNameRef & pIMAGE_ORDINAL_FLAG) 
    				*lpFuncAddr = (DWORD) GetProcAddress(hDll,
    					 (const char *)(*lpFuncNameRef & 0xFFFF)); 
    			else
    				*lpFuncAddr = (DWORD) GetProcAddress(hDll,
    						 (const char *)pOrdinalName->Name); 
    
    			if (lpFuncAddr == 0) 
    			{
    				VirtualFree(dosHeader,0, MEM_RELEASE); 
    				return 10;// Can''t GetProcAddress 
    			}
    
    			lpFuncAddr++;
    			lpFuncNameRef++;
    		}
    		pImportDesc++;
    	}
    
    	DWORD TpOffset; 
    	baseReloc = (PIMAGE_BASE_RELOCATION)((DWORD)pNTHeader->
         OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress); 
    
    	if (baseReloc !=0) 
    	{
    		baseReloc = (PIMAGE_BASE_RELOCATION) ((DWORD)baseReloc + (DWORD)dosHeader); 
    		while(baseReloc->VirtualAddress != 0) 
    		{
    			PWORD lpTypeOffset = (PWORD) ((DWORD)baseReloc +
    					 sizeof(IMAGE_BASE_RELOCATION)); 
    			while (lpTypeOffset < (PWORD)((DWORD)baseReloc +
    						 (DWORD)baseReloc->SizeOfBlock)) 
    			{
    				TpOffset = *lpTypeOffset & 0xF000; 
    				if(TpOffset == 0x3000) 
    				{
    					lpLink = (PDWORD) ((DWORD)dosHeader +
                                       baseReloc->VirtualAddress +
                                                          (*lpTypeOffset & 0xFFF)); 
    					*lpLink = (DWORD)dosHeader + 
                                                (*lpLink) - pNTHeader->OptionalHeader.ImageBase; 
    				}
    				else
    				{
    					if (TpOffset != 0) 
    					{
    						VirtualFree(dosHeader,0, MEM_RELEASE); 
    						return 10; 
    					}
    				}
    				lpTypeOffset++;
    			}
    			baseReloc = (PIMAGE_BASE_RELOCATION)((DWORD)baseReloc + 
    				(DWORD)baseReloc->SizeOfBlock); 
    		}
    	}
    
    	// 取得原始的内存状态 
    	memset(Protection,0,4096);
    	for (i = 0;i<=pNTHeader->FileHeader.NumberOfSections;i++) 
    	{
    		if (i == pNTHeader->FileHeader.NumberOfSections) 
    		{
    			Addr1 = 0; 
    			Addr2 = HdrLen; 
    			j = 0x60000000; 
    		}
    		else
    		{
    			Addr1 = section[i].VirtualAddress; 
    			Addr2 = section[i].SizeOfRawData; 
    			j = section[i].Characteristics; 
    		}
    		Addr2 += Addr1 - 1; 
    
    		Pg1 = Addr1 / sSysInfo.dwPageSize; 
    		Pg2 = Addr2 / sSysInfo.dwPageSize; 
    		for(Pg = Pg1 ;Pg<=Pg2;Pg++) 
    		{
    			if (j & 0x20000000) Protection[Pg] |= 1; // Execute 
    			if (j & 0x40000000) Protection[Pg] |= 2; // Read 
    			if (j & 0x80000000) Protection[Pg] |= 4; // Write 
    		}
    	}
    
    	// 恢复原始的内存状态 
    	Addr1 = (DWORD)dosHeader; 
    	for (Pg = 0 ;Pg<= ImagePages;Pg++) 
    	{
    		switch(Protection[Pg])
    		{
    		case 2: 
    			fOldProtect = PAGE_READONLY; 
    			break;
    		case 3: 
    			fOldProtect = PAGE_EXECUTE_READ; 
    			break;
    		case 6: 
    			fOldProtect = PAGE_READWRITE; 
    			break;
    		default: 
    			// Ignore strange combinations
    			fOldProtect = PAGE_EXECUTE_READWRITE;  
    			break;
    		}
    
    		if (fOldProtect !=PAGE_EXECUTE_READWRITE) 
    		{
    			if (VirtualProtect((void *)Addr1, 
    				sSysInfo.dwPageSize, 
    				fOldProtect,
    				&fOldProtect) == 0) 
    			{
    				VirtualFree(dosHeader,0, MEM_RELEASE); 
    				return 11; 
    			}
    		}
    		Addr1 += sSysInfo.dwPageSize; 
    	}
    
    	EntryPoint = (LPENTRYPOINT) ((DWORD)pNTHeader->OptionalHeader.AddressOfEntryPoint +
    				 (DWORD)dosHeader); 
    	LPVOID lpReserved = 0; 
    	EntryPoint((HINSTANCE)dosHeader, DLL_PROCESS_ATTACH, lpReserved); 
    	lpImageDll2=lpImageDll;
    	return 0; 
    }
    
      一但 DLL 被正确地载入到内存中,我们就可以通过自定义函数 GetProcAddressDirectly 来获取某函数在内存中的地址,并根据该地址来调用该函数,该函数也有两个参数,第一个参数是指向载入到内存中的 DLL 的起始地址的指针,第二个是要调用的函数的函数名。以下是 GetProcAddressDirectly 函数代码:
    
    DWORD GetProcAddressDirectly(PIMAGE_DOS_HEADER dosHeader, char * FuncName)  
    { 
    	PIMAGE_NT_HEADERS pNTHeader;  
    	PIMAGE_EXPORT_DIRECTORY pExportDir;  
    	PWORD lpNameOrdinals;  
    	LPDWORD lpFunctions;  
    	DWORD * lpName;  
    	char * lpExpFuncName;  
    	DWORD i;  
    	DWORD j;  
    	char * lpFuncName;  
    
    	if(dosHeader->e_magic != IMAGE_DOS_SIGNATURE) return 0;  
    
    	pNTHeader = (PIMAGE_NT_HEADERS)((DWORD)dosHeader + dosHeader->e_lfanew);  
    
    	if (pNTHeader->Signature != IMAGE_NT_SIGNATURE) return 0;  
    
    	if ((pNTHeader->FileHeader.SizeOfOptionalHeader != sizeof(pNTHeader->OptionalHeader)) ||  
    		(pNTHeader->OptionalHeader.Magic != IMAGE_NT_OPTIONAL_HDR32_MAGIC))  
    		return 0;  
    
    	DWORD exportsStartRVA, exportsEndRVA;  
    	pImageBase = (PBYTE)dosHeader;  
    
    	// Make pointers to 32 and 64 bit versions of the header.  
    	pNTHeader = MakePtr( PIMAGE_NT_HEADERS, dosHeader,dosHeader->e_lfanew );  
    
    	exportsStartRVA = GetImgDirEntryRVA(pNTHeader,IMAGE_DIRECTORY_ENTRY_EXPORT);  
    	exportsEndRVA = exportsStartRVA +  
    		GetImgDirEntrySize(pNTHeader, IMAGE_DIRECTORY_ENTRY_EXPORT);  
    
    	// Get the IMAGE_SECTION_HEADER that contains the exports. This is  
    	// usually the .edata section, but doesn''t have to be.  
    	PIMAGE_SECTION_HEADER header;  
    	header = GetEnclosingSectionHeader( exportsStartRVA, pNTHeader );  
    	if ( !header ) return 0;  
    
    	INT delta;  
    	delta = (INT)(header->VirtualAddress - header->PointerToRawData);  
    	pExportDir = (PIMAGE_EXPORT_DIRECTORY)GetPtrFromRVA(exportsStartRVA, 
    				pNTHeader, pImageBase);  
    
    
    	pExportDir =(PIMAGE_EXPORT_DIRECTORY) (pNTHeader->
    	OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);  
    
    	if (pExportDir == 0)  
    	{ 
    		MessageBox(NULL,"Error in GetProcAddressDirectly()",0,0);  
    		return 0;  
    	} 
    
    	pExportDir =(PIMAGE_EXPORT_DIRECTORY) ((DWORD)pExportDir + (DWORD)dosHeader);  
    	lpNameOrdinals =(PWORD)((DWORD)pExportDir->AddressOfNameOrdinals + (DWORD)dosHeader);  
    	lpName =(LPDWORD) (pExportDir->AddressOfNames + (DWORD)dosHeader);  
    	lpFunctions =(LPDWORD) (pExportDir->AddressOfFunctions + (DWORD)dosHeader);  
    	lpFuncName = FuncName;  
    
    	if(HIWORD(lpFuncName)!=0 )  
    	{ 
    		for( i = 0;i<=pExportDir->NumberOfFunctions - 1;i++)  
    		{ 
    			DWORD entryPointRVA = *lpFunctions;  
    
    			// Skip over gaps in exported function  
    			if ( entryPointRVA == 0 ) continue; 
    			for( j = 0;j<=pExportDir->NumberOfNames-1;j++)  
    			{ 
    				if( lpNameOrdinals[j] == i)  
    				{ 
    					lpExpFuncName = (char *) (lpName[j] + 
    							(DWORD)dosHeader);  
    					if(strcmp((char *)lpExpFuncName,(char *)FuncName)==0)  
    						return (DWORD) (lpFunctions[i] + 
    								(DWORD)dosHeader);  
    				} 
    			} 
    		} 
    	} 
    	else 
    	{ 
    		for (i = 0 ;i<=pExportDir->NumberOfFunctions - 1;i++)  
    		{ 
    			if (lpFuncName == (char *)(pExportDir->Base + i))  
    			{ 
    				if (lpFunctions[i]) return (unsigned long) (lpFunctions[i] + 
    							dosHeader);  
    			} 
    		} 
    	} 
    	return 0;  
    }
    
    
    在调用完函数后,不要忘记用 UnloadPbDllFromMemory 来从内存中移去 DLL 以释放分配的内存,该函数还会用 DLL_PROCESS_DETACH 参数调用 DLL 的入口函数 DllMain 来从调用进程的地址空间卸载该 DLL。 以下是 UnloadPbDllFromMemory 函数代码:
    
    DWORD UnloadPbDllFromMemory(PIMAGE_DOS_HEADER dosHeader) 
    {
    	PIMAGE_NT_HEADERS pNTHeader; 
    	pNTHeader = (PIMAGE_NT_HEADERS)((DWORD)dosHeader + (DWORD)dosHeader->e_lfanew); 
    	EntryPoint = (LPENTRYPOINT)(pNTHeader->OptionalHeader.AddressOfEntryPoint +
    					 (DWORD)dosHeader); 
    	EntryPoint((HINSTANCE)dosHeader, DLL_PROCESS_DETACH, 0); 
    	return VirtualFree(dosHeader, 0, MEM_RELEASE); 
    }
    
    
    关于示例代码的说明
    
      在本文附带的示例代码中,合并了一个名为 hardware.dll 的动态连接库,该动态连接库是一个获取系统硬件信息的库文件,其中包括了以下函数:
    
       getmac 		取得网卡 MAC 
       VolumeNumber 	取得硬盘卷标 
       changeres            改变屏幕分辩率 
       IsDiskInDrive        检查软驱中是否插有盘 
       DPGetDefaultPrinter  取得默认的打印机名 
       DPSetDefaultPrinter  设置默认的打印机 
       getserial            取得硬盘的出厂序列号 
       getmetric            取得显示分辩率 
       PrintStringDirect    直接向打印机发送一个串 
       vfpbeep              让 PC 喇叭发声 
       getcpuid             取得 CPU ID 
       getbios              取得主板 BIOS ID 
    
      在示例代码中,只调用了其中一个函数 getbios 来获取主板 BIOS ID, 这里说明一下,该函数实际上好象只能检测 AWARD 主板的 BIOS, 也就是说它是读取的是系统内存 0x000fex71 处的值。因为其它牌子的主板 BIOS 的位置稍有不同,但在程序中没有进行这方面的处理,所以在读其它牌子的主板 BIOS 时可能会有些问题(读出的内容可能不正确)。关于此 DLL 的内容和实现,也许我会在另一篇文章中论及。
     
    局限
      在我进行测试时,发现对于有些含有资源的 DLL,在 9x 平台下可能会有问题。
    
    题外话
      另外,其它一些本文未提及的非主要的函数,请自行参见源代码中的注释。
    再,本文涉及 PE 文件格式方面的知识,它们已经超出了本文的范围,具体信息可参见 MSDM 中的:
    Peering Inside the PE: A Tour of the Win32 Portable Executable File Format 一文和
    Microsoft Portable Executable and Common Object File Format Specification 一文
    
    特别感谢卢春明(Aming)在我编写本文时所作的一些技术方面的建议和指导

    展开全文
  • 程序载入内存后的结构

    千次阅读 2013-03-23 00:36:09
    首先我们以Linux为例来研究,这代表了现在操作系统的有多进程的处理方式:...来看一幅很经典的内存结构图: ------------------------------低地址 代码区 | ------------------------------ 全局数据区 | --
  • 汇编加载exe 内存过程

    2019-10-23 14:02:52
    在我们进行debug xxx.exe 的时候 发现一个问题 ds 和cs 竟然不一样 那么问题来了 为什么cs 比ds段多了256个字节 因为我们的程序载入主存储器的时候 会在ds段中的前256个字节预先加载一个psp 程序前缀 目...
  • 内存加载exe的两种方式(支持win7)
  • vb的exe内存能不能直接同时读取ocx的内存里定义的全局变量的变量名?怎么知道一个ocx内存里有几个全局变量?
  • 内存中加载并运行exe (c)

    千次阅读 2008-07-14 12:09:00
    原理很简单:就是“借尸还魂”,启动一个僵尸进程(NT下可以是自身程序启动的另一个进程),然后在它运行前将其整个替换成内存中的exe内容,待正式运行后执行的就是你的目标代码了。 不过代码中还有一些不尽人意的...
  • 被加载的映像如果是EXE比必须关闭 固定基址(/FIXED:NO)即必须有重定位表, 否则无法处理重定位. void load_image() { auto pImage = data;//欲加载映像的内存地址 void *pDest = NULL; HANDLE pSection; ...
  • Java的类载入

    2014-08-06 17:49:21
    每次创建Java类的实例时,都必须现将类载入内存中。Java虚拟机使用类载入器来载入需要的类。一般情况下,类在如期会在一些Java核心类库,以及环境变量CLASSPATH中指明的目录中搜索相关类。如果在这些位置它都找不...
  • 谈谈内存映射文件

    千次阅读 2014-11-24 22:26:29
    内存映射文件允许开发人员预订一块地址空间并为该区域调拨物理存储器,与虚拟...将文件映射到内存中后,我们就可以在内存中操作他们了,就像他们被载入内存中一样。 内存映射文件主要有三方面的用途: 1:系
  • 《windows核心编程系列》十六谈谈内存映射文件

    千次阅读 多人点赞 2011-11-22 21:30:41
    将文件映射到内存中后,我们就可以在内存中操作他们了,就像他们被载入内存中一样。 内存映射文件主要有三方面的用途: 1:系统使用内存映射文件来将exe或是dll文件本身作为后备存储器,而非系统页交换文件,这...
  • 【面经笔记】内存映射、共享内存

    千次阅读 2017-09-05 17:05:29
    系统使用内存映射文件载入EXE,DLL文件。这节省了大量页交换文件的空间以及程序启动时间。 开发人员使用内存映射文件来访问磁盘上的数据文件,这使得我们避免直接对文件I/O操作和文件内容的缓存 通过使用内存映射文件...
  • Windows内存体系(1) -- 虚拟地址空间

    万次阅读 多人点赞 2018-03-19 14:07:17
    在8086或者80186以前,要运行一个程序,操作系统会把这些程序全都装入内存,程序都是直接运行在物理内存上的,也就是说程序中访问的内存地址都是实际的物理内存地址。当计算机同时运行多个程序时,必须保证这些程序...
  • 将文件映射到内存中后,我们就可以在内存中操作他们了,就像他们被载入内存中一样。 内存映射文件主要有三方面的用途: 1:系统使用内存映射文件来将exe或是dll文件本身作为后备存储器,而非系统页交换文件,...
  • 将dll打包入exe

    热门讨论 2008-11-19 12:59:30
    Win32 EXE 在调用一个外部 DLL 中的函数时,首先要调用 LoadLibary 函数来载入此 DLL 到程序的进程地址空间。 如果 LoadLibary 载入此 DLL 成功,将返回一个该 DLL 的句柄。 这个句柄实际上就是该 DLL 在内存中的...
  • matlab 内存管理 清理内存

    千次阅读 2018-11-14 15:17:00
    一、利用clear清除内存时,要用pack函数进行内存整理 二、查询matlab内存使用,计算要处理的数据大小 三、matlab内存管理 一、利用clear清除内存时,要用pack函数进行内存整理 Matlab在运行大数据时,会出现Out ...
  •  接着是,一个简单的读取函数将进行寻文件读取,解码以及内存的分配。 img = cv:imread("../../../waves.jpg"); 首先在显示图像之前时,需定义一个图像显示的窗口,接着指定需要显示的图像。 cv::...
  • tomcat(8)载入

    千次阅读 2016-04-23 18:18:05
    【0】README 0.0)本文部分描述转自“深入...0.2)servlet容器需要实现一个自定义的载入器,而不能简单地使用系统的类载入器的原因:(干货——为什么servlet容器要实现一个自定义的载入器) 0.2.1)原因1: 因为ser
  • 以前应用程序必须在载入内存后才能执行,现代操作系统的内存管理为解决这个问题而引入了虚拟内存。 本质上虚拟内存就是要让一个程序的代码和数据在没有全部载入内存时即可运行。运行过程中,当执行到尚未载入内存的...
  • WinCE内存管理

    千次阅读 2012-08-08 10:02:16
    内存管理   如果你在写Windows CE 程序中遇到的最重要的问题,那一定是内存问题。一个WinCE 系统可能只有4MB 的RAM,这相对于个人电脑来说是十分少的,因为个人电脑的标准配置已经到了128MB 甚至更多。事实上...
  • 动态加载EXE和DLL

    2008-10-23 10:26:07
    第一个参数:一个载入EXE的资源流或者内存流等流类型。 第二个参数:传递调用EXE的参数。如果EXE调用不需要参数,可设置为空串。 第三个参数:如果调用成功,则返回被调用的EXE对应的进程ID。 细节性问题,请...
  • Java内存溢出详解

    2015-05-20 10:04:06
    Java内存溢出详解 一、常见的Java内存溢出有以下三种: 1 java.lang.OutOfMemoryError: Java heap space —-JVM Heap(堆)溢出 JVM在启动的时候会自动设置JVM Heap的值,其初始空间(即-Xms)是物理内存的1/64,...
  • 内存技术

    2013-08-20 20:33:31
    什么是内存Bank? Bank从物理上理解为北桥芯片到内存的通道,通常每个通道为64bit。我们知道,一块主板的性能优劣主要取决于它的芯片组。不同的芯片组所支持的Bank是不同的。如Intel 82845系列芯片组支持4个Bank,...
  • 动态载入 DLL 动态载入方式是指在编译之前并不知道将会调用哪些 DLL 函数, 完全是在运行过程中根据需要决定应调用哪些函数。 方法是:用 LoadLibrary 函数加载动态链接库到内存,用 GetProcAddress函数动态获得 DLL...
  • window内存管理与内存原理

    千次阅读 2011-09-27 15:08:56
    WIndows为每个进程分配了4GB的虚拟地址空间,让每个进程都认为自己拥有4GB的内存空间,4GB怎么来的? 32位 CPU可以取地址的空间为2的32次方,就是4GB(正如16位CPU有20根寻址线所有拥有2的20次方的寻址空间一样) ...
  • ...WIndows为每个进程分配了4GB的虚拟地址空间,让每个进程都认为自己拥有4GB的内存空间,4GB怎么来的? 32位 CPU可以取地址的空间为2的32次方,就是4GB(正如16位CPU有20根寻址线所有拥有2的20次

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 21,456
精华内容 8,582
关键字:

exe载入内存