首页
社区
课程
招聘
[原创]重读老文章系列:内核同步那些事儿
发表于: 2012-7-28 20:48 9148

[原创]重读老文章系列:内核同步那些事儿

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虚拟机自动化脱壳的方法

收藏
免费 6
支持
分享
最新回复 (9)
雪    币: 2177
活跃值: (2045)
能力值: (RANK:400 )
在线值:
发帖
回帖
粉丝
2
VOID WaitForHook(
				 __in struct _KDPC  *Dpc,
				 __in_opt PVOID  DeferredContext,
				 __in_opt PVOID  SystemArgument1,
				 __in_opt PVOID  SystemArgument2
				 )
{
	KIRQL OldIrql;

	OldIrql = KeRaiseIrqlToDpcLevel();
	InterlockedIncrement(&g_nRaisedCpuCnt);
	KeAcquireSpinLockAtDpcLevel(&g_SpinLock);
	KeReleaseSpinLockFromDpcLevel(&g_SpinLock);
	KeLowerIrql(OldIrql);
}

我一般都是让其他cpu等待同一个SpinLock。
2012-7-28 21:05
0
雪    币: 8865
活跃值: (2379)
能力值: ( LV12,RANK:760 )
在线值:
发帖
回帖
粉丝
3
DPC里貌似M$说要interlock才靠谱~
2012-7-28 21:09
0
雪    币: 2177
活跃值: (2045)
能力值: (RANK:400 )
在线值:
发帖
回帖
粉丝
4
求出处。
2012-7-28 22:03
0
雪    币: 27
活跃值: (90)
能力值: ( LV8,RANK:120 )
在线值:
发帖
回帖
粉丝
5
向V校学习
2012-7-28 22:04
0
雪    币: 27
活跃值: (90)
能力值: ( LV8,RANK:120 )
在线值:
发帖
回帖
粉丝
6
第二大类同步“IRQL提升方式同步”里的SpinLock和DISPATCH_LEVEL能不能讲一讲

不太理解
2012-7-28 22:42
0
雪    币: 239
活跃值: (133)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
7
老V我你是不是神父?我蛮好想资助的。
2012-7-28 22:56
0
雪    币: 220
活跃值: (701)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
老V不是神父,但他的网名叫神父
2012-7-29 11:01
0
雪    币: 8865
活跃值: (2379)
能力值: ( LV12,RANK:760 )
在线值:
发帖
回帖
粉丝
9
这才是正解。
2012-7-29 12:37
0
雪    币: 31
活跃值: (43)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
10
顶,虽然代码还看不懂。
2012-8-2 23:47
0
游客
登录 | 注册 方可回帖
返回
//