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

SetProcessValidCallTargets调用返回错误87(无效参数)问题排查

CFG API调用报错ERROR_INVALID_PARAMETER(87)问题原因与修复方案

核心问题点

  • 提前释放了依赖模块
    你在获取到SetProcessValidCallTargets、NtSetContextThread的函数地址后,直接调用FreeLibrary释放了ntdll.dll和kernelbase.dll,这会导致后续调用SetProcessValidCallTargets时,函数指针指向的内存已经被系统回收,调用行为完全不可预期,必然会出现参数错误或直接崩溃。
  • 内存区域大小参数错误
    VirtualQuery返回的RegionSize是当前单段内存区域的大小,而SetProcessValidCallTargets要求传入的RegionSize必须是VirtualAddress(也就是你拿到的分配基址)对应的整个内存分配块的总大小,参数不匹配会直接返回参数错误。
  • 修改对象错误
    你尝试给系统模块ntdll.dll的导出函数NtSetContextThread添加CFG合法标记,首先系统导出函数默认已经被CFG标记为合法调用目标,其次系统模块的内存页受保护,不允许用户态进程修改其CFG位图,调用必然会失败。该API的设计用途是给用户自己分配的可执行内存(比如动态生成shellcode的内存页)添加合法调用标记。
  • 前置条件不满足
    如果你的进程编译时没有开启CFG(VS编译选项为/guard:cf),系统不会为进程维护CFG调用位图,调用SetProcessValidCallTargets会直接返回参数错误。
  • 地址对齐问题
    CFG要求合法调用目标必须是16字节对齐,如果你计算出的偏移对应的目标地址没有对齐,也会触发参数错误。

修复步骤

  1. 把FreeLibrary(hNtdll)、FreeLibrary(hKernelbase)的调用移到lblCleanup代码块中,确保调用完SetProcessValidCallTargets之后再释放加载的模块。
  2. 修正内存大小获取逻辑,遍历分配基址下的所有连续内存段,累加得到整个分配块的总大小后再传入API。
  3. 将修改目标换成你自己分配的可执行内存区域,不要尝试修改系统模块的CFG配置。
  4. 确认编译选项开启了/guard:cf,确保进程本身启用了CFG功能。
  5. 校验目标地址是否为16字节对齐,调整偏移值满足对齐要求。

内容的提问来源于stack exchange,提问作者woldgrep

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.16 15:54:08