自定义LoadLibrary函数调用DLL入口点时出错求助
嘿,我看你在手动实现C版自定义LoadLibrary时碰到了执行入口函数的错误,这大概率是内存权限配置的问题,我来帮你理清楚问题和修复步骤:
问题根源
你用VirtualAllocEx申请内存时用了PAGE_READWRITE权限,这会触发系统的内存保护机制——默认情况下,可写的内存页是不允许执行代码的。而原生LoadLibrary加载DLL时,会把代码段(比如.text)设置为PAGE_EXECUTE_READ(可读可执行),数据段才用PAGE_READWRITE,你统一用PAGE_READWRITE的话,代码页没有执行权限,执行入口函数自然会报错。
具体修复步骤
区分代码段和数据段的权限
解析PE文件的节表时,要针对不同类型的节设置不同权限:- 代码节(通常名称是
.text):申请内存时用PAGE_EXECUTE_READWRITE,或者先以PAGE_READWRITE写入内容,之后再用VirtualProtectEx改成PAGE_EXECUTE_READ(更安全) - 数据节(比如
.data、.rdata):保持PAGE_READWRITE权限即可
- 代码节(通常名称是
修正内存权限的代码示例
如果你已经用PAGE_READWRITE申请了整块内存,写完DLL内容后,对代码节对应的内存范围修改权限:DWORD oldProtect; // 假设section是当前遍历到的代码节 BOOL ret = VirtualProtectEx( hProcess, (LPVOID)(imageBase + section->VirtualAddress), section->Misc.VirtualSize, PAGE_EXECUTE_READ, &oldProtect ); if (!ret) { // 处理权限修改失败的情况 printf("VirtualProtectEx failed: %d\n", GetLastError()); }检查PE解析的其他细节
还要确认入口点地址计算正确:入口点是nth->OptionalHeader.ImageBase + nth->OptionalHeader.AddressOfEntryPoint,如果你申请的内存地址和DLL默认的ImageBase不一致,必须处理PE的重定位表,否则函数调用、全局变量引用都会出错;另外还要确保导入表已经解析,依赖的DLL都已经加载,不然入口函数执行时也会因为找不到依赖而出错。
小提示
调试时可以用GetLastError()获取具体错误码,比如如果是0xC0000005(ERROR_ACCESS_VIOLATION),就坐实了是内存权限的问题。原生LoadLibrary还有很多细节要处理,比如TLS初始化、异常处理等,如果你只是做简单的加载执行,先把权限和重定位、导入表这几个核心点搞定。
内容的提问来源于stack exchange,提问作者Nick




