欢迎来到 嗅灵易学

零基础也能上手的脚本技术课,一对一答疑带你入门

[原创]某驱动里面的摘取系统注册表回调的方法

[原创]某驱动里面的摘取系统注册表回调的方法

换工作环境了,比以前自由多了,这几天没多少事,之前分析过了这个驱动一直没有还原,这2天抽空还原了一下,大牛飘过~~
基本原理:  
     在自己驱动里面调用CMRegistercallback注册一个回调函数,然后在回调函数里面根据
  ebx寄存器里面存储的是当前回调函数_EX_CALLBACK结构地址,而这一地址又一定在系统的回调链上的这一特性,  在XP系统上找到CmpCallBackVector 首地址,在Vista以上系统上找到CallbackListHead  首地址,然后依次遍历下了,找到CallBackFunction和Cookie,然后有了CallBackFunction  就能找到模块名称,根据Cookie就能进行注册表回调的摘取了~~~  
  
先补充下XP下的CmpCallBackVector的节点怎么找打Cookie和Funtion的方法:
CmpCallBackVector--> Node.Object
--->EX_CALLBACK_ROUTINE_BLOCK
-->CM_CALLBACK_CONTEXT_BLOCKXP
在EX_CALLBACK_ROUTINE_BLOCK 找到CallBackFuntion
在CM_CALLBACK_CONTEXT_BLOCK中找到Context和Cookie
ebx在指向的是当前函数注册的在nt!CmpCallBackVector里面的节点位置
由于在XP系统上CmpCallBackVector里面存放的是EX_FAST_REF指针,因此从当前位置一直向
低内存位置查找DWORD值,直到为0,即为CmpCallBackVector的第一结构
从EX_FASTREF.object-->EX_CALLBACK_ROUTINE_BLOCK使用如下函数


PVOID FORCEINLINE MyFastRefGetObject (EX_FAST_REF FastRef)

{

    return (PVOID) (FastRef.Value & ~MAX_FAST_REFS);

}

#if defined (_WIN64)

    #define MAX_FAST_REFS 15

#else

    #define MAX_FAST_REFS 7

#endif


XP系统下的各个结构体:

_EX_CALLBACK  CmpCallBackVector[100];

typedef struct _EX_CALLBACK 

{

	EX_FAST_REF RoutineBlock;

} EX_CALLBACK, *PEX_CALLBACK;

typedef struct _EX_FAST_REF 

{

	union {

		PVOID Object;

		#if defined (_WIN64)

					ULONG_PTR RefCnt : 4;

		#else

					ULONG_PTR RefCnt : 3;

		#endif

		ULONG_PTR Value;

	};

} EX_FAST_REF, *PEX_FAST_REF;

typedef struct _EX_CALLBACK_ROUTINE_BLOCKXP

{

	EX_RUNDOWN_REF		  RundownProtect;

	[COLOR="Red"]PEX_CALLBACK_FUNCTION Function;[/COLOR]

	PVOID				  Context;

	PVOID				  pValid;

}EX_CALLBACK_ROUTINE_BLOCKXP, *PEX_CALLBACK_ROUTINE_BLOCKXP;

typedef struct _CM_CALLBACK_CONTEXT_BLOCK {

	[COLOR="Red"]LARGE_INTEGER               Cookie;          [/COLOR]  

	LIST_ENTRY                  ThreadListHead;     

	EX_PUSH_LOCK                ThreadListLock;    

	PVOID                       CallerContext;

} CM_CALLBACK_CONTEXT_BLOCK, *PCM_CALLBACK_CONTEXT_BLOCK;


Vista系统下的结构体

LIST_ENTRY* CallbackListHead ;

typedef struct _CM_CALLBACK_CONTEXT_BLOCKEX-------// 0x30

{

	struct _LIST_ENTRY CallbackListEntry;               // +0x0(0x8)

	ULONG               PreCallListCount;                    // +0x8(0x4)

	ULONG		pda;				          // Pad

	LARGE_INTEGER Cookie;					   // +0x10(0x8)

	void*              CallerContext;                           // +0x18(0x4)

	long (__stdcall * Function)(void*, void*, void*);  // +0x1c(0x4)

	struct _UNICODE_STRING Altitude;                      // +0x20(0x8)

	struct _LIST_ENTRY ObjectContextListHead;         // +0x28(0x8)

}CM_CALLBACK_CONTEXT_BLOCKEX,*P_CM_CALLBACK_CONTEXT_BLOCKEX;


ok下面开始看看某驱动的代码:
-----在explorer.exe或者winlogon.exe退出的时候,调用如下函数获取callbacks

_EX_REG_CALL_CONTEXT *__cdecl GetCmRegCallBackFunctions()

{

  _EX_REG_CALL_CONTEXT *pContext; // esi@1

  _EX_REG_CALL_CONTEXT *result; // eax@1

  LARGE_INTEGER Cookie; // [sp+Ch] [bp-Ch]@2

  HANDLE KeyHandle; // [sp+14h] [bp-4h]@4

  pContext = (_EX_REG_CALL_CONTEXT *)ExAllocatePoolWithTag(0, 0x4D8u, 0x20747362u);

  result = 0;

  if ( pContext )

  {

    pContext->regCallBackCount = 0;

    pContext->mutex.Count = 1;                  // ExInitializeFastMutex

    pContext->mutex.Owner = 0;

    pContext->mutex.Contention = 0;

    KeInitializeEvent(&pContext->mutex.Event, SynchronizationEvent, 0);

    if ( CmRegisterCallback((PEX_CALLBACK_FUNCTION)regCallbackFunction, pContext, &Cookie) >= 0 )// register reg call back

    {

      ZwOpenKey(&KeyHandle, 0x20019u, &ObjectAttributes);// trigger it

      CmUnRegisterCallback(Cookie);

      result = pContext;

    }

    else

    {

      ExFreePoolWithTag(pContext, 0x20747362u);

      result = 0;

    }

  }

  return result;

}


在callback里面做如下事情:

int __userpurge regCallbackFunction<eax>(int pMayCmpCallBackVector<ebx>, _EX_REG_CALL_CONTEXT *pContext, int nOpType, int nOpInformations)

{

  if ( nOpType == 12 )                          // RegNtPreOpenKey

  {

    RegCallBackXP(pContext, (_REG_PRE_OPEN_KEY_INFORMATION *)nOpInformations, (PVOID)pMayCmpCallBackVector);

  }

  else

  {

    if ( nOpType == 28 )                        // RegNtPreOpenKeyEx--28

      Reg_CallBackWin7(

        pContext,

        (_REG_CREATE_KEY_INFORMATION *)nOpInformations,

        (_CM_CALLBACK_CONTEXT_BLOCK *)pMayCmpCallBackVector);

  }

  return 0;

}


Vista代码如下:

int __stdcall Reg_CallBackWin7(_EX_REG_CALL_CONTEXT *pContext, _REG_CREATE_KEY_INFORMATION *a2, _CM_CALLBACK_CONTEXT_BLOCK *pCurCallBackRef)

{

  BOOLEAN (__stdcall *pMMisAddressValid)(PVOID); // ebx@1

  _CM_CALLBACK_CONTEXT_BLOCK *cmListHead; // edi@5

  _EX_REG_CALL_CONTEXT *pcontext; // esi@6

  DWORD ulIndex; // ecx@9

  LARGE_INTEGER *curCookie; // eax@10

  _CM_CALLBACK_CONTEXT_BLOCK *callBackListHead; // [sp+Ch] [bp-4h]@5

  struct _FAST_MUTEX *FastMutexa; // [sp+18h] [bp+8h]@6

  DWORD nContextIndex; // [sp+20h] [bp+10h]@9

  pMMisAddressValid = MmIsAddressValid;

  if ( MmIsAddressValid(pCurCallBackRef) )

  {

    if ( MmIsAddressValid(&pCurCallBackRef->Altitude) )

    {

      if ( MmIsAddressValid(pCurCallBackRef->Function) )

      {

        if ( (int (__userpurge *)<eax>(int<ebx>, _EX_REG_CALL_CONTEXT *, int, int))pCurCallBackRef->Function == regCallbackFunction )

        {

          cmListHead = GetCallVectorListHeadWin7((int)pCurCallBackRef);

          callBackListHead = cmListHead;

          if ( cmListHead )

          {

            pcontext = pContext;

            FastMutexa = &pContext->mutex;

            ExAcquireFastMutex(FastMutexa);

            while ( 1 )

            {

              cmListHead = (_CM_CALLBACK_CONTEXT_BLOCK *)cmListHead->CallbackListEntry.Flink;

              if ( cmListHead == callBackListHead )

                break;

              if ( !pMMisAddressValid(cmListHead) || !pMMisAddressValid(&cmListHead->Altitude) )

                break;

              ulIndex = pcontext->regCallBackCount;

              nContextIndex = 0;

              if ( pcontext->regCallBackCount )

              {

                curCookie = pcontext->callBackCookie;

                do

                {

                  if ( curCookie->low == cmListHead->Cookie.low && curCookie->high == cmListHead->Cookie.high )

                    break;

                  ++nContextIndex;

                  ++curCookie;

                }

                while ( nContextIndex < ulIndex );

                pMMisAddressValid = MmIsAddressValid;

              }

              if ( nContextIndex == ulIndex && ulIndex < 0x64 )

              {

                pcontext->callBackCookie[ulIndex].low = cmListHead->Cookie.low;

                pcontext->callBackCookie[ulIndex].high = cmListHead->Cookie.high;

                pcontext->pCallBackFunnction[pcontext->regCallBackCount++] = cmListHead->Function;

              }

            }

            ExReleaseFastMutex(FastMutexa);

          }

        }

      }

    }

  }

  return 0;

}


XP代码如下

int __stdcall RegCallBackXP(_EX_REG_CALL_CONTEXT *a1, _REG_PRE_OPEN_KEY_INFORMATION *a2, PVOID pCmpCallBackVector)

{

  _EX_CALLBACK_ROUTINE_BLOCKXP *pRegCallBackRouting; // eax@4

  int v4; // esi@4

  PVOID pCurCallBackNode; // edi@8

  _EX_REG_CALL_CONTEXT *v6; // esi@9

  int pCallBackObject; // edi@12

  _EX_CALLBACK_ROUTINE_BLOCKXP *pCMRoutBlock; // edi@13

  _CM_CONTEXT_XP *pCurContext; // eax@18

  DWORD v10; // ecx@18

  ULONG CookieHigh; // [sp+8h] [bp-14h]@18

  ULONG CookieLow; // [sp+Ch] [bp-10h]@18

  struct _FAST_MUTEX *FastMutex; // [sp+10h] [bp-Ch]@9

  PVOID pfCmpCallBackVector_1; // [sp+14h] [bp-8h]@8

  int nLoopIndex1; // [sp+18h] [bp-4h]@9

  DWORD v17; // [sp+24h] [bp+8h]@18

  int pCMContextBLock; // [sp+2Ch] [bp+10h]@16

  LARGE_INTEGER *pCurCookie; // [sp+2Ch] [bp+10h]@19

  if ( MmIsAddressValid(pCmpCallBackVector) )

  {

    if ( MmIsAddressValid((char *)pCmpCallBackVector + 4) )

    {

      if ( *(_DWORD *)pCmpCallBackVector )

      {

        pRegCallBackRouting = (_EX_CALLBACK_ROUTINE_BLOCKXP *)(*(_DWORD *)pCmpCallBackVector & 0xFFFFFFF8);

        v4 = (int)pRegCallBackRouting;

        if ( pRegCallBackRouting )

        {

          if ( MmIsAddressValid(pRegCallBackRouting) )

          {

            if ( MmIsAddressValid((PVOID)(v4 + 0xC)) )

            {

              if ( *(int (__userpurge **)<eax>(int<ebx>, _EX_REG_CALL_CONTEXT *, int, int))(v4 + 4) == regCallbackFunction )// Check Whether is found correnct

              {

                pCurCallBackNode = FoundRegCallVectorStart(pCmpCallBackVector);

                pfCmpCallBackVector_1 = pCurCallBackNode;

                if ( pCurCallBackNode )

                {

                  v6 = a1;

                  FastMutex = &a1->mutex;

                  ExAcquireFastMutex(&a1->mutex);// loop to deal the callback vectors

                  for ( nLoopIndex1 = 0;

                        *(_DWORD *)pCurCallBackNode;

                        pCurCallBackNode = (char *)pfCmpCallBackVector_1 + 4 * nLoopIndex1 )

                  {

                    if ( !MmIsAddressValid(pCurCallBackNode) )

                      break;

                    if ( !MmIsAddressValid((char *)pCurCallBackNode + 4) )

                      break;

                    pCallBackObject = *(_DWORD *)pCurCallBackNode;

                    if ( !pCallBackObject )

                      break;

                    pCMRoutBlock = (_EX_CALLBACK_ROUTINE_BLOCKXP *)(pCallBackObject & 0xFFFFFFF8);

                    if ( !pCMRoutBlock )

                      break;

                    if ( !MmIsAddressValid(pCMRoutBlock) || !MmIsAddressValid(&pCMRoutBlock->UNKNOW) )

                      break;

                    pCMContextBLock = (int)pCMRoutBlock->Context;

                    if ( MmIsAddressValid(pCMRoutBlock->Context) && MmIsAddressValid((PVOID)(pCMContextBLock + 8)) )

                    {

                      pCurContext = (_CM_CONTEXT_XP *)pCMRoutBlock->Context;

                      v17 = 0;

                      CookieHigh = pCurContext->Cookie.low;

                      v10 = v6->regCallBackCount;

                      CookieLow = pCurContext->Cookie.high;

                      if ( v6->regCallBackCount )

                      {

                        pCurCookie = v6->callBackCookie;

                        do

                        {

                          if ( pCurCookie->low == CookieHigh && pCurCookie->high == CookieLow )

                            break;

                          ++v17;

                          ++pCurCookie;

                        }

                        while ( v17 < v10 );

                      }

                      if ( v17 == v10 && v10 < 100 )

                      {

                        v6->callBackCookie[v10].low = CookieHigh;

                        v6->callBackCookie[v10].high = CookieLow;

                        v6->pCallBackFunnction[v6->regCallBackCount++] = pCMRoutBlock->Function;

                      }

                    }

                    ++nLoopIndex1;

                  }

                  ExReleaseFastMutex(FastMutex);

                }

              }

            }

          }

        }

      }

    }

  }

  return 0;

}


附件是源码只枚举了,没有删除

上传的附件 regcallback.rar

注意:上传附件及图片大小不得大于30M。

⚠️ 版权声明:
本博客所有内容(含教程、源码、工具)仅供个人技术学习与研究交流使用,严禁商用、倒卖、二次分发及非法用途。
未经作者书面授权,任何组织或个人不得转载、复制或用于其他平台,违者将追究相关责任。

0 0 0 举报
复制成功