-
-
[原创]重读老文章系列:内核同步那些事儿
-
发表于:
2012-7-28 20:48
9148
-
自从有了多核啊,多cpu啊,超线程啊~
同步就有了更多的麻烦事儿
第一大类同步,让其他核都歇着的同步
一本老书《Rootkits: Subverting the Windows Kernel》里有详细的代码。
第二大类同步,IRQL提升方式同步
比如spinlock啊,resourceLock啊~都是这样的,提升到DISPATCH_LEVEL从而保证了同时只有一个DISPATCH_LEVEL的运行,缺点是对于大于DISPATCH-LEVEL的运行者无作用(一般来说我们也不会自身运行在超DPCLevel的世界里)。不过可以使用RaiseIrql来提升到非常高的irql,但是irql高了有时候会死的很难看。
详细请看MSDN有关内容。
PS:有意资助者请联系QQ:86879759
下面摘录了 Rootkits书上的代码并编写了简单的测试代码~
PKDPC GainExclusivity(void);
NTSTATUS ReleaseExclusivity(PVOID pkdpc);
VOID RaiseCPUIrqlAndWait(PKDPC Dpc, PVOID DeferredContext, PVOID SysArg1, PVOID SysArg2);
DWORD AllCPURaised, NumberOfRaisedCPU;
/*******************************************************************
* GainExclusivity()
* Code from "Rootkits: Subverting the Windows Kernel"
* by Greg Hoglund and James Butler
* This has too run on dispatch level
*******************************************************************/
PKDPC
GainExclusivity(void)
{
NTSTATUS us;
ULONG u_currentCPU;
CCHAR i;
PKDPC pkdpc, temp_pkdpc;
// Check level
if(KeGetCurrentIrql() != DISPATCH_LEVEL)
return NULL;
// Interlocked zero the globals
InterlockedAnd(&AllCPURaised, 0);
InterlockedAnd(&NumberOfRaisedCPU, 0);
// Setup nonpaged space for DPC functions
temp_pkdpc = (PKDPC)ExAllocatePool(NonPagedPool, KeNumberProcessors * sizeof(KDPC));
if(temp_pkdpc == NULL)
return NULL; // Huh, no mem
u_currentCPU = KeGetCurrentProcessorNumber();
pkdpc = temp_pkdpc;
// XXX: removed '*'
for(i = 0; i < KeNumberProcessors; i++, temp_pkdpc++)
{
// The DPC must not run on the current CPU
if(i == u_currentCPU) continue;
KeInitializeDpc(temp_pkdpc, RaiseCPUIrqlAndWait, NULL);
KeSetTargetProcessorDpc(temp_pkdpc, i);
KeInsertQueueDpc(temp_pkdpc, NULL, NULL);
}
// Wait
while(InterlockedCompareExchange(&NumberOfRaisedCPU, KeNumberProcessors-1, KeNumberProcessors-1) != KeNumberProcessors-1)
{
__asm nop;
}
// Return
return pkdpc;
}
/*******************************************************************
* ReleaseExclusivity()
* Code from "Rootkits: Subverting the Windows Kernel"
* by Greg Hoglund and James Butler
*******************************************************************/
NTSTATUS
ReleaseExclusivity(PVOID pkdpc)
{
// Inc CPU counter
InterlockedIncrement(&AllCPURaised);
// Wait for...
while(InterlockedCompareExchange(&NumberOfRaisedCPU, 0, 0))
{
__asm nop;
}
// Free mem
if(pkdpc != NULL)
{
ExFreePool(pkdpc);
pkdpc = NULL;
}
return STATUS_SUCCESS;
}
/*******************************************************************
* RaiseCPUIrqlAndWait()
* Code from "Rootkits: Subverting the Windows Kernel"
* by Greg Hoglund and James Butler
*******************************************************************/
VOID
RaiseCPUIrqlAndWait(PKDPC Dpc, PVOID DeferredContext, PVOID SysArg1, PVOID SysArg2)
{
InterlockedIncrement(&NumberOfRaisedCPU);
while(!InterlockedCompareExchange(&AllCPURaised, 1, 1))
{
__asm nop;
}
InterlockedDecrement(&NumberOfRaisedCPU);
}
void DoSomeThing()
{
// Get exclusivity
KIRQL CurrentIrql, OldIrql;
PKDPC pkdpc;
// Get into dispatch mode
CurrentIrql = KeGetCurrentIrql();
OldIrql = CurrentIrql;
if(CurrentIrql < DISPATCH_LEVEL)
KeRaiseIrql(DISPATCH_LEVEL, &OldIrql);
// Gain exclusivity on multicore/multiCPU machines
pkdpc = GainExclusivity();
//TODO:inlinehook什么的的代码放这里
// Release exclusivity and leave DISPATCH_LEVEL
ReleaseExclusivity(pkdpc);
KeLowerIrql(OldIrql);
}
[培训]《安卓高级研修班(网课)》月薪三万计划,掌握调试、分析还原ollvm、vmp的方法,定制art虚拟机自动化脱壳的方法