首页
社区
课程
招聘
[求助]MemoryLoadLibrary 加载MFC 易语言 DLL 失败
发表于: 2011-10-6 13:32 15840

[求助]MemoryLoadLibrary 加载MFC 易语言 DLL 失败

2011-10-6 13:32
15840
接着昨天发的求助 DLL补丁,网上找了一份代码, Memory DLL loading code
模拟LoadLibrary ,经过调用发现对win32 DLL有效,但是加载MFC DLL
发现 停止在 调用 DLLMAIN 处,易语言直接 报错,我把代码发下,大家帮忙
分析下。
可以直接在MFC 程序上用,UNICODE,此代码是最新的支持64位

//"MemoryModule.h"

#ifndef __MEMORY_MODULE_HEADER
#define __MEMORY_MODULE_HEADER

#include <Windows.h>

typedef void *HMEMORYMODULE;

#ifdef __cplusplus
extern "C" {
#endif

HMEMORYMODULE MemoryLoadLibrary(const void *);

FARPROC MemoryGetProcAddress(HMEMORYMODULE, const char *);

void MemoryFreeLibrary(HMEMORYMODULE);

#ifdef __cplusplus
}
#endif

#endif  // __MEMORY_MODULE_HEADER

//"MemoryModule.cpp"
/*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
【】【】【】【】【】【】【】【】【】【】【】【】【】【】【】【】【】【】【】【】【】
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
**  FileName    :   MemoryModule.cpp
**  Version     :   0.10
**  Author      :   joachim
**  Date        :   2011-03-22
**  Comment     :   加载模块,下载地址:97cK9s2c8@1M7q4)9K6b7g2)9J5c8W2)9J5c8Y4N6%4N6#2)9J5k6h3A6G2j5h3y4Z5K9h3#2Q4x3X3c8T1j5i4g2U0K9q4)9J5k6h3c8W2
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
【】【】【】【】【】【】【】【】【】【】【】【】【】【】【】【】【】【】【】【】【】
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@*/
#include "stdafx.h"
#include <Windows.h>
#include <winnt.h>
#include "Print.h"
#include "MemoryModule.h"

#ifndef __GNUC__
// disable warnings about pointer <-> DWORD conversions
#pragma warning( disable : 4311 4312 )
#endif

#ifdef _WIN64
#define POINTER_TYPE ULONGLONG
#else
#define POINTER_TYPE DWORD
#endif

#ifdef DEBUG_OUTPUT
#include <stdio.h>
#endif

#ifndef IMAGE_SIZEOF_BASE_RELOCATION
#define IMAGE_SIZEOF_BASE_RELOCATION (sizeof(IMAGE_BASE_RELOCATION))
#endif

typedef struct
{
        PIMAGE_NT_HEADERS headers;
        unsigned char *codeBase;
        HMODULE *modules;
        int numModules;
        int initialized;
} MEMORYMODULE, *PMEMORYMODULE;

typedef BOOL (WINAPI *DllEntryProc)(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved);

#define GET_HEADER_DICTIONARY(module, idx)        &(module)->headers->OptionalHeader.DataDirectory[idx]

static void CopySections(const unsigned char *data, PIMAGE_NT_HEADERS old_headers, PMEMORYMODULE module)
{
        int i, size;

        unsigned char *codeBase = module->codeBase;

        unsigned char *dest;

        PIMAGE_SECTION_HEADER section = IMAGE_FIRST_SECTION(module->headers);

        for (i=0; i<module->headers->FileHeader.NumberOfSections; i++, section++)
        {
                if (section->SizeOfRawData == 0)
                {
                        size = old_headers->OptionalHeader.SectionAlignment;

                        if (size > 0)
                        {
                                dest = (unsigned char *)VirtualAlloc(codeBase + section->VirtualAddress,size,MEM_COMMIT,PAGE_READWRITE);

                                section->Misc.PhysicalAddress = (POINTER_TYPE)dest;

                                memset(dest, 0, size);
                        }
                        continue;
                }

                dest = (unsigned char *)VirtualAlloc(codeBase + section->VirtualAddress,section->SizeOfRawData,MEM_COMMIT,PAGE_READWRITE);

                memcpy(dest, data + section->PointerToRawData, section->SizeOfRawData);

                section->Misc.PhysicalAddress = (POINTER_TYPE)dest;
        }
}

static int ProtectionFlags[2][2][2] = {
        {
                {PAGE_NOACCESS, PAGE_WRITECOPY},
                {PAGE_READONLY, PAGE_READWRITE},
        },
        {
                {PAGE_EXECUTE, PAGE_EXECUTE_WRITECOPY},
                {PAGE_EXECUTE_READ, PAGE_EXECUTE_READWRITE},
        },
};

static void FinalizeSections(PMEMORYMODULE module)
{
        int i;

        PIMAGE_SECTION_HEADER section = IMAGE_FIRST_SECTION(module->headers);

#ifdef _WIN64
        POINTER_TYPE imageOffset = (module->headers->OptionalHeader.ImageBase & 0xffffffff00000000);
#else
        #define imageOffset 0
#endif
       
        for (i=0; i<module->headers->FileHeader.NumberOfSections; i++, section++)
        {
                DWORD protect, oldProtect, size;

                int executable = (section->Characteristics & IMAGE_SCN_MEM_EXECUTE) != 0;

                int readable =   (section->Characteristics & IMAGE_SCN_MEM_READ) != 0;

                int writeable =  (section->Characteristics & IMAGE_SCN_MEM_WRITE) != 0;

                if (section->Characteristics & IMAGE_SCN_MEM_DISCARDABLE)
                {
                        VirtualFree((LPVOID)((POINTER_TYPE)section->Misc.PhysicalAddress | imageOffset), section->SizeOfRawData, MEM_DECOMMIT);
                        continue;
                }

                protect = ProtectionFlags[executable][readable][writeable];

                if (section->Characteristics & IMAGE_SCN_MEM_NOT_CACHED)
                {
                        protect |= PAGE_NOCACHE;
                }

                size = section->SizeOfRawData;

                if (size == 0)
                {
                        if (section->Characteristics & IMAGE_SCN_CNT_INITIALIZED_DATA)
                        {
                                size = module->headers->OptionalHeader.SizeOfInitializedData;
                        } else if (section->Characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA)
                        {
                                size = module->headers->OptionalHeader.SizeOfUninitializedData;
                        }
                }
                if (size > 0)
                {
                        if (VirtualProtect((LPVOID)((POINTER_TYPE)section->Misc.PhysicalAddress | imageOffset), size, protect, &oldProtect) == 0)
                        {
                                dPrintf("Error protecting memory page");
                        }
                }
        }
#ifndef _WIN64
#undef imageOffset
#endif
}

static void PerformBaseRelocation(PMEMORYMODULE module, SIZE_T delta)
{
        DWORD i;

        unsigned char *codeBase = module->codeBase;

        PIMAGE_DATA_DIRECTORY directory = GET_HEADER_DICTIONARY(module, IMAGE_DIRECTORY_ENTRY_BASERELOC);

        if (directory->Size > 0)
        {
                PIMAGE_BASE_RELOCATION relocation = (PIMAGE_BASE_RELOCATION) (codeBase + directory->VirtualAddress);

                for (; relocation->VirtualAddress > 0; )
                {
                        unsigned char *dest = codeBase + relocation->VirtualAddress;

                        unsigned short *relInfo = (unsigned short *)((unsigned char *)relocation + IMAGE_SIZEOF_BASE_RELOCATION);

                        for (i=0; i<((relocation->SizeOfBlock-IMAGE_SIZEOF_BASE_RELOCATION) / 2); i++, relInfo++)
                        {
                                DWORD *patchAddrHL;
#ifdef _WIN64
                                ULONGLONG *patchAddr64;
#endif
                                int type, offset;

                                type = *relInfo >> 12;

                                offset = *relInfo & 0xfff;
                               
                                switch (type)
                                {
                                case IMAGE_REL_BASED_ABSOLUTE:
                                        break;
                                case IMAGE_REL_BASED_HIGHLOW:
                                        // change complete 32 bit address
                                        patchAddrHL = (DWORD *) (dest + offset);
                                        *patchAddrHL += delta;
                                        break;
#ifdef _WIN64
                                case IMAGE_REL_BASED_DIR64:
                                        patchAddr64 = (ULONGLONG *) (dest + offset);
                                        *patchAddr64 += delta;
                                        break;
#endif
                                default:
                                        break;
                                }
                        }
                        relocation = (PIMAGE_BASE_RELOCATION) (((char *) relocation) + relocation->SizeOfBlock);
                }
        }
}

static int BuildImportTable(PMEMORYMODULE module)
{
        int result = 1;

        unsigned char *codeBase = module->codeBase;

        PIMAGE_DATA_DIRECTORY directory = GET_HEADER_DICTIONARY(module, IMAGE_DIRECTORY_ENTRY_IMPORT);

        if (directory->Size > 0)
        {
                PIMAGE_IMPORT_DESCRIPTOR importDesc = (PIMAGE_IMPORT_DESCRIPTOR) (codeBase + directory->VirtualAddress);

                for (; !IsBadReadPtr(importDesc, sizeof(IMAGE_IMPORT_DESCRIPTOR)) && importDesc->Name; importDesc++)
                {
                        POINTER_TYPE *thunkRef;

                        FARPROC *funcRef;

                        HMODULE handle = LoadLibraryA((LPCSTR) (codeBase + importDesc->Name));

                        if (handle == INVALID_HANDLE_VALUE)
                        {
                                dPrintf("Can't load library");
                                result = 0;
                                break;
                        }

                        module->modules = (HMODULE *)realloc(module->modules, (module->numModules+1)*(sizeof(HMODULE)));

                        if (module->modules == NULL)
                        {
                                result = 0;
                                break;
                        }

                        module->modules[module->numModules++] = handle;

                        if (importDesc->OriginalFirstThunk)
                        {
                                thunkRef = (POINTER_TYPE *) (codeBase + importDesc->OriginalFirstThunk);
                                funcRef = (FARPROC *) (codeBase + importDesc->FirstThunk);
                        }
                        else
                        {
                                thunkRef = (POINTER_TYPE *) (codeBase + importDesc->FirstThunk);
                                funcRef = (FARPROC *) (codeBase + importDesc->FirstThunk);
                        }
                        for (; *thunkRef; thunkRef++, funcRef++)
                        {
                                if (IMAGE_SNAP_BY_ORDINAL(*thunkRef))
                                {
                                        *funcRef = (FARPROC)GetProcAddress(handle, (LPCSTR)IMAGE_ORDINAL(*thunkRef));
                                }
                                else
                                {
                                        PIMAGE_IMPORT_BY_NAME thunkData = (PIMAGE_IMPORT_BY_NAME) (codeBase + (*thunkRef));
                                        *funcRef = (FARPROC)GetProcAddress(handle, (LPCSTR)&thunkData->Name);
                                }
                                if (*funcRef == 0)
                                {
                                        result = 0;
                                        break;
                                }
                        }
                        if (!result)
                        {
                                break;
                        }
                }
        }
        return result;
}

//##############################################################################################################
//功能:加载模块
//##############################################################################################################
HMEMORYMODULE MemoryLoadLibrary(const void *data)
{
        PMEMORYMODULE result;

        PIMAGE_DOS_HEADER dos_header;

        PIMAGE_NT_HEADERS old_header;

        unsigned char *code, *headers;

        SIZE_T locationDelta;

        DllEntryProc DllEntry;

        BOOL successfull;

        dos_header = (PIMAGE_DOS_HEADER)data;

        if (dos_header->e_magic != IMAGE_DOS_SIGNATURE)
        {
                dPrintf("Not a valid executable file.\n");
                return NULL;
        }

        old_header = (PIMAGE_NT_HEADERS)&((const unsigned char *)(data))[dos_header->e_lfanew];

        if (old_header->Signature != IMAGE_NT_SIGNATURE)
        {
                dPrintf("No PE header found.\n");
                return NULL;
        }

        code = (unsigned char *)VirtualAlloc((LPVOID)(old_header->OptionalHeader.ImageBase),old_header->OptionalHeader.SizeOfImage,MEM_RESERVE,PAGE_READWRITE);

    if (code == NULL)
        {
        code = (unsigned char *)VirtualAlloc(NULL,old_header->OptionalHeader.SizeOfImage,MEM_RESERVE,PAGE_READWRITE);

                if (code == NULL)
                {
                        dPrintf("Can't reserve memory");
                        return NULL;
                }
        }
   
        result = (PMEMORYMODULE)HeapAlloc(GetProcessHeap(), 0, sizeof(MEMORYMODULE));

        result->codeBase = code;

        result->numModules = 0;

        result->modules = NULL;

        result->initialized = 0;

        VirtualAlloc(code,old_header->OptionalHeader.SizeOfImage,MEM_COMMIT,PAGE_READWRITE);

        headers = (unsigned char *)VirtualAlloc(code,old_header->OptionalHeader.SizeOfHeaders,MEM_COMMIT,PAGE_READWRITE);
       
        // 复制 PE文件头到代码
        memcpy(headers, dos_header, dos_header->e_lfanew + old_header->OptionalHeader.SizeOfHeaders);

        result->headers = (PIMAGE_NT_HEADERS)&((const unsigned char *)(headers))[dos_header->e_lfanew];

        // 更新位置
        result->headers->OptionalHeader.ImageBase = (POINTER_TYPE)code;

        // 复制DLL数据到新的内存
        CopySections((const unsigned char*)data, old_header, result);

        // 处理输入数据基址
        locationDelta = (SIZE_T)(code - old_header->OptionalHeader.ImageBase);

        if (locationDelta != 0)
        {
                PerformBaseRelocation(result, locationDelta);
        }

        // 处理输入表
        if (!BuildImportTable(result))
        {
                goto error;
        }

        FinalizeSections(result);

        //调用DLL入口函数 DllMain
        if (result->headers->OptionalHeader.AddressOfEntryPoint != 0)
        {
                DllEntry = (DllEntryProc) (code + result->headers->OptionalHeader.AddressOfEntryPoint);

                if (DllEntry == 0)
                {
                        dPrintf("Library has no entry point.\n");
                        goto error;
                }

                successfull = (*DllEntry)((HINSTANCE)code, DLL_PROCESS_ATTACH, 0); //调试发现加载MFC DLL直接停在这里,不向下运行了

                if (!successfull)
                {
                        dPrintf("Can't attach library.\n");
                        goto error;
                }
                result->initialized = 1;
        }
        return (HMEMORYMODULE)result;

error:

        MemoryFreeLibrary(result);

        return NULL;
}
//##############################################################################################################
//功能:获取模块函数地址
//##############################################################################################################
FARPROC MemoryGetProcAddress(HMEMORYMODULE module, const char *name)
{
        unsigned char *codeBase = ((PMEMORYMODULE)module)->codeBase;

        int idx = -1;

        DWORD i,*nameRef;

        WORD *ordinal;

        PIMAGE_EXPORT_DIRECTORY exports;

        PIMAGE_DATA_DIRECTORY directory = GET_HEADER_DICTIONARY((PMEMORYMODULE)module, IMAGE_DIRECTORY_ENTRY_EXPORT);

        if (directory->Size == 0)
        {
                return NULL;
        }

        exports = (PIMAGE_EXPORT_DIRECTORY) (codeBase + directory->VirtualAddress);

        if (exports->NumberOfNames == 0 || exports->NumberOfFunctions == 0)
        {
                return NULL;
        }

        nameRef = (DWORD *) (codeBase + exports->AddressOfNames);

        ordinal = (WORD *) (codeBase + exports->AddressOfNameOrdinals);

        for (i=0; i<exports->NumberOfNames; i++, nameRef++, ordinal++)
        {
                if (stricmp(name, (const char *) (codeBase + (*nameRef))) == 0)
                {
                        idx = *ordinal;
                        break;
                }
        }

        if (idx == -1)
        {
                return NULL;
        }

        if ((DWORD)idx > exports->NumberOfFunctions)
        {
                return NULL;
        }
        return (FARPROC) (codeBase + (*(DWORD *) (codeBase + exports->AddressOfFunctions + (idx*4))));
}
//##############################################################################################################
//功能:卸载模块
//##############################################################################################################
void MemoryFreeLibrary(HMEMORYMODULE mod)
{
        int i;

        PMEMORYMODULE module = (PMEMORYMODULE)mod;

        if (module != NULL)
        {
                if (module->initialized != 0)
                {
                        DllEntryProc DllEntry = (DllEntryProc) (module->codeBase + module->headers->OptionalHeader.AddressOfEntryPoint);

                        (*DllEntry)((HINSTANCE)module->codeBase, DLL_PROCESS_DETACH, 0);

                        module->initialized = 0;
                }

                if (module->modules != NULL)
                {
                        for (i=0; i<module->numModules; i++)
                        {
                                if (module->modules[i] != INVALID_HANDLE_VALUE)
                                {
                                        FreeLibrary(module->modules[i]);
                                }
                        }

                        free(module->modules);
                }

                if (module->codeBase != NULL)
                {
                        VirtualFree(module->codeBase, 0, MEM_RELEASE);
                }
                HeapFree(GetProcessHeap(), 0, module);
        }
}

[培训]传播安全知识、拓宽行业人脉——看雪讲师团队等你加入!

收藏
免费 0
支持
分享
最新回复 (5)
雪    币: 1787
活跃值: (345)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
2
140K9s2c8@1M7q4)9K6b7g2)9J5c8W2)9J5c8X3u0D9L8$3N6Q4x3X3g2U0M7$3c8F1i4K6u0W2L8X3g2@1i4K6u0r3L8r3W2K6N6h3&6D9K9h3^5H3i4K6u0r3j5i4u0@1K9h3y4D9k6g2)9J5c8X3c8W2N6r3q4A6L8s2y4Q4x3V1j5I4y4K6b7^5x3e0M7K6i4K6t1$3L8X3u0K6M7q4)9K6b7W2)9J5y4X3&6T1M7%4m8Q4x3@1u0Q4c8e0S2Q4b7V1k6Q4z5e0W2Q4c8e0W2Q4z5o6N6Q4z5p5y4Q4c8e0c8Q4b7U0W2Q4z5f1k6Q4c8e0c8Q4b7U0S2Q4z5o6m8Q4c8e0c8Q4b7V1q4Q4z5f1u0Q4c8e0k6Q4z5p5k6Q4z5p5k6Q4c8e0S2Q4b7V1k6Q4b7U0m8Q4c8e0y4Q4z5o6m8Q4z5o6u0Q4c8e0c8Q4b7V1c8Q4b7e0m8Q4c8e0g2Q4z5p5g2Q4b7V1u0Q4c8e0N6Q4z5f1y4Q4z5p5u0Q4c8e0N6Q4z5f1y4Q4z5p5u0Q4c8f1k6Q4b7V1y4Q4z5p5y4Q4c8e0c8Q4b7V1u0Q4z5e0k6Q4c8e0g2Q4z5p5k6Q4b7f1q4Q4c8e0k6Q4z5e0c8Q4b7V1g2Q4c8e0g2Q4z5o6N6Q4b7V1q4Q4c8e0c8Q4b7V1q4Q4z5o6k6D9K9h3u0Q4c8f1k6Q4b7V1y4Q4z5p5y4Q4c8e0k6Q4b7U0u0Q4b7e0q4Q4c8e0k6Q4z5f1y4Q4z5o6W2Q4c8e0k6Q4b7V1q4Q4z5e0m8Q4c8e0N6Q4b7e0m8Q4z5o6q4Q4c8f1k6Q4b7V1y4Q4z5p5y4Q4c8e0k6Q4z5f1y4Q4b7f1y4Q4c8e0k6Q4z5f1c8Q4b7e0g2Q4c8e0k6Q4z5o6W2Q4z5e0y4Q4c8e0N6Q4b7f1g2Q4z5e0N6Q4c8e0W2Q4z5o6m8Q4z5o6k6Q4c8e0c8Q4b7U0S2Q4z5p5u0Q4c8e0N6Q4z5f1q4Q4z5o6c8Q4c8f1k6Q4b7V1y4Q4z5p5y4Q4c8e0g2Q4z5e0m8Q4z5p5g2Q4c8e0W2Q4z5f1c8Q4b7e0u0Q4c8e0g2Q4b7V1y4Q4z5o6c8Q4c8e0c8Q4b7V1q4Q4z5o6k6Q4c8e0c8Q4b7U0S2Q4z5o6m8Q4c8e0g2Q4z5p5c8Q4z5p5q4Q4c8f1k6Q4b7V1y4Q4z5p5y4Q4c8e0k6Q4z5f1q4Q4z5o6u0Q4c8e0k6Q4z5e0N6Q4b7U0k6Q4c8e0k6Q4z5e0c8Q4b7V1g2Q4c8e0g2Q4b7V1y4Q4z5o6y4Q4c8e0c8Q4b7V1q4Q4z5o6k6Q4c8e0y4Q4z5o6m8Q4z5o6t1`.

下面是原话:
在测试Bo2000的源代码时发现可以使多数的简单.dll文件正确加载,却无法正确加载用MFC生成的.dll文件以及压缩过的可执行文件,仔细调试发现GetModuleFileName是罪魁祸首(另外BO2k里面dll_load存在好几个BUG,这也是其不稳定的直接原因.),调用这个函数将返回NULL,而一般的Dll编写者都默认这个返回结果不会是NULL,并且依赖这个返回结果。
既然找到了原因,那么就可以使用相应的对策来克服之。在这里,我是通过在Pe的映象尾部附加了一个PeBlock的块来解决这个问题(如果仅要求在进程本身加载.dll,这个PeBlock是没有必要的,但是为了能够在其它进程中加载和兼顾加载.exe,使用这个PeBlock是必要的),通过这个PeBlock,不但可以加载.dll,还可以加载.exe(包括压缩的DLL和EXE.)。
2011-10-6 13:45
0
雪    币: 773
活跃值: (447)
能力值: ( LV9,RANK:200 )
在线值:
发帖
回帖
粉丝
3
多谢yezhulove兄,我去详细看下
2011-10-6 14:13
0
雪    币: 773
活跃值: (447)
能力值: ( LV9,RANK:200 )
在线值:
发帖
回帖
粉丝
4
可惜 那个博客没有开发完整源代码,PeBlock 进程环境块,我看他是申请内存 然后将 路径写入 内存
然后创建远程线程 ,实验了下出错。。
2011-10-6 16:41
0
雪    币: 29893
活跃值: (3302)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
5
应该是有些东西没处理.
如果DLL是DELPHIXE2编译的,64位的,也有问题.加载后就0x0eedfade错误.
但如果用VS编译的64位DLL,网上的代码都工作的很好.
2011-11-17 13:17
0
雪    币: 100
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
FinalizeSections(result); 对加壳不兼容就因为这函数,注视掉这个,加载vmp不校验的dll,毫无压力,校验了,不行

                //if (section->Characteristics & IMAGE_SCN_MEM_DISCARDABLE)
                //{
                        // section is not needed any more and can safely be freed
                        //VirtualFree((LPVOID)section->Misc.PhysicalAddress, section->SizeOfRawData, MEM_DECOMMIT);
                //        continue;
                //}
上传的附件:
2011-11-17 17:06
0
游客
登录 | 注册 方可回帖
返回