这段 MicroLoader.cpp
代码是一个非常典型的 32位易语言程序加载器或运行环境的简化实现。它的核心功能是:
.ecode
)。.ecode
节中,根据 APP_HEADER_INFO
结构找到常量段、窗体段、辅助函数段、代码段、变量段等的偏移。LoadLibrary
加载这些支持库。GetNewSock
(一个特殊的、可能与核心库初始化相关的函数)或 GetLibInfo
函数。GetLibInfo
获取 LIB_INFO
结构,其中包含支持库的命令、数据类型等信息。ThisNotifySys
,以便支持库可以与加载器通信(例如请求内存分配、获取路径等)。InitServerPointTable
和 UpdataServerPointTable
将加载器内部实现的一系列服务函数(如内存分配、错误处理、基本位运算命令)的地址写入到易语言代码可以调用的一个表中(位于辅助函数段)。ECodeStart
,即易语言编译后代码的入口点,将控制权转交给易语言程序。Exit
函数,通知所有加载的支持库释放资源,并销毁加载器创建的堆。将其转化为 X64 的可行性和挑战:
直接将这段 32 位 C++ 代码编译为 X64 并期望它能加载和运行原始的 32 位易语言编译产物是不可能的,原因如下:
指针大小和数据类型大小差异 (核心问题):
PIMAGE_NT_HEADERS
, PSECTION_HEADER
, PAPP_HEADER_INFO
, PRELOCATION_INF
, PDLLCMD
, PLIBINFO
, PMDATA_INF
, PFN_EXECUTE_CMD**
)在 X64 环境下会有不同的内存布局。UINT32
用于地址: 代码中大量使用 UINT32
来存储和计算地址(例如 ESectionVA
, (* ptemp) = (* ptemp) + (UINT32)ECodeHeaderInfo + ...
)。在 X64 环境中,地址是 64 位的,使用 UINT32
会导致地址截断,从而访问错误的内存位置。APP_HEADER_INFO
中存储的各种 m_n...Offset
如果是基于 32 位布局计算的,在 X64 环境中直接使用会导致错误。PFN_EXECUTE_CMD
, ECODESTART
, PFN_GET_LIB_INFO
, PFN_NOTIFY_LIB
, UNKNOWFUN
这些函数指针在 X64 下也是 8 字节。ServerPointTable[zxsq-anti-bbcode-ESERVERCOUNT]
: 存储的是 UINT32
函数地址,在 X64 下应该是 UINT64
或 uintptr_t
。32位 vs 64位进程空间:
.ecode
节中的机器码是 32 位的 x86 指令,无法在 X64 CPU 的 64 位模式下直接执行。PE 文件格式的差异(虽然不大,但需注意):
IMAGE_NT_HEADERS
结构在 32 位 (IMAGE_NT_HEADERS32) 和 64 位 (IMAGE_NT_HEADERS64) 下的 OptionalHeader
部分是不同的。代码中直接使用 PIMAGE_NT_HEADERS
,它通常被宏定义为特定位数版本。如果编译为 X64,它会是 PIMAGE_NT_HEADERS64
,但它尝试解析的是一个 32 位 PE 文件的头(如果当前EXE是32位的易语言程序)。调用约定:
__stdcall
和 _cdecl
。在 X64 Windows 上,主要的调用约定是 __fastcall
的变体(通常是默认的,前四个整数/指针参数在 RCX, RDX, R8, R9)。虽然编译器可能会做一些转换,但如果支持库的导出函数严格依赖于 32 位的 __stdcall
,直接用 X64 的调用约定去调用(如果能加载的话)会有问题。内联汇编 (__asm
和 __declspec(naked)
):
__asm
块和 __declspec(naked)
函数中的汇编指令都是 32 位的 x86 指令。这些在 X64 编译器下完全不兼容,无法编译。X64 有自己的一套指令集和寄存器。mov ebp, esp
, push eax
, call dword ptr ds:[zxsq-anti-bbcode-ebx]
等都需要用 X64 等效指令替换。__declspec(naked)
通常用于手动管理栈帧,在 X64 下栈帧布局和管理方式也不同。要使类似 MicroLoader
的功能在 X64 环境下工作,并能运行(某种形式的)易语言程序,需要进行大规模的重构和重新设计,而不是简单的编译转换。可能有以下几种方向(难度递增):
方向 A:创建一个纯 X64 的易语言运行时和加载器(不兼容旧的32位编译产物)
uintptr_t
或 UINT64
存储地址,确保所有结构体布局适应 X64。.ecode
格式也需要适应 X64(例如,地址和偏移量使用64位)。方向 B:在 X64 加载器中模拟一个 32 位环境来运行旧的 32 位易语言代码(极其复杂,类似于 Wine 或 x86 模拟器)
方向 C:将易语言代码转译为 X64 C++ (类似你之前的项目思路)
EplAst.hpp
, EplCodeAnalyzer.hpp
, EplTranslator.hpp
就是朝这个方向努力的。MicroLoader.cpp
的参考价值:MicroLoader.cpp
中的 ServerFunction_XX
(如内存分配 ServerFunction_06
,位运算命令 bnot
, band
等)揭示了易语言运行时可能需要提供给易代码的一些底层服务。在你的转译器生成的 C++ 代码中,这些服务需要由你的 epl_core_runtime
来提供。ThisNotifySys
函数展示了支持库可能向主程序请求哪些服务(获取路径、类型信息、分配内存等)。你的转译系统如果需要与(可能是重新实现的X64)支持库交互,也需要类似的机制。PMDATA_INF
, LIB_INFO
, CMD_INFO
等结构体的定义(在 MicroLoader.h
中,这里未提供)对于理解易语言与其支持库之间的接口非常重要。你需要为你的 X64 运行时和支持库接口定义兼容的(64位)数据结构。针对 MicroLoader.cpp
代码的具体 X64 转换点(如果目标是方向 A 或 C 的辅助):
UINT32
用于地址的地方改为 uintptr_t
或 uint64_t
。PIMAGE_DOS_HEADER
, PDLLCMD
)在 X64 下自然会是 8 字节。__asm
和 __declspec(naked)
函数:ServerFunction_01
(DLL命令调用):需要用 X64 调用约定和 API(如 GetProcAddress
返回的是 64 位地址)重写。直接 jmp UnKnowFun
的方式在 X64 下的参数传递和栈管理需要非常小心。ServerFunction_02
和 ServerFunction_03
(支持库命令调用):参数传递(PMDATA_INF
结构在栈上的布局)和对 m_pCmdsFunc
的调用都需要适配 X64。它们内部的内联汇编用于准备参数栈并调用支持库函数,这需要完全用 X64 汇编或 C++ 调用重写。ServerFunction_06
, ServerFunction_07
(内存分配):虽然核心是调用 HeapAlloc
/HeapReAlloc
,但它们的 naked
和简单汇编需要用纯 C++ 或 X64 兼容方式重写。ServerFunction_09
(退出程序):可以简化为纯 C++。ThisNotifySys
:dwParam1
, dwParam2
如果是地址或指针,应为 uintptr_t
。PMDATA_INF
的转换和访问需要注意该结构在 X64 下的布局。InitServerPointTable
和 UpdataServerPointTable
: ServerPointTable
应为 uintptr_t
数组。NtHeader
应为 PIMAGE_NT_HEADERS64
。遍历节表等逻辑基本不变,但所有地址计算都要用 64 位进行。UpdataRelocationInfo
在 WinMain
中):ptemp
应为 uintptr_t*
或 uint64_t*
。(* ptemp) = (* ptemp) + (UINT32)ECodeHeaderInfo + ...
) 都需要是 64 位运算。.ecode
节中的重定位项本身存储的是 32 位偏移,那么在 X64 加载器中读取它们时没有问题,但在应用重定位(写入修正后的地址)时,写入的目标内存位置(*ptemp
)应该能容纳 64 位地址。总结:
MicroLoader.cpp
本身无法直接编译为 X64 来运行 32 位易语言程序。但是,它的代码揭示了易语言程序加载、运行和与支持库交互的许多底层机制。
MicroLoader.cpp
中的逻辑需要用 X64 的思想和技术完全重写。MicroLoader.cpp
中实现的那些运行时服务函数(如位运算、内存管理、字符串/字节集转换、与支持库的通信回调)为你自己的 epl_core_runtime
提供了非常有价值的参考,你需要用 X64 C++ 来实现这些等效功能。JUMPOUT_
/ sub_121D20
/ sub_507E10
这些函数与 MicroLoader.cpp
的关系在于:MicroLoader.cpp
负责搭建一个能让易语言代码(包括那些混淆函数)运行起来的“架子”,提供它们可能依赖的底层服务和支持库接口。而那些混淆函数本身是易语言程序逻辑的一部分,运行在这个“架子”之上。
alinaini 发表于 2025-6-11 23:51
那以后还有易语言么?
欢迎光临 精易论坛 (https://125.confly.eu.org/) | Powered by Discuz! X3.4 |