Windows下CmRegisterCallback简单分析

IDA看一下
在这里插入图片描述

进入Internal函数

`signed __int64 __fastcall CmpRegisterCallbackInternal(__int64 Function, __int64 Context, const void **CmLegacyAltitude, char c_1, _QWORD *Cookie)
{
  __int64 _Context; // rsi
  __int64 _Function; // rbp
  const void **_CmLegacyAltitude; // rbx`
  `char _c_1; // r12`
  `__int64 v9; // rax
  __int64 v10; // rdi`
  `__int64 v12; // rax`
  `_ETW_REG_ENTRY *v13; // rax`
  `unsigned int v14; // ebx`
  `signed int v15; // eax`
  `_ETW_REG_ENTRY *v16; // rcx`

  `_Context = Context;
  _Function = Function;
  _CmLegacyAltitude = CmLegacyAltitude;
  _c_1 = c_1;
  // 这个是callback数据项
  v9 = (__int64)ExAllocatePoolWithTag(PagedPool, 80ui64, 'bcMC');
  v10 = v9;
  if ( !v9 )
    return 0xC000009Ai64;
  // 开头是LIST_ENTRY,这里是初始化LIST_ENTRY
  *(_QWORD *)(v9 + 8) = v9;`
  `*(_QWORD *)v9 = v9;
  // 这里在结尾16字节填充了同样的地址,是防止溢出的?
  v12 = v9 + 64;
  *(_QWORD *)(v12 + 8) = v12;`
  `*(_QWORD *)v12 = v12;
  // 这里是真正填写CALLBACK函数地址和参数
  *(_DWORD *)(v10 + 16) = 0;`
  `*(_QWORD *)(v10 + 32) = _Context;
  *(_QWORD *)(v10 + 40) = _Function;
  LOWORD(v12) = *(_WORD *)_CmLegacyAltitude;
  *(_WORD *)(v10 + 50) = *(_WORD *)_CmLegacyAltitude;`
  `*(_WORD *)(v10 + 48) = v12;
  // 这里申请内存保存了CmLegacyAltitude的值
  v13 = (_ETW_REG_ENTRY *)ExAllocatePoolWithTag(PagedPool, *(unsigned __int16 *)_CmLegacyAltitude, 'acMC');
  *(_QWORD *)(v10 + 56) = v13;
  if ( !v13 )
  {
    v14 = 0xC000009A;
LABEL_6:
    v16 = *(_ETW_REG_ENTRY **)(v10 + 56);
    if ( v16 )
      ExFreePoolWithTag(v16, 0);
    ExFreePoolWithTag((PVOID)v10, 0);
    return v14;
  }
  memmove(v13, _CmLegacyAltitude[1], *(unsigned __int16 *)_CmLegacyAltitude);
  // 最后将CALLBACK项传入此函数进行注册
  v15 = CmpInsertCallbackInListByAltitude((_QWORD *)v10, _c_1);
  *Cookie = *(_QWORD *)(v10 + 24);`
  `v14 = v15;`
  `if ( v15 < 0 )`
    `goto LABEL_6;`
  `return v14;`
`}`

进入 CmpInsertCallbackInListByAltitude,

__`int64 __fastcall CmpInsertCallbackInListByAltitude(_QWORD *a1, char a2)`
`{`
  `struct _KTHREAD *v2; // rax`
  `char v3; // bp`
  `__int64 v4; // rbx
  unsigned int v5; // esi
  __int64 *v6; // rdi`
  `int v7; // eax`
  `__int64 *v8; // rcx
  __int64 v9; // rax`
  `signed __int64 v10; // rcx
  __int64 v11; // rtt`
  `struct _KTHREAD *v12; // rdx`
  `bool v13; // zf`

  `v2 = KeGetCurrentThread();`
  `v3 = a2;`
  `--v2->KernelApcDisable;`
  `v4 = (__int64)a1;
  v5 = 0;
  if ( _interlockedbittestandset64((volatile signed __int32 *)&CallbackListLock, 0i64) )
    ExfAcquirePushLockExclusive(&CallbackListLock);
  *(_QWORD *)(v4 + 24) = ++CmpCallbackCookie;
  v6 = (__int64 *)CallbackListHead;
  if ( (__int64 *)CallbackListHead != &CallbackListHead )
  {
    do
    {
      v7 = RtlCompareAltitudes(v6 + 6, v4 + 48);
      if ( v7 )
      {
        if ( v7 < 0 )
          break;
      }
      else if ( !v3 )
      {
        goto LABEL_11;
      }
      v6 = (__int64 *)*v6;`
    `}`
    `while ( v6 != &CallbackListHead );`
    `if ( !v7 && !v3 )`
    `{`
`LABEL_11:`
      `v5 = 0xC01C0011;`
      `goto LABEL_13;`
    `}`
  `}`
  `v8 = (__int64 *)v6[1];
  v9 = *v8;
  *(_QWORD *)(v4 + 8) = v8;
  *(_QWORD *)v4 = v9;
  *(_QWORD *)(v9 + 8) = v4;
  *v8 = v4;
  _InterlockedAdd(&CmpCallBackCount, 1u);
LABEL_13:
  __asm { prefetchw byte ptr cs:CallbackListLock }`
  `v10 = CallbackListLock - 16;`
  `if ( (CallbackListLock & 0xFFFFFFFFFFFFFFF0ui64) <= 0x10 )`
    `v10 = 0i64;`
  `if ( CallbackListLock & 2`
    `|| (v11 = CallbackListLock, v11 != _InterlockedCompareExchange(&CallbackListLock, v10, CallbackListLock)) )`
  `{`
    `ExfReleasePushLock(&CallbackListLock);`
  `}`
  `v12 = KeGetCurrentThread();`
  `v13 = v12->KernelApcDisable++ == -1;`
  `if ( v13`
    `&& ($A23C80C4E4519FC60176F3D7BA3A3B67 *)v12->ApcState.ApcListHead[0].Flink != &v12->80`
    `&& !v12->SpecialApcDisable )`
  `{`
    `KiCheckForKernelApcDelivery();`
  `}`
  `return v5;`
`}`

总结

在这个函数里将CALLBACK ITEM 插入了CallbackListHead 链表。

CALLBACK ITEM 数据结构总结:

typedef struct CALLBACK_ITEM    
{ 
LIST_ENTRY Item;    
ULONG_PTR Unkonwn[2];    
ULONG_PTR Context;    
ULONG_PTR Function;    
UNICODE_STRING Altitude;    
ULONG_PTR Unkonwn[2];    
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值