К сожалению как обычно - внутренности их реализации недокументированы. Но кого и когда эта мелкая неприятность останавливала ?
Предположим что нам хочется посмотреть какие драйвера (или точнее какие адреса функций) зарегистрированы как получатели на каждый callback
Начнем как обычно - с чтения документации - ExCreateCallback & ExRegisterCallback
Cтруктура _CALLBACK_OBJECT в wdk7 описана как
typedef struct _CALLBACK_OBJECT *PCALLBACK_OBJECT;но довольно легко находится например в native-nt-toolkit. Там же чуть ниже описана и вторая структура, которая нам потребуется - _CALLBACK_REGISTRATION:
typedef struct _CALLBACK_OBJECT
{
ULONG Signature;
KSPIN_LOCK Lock;
LIST_ENTRY RegisteredCallbacks;
BOOLEAN AllowMultipleCallbacks;
UCHAR reserved[3];
} CALLBACK_OBJECT, *PCALLBACK_OBJECT;
typedef struct _CALLBACK_REGISTRATION
{
LIST_ENTRY Link;
PCALLBACK_OBJECT CallbackObject;
PCALLBACK_FUNCTION CallbackFunction;
PVOID CallbackContext;
ULONG Busy;
BOOLEAN UnregisterWaiting;
} CALLBACK_REGISTRATION, *PCALLBACK_REGISTRATION;
Очевидно что поле _CALLBACK_OBJECT.RegisteredCallbacks содержит связный список из структур _CALLBACK_REGISTRATION, откуда уже можно достать адреса CallbackFunction. Значительно менее очевидно как получить саму _CALLBACK_OBJECT - медитация в дизассемблере подсказывает что для этого можно вызвать ObReferenceObjectByName или пару функций ObOpenObjectByName/ObReferenceObjectByHandle с правильным типом объекта - в данном случае он должен быть ExCallbackObjectType
Здесь нас поджидает еще одна засада - ExCallbackObjectType не экспортируется, хотя и может быть найден дизассемблированием все той же функции ExCreateCallback например.
Итак, порядок действий примерно такой:
- Находим (например дизассемблированием ExCreateCallback) адрес ExCallbackObjectType - это может быть сделано как в kernel mode, так и в user mode
- Перечисляем все объекты из \Callback, сохраняем их полные имена - аналогично достижимо как в kernel mode, так и в user mode
- Открываем объект Callback по имени с ранее найденным типом ExCallbackObjectType, лочим его _CALLBACK_OBJECT.Lock и перебираем список _CALLBACK_OBJECT.RegisteredCallbacks - kernel mode only
- PROFIT
PCALLBACK_OBJECT cbObject;
HANDLE Handle = NULL;
InitializeObjectAttributes(&ObjAttr, &UnicodeString, OBJ_CASE_INSENSITIVE, NULL, NULL);
// получим HANDLE объекта
res = ObOpenObjectByName(&ObjAttr,
(POBJECT_TYPE *)exCBType,
KernelMode,
NULL,
0, // DesiredAccess,
NULL,
&Handle
);
// получим PCALLBACK_OBJECT
res = ObReferenceObjectByHandle(
Handle,
0, // DesiredAccess
(POBJECT_TYPE *)exCBType,
KernelMode,
&cbObject,
NULL
);
ZwClose(Handle); // HANDLE больше не нужен
// вытащим адреса ф-ций, зарегистрированных для данного callback object
if ( NT_SUCCESS(res) )
{
// ok, lets iterate on all callbacks
PLIST_ENTRY Link;
PCALLBACK_REGISTRATION CallbackRegistration;
KIRQL OldIrql;
ULONG total;
// встаем на Lock
KeAcquireSpinLock(&cbObject->Lock, &OldIrql);
for ( total = 0, Link = cbObject->RegisteredCallbacks.Flink;
Link != &cbObject->RegisteredCallbacks;
Link = Link->Flink, total++
)
{
CallbackRegistration = CONTAINING_RECORD (Link, CALLBACK_REGISTRATION, Link);
// Gotcha ! у нас есть еще один адрес - тут с ним можно что-нть сделать
... // perl yada yada operator
}
// отпускаем Lock
KeReleaseSpinLock(&cbObject->Lock, OldIrql);
}
// объект Callback больше не нужен
ObDereferenceObject(cbObject);
Примерчик работы вышеописанного кода на моей машине:
CB: Ndis1394CallbackObject, total 1:
F768C548 (\SystemRoot\system32\DRIVERS\nic1394.sys)
CB: SetSystemState, total 0:
CB: NdisBindUnbind, total 0:
CB: PowerState, total 9:
806D46F8 (\WINDOWS\system32\hal.dll)
F74BB568 (ACPI.sys)
F72DD5B0 (PGPwded.sys)
F7208174 (NDIS.sys)
F76D1578 (\SystemRoot\system32\DRIVERS\processr.sys)
F60B4498 (\SystemRoot\system32\DRIVERS\parport.sys)
F62F2BA0 (\SystemRoot\system32\drivers\ALCXWDM.SYS)
F60C451E (\SystemRoot\system32\DRIVERS\VIDEOPRT.SYS)
EC7FF4EE (\??\C:\WINDOWS\system32\Drivers\vmx86.sys)
CB: TcpConnectionCallback, total 1:
EFAF761E (\SystemRoot\system32\DRIVERS\ipnat.sys)
CB: SetSystemTime, total 0:
Комментариев нет:
Отправить комментарий