You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

自定义LoadLibrary函数调用DLL入口点时出错求助

自定义LoadLibrary执行入口点出错的解决方案

嘿,我看你在手动实现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

火山引擎 最新活动