• windows内核情景分析之—— KeRaiseIrql函数与KeLowerIrql()函数


    windows内核情景分析之—— KeRaiseIrql函数与KeLowerIrql()函数

    1.KeRaiseIrql函数

    这个 KeRaiseIrql() 只是简单地调用 hal 模块的 KfRaiseIrql() 函数,返回原来的 IRQL 写入 KeRaiseIrql() 的第 2 个参数里,将它写回 C 代码如下:

    VOID KeRaiseIrql(KIRQL NewIrql, PKIRQL OldIrql)
    {
    KIRQL Irql = KfRaiseIrql(NewIrql);
    *OldIrql = Irql;
    }
    
     KIRQL KfRaiseIrql(KIRQL Irql)
    {
    KIRQL OldIrql = GetCurrentKPcr()->Irql; // 从 _KPCR.Irql(fs:[24])得到 Irql 值
    
    if (HalpEnableIrqlAudit != 0)
    {
    eflags = GetCurrentElfags(); // 得到 eflags 值
    DisableInterrupt();  // 关闭中断
    HalpValidatePendingInterrts();
    
    if (HalpEnableIrqlAudit == 0
    || OldIrql >= DPC_LEVE
    || OldIrql >= ((USHORT *)GetCurrentKPcr()->HalReserved)[1]; // fs:[96h]
    || HalpAssertFailedOnce != 0)
    {
    if (eflags.IF == 0)
    EnableInterrupt():  // 开中断
    }
    
    }
    
    if (HalpEnableIrqlAudit == 0 || OldIrql <= Irql)
    {
    // 空,跳出 if()
    }
    else
    {
    HalpAssertFailedOnce = 1;
    DbgBreakPoint();  // 被断下
    }
    
    GetCurrentKPcr()->Irql = Irql; // 设置新的 IRQL 值
    return OldIrql;// 返回旧的 IRQL 值
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41

    KfRaiseIrql() 函数能提升 IRQL 需符合下面的条件之一:

    1.HalpEnableIrqlAudit 为 0(HalpEnableIrqlAudit 是个 hal 模块内的全局变量,但我不知道它是什么意思

    2.NewIrql >= OldIrql(也就是要提升的 IRQL 必须大于或等于原值)

    2.KeLowerIrql()函数

    #define KeLowerIrql(a) KfLowerIrql(a)  
    
    VOID FASTCALL KfLowerIrql (KIRQLNewIrql)  
    {  
      if (NewIrql > KeGetPcr()->Irql)  
      {  
      KEBUGCHECK(0);  
      for(;;);  
      }  
      HalpLowerIrql(NewIrql);  
    }  
    
    VOID HalpLowerIrql(KIRQL NewIrql) //主要函数
    {  
      if (NewIrql >= PROFILE_LEVEL) //如果所要降到的中断请求级大于PROFILE_LEVEL,则直接设置当前的中断请求级
      {  
      KeGetPcr()->Irql = NewIrql;  
      return;  
      }  
      HalpExecuteIrqs(NewIrql);  
      if (NewIrql >= DISPATCH_LEVEL) //如果所要降到的中断请求级大于DISPATCH_LEVEL,则直接设置当前的中断请求级
      {  
      KeGetPcr()->Irql = NewIrql;  
      return;  
      }  
      //NewIrql低于DISPATCH_LEVEL  
      KeGetPcr()->Irql = DISPATCH_LEVEL; //所要降到的中断请求级小于DISPATCH_LEVEL,设置当前的中断请求级为DISPATCH_LEVEL,
                                         //然后扫描dpc队列,如果不为空,则触发dpc软件中断
      if (((PKIPCR)KeGetPcr())->HalReserved[HAL_DPC_REQUEST])  
      {  //DPC请求队列非空  
      ((PKIPCR)KeGetPcr())->HalReserved[HAL_DPC_REQUEST] = FALSE;  
      KiDispatchInterrupt();  
      }  
      KeGetPcr()->Irql = APC_LEVEL; //所要降到的中断请求级小于APC_LEVEL,设置当前的中断请求级为APC_LEVEL,
                                    //然后扫描apc队列,如果不为空,则触发apc软件中断
      if (NewIrql == APC_LEVEL)  
      {  
      return;  
      }  
      //NewIrql低于APC_LEVEL  
      if (KeGetCurrentThread() != NULL &&
    KeGetCurrentThread()->ApcState.KernelApc Pending)  
      {  
      KiDeliverApc(KernelMode, NULL, NULL);  
      }  
      KeGetPcr()->Irql = PASSIVE_LEVEL;  
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • jpg 改 rar 
  • 相关阅读:
    微信下载远程图片的公用方法
    微信接口调用
    微信
    post方法
    asp.net pagebase获取缓存的方法
    sql查询最大id
    Controller里写自己需要的Action,参数的名字必须和路由设置的参数名一致

    递归调用
    队列及其应用
  • 原文地址:https://www.cnblogs.com/kuangke/p/9397585.html
Copyright © 2020-2023  润新知