开启辅助访问 切换到宽版

精易论坛

 找回密码
 注册

QQ登录

只需一步,快速开始

用微信号发送消息登录论坛

新人指南 邀请好友注册 - 我关注人的新帖 教你赚取精币 - 每日签到


求职/招聘- 论坛接单- 开发者大厅

论坛版规 总版规 - 建议/投诉 - 应聘版主 - 精华帖总集 积分说明 - 禁言标准 - 有奖举报

查看: 1512|回复: 32
收起左侧

[易源码分享] 【汇编/置入代码】PE加载器:内存运行EXE、加载DLL

[复制链接]
结帖率:100% (3/3)
发表于 6 天前 | 显示全部楼层 |阅读模式   广东省汕头市
分享源码
界面截图:
是否带模块: -
备注说明: -
本帖最后由 LLJ 于 2026-2-26 23:40 编辑

PE加载器

  • 可执行文件数据不会写入盘中。

    • 常见用法是将可执行文件导入资源表,或者从网络下载到内存,然后调用加载内存DLL运行内存EXE
  • 加载内存DLL是无模块、无文件的形式加载。相关术语是Manual MappingReflective DLL

    • 可能不兼容某些需要读取自身文件的DLL,但这种情况比较少见!
  • 运行内存EXE易语言纯源码可以看 https://bbs.ijingyi.com/thread-14872894-1-1.html

汇编代码是直接通过C语言实现从PEB及LDR获取API调用并由VC优化编译器生成。


PE加载器.zip (6.01 KB, 下载次数: 163)

评分

参与人数 4好评 +2 精币 +11 收起 理由
cbl521ysys + 1 感谢分享,很给力!~
猪滴寳貝哝 + 1 + 2 感谢分享,很给力!~
sinewtec + 1 + 3 支持开源~!感谢分享
bianyuan456 + 5 支持开源~!感谢分享

查看全部评分


本帖被以下淘专辑推荐:

  • · 鱼木|主题: 1632, 订阅: 159
  • · 收藏|主题: 364, 订阅: 6
结帖率:100% (3/3)
 楼主| 发表于 4 天前 | 显示全部楼层   广东省汕头市

这是C源码,有特殊需求的可以自己修改,也可以看看代码。
[C] 纯文本查看 复制代码
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <stddef.h>

#if !defined(NTSTATUS)
typedef LONG NTSTATUS;
typedef NTSTATUS *PNTSTATUS;
#endif
#define STATUS_SUCCESS            ((NTSTATUS)0x00000000L)
#define STATUS_UNSUCCESSFUL        ((NTSTATUS)0xC0000001L)

#if defined(_M_IX86)
#define GET_PEB() (uintptr_t)__readfsdword(0x30)
#elif defined(_M_AMD64)
#define GET_PEB() (uintptr_t)__readgsqword(0x60)
#endif

struct UNICODE_STRING {
        USHORT Length;
        USHORT MaximumLength;
        PWSTR  Buffer;
};

static struct MY_LIST_ENTRY
{
        struct MY_LIST_ENTRY *Flink;
        struct MY_LIST_ENTRY *Blink;
};

struct PEB_LDR_DATA
{
        ULONG                Length;
        UCHAR                Initialized;
        VOID*                SsHandle;
        struct MY_LIST_ENTRY InLoadOrderModuleList;
        struct MY_LIST_ENTRY InMemoryOrderModuleList;
        struct MY_LIST_ENTRY InInitializationOrderModuleList;
        VOID*                EntryInProgress;
        UCHAR                ShutdownInProgress;
        VOID*                ShutdownThreadId;
};

struct PEB
{
        UCHAR                InheritedAddressSpace;
        UCHAR                ReadImageFileExecOptions;
        UCHAR                BeingDebugged;
        UCHAR                BitField;
        VOID*                Mutant;
        VOID*                ImageBaseAddress;
        struct PEB_LDR_DATA* Ldr;
        // 省略...
};

struct LDR_DATA_TABLE_ENTRY
{
        struct MY_LIST_ENTRY  InLoadOrderLinks;
        struct MY_LIST_ENTRY  InMemoryOrderLinks;
        struct MY_LIST_ENTRY  InInitializationOrderLinks;
        VOID*                 DllBase;
        VOID*                 EntryPoint;
        ULONG                 SizeOfImage;
        struct UNICODE_STRING FullDllName;
        struct UNICODE_STRING BaseDllName;
        ULONG                 Flags;
        USHORT                LoadCount;
        USHORT                TlsIndex;
        // 省略...
};


static __forceinline int my_wcsnicmp(wchar_t *s1, wchar_t *s2, size_t n)
{
        wchar_t c1 = 0, c2 = 0;
        size_t i;
        for(i = 0; i < n; i++)
        {
                c1 = s1;
                c2 = s2;
                if (c1 == 0) break;
                if (c1 >= 'A' && c1 <= 'Z') c1 += 32;
                if (c2 >= 'A' && c2 <= 'Z') c2 += 32;
                if (c1 != c2) break;
        }
        return (c1 - c2);
}

static __forceinline int my_strcmp(const char *s1, const char *s2)
{
        while (*s1 && *s1 == *s2) {
                s1++; s2++;
        }
        return *s1 - *s2;
}

static __forceinline void* my_memcpy(void* d, const void* s, size_t n)
{
        size_t i;
        for (i = 0; i < n; i++) {
                ((char*)d) = ((char*)s);
        }
        return d;
}

static __forceinline int my_wcsnicmpA(wchar_t *s1, char *s2, size_t n)
{
        wchar_t c1 = 0, c2 = 0;
        size_t i;
        for(i = 0; i < n; i++)
        {
                c1 = s1;
                c2 = s2;
                if (c1 == 0) break;
                if (c1 >= 'A' && c1 <= 'Z') c1 += 32;
                if (c2 >= 'A' && c2 <= 'Z') c2 += 32;
                if (c1 != c2) break;
        }
        return (c1 - c2);
}

static void* myGetModuleHandleW(wchar_t* name)
{
        struct PEB* peb = (struct PEB*)GET_PEB();
        struct MY_LIST_ENTRY* head = &peb->Ldr->InLoadOrderModuleList;
        struct LDR_DATA_TABLE_ENTRY* entry = (struct LDR_DATA_TABLE_ENTRY*)head->Flink;
        while((struct MY_LIST_ENTRY*)entry != head)
        {
                if (my_wcsnicmp(entry->BaseDllName.Buffer, name, entry->BaseDllName.Length) == 0)
                {
                        return entry->DllBase;
                }
                entry = (struct LDR_DATA_TABLE_ENTRY*)entry->InLoadOrderLinks.Flink;
        }
        return NULL;
}

static __forceinline void* myGetModuleHandleA(char* name) // 不支持扩展字符
{
        struct PEB* peb = (struct PEB*)GET_PEB();
        struct MY_LIST_ENTRY* head = &peb->Ldr->InLoadOrderModuleList;
        struct LDR_DATA_TABLE_ENTRY* entry = (struct LDR_DATA_TABLE_ENTRY*)head->Flink;
        while((struct MY_LIST_ENTRY*)entry != head)
        {
                if (my_wcsnicmpA(entry->BaseDllName.Buffer, name, entry->BaseDllName.Length) == 0)
                {
                        return entry->DllBase;
                }
                entry = (struct LDR_DATA_TABLE_ENTRY*)entry->InLoadOrderLinks.Flink;
        }
        return NULL;
}

static __forceinline void* myGetProcAddress(void* base, char* name)
{
        IMAGE_DOS_HEADER* dos = (PIMAGE_DOS_HEADER)base;
        IMAGE_NT_HEADERS* nt = (PIMAGE_NT_HEADERS)((UINT_PTR)base + dos->e_lfanew);
        IMAGE_DATA_DIRECTORY* dir = &nt->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT];
        if (dir->Size > 0)
        {
                IMAGE_EXPORT_DIRECTORY* exportDir = (IMAGE_EXPORT_DIRECTORY*)((UINT_PTR)base + dir->VirtualAddress);
                DWORD* names = (DWORD*)((UINT_PTR)base + exportDir->AddressOfNames);
                DWORD* functions = (DWORD*)((UINT_PTR)base + exportDir->AddressOfFunctions);
                WORD* ordinals = (WORD*)((UINT_PTR)base + exportDir->AddressOfNameOrdinals);
                DWORD i;
                for (i = 0; i < exportDir->NumberOfNames; i++)
                {
                        if (my_strcmp((char*)base + names, name) == 0)
                        {
                                return (void*)((UINT_PTR)base + functions[ordinals]);
                        }
                }
        }
        return NULL;
}


// 相对虚拟地址转文件偏移
static __forceinline UINT_PTR RVA2FO(UINT16 SectionNumber, IMAGE_SECTION_HEADER* SectionPtr, UINT_PTR RVA)
{
        UINT16 i;
        for (i = 0; i < SectionNumber; i++)
        {
                if (RVA >= SectionPtr.VirtualAddress && RVA <= SectionPtr.VirtualAddress + SectionPtr.SizeOfRawData)
                {
                        return RVA - SectionPtr.VirtualAddress + SectionPtr.PointerToRawData;
                }
        }
        return 0;
}

BOOL __stdcall RunEXE(char* pFileData, BOOL wait, char** CommandLine, char** ApplicationName) // Process Hollowing
{
        const size_t OffsetOf_PEB_ImageBaseAddress = offsetof(struct PEB, ImageBaseAddress);
        char str1[] = {'k', 'e', 'r', 'n', 'e', 'l', '3', '2', '.', 'd', 'l', 'l', 0};
        char str2[] = {'G', 'e', 't', 'P', 'r', 'o', 'c', 'A', 'd', 'd', 'r', 'e', 's', 's', 0};
        char str3[] = {'G', 'e', 't', 'S', 'y', 's', 't', 'e', 'm', 'D', 'i', 'r', 'e', 'c', 't', 'o', 'r', 'y', 'A', 0};
        char str4[] = {'C', 'r', 'e', 'a', 't', 'e', 'P', 'r', 'o', 'c', 'e', 's', 's', 'A', 0};
        char str5[] = {'V', 'i', 'r', 't', 'u', 'a', 'l', 'A', 'l', 'l', 'o', 'c', 'E', 'x', 0};
        char str6[] = {'C', 'l', 'o', 's', 'e', 'H', 'a', 'n', 'd', 'l', 'e', 0};
        char str7[] = {'W', 'a', 'i', 't', 'F', 'o', 'r', 'S', 'i', 'n', 'g', 'l', 'e', 'O', 'b', 'j', 'e', 'c', 't', 0};
        //char str8[] = {'G', 'e', 't', 'E', 'x', 'i', 't', 'C', 'o', 'd', 'e', 'P', 'r', 'o', 'c', 'e', 's', 's', 0};
        void *kernel32 = myGetModuleHandleA(str1);
        void * (WINAPI *api_GetProcAddress)      (HMODULE hModule, LPCSTR lpProcName) = myGetProcAddress(kernel32, str2);
        UINT   (WINAPI *api_GetSystemDirectoryA) (LPSTR lpBuffer, UINT uSize) = api_GetProcAddress(kernel32, str3);
        BOOL   (WINAPI *api_CreateProcessA)      (LPCSTR lpApplicationName, LPSTR lpCommandLine, LPSECURITY_ATTRIBUTES lpProcessAttributes, LPSECURITY_ATTRIBUTES lpThreadAttributes, BOOL bInheritHandles, DWORD dwCreationFlags, LPVOID lpEnvironment, LPCSTR lpCurrentDirectory, LPSTARTUPINFOA lpStartupInfo, LPPROCESS_INFORMATION lpProcessInformation) = api_GetProcAddress(kernel32, str4);
        LPVOID (WINAPI *api_VirtualAllocEx)      (HANDLE hProcess, LPVOID lpAddress, SIZE_T dwSize, DWORD flAllocationType, DWORD flProtect) = api_GetProcAddress(kernel32, str5);
        BOOL   (WINAPI *api_CloseHandle)         (HANDLE hObject) = api_GetProcAddress(kernel32, str6);
        DWORD  (WINAPI *api_WaitForSingleObject) (HANDLE hHandle, DWORD dwMilliseconds) = api_GetProcAddress(kernel32, str7);
        //BOOL   (WINAPI *api_GetExitCodeProcess)  (HANDLE hProcess, LPDWORD lpExitCode) = api_GetProcAddress(kernel32, str8);
        char str9[]  = {'n', 't', 'd', 'l', 'l', '.', 'd', 'l', 'l', 0};
        char str10[] = {'N', 't', 'G', 'e', 't', 'C', 'o', 'n', 't', 'e', 'x', 't', 'T', 'h', 'r', 'e', 'a', 'd', 0};
        char str11[] = {'N', 't', 'S', 'e', 't', 'C', 'o', 'n', 't', 'e', 'x', 't', 'T', 'h', 'r', 'e', 'a', 'd', 0};
        char str12[] = {'N', 't', 'R', 'e', 's', 'u', 'm', 'e', 'T', 'h', 'r', 'e', 'a', 'd', 0};
        char str13[] = {'N', 't', 'T', 'e', 'r', 'm', 'i', 'n', 'a', 't', 'e', 'P', 'r', 'o', 'c', 'e', 's', 's', 0};
        char str14[] = {'N', 't', 'R', 'e', 'a', 'd', 'V', 'i', 'r', 't', 'u', 'a', 'l', 'M', 'e', 'm', 'o', 'r', 'y', 0};
        char str15[] = {'N', 't', 'W', 'r', 'i', 't', 'e', 'V', 'i', 'r', 't', 'u', 'a', 'l', 'M', 'e', 'm', 'o', 'r', 'y', 0};
        char str16[] = {'N', 't', 'U', 'n', 'm', 'a', 'p', 'V', 'i', 'e', 'w', 'O', 'f', 'S', 'e', 'c', 't', 'i', 'o', 'n', 0};
        void *ntdll = myGetModuleHandleA(str9);
        NTSTATUS (NTAPI *api_NtGetContextThread)  (HANDLE, PCONTEXT) = api_GetProcAddress(ntdll, str10);
        NTSTATUS (NTAPI *api_NtSetContextThread)  (HANDLE, PCONTEXT) = api_GetProcAddress(ntdll, str11);
        NTSTATUS (NTAPI *api_NtResumeThread)      (HANDLE, PULONG) = api_GetProcAddress(ntdll, str12);
        NTSTATUS (NTAPI *api_NtTerminateProcess)  (HANDLE, NTSTATUS) = api_GetProcAddress(ntdll, str13);
        NTSTATUS (NTAPI *api_NtReadVirtualMemory) (HANDLE, PVOID, PVOID, ULONG, PULONG) = api_GetProcAddress(ntdll, str14);
        NTSTATUS (NTAPI *api_NtWriteVirtualMemory)(HANDLE, PVOID, PVOID, ULONG, PULONG) = api_GetProcAddress(ntdll, str15);
        NTSTATUS (NTAPI *api_NtUnmapViewOfSection)(HANDLE, PVOID) = api_GetProcAddress(ntdll, str16);

        IMAGE_DOS_HEADER* idh;
        IMAGE_NT_HEADERS* inh;
        STARTUPINFOA si;
        PROCESS_INFORMATION pi;
        char path[MAX_PATH];
        char *pAppName = *ApplicationName;

        idh = (IMAGE_DOS_HEADER*)pFileData;
        if (idh->e_magic != IMAGE_DOS_SIGNATURE) return FALSE;
        inh = (IMAGE_NT_HEADERS*)(pFileData + idh->e_lfanew);
        if (inh->Signature != IMAGE_NT_SIGNATURE) return FALSE;

        if (pAppName == 0 || *pAppName == 0)
        {
                size_t len = api_GetSystemDirectoryA(path, MAX_PATH);
                { // strcat
                        char str[] = {'\\', 'c', 'm', 'd', '.', 'e', 'x', 'e', 0};
                        char* destination = path + len;
                        char* source = str;
                        //while (*destination) ++destination; //strlen
                        while ((*destination++ = *source++)); //strcpy
                }
                pAppName = path;
        }
        si.cb = sizeof(si);
        si.lpReserved = NULL;
        si.lpDesktop = NULL;
        si.lpTitle = NULL;
        si.dwX = 0;
        si.dwY = 0;
        si.dwXSize = 0;
        si.dwYSize = 0;
        si.dwXCountChars = 0;
        si.dwYCountChars = 0;
        si.dwFillAttribute = 0;
        si.dwFlags = 0;
        si.wShowWindow = 0;
        si.cbReserved2 = 0;
        si.lpReserved2 = NULL;
        si.hStdInput = NULL;
        si.hStdOutput = NULL;
        si.hStdError = NULL;
        if (!api_CreateProcessA(pAppName, *CommandLine, NULL, NULL, FALSE, CREATE_SUSPENDED, NULL, NULL, &si, &pi))
        {
                // 创建进程 失败
                return FALSE;
        }
        do
        {
                IMAGE_SECTION_HEADER* ish;
                CONTEXT context;
                UINT_PTR FakeImageBase;
                UINT_PTR OldImageBase;
                UINT_PTR NewImageBase;
                UINT_PTR NewImageSize;
                UINT_PTR peb;
                UINT16 sectionsNumber;
                UINT16 sectionsIndex;
                ULONG PreviousSuspendCount;

                context.ContextFlags = CONTEXT_FULL;
                if (api_NtGetContextThread(pi.hThread, &context) != STATUS_SUCCESS)
                {
                        // 获取线程上下文 失败
                        break;
                }
#ifndef _WIN64
                peb = context.Ebx;
#else
                peb = context.Rdx;
#endif
                if (api_NtReadVirtualMemory(pi.hProcess, (PVOID)(peb + OffsetOf_PEB_ImageBaseAddress), &FakeImageBase, sizeof(FakeImageBase), NULL) != STATUS_SUCCESS) //PEB.ImageBase
                {
                        // 读进程内存 失败
                        break;
                }
                OldImageBase = inh->OptionalHeader.ImageBase;
                NewImageSize = inh->OptionalHeader.SizeOfImage;
                if (OldImageBase == FakeImageBase) // 冲突
                {
                        if ((inh->FileHeader.Characteristics & IMAGE_FILE_RELOCS_STRIPPED) != 0)
                        {
                                if (api_NtUnmapViewOfSection(pi.hProcess, (PVOID)FakeImageBase) != STATUS_SUCCESS)
                                {
                                        // 此文件没有重定位信息,不支持动态基址,并且固定基址不可用!
                                        break;
                                }
                        }
                }
                NewImageBase = (UINT_PTR)api_VirtualAllocEx(pi.hProcess, (PVOID)OldImageBase, NewImageSize, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
                if (!NewImageBase) // 不能使用固定基址
                {
                        // 尝试使用动态基址
                        NewImageBase = (UINT_PTR)api_VirtualAllocEx(pi.hProcess, NULL, NewImageSize, MEM_RESERVE | MEM_COMMIT, PAGE_EXECUTE_READWRITE);
                        if (!NewImageBase)
                        {
                                // 调用 VirtualAllocEx 函数失败!
                                break;
                        }
                        // 动态基址在 Windows 10 不需要自己重定位,但以防万一和为了兼容还是自己重定位。
                        { // 修改PE文件的重定位地址
                                IMAGE_DATA_DIRECTORY* pDir = &inh->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC];
                                UINT_PTR size = pDir->Size;
                                ish = (IMAGE_SECTION_HEADER*)((UINT_PTR)inh + offsetof(IMAGE_NT_HEADERS, OptionalHeader) + inh->FileHeader.SizeOfOptionalHeader);
                                sectionsNumber = inh->FileHeader.NumberOfSections;
                                if (size > 0)
                                {
                                        IMAGE_BASE_RELOCATION* pBaseRelocation = (IMAGE_BASE_RELOCATION*)((UINT_PTR)idh + RVA2FO(sectionsNumber, ish, pDir->VirtualAddress));
                                        INT_PTR deltaBase = NewImageBase - OldImageBase;
                                        UINT_PTR end_ptr = (UINT_PTR)pBaseRelocation + size;
                                        while (end_ptr > (UINT_PTR)pBaseRelocation)
                                        {
                                                UINT_PTR address = pBaseRelocation->VirtualAddress;
                                                size_t size = pBaseRelocation->SizeOfBlock;
                                                WORD* blockPtr = (WORD*)((UINT_PTR)pBaseRelocation + sizeof(IMAGE_BASE_RELOCATION));
                                                UINT_PTR blockEndPtr = (UINT_PTR)pBaseRelocation + pBaseRelocation->SizeOfBlock;
                                                for (; blockEndPtr > (UINT_PTR)blockPtr; blockPtr++)
                                                {
                                                        WORD type = *blockPtr >> 0x0C;
                                                        WORD offset = *blockPtr & 0x0FFF;
#ifndef _WIN64
                                                        if (type == IMAGE_REL_BASED_HIGHLOW)
                                                        {
                                                                UINT_PTR p = (UINT_PTR)idh + RVA2FO(sectionsNumber, ish, address + offset);
                                                                *(UINT32*)(p) += deltaBase;
                                                        }
#else
                                                        if (type == IMAGE_REL_BASED_DIR64)
                                                        {
                                                                UINT_PTR p = (UINT_PTR)idh + RVA2FO(sectionsNumber, ish, address + offset);
                                                                *(UINT64*)(p) += deltaBase;
                                                        }
#endif
                                                }
                                                pBaseRelocation = (IMAGE_BASE_RELOCATION*)blockEndPtr;
                                        }
                                }
                                inh->OptionalHeader.ImageBase = NewImageBase;
                        }
                }

                if (api_NtWriteVirtualMemory(pi.hProcess, (PVOID)(peb + OffsetOf_PEB_ImageBaseAddress), &NewImageBase, sizeof(NewImageBase), NULL) != STATUS_SUCCESS)
                {
                        // 写进程内存 失败
                        break;
                }
#ifndef _WIN64
                context.Eax = NewImageBase + inh->OptionalHeader.AddressOfEntryPoint; //入口点
#else
                context.Rcx = NewImageBase + inh->OptionalHeader.AddressOfEntryPoint; //入口点
#endif
                if (api_NtSetContextThread(pi.hThread, &context) != STATUS_SUCCESS)
                {
                        break;
                }

                if (api_NtWriteVirtualMemory(pi.hProcess, (PVOID)NewImageBase, idh, inh->OptionalHeader.SizeOfHeaders, NULL) != STATUS_SUCCESS)
                {
                        break;
                }

                ish = IMAGE_FIRST_SECTION(inh);
                sectionsNumber = inh->FileHeader.NumberOfSections;
                for (sectionsIndex = 0; sectionsIndex < sectionsNumber; sectionsIndex++)
                {
                        DWORD VirtualAddress = ish[sectionsIndex].VirtualAddress;
                        DWORD VirtualSize = ish[sectionsIndex].Misc.VirtualSize;
                        DWORD PointerToRawData = ish[sectionsIndex].PointerToRawData;
                        DWORD SizeOfRawData = ish[sectionsIndex].SizeOfRawData;
                        api_NtWriteVirtualMemory(pi.hProcess, (PVOID)(NewImageBase + VirtualAddress), (PVOID)((UINT_PTR)idh + PointerToRawData), SizeOfRawData, NULL);
                }
                if (api_NtResumeThread(pi.hThread, &PreviousSuspendCount) != STATUS_SUCCESS)
                {
                        break;
                }
                api_CloseHandle(pi.hThread);
                if (wait)
                {
                        api_WaitForSingleObject(pi.hProcess, -1);
                }
                api_CloseHandle(pi.hProcess);
                return TRUE;
        } while (FALSE);
        api_NtTerminateProcess(pi.hProcess, 0);
        api_CloseHandle(pi.hThread);
        api_CloseHandle(pi.hProcess);
        return FALSE;
}


void* __stdcall LoadDLL(char* pFileData) // Manual Mapping
{
        char str1[] = {'k', 'e', 'r', 'n', 'e', 'l', '3', '2', '.', 'd', 'l', 'l', 0};
        char str2[] = {'G', 'e', 't', 'P', 'r', 'o', 'c', 'A', 'd', 'd', 'r', 'e', 's', 's', 0};
        char str3[] = {'L', 'o', 'a', 'd', 'L', 'i', 'b', 'r', 'a', 'r', 'y', 'A', 0};
        char str4[] = {'V', 'i', 'r', 't', 'u', 'a', 'l', 'A', 'l', 'l', 'o', 'c', 0};
        char str5[] = {'V', 'i', 'r', 't', 'u', 'a', 'l', 'F', 'r', 'e', 'e', 0};
        void *kernel32 = myGetModuleHandleA(str1);
        FARPROC (WINAPI *api_GetProcAddress)(HMODULE hModule, LPCSTR lpProcName) = myGetProcAddress(kernel32, str2);
        HMODULE (WINAPI *api_LoadLibraryA)  (LPCSTR lpLibFileName) = (void*)api_GetProcAddress(kernel32, str3);
        LPVOID  (WINAPI *api_VirtualAlloc)  (LPVOID lpAddress, SIZE_T dwSize, DWORD flAllocationType, DWORD flProtect) = (void*)api_GetProcAddress(kernel32, str4);
        BOOL    (WINAPI *api_VirtualFree)   (LPVOID lpAddress, SIZE_T dwSize, DWORD dwFreeType) = (void*)api_GetProcAddress(kernel32, str5);

        PIMAGE_DOS_HEADER dos;
        PIMAGE_NT_HEADERS nt;
        DWORD imageSize;
        char* imageBuffer;
        PIMAGE_SECTION_HEADER sections;
        WORD sectionNumber;
        WORD sectionIndex;
        BOOL (WINAPI *ep)(HMODULE, DWORD, LPVOID);

        dos = (PIMAGE_DOS_HEADER)pFileData;
        if (IMAGE_DOS_SIGNATURE != dos->e_magic) return NULL;
        nt = (PIMAGE_NT_HEADERS)((UINT_PTR)pFileData + dos->e_lfanew);
        if (IMAGE_NT_SIGNATURE != nt->Signature) return NULL;
#ifdef _WIN64
        if (IMAGE_FILE_MACHINE_AMD64 != nt->FileHeader.Machine) return NULL;
#else
        if (IMAGE_FILE_MACHINE_I386 != nt->FileHeader.Machine) return NULL;
#endif
        imageSize = nt->OptionalHeader.SizeOfImage;
        imageBuffer = (char*)api_VirtualAlloc(NULL, imageSize, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
        if (!imageBuffer) return NULL;

        // Header
        my_memcpy(imageBuffer, pFileData, nt->OptionalHeader.SizeOfHeaders);

        // Section
        sections = (PIMAGE_SECTION_HEADER)((UINT_PTR)nt + FIELD_OFFSET(IMAGE_NT_HEADERS, OptionalHeader) + nt->FileHeader.SizeOfOptionalHeader);
        sectionNumber = nt->FileHeader.NumberOfSections;
        for (sectionIndex = 0; sectionIndex < sectionNumber; sectionIndex++)
        {
                my_memcpy(imageBuffer + sections[sectionIndex].VirtualAddress, pFileData + sections[sectionIndex].PointerToRawData, sections[sectionIndex].SizeOfRawData);
        }

        // BaseReloc
        {
                PIMAGE_DATA_DIRECTORY pDir = &nt->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC];
                if (pDir->Size > 0)
                {
                        UINT_PTR oldBase = (UINT_PTR)nt->OptionalHeader.ImageBase;
                        UINT_PTR newBase = (UINT_PTR)imageBuffer;
                        UINT_PTR deltaBase = newBase - oldBase;
                        PIMAGE_BASE_RELOCATION pBaseRelocation = (PIMAGE_BASE_RELOCATION)(imageBuffer + pDir->VirtualAddress);
                        UINT_PTR relocationEndPtr = (UINT_PTR)pBaseRelocation + pDir->Size;
                        while (relocationEndPtr > (UINT_PTR)pBaseRelocation)
                        {
                                UINT_PTR address = (UINT_PTR)imageBuffer + pBaseRelocation->VirtualAddress;
                                WORD* blockPtr = (WORD*)((UINT_PTR)pBaseRelocation + sizeof(IMAGE_BASE_RELOCATION));
                                UINT_PTR blockEndPtr = (UINT_PTR)pBaseRelocation + pBaseRelocation->SizeOfBlock;
                                while (blockEndPtr > (UINT_PTR)blockPtr)
                                {
                                        WORD type = *blockPtr >> 0x0C;
                                        WORD offset = *blockPtr & 0x0FFF;
#ifndef _WIN64
                                        if (type == IMAGE_REL_BASED_HIGHLOW)
                                        {
                                                *(UINT32*)(address + offset) += deltaBase;
                                        }
#else
                                        if (type == IMAGE_REL_BASED_DIR64)
                                        {
                                                *(UINT64*)(address + offset) += deltaBase;
                                        }
#endif
                                        blockPtr++;
                                }
                                pBaseRelocation = (IMAGE_BASE_RELOCATION*)blockEndPtr;
                        }
                }
        }

        // Import
        {
                PIMAGE_DATA_DIRECTORY pDir = &nt->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT];
                if (pDir->Size > 0)
                {
                        PIMAGE_IMPORT_DESCRIPTOR pImportDescriptor = (PIMAGE_IMPORT_DESCRIPTOR)(imageBuffer + pDir->VirtualAddress);
                        for (; pImportDescriptor->Characteristics; pImportDescriptor++)
                        {
                                char* name = imageBuffer + pImportDescriptor->Name;
                                HMODULE hModule = api_LoadLibraryA(name);
                                IMAGE_THUNK_DATA* pOriginalFirstThunk;
                                IMAGE_THUNK_DATA* pThunkData;
                                if (hModule == NULL)
                                {
                                        api_VirtualFree(imageBuffer, 0, MEM_RELEASE); return NULL;
                                }
                                pOriginalFirstThunk = (IMAGE_THUNK_DATA*)(imageBuffer + pImportDescriptor->OriginalFirstThunk);
                                pThunkData = (IMAGE_THUNK_DATA*)(imageBuffer + pImportDescriptor->FirstThunk);
                                while (pOriginalFirstThunk->u1.Function)
                                {
                                        FARPROC address;
                                        if (pOriginalFirstThunk->u1.Ordinal & IMAGE_ORDINAL_FLAG)
                                        {
                                                UINT_PTR ordinal = IMAGE_ORDINAL(pOriginalFirstThunk->u1.Ordinal);
                                                address = api_GetProcAddress(hModule, (LPCSTR)ordinal);
                                        }
                                        else
                                        {
                                                IMAGE_IMPORT_BY_NAME* pName = (IMAGE_IMPORT_BY_NAME*)(imageBuffer + pOriginalFirstThunk->u1.AddressOfData);
                                                address = api_GetProcAddress(hModule, (LPCSTR)pName->Name);
                                        }
                                        if (address == NULL)
                                        {
                                                api_VirtualFree(imageBuffer, 0, MEM_RELEASE); return NULL;
                                        }
                                        pThunkData->u1.Function = (UINT_PTR)address;
                                        pOriginalFirstThunk++; pThunkData++;
                                }
                        }
                }
        }

        // ImageBase
        dos = (PIMAGE_DOS_HEADER)imageBuffer;
        nt = (PIMAGE_NT_HEADERS)((UINT_PTR)imageBuffer + dos->e_lfanew);
        nt->OptionalHeader.ImageBase = (UINT_PTR)imageBuffer;
/*
        // TLS
        {
                PIMAGE_DATA_DIRECTORY pDir = &nt->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_TLS];
                if (pDir->Size > 0)
                {
                        PIMAGE_TLS_DIRECTORY TLS = (PIMAGE_TLS_DIRECTORY)(imageBuffer + pDir->VirtualAddress);
                        PIMAGE_TLS_CALLBACK* CallBacks = (PIMAGE_TLS_CALLBACK*)TLS->AddressOfCallBacks;
                        for (; *CallBacks; CallBacks++)
                        {
                                ep = (void*)*CallBacks;
                                ep((HMODULE)imageBuffer, DLL_PROCESS_ATTACH, NULL);
                        }
                }
        }
*/
        // DllMain
        ep = (void*)(imageBuffer + nt->OptionalHeader.AddressOfEntryPoint);
        ep((HMODULE)imageBuffer, DLL_PROCESS_ATTACH, NULL);
        return imageBuffer;
}

BOOL __stdcall FreeDll(void* h)
{
        char str1[] = {'k', 'e', 'r', 'n', 'e', 'l', '3', '2', '.', 'd', 'l', 'l', 0};
        char str2[] = {'V', 'i', 'r', 't', 'u', 'a', 'l', 'F', 'r', 'e', 'e', 0};
        void *kernel32 = myGetModuleHandleA(str1);
        BOOL (WINAPI *api_VirtualFree)(LPVOID lpAddress, SIZE_T dwSize, DWORD dwFreeType) = (void*)myGetProcAddress(kernel32, str2);

        PIMAGE_DOS_HEADER dos;
        PIMAGE_NT_HEADERS nt;
        BOOL (WINAPI *ep)(HMODULE, DWORD, LPVOID);

        dos = (PIMAGE_DOS_HEADER)h;
        nt = (PIMAGE_NT_HEADERS)((UINT_PTR)h + dos->e_lfanew);
        ep = (void*)((UINT_PTR)h + nt->OptionalHeader.AddressOfEntryPoint);
        ep((HMODULE)h, DLL_PROCESS_DETACH, NULL);
        return api_VirtualFree(h, 0, MEM_RELEASE);
}

#pragma comment(linker, "/ENTRY:EntryPoint")
int EntryPoint(void* peb)
{
        void *kernel32 = myGetModuleHandleW(L"kernel32.dll");
        HMODULE (WINAPI *LoadLibraryW)(LPCWSTR lpLibFileName) = myGetProcAddress(kernel32, "LoadLibraryW");
        void *msvcrt = LoadLibraryW(L"msvcrt.dll");
        void (*printf)(const char*, ...) = myGetProcAddress(msvcrt, "printf");
        // 为了提取汇编给易语言调用,注意调用约定是 stdcall、文本型是 char**
        printf("LoadDLL: %p\n", LoadDLL);
        printf("FreeDll: %p\n", FreeDll);
        printf("RunEXE: %p\n", RunEXE);
        return 0;
}

回复 支持 反对

使用道具 举报

签到天数: 2 天

发表于 16 分钟前 | 显示全部楼层   重庆市重庆市
膜拜膜拜,心情澎湃
回复 支持 反对

使用道具 举报

结帖率:100% (3/3)

签到天数: 1 天

发表于 前天 22:12 | 显示全部楼层   河北省秦皇岛市
好东西,学习了
回复 支持 反对

使用道具 举报

结帖率:0% (0/1)

签到天数: 3 天

发表于 3 天前 | 显示全部楼层   山东省德州市
感谢分享
回复 支持 反对

使用道具 举报

结帖率:97% (29/30)

签到天数: 3 天

发表于 3 天前 | 显示全部楼层   广西壮族自治区柳州市
感谢分享
回复 支持 反对

使用道具 举报

结帖率:80% (8/10)

签到天数: 4 天

发表于 4 天前 | 显示全部楼层   江苏省常州市
能内存加载易语言静态编译的dll,且不执行“_启动子程序”?
回复 支持 反对

使用道具 举报

签到天数: 4 天

发表于 4 天前 | 显示全部楼层   河北省邯郸市
666666666666666
回复 支持 反对

使用道具 举报

签到天数: 1 天

发表于 4 天前 | 显示全部楼层   贵州省安顺市
怎么返回DLL函数的值呢
回复 支持 反对

使用道具 举报

结帖率:100% (4/4)

签到天数: 4 天

发表于 4 天前 高大上手机用户 | 显示全部楼层   山东省淄博市
感谢分享
回复 支持 反对

使用道具 举报

签到天数: 2 天

发表于 5 天前 | 显示全部楼层   江苏省连云港市
感谢分享
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则 致发广告者

发布主题 收藏帖子 返回列表

sitemap| 易语言源码| 易语言教程| 易语言论坛| 易语言模块| 手机版| 广告投放| 精易论坛
拒绝任何人以任何形式在本论坛发表与中华人民共和国法律相抵触的言论,本站内容均为会员发表,并不代表精易立场!
论坛帖子内容仅用于技术交流学习和研究的目的,严禁用于非法目的,否则造成一切后果自负!如帖子内容侵害到你的权益,请联系我们!
防范网络诈骗,远离网络犯罪 违法和不良信息举报QQ: 793400750,邮箱:wp@125.la
网站简介:精易论坛成立于2009年,是一个程序设计学习交流技术论坛,隶属于揭阳市揭东区精易科技有限公司所有。
Powered by Discuz! X3.4 揭阳市揭东区精易科技有限公司 ( 粤ICP备2025452707号) 粤公网安备 44522102000125 增值电信业务经营许可证 粤B2-20192173

快速回复 返回顶部 返回列表