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

时间:2023-03-08 17:27:37

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 windows内核情景分析之—— KeRaiseIrql函数与KeLowerIrql()函数