您的位置:首页 > 其它

多CPU下安全inline hook

2012-11-22 13:51 225 查看
去師父神牛的空間里看了下關於内核安全inline hook的討論,感覺受益匪淺,查閲資料后,得知了一種CPU中較爲安全的安裝鈎子的方法。

該代碼來自《Rootkits:Subverting the Windows Kernel》一書,原理是通過向所有非當前的CPU插入DPC,並且在DPC例程中實現忙等待,這是一種比較可愛的方法(PS:雖然我還是糾結于,如果其他CPU當前就已經在執行DPC那不是情況會非常複雜嗎。。。)

Windows使用軟件中斷優先級,稱爲IRQL(Interrupt Request Level,中斷請求級別),Windows定義IRQL的範圍是0~31,數字越大,優先級越高。處理器執行時,擁有一個當前的IRQL,當發生中斷時,如果中斷的IRQL大於當前IRQL,當前執行會被打斷,處理器轉向執行中斷代碼,然後再根據需要繼續執行。IRQL最低是PASSIVE_LEVEL(0),也就是被動級別,普通的綫程都運行于這個級別,正因為這個級別最低,所以可以被所有更高的IRQL的例程打斷。比PASSIVE_LEVEL高的是APC_LEVEL(1),通常是APC(Asynchronous
Procedure Call,異步過程調用)的等級。然後是DISPATCH_LEVEL(2),,通常被用於DPC(Deferred Procedure Call,延遲過程調用)或者綫程的調度。3~26是設備IRQL,27-31是一些硬件的中斷。DPC一般用於處理一些需要高優先級,但是又不是非常緊急的事務,而APC一般適用於綫程異步通知。

下面是來自書上的代碼以及我寫的一些:

//Source code from <Rootkits:Subverting the Windows Kernel>, Chapter 7

PKDPC GainExclusivity()
{
NTSTATUS ns;
ULONG u_currentCPU;
CCHAR i;
PKDPC pkdpc, temp_pkdpc;
if (KeGetCurrentIrql() != DISPATCH_LEVEL)
return NULL;
InterlockedAnd(&AllCPURaised, 0); //AllCPURaised = 0
InterlockedAnd(&NumberOfRaisedCPU, 0); //NumberOfRaisedCPU = 0

temp_pkdpc = (PKDPC) ExAllocatePool(NonPagedPool, KeNumberProcessors *
sizeof(KDPC)); //分配處理器對應數量的
if (temp_pkdpc == NULL)
return NULL;
u_currentCPU = KeGetCurrentProcessorNumber(); //獲取當前CPU號
pkdpc = temp_pkdpc;
for (i = 0; i < KeNumberProcessors; i++, *temp_pkdpc++)
{
if (i != u_currentCPU)
{
KeInitializeDpc(temp_pkdpc,
RaiseCPUIrqlAndWait,
NULL);

KeSetTargetProcessorDpc(temp_pkdpc, i);
KeInsertQueueDpc(temp_pkdpc, NULL, NULL); //對所有非當前CPU插入一個dpc
}
}
while (InterlockedCompareExchange(&NumberOfRaisedCPU,
KeNumberProcessors - 1, KeNumberProcessors - 1) !=
KeNumberProcessors - 1) //所有CPU都在忙等待
{
__asm nop;
}
return pkdpc;//返回分配的内存等待釋放
}

//DPC例程
VOID RaiseCPUIrqlAndWait(IN PKDPC Dpc,
IN PVOID DeferredContext,
IN PVOID SystemArgument1,
IN PVOID SystemArgument2)
{
InterlockedIncrement(&NumberOfRaisedCPU); //宣佈挂起
while (!InterlockedCompareExchange(&AllCPURaised, 1, 1))
{
__asm nop;
}
InterlockedDecrement(&NumberOfRaisedCPU); //宣佈釋放
}

NTSTATUS ReleaseExclusivity(PVOID pkdpc)
{
InterlockedIncrement(&AllCPURaised); //釋放所有CPU
while (InterlockedCompareExchange(&NumberOfRaisedCPU, 0, 0)) //等待所有CPU都被釋放
{
__asm nop;
}
if (pkdpc != NULL)
{
ExFreePool(pkdpc); //釋放内存
pkdpc = NULL;
}
return STATUS_SUCCESS;
}

NTSTATUS InstallHook(PVOID pTarget,PVOID pSource,LONG nSize)
{
PKDPC pkdpc;

if(pkdpc = GainExclusivity()) {
//關閉寫保護
__asm {
cli
mov eax,cr0
push eax
xor eax,0x10000
mov cr0,eax
}
RtlCopyMemory(pTarget,pSource,nSize);
//開啓寫保護
__asm {
pop eax
mov cr0,eax
sti
}
ReleaseExclusivity(pkdpc);
}
return STATUS_SUCCESS;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: