More on callbacks: ObRegisterCallbacks

Today is ObRegisterCallbacks‘s turn: available since Vista SP1, permits to “register a list of callback routines for thread and process handle operations”. Together with the last blog from Zairon should cover the main callbacks.

After a few checks on the parameters passed the function iterates over the Operations array, checking that every entry (of type OB_OPERATION_REGISTRATION) satisfies these conditions:

  • at least one of the operations is not NULL
  • if one of the ops is not NULL it is checked with MmVerifyCallbackFunction. This function verifies that the address of the function belongs to a signed driver, as documented here (together with how to bypass that check :>).
  • check that the ObjectType for the operation supports the callbacks: SupportsObjectCallbacks (40h) must be set in ObjectType.TypeInfo.ObjectTypeFlags

On Windows 7 x86 I’ve checked the other nt!*ObjectType to see if there were other not officially supported object types but didn’t find any.

If all the checks have been successfully passed, a CALLBACK_ENTRY structure is filled with all the information and passed along with ObjectType to ObpInsertCallbackByAltitude.

CALLBACK_ENTRY:
+000 LIST_ENTRY CallbackList
+008 OB_OPERATION  Operations
+00C ULONG Active // set to 1 after all the callbacks have been successfully inserted
+010 OB_HANDLE Handle
+014 POBJECT_TYPE ObjectType
+018 POB_PRE_OPERATION_CALLBACK  PreOperation
+01c POB_POST_OPERATION_CALLBACK PostOperation
+020 ULONG unknown

ObpInsertCallbackByAltitude, as the name suggests, will link the CALLBACK_ENTRY in ObjectType.CallbackList.
When all the callbacks have been inserted a RegistrationHandle (OB_HANDLE) is returned:

OB_HANDLE:
+000  WORD Version
+002  WORD OperationRegistrationCount
+004  PVOID RegistrationContext
+008  UNICODE_STRING Altitude
+010  CALLBACK_ENTRY entries[1] // array of OperationRegistrationCount entries

At this point the registration is complete.

An alternative system to bypass MmVerifyCallbackFunction could be to have the pre/post function point to an address inside a signed driver (basically the address of a xor eax,eax retn 8 gadget), and changing the address back to our function after the registration.

So now we can list the callbacks for a given object type and eventually hijack them if you don’t feel like registering your own. Two more questions are left: where are the callbacks called ? and can we enable more object types ?

The first is easily answered placing a breakpoint on the pre/post function and inspecting the call stack: the callbacks are called by ObpCreateHandle and ObDuplicateHandle, as expected, respectively through ObpPreInterceptHandleCreate and ObpPreInterceptHandleDuplicate

As for the second question, we know which bit to change so let’s do it and see if it works even if that is not a definitive guarantee it will always work (meaning: use at your own risk!).

VOID
EnableObType(POBJECT_TYPE ObjectType)
{
	PMY_OBJECT_TYPE myobtype = (PMY_OBJECT_TYPE)ObjectType;
	myobtype->TypeInfo.SupportsObjectCallbacks = 1;
}

I tested it with IoFileObjectType and looks good!

[PRE] object:8CFA4220 access:100080 file:\Users\PCNAME\Desktop\obtest.sys
[PRE] object:8CFA4220 access:100080 file:\Users\PCNAME\Desktop\obtest.sys
[PRE] object:8CFA4220 access:100080 file:\Users\PCNAME\Desktop\obtest.sys
[PRE] object:8CFA4220 access:100080 file:\Users\PCNAME\Desktop\obtest.sys
[PRE] object:8BBD42C8 access:100001 file:\Windows\Temp
[PRE] object:8BBD42C8 access:100001 file:\Windows
[PRE] object:8BBD42C8 access:100001 file:\
[PRE] object:8CFA4220 access:13019F file:\Windows\Temp\TMP00000307CD5B57B5F20A8716
[PRE] object:8D321340 access:100080 file:\Users\PCNAME\Desktop\obtest.sys
[PRE] object:8D3155B8 access:120089 file:\Users\PCNAME\Desktop\obtest.sys
[PRE] object:8D29E6B8 access:120089 file:\Windows\Prefetch\OPERA.EXE-103FF2EC.pf
[PRE] object:8D29E6B8 access:12019F file:\Windows\Prefetch\OPERA.EXE-103FF2EC.pf
[PRE] object:8B591228 access:100001 file:\Users\PCNAME\AppData\Local\Opera\Opera\mail
...

and that’s it, here’s the code, have fun!

 
Copyright (c) 2010-2011 InREVERSE - All Right Reserved
Büyükçekmece Evden Eve Nakliyat Esenler Evden Eve Nakliyat Gaziosmanpasa Evden Eve Nakliyat Güngören Evden Eve Nakliyat Kadiköy Evden Eve Nakliyat Kartal Evden Eve Nakliyat Küçükçekmece Evden Eve Nakliyat Maltepe EvdenEve Nakliyat Sisli Evden Eve Nakliyat Tuzla Evden Eve Nakliyat Ümraniye Evden Eve Nakliyat Üsküdar Evden Eve Nakliyat Içerenköy Evden Eve Nakliyat Erenköy Nakliyat Etiler Evden Eve Nakliyat