You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C++ DLL注入后打NOP字节补丁出现错误码5的问题求助

C++ DLL注入后打NOP字节补丁出现错误码5的问题求助

哎,看到你遇到这个错误码5(拒绝访问)的坑了,虽说已经用管理员权限跑加载器了,但还是栽了对吧?我来帮你捋捋可能的原因和实际的解决思路。

首先,先建议你精准定位错误发生的阶段——你可以在VirtualProtect调用失败后,立刻用GetLastError()把错误码打出来,这样能明确是第一次修改权限的时候就失败了,还是最后恢复权限时出的问题。不过从你描述的场景看,大概率是第一次调用VirtualProtect就卡壳了,毕竟要写内存的第一步就是改权限。

接下来给你拆解几个常见的踩坑点:

  • 目标地址的有效性与内存属性问题
    你用find_pattern找到了地址,但有没有确认这个地址真的在目标进程的可修改内存区域里?比如很多程序会把代码段设为PAGE_EXECUTE_READ(只读+执行),这时候要改内存必须先把权限改成可读写执行,但如果目标地址所在的内存页有额外的保护(比如系统进程的代码页、启用了CFG/内存完整性的页),就算是管理员也没法直接改。另外还要确认find_pattern返回的地址是不是精准指向你要改的75字节——比如你找的模式是75 ? 85 c9 ...,地址必须刚好落在第一个75的位置,差一个字节都可能导致权限修改失败。

  • 进程权限的隐性限制
    虽然你用管理员运行了加载器,但DLL注入到目标进程后,权限是继承目标进程的。如果目标进程是高完整性级别(比如系统核心进程、受Windows Defender核心隔离保护的进程),就算你是管理员,也拿不到修改它内存的权限。还有些程序会自己加自定义的内存保护(比如内存加密、实时校验钩子),这时候就算权限够,也会被程序自身的机制拦截。

  • VirtualProtect调用的小细节
    看你的patch_bytes函数,最后恢复权限的时候,把old_protection又当成了输出参数,虽说逻辑上没问题,但容易搞混,建议单独用个临时变量,比如:

    DWORD temp_protect;
    return VirtualProtect(dest, bytes.size(), old_protection, &temp_protect);
    

    不过这个不是导致错误码5的直接原因,只是规范点更稳妥。

  • 跨内存页的情况
    你要改的两个字节会不会刚好跨了两个内存页?比如第一个字节在某页的最后一位,第二个在下一页。这时候VirtualProtect只修改了第一页的权限,第二页还是只读,写内存的时候就会直接报拒绝访问。你可以用VirtualQuery查一下目标地址所在内存页的起始地址和大小,确认要修改的字节都在同一个页里。

给你几个具体的调试和解决步骤:

  1. 精准定位错误环节
    在patch_bytes里加个调试输出,比如:

    if (!VirtualProtect(dest, bytes.size(), PAGE_EXECUTE_READWRITE, &old_protection))
    {
        DWORD err = GetLastError();
        // 可以用OutputDebugString把err输出到调试器,或者写日志文件
        return false;
    }
    

    这样能明确是哪一步的VirtualProtect出了问题。

  2. 检查目标地址的内存属性
    用VirtualQuery获取目标地址的内存页信息,看看当前的保护属性是什么:

    MEMORY_BASIC_INFORMATION mbi;
    if (VirtualQuery(reinterpret_cast<void*>(integrity_check), &mbi, sizeof(mbi)))
    {
        // 打印mbi.Protect的值,比如如果是PAGE_NOACCESS或者PAGE_EXECUTE_WRITECOPY,那肯定改不了
    }
    
  3. 排查系统或程序的额外保护
    如果是自己测试的程序,可以暂时关闭Windows Defender的核心隔离(内存完整性),或者暂停第三方安全软件。要是目标程序有自己的内存校验机制,可能得先找到并禁用这个校验逻辑,再去打补丁。

  4. 确认位数匹配
    别忽略最基础的点:你的DLL和目标进程的位数必须一致!如果是32位DLL注入64位进程,或者反过来,find_pattern找到的地址完全是无效的,调用VirtualProtect自然会报拒绝访问。

最后再确认下string_to_bytes函数有没有正确把"90 90"转换成两个0x90的字节——如果转换逻辑出错,比如把字符串转换成了其他字节,虽然错误码大概率不是5,但排除下总是好的。

备注:内容来源于stack exchange,提问作者Eray Eser

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.15 09:24:48