[原创]某驱动里面的摘取系统注册表回调的方法
换工作环境了,比以前自由多了,这几天没多少事,之前分析过了这个驱动一直没有还原,这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;
}
附件是源码只枚举了,没有删除
