名字长了总有XX跟着念 2024-06-19 22:54 采纳率: 77.8%
浏览 15

驱动开发遇到奇怪的PAGE_FAULT_IN_NONPAGED_AREA

C语言驱动开发蓝屏,dump文件解析如下:
PAGE_FAULT_IN_NONPAGED_AREA (50)
Invalid system memory was referenced. This cannot be protected by try-except.
Typically the address is just plain bad or it is pointing at freed memory.


```c
    12: 
>   13: NTSTATUS ProcessRegCB(REG_NOTIFY_CLASS op_type, PVOID ex_info,HANDLE reger_pid, PUNICODE_STRING reg_path) {
    14:     
    15:     HANDLE father_pid = GetFatherPid(reger_pid);
    16: 
    17:     if (op_type == RegNtPreDeleteKey) {
    18:         PREG_DELETE_KEY_INFORMATION p_info = (PREG_DELETE_KEY_INFORMATION)ex_info;


这个函数的调用方:

```c
NTSTATUS RegistryCallback(
    IN PVOID CallbackContext,
    IN REG_NOTIFY_CLASS OpType,
    IN PVOID Argument
)
{
    if (OpType>2) {
        return STATUS_SUCCESS;
    }
    PVOID reg_path_obj = *(PVOID*)Argument;//结构体的第一个参数object就是PVOID
    HANDLE reger_pid = PsGetCurrentProcessId();
    PUNICODE_STRING reg_path = GetRegistryObjectCompleteName(reg_path_obj);
    if (reg_path == NULL) {
        return STATUS_SUCCESS;
    }
    NTSTATUS cb_status = ProcessRegCB(OpType, Argument, reger_pid, reg_path);
    ExFreePoolWithTag(reg_path, REGISTRY_POOL_TAG);
    return cb_status;
}

dump是添加了源码和对应pdb解析的,驱动是win10 or higher 64位 debug版的
dump显示是13行触发的.
这是什么原因啊?这里这么会触发内存访问?

  • 写回答

1条回答 默认 最新

  • 专家-赤兔[在线] 优质创作者: 编程框架技术领域 2024-06-19 22:54
    关注

    引自免费微信小程序:皆我百晓生

    面对PAGE_FAULT_IN_NONPAGED_AREA这类错误,通常意味着在非分页池或系统空间内发生了非法的内存访问。这可能由多种原因引起,包括但不限于:错误的指针引用、释放后重用的内存、越界访问以及硬件故障等。

    在你提供的代码片段中,ProcessRegCB函数被调用时,它接收了来自注册表通知的参数。具体到RegistryCallback函数中,Argument参数被间接地通过*(PVOID*)Argument获取,然后传递给ProcessRegCB函数。这里的操作存在潜在风险,因为Argument的类型未明确指定,而直接解引用可能导致对无效内存的访问。

    解决方案建议

    1. 验证Argument的类型和内容: 确保Argument指向的数据结构与预期相符。如果Argument包含一个指针,确保这个指针有效且没有被释放。可以通过RtlpCheckPointer函数检查指针有效性。

    2. 使用ExAllocatePoolWithTagExFreePoolWithTag管理内存: 如果在ProcessRegCB或其调用链中分配了内存,请确保使用ExFreePoolWithTag释放所有通过ExAllocatePoolWithTag分配的内存。这有助于避免释放后重用的问题。

    3. 检查指针解引用: 在解引用任何指针前,使用KeBugCheckEx中的STATUS_INVALID_POINTER进行检查。例如,在ProcessRegCB中处理ex_info之前,可以增加如下检查:

      if (!NT_SUCCESS(MmIsAddressValid(ex_info))) {
          return STATUS_INVALID_POINTER;
      }
      
    4. 避免使用释放后的内存: 在RegistryCallback中,reg_path是在GetRegistryObjectCompleteName中获得的,并在之后的代码中使用。确保ExFreePoolWithTag(reg_path, REGISTRY_POOL_TAG);之前没有对该指针进行任何操作。

    5. 审查PDB和源代码一致性: 确保使用的PDB文件与源代码版本匹配,以便准确地调试和分析问题。

    6. 增强调试信息: 在关键位置添加调试输出(例如使用DbgPrint),可以帮助定位问题发生的具体位置和上下文。

    进一步诊断步骤

    • 使用WinDbg或其他调试工具,分析dump文件中引发异常的具体地址和调用堆栈。
    • 检查与Argument相关的数据结构定义,确认其是否正确无误。
    • 审视与注册表操作相关的系统API,确保正确使用。

    通过上述步骤,你应该能更深入地理解问题所在,并采取相应措施修复错误。如果问题依旧存在,进一步的系统日志分析或专业的内存调试工具可能会提供额外线索。

    评论 编辑记录

报告相同问题?

问题事件

  • 修改了问题 6月19日
  • 创建了问题 6月19日