A forum for reverse engineering, OS internals and malware analysis 

Forum for discussion about kernel-mode development.
 #9784  by lorddoskias
 Sun Nov 20, 2011 11:38 pm
Hello,

I'm trying to hook object_type_initializer's OpenProcedure for FILE_OBJECT. Here is my setup:

I'm using Windows 7 x32. Here are the definitions of the structures I'm using:
Code: Select all
typedef struct _EX_PUSH_LOCK
{
	union
	{
		ULONG Locked: 1;
		ULONG Waiting: 1;
		ULONG Waking: 1;
		ULONG MultipleShared: 1;
		ULONG Shared: 28;
		ULONG Value;
		PVOID Ptr;
	};
} EX_PUSH_LOCK, *PEX_PUSH_LOCK;

typedef struct _OBJECT_TYPE_INITIALIZER
{

	USHORT Length;
	UCHAR ObjectTypeFlags;
	UCHAR CaseInsensitive: 1;
	UCHAR UnnamedObjectsOnly: 1;
	UCHAR UseDefaultObject: 1;
	UCHAR SecurityRequired: 1;
	UCHAR MaintainHandleCount: 1;
	UCHAR MaintainTypeList: 1;
	UCHAR SupportsObjectCallbacks: 1;
	ULONG ObjectTypeCode;
	ULONG InvalidAttributes;
	GENERIC_MAPPING GenericMapping;
	ULONG ValidAccessMask;
	ULONG RetainAccess;
	POOL_TYPE PoolType;
	ULONG DefaultPagedPoolCharge;
	ULONG DefaultNonPagedPoolCharge;
	PVOID DumpProcedure;
	LONG * OpenProcedure;
	PVOID CloseProcedure;
	PVOID DeleteProcedure;
	LONG * ParseProcedure;
	LONG * SecurityProcedure;
	LONG * QueryNameProcedure;
	UCHAR * OkayToCloseProcedure;
} OBJECT_TYPE_INITIALIZER, *POBJECT_TYPE_INITIALIZER;


typedef struct _OBJECT_TYPE {
	LIST_ENTRY TypeList;             
	UNICODE_STRING Name;             
	PVOID        DefaultObject;
	UCHAR        Index;
	ULONG      TotalNumberOfObjects;
	ULONG      TotalNumberOfHandles;
	ULONG      HighWaterNumberOfObjects;
	ULONG      HighWaterNumberOfHandles;
	OBJECT_TYPE_INITIALIZER TypeInfo; 
	EX_PUSH_LOCK TypeLock;            
	ULONG32      Key;
	LIST_ENTRY CallbackList;          
} OBJECT_TYPE, *POBJECT_TYPE;
The reason I'm posting them is because initially I was having problems finding the correct ones but after some time in windbg I finally managed to get them working. Here is the function performing the hooking:
Code: Select all
void hookFileObject() {
	
	DbgPrint("Dereferences address is 0x%p", *IoFileObjectType);
	 (*IoFileObjectType)->TypeInfo.OpenProcedure = myOpenProcedure;

}
Output is:
Code: Select all
Dereferences address is 0x841E87A8
Here is the hooked function. Very simple as you can see:
Code: Select all
void myOpenProcedure(IN OB_OPEN_REASON OpenReason, IN PEPROCESS Process OPTIONAL,  IN PVOID Object,  IN ACCESS_MASK GrantedAccess,  IN ULONG HandleCount  ) {

	DbgPrint("Our openProcedure routine has been invoked\n");

	if(Process != NULL) {
		DbgPrint("Process with name: %s is requesting file opening", getName(Process));
	}
	
}
My getname func:
Code: Select all
char * getName(char *eproc) {

	return eproc + EPROCESS_NAME_OFFSET;
}
And the offset is: #define EPROCESS_NAME_OFFSET 0x16c

This code has been tested and is working, but still I'm pasting it for completeness.

Here is the state of the object_type_initializer for FILE_OBJECT AFTER the hooking:
Code: Select all
dt _OBJECT_TYPE_INITIALIZER 0x841E87A8+0x28
nt!_OBJECT_TYPE_INITIALIZER
   +0x000 Length           : 0x50
   +0x002 ObjectTypeFlags  : 0x11 ''
   +0x002 CaseInsensitive  : 0y1
   +0x002 UnnamedObjectsOnly : 0y0
   +0x002 UseDefaultObject : 0y0
   +0x002 SecurityRequired : 0y0
   +0x002 MaintainHandleCount : 0y1
   +0x002 MaintainTypeList : 0y0
   +0x002 SupportsObjectCallbacks : 0y0
   +0x004 ObjectTypeCode   : 1
   +0x008 InvalidAttributes : 0x130
   +0x00c GenericMapping   : _GENERIC_MAPPING
   +0x01c ValidAccessMask  : 0x1f01ff
   +0x020 RetainAccess     : 0
   +0x024 PoolType         : 0 ( NonPagedPool )
   +0x028 DefaultPagedPoolCharge : 0x400
   +0x02c DefaultNonPagedPoolCharge : 0xf8
   +0x030 DumpProcedure    : (null) 
   +0x034 OpenProcedure    : 0x954781d0     long  DKOM_Proc!myOpenProcedure+0
   +0x038 CloseProcedure   : 0x82a99baf     void  nt!IopCloseFile+0
   +0x03c DeleteProcedure  : 0x82a7fcbb     void  nt!IopDeleteFile+0
   +0x040 ParseProcedure   : 0x82ac7fe0     long  nt!IopParseFile+0
   +0x044 SecurityProcedure : 0x82a9e41d     long  nt!IopGetSetSecurityObject+0
   +0x048 QueryNameProcedure : 0x82aabe11     long  nt!IopQueryName+0
   +0x04c OkayToCloseProcedure : (null) 
Apparently it has completed successfully since DKOM_Proc!myOpenProcedure is my driver. But unfortunately I get an exception. Here is the output of !analyze -v after the bug check:
Code: Select all
*******************************************************************************
*                                                                             *
*                        Bugcheck Analysis                                    *
*                                                                             *
*******************************************************************************

Unknown bugcheck code (0)
Unknown bugcheck description
Arguments:
Arg1: 00000000
Arg2: 00000000
Arg3: 00000000
Arg4: 00000000

Debugging Details:
------------------


PROCESS_NAME:  svchost.exe

FAULTING_IP: 
nt!ObpIncrementHandleCountEx+2a4
82a5fc66 f00fba2800      lock bts dword ptr [eax],0

EXCEPTION_RECORD:  ffffffff -- (.exr 0xffffffffffffffff)
ExceptionAddress: 82a5fc66 (nt!ObpIncrementHandleCountEx+0x000002a4)
   ExceptionCode: c0000005 (Access violation)
  ExceptionFlags: 00000000
NumberParameters: 2
   Parameter[0]: 00000001
   Parameter[1]: 00000000
Attempt to write to address 00000000

ERROR_CODE: (NTSTATUS) 0xc0000005 - The instruction at 0x%08lx referenced memory at 0x%08lx. The memory could not be %s.

EXCEPTION_CODE: (NTSTATUS) 0xc0000005 - The instruction at 0x%08lx referenced memory at 0x%08lx. The memory could not be %s.

EXCEPTION_PARAMETER1:  00000001

EXCEPTION_PARAMETER2:  00000000

WRITE_ADDRESS:  00000000 

FOLLOWUP_IP: 
nt!ObpIncrementHandleCountEx+2a4
82a5fc66 f00fba2800      lock bts dword ptr [eax],0

BUGCHECK_STR:  ACCESS_VIOLATION

DEFAULT_BUCKET_ID:  NULL_DEREFERENCE

CURRENT_IRQL:  0

LAST_CONTROL_TRANSFER:  from 82a6078c to 82a5fc66

STACK_TEXT:  
945b7b74 82a6078c 00000000 945b7bac 847ccd40 nt!ObpIncrementHandleCountEx+0x2a4
945b7be0 82a8540c 00000000 84990940 00000000 nt!ObpCreateHandle+0xff
945b7c38 82a7d5ab 015af2d4 841e87a8 00000001 nt!ObOpenObjectByName+0x318
945b7cb4 82a88eb6 015af330 00100080 015af2d4 nt!IopCreateFile+0x673
945b7d00 8288142a 015af330 00100080 015af2d4 nt!NtCreateFile+0x34
945b7d00 77c464f4 015af330 00100080 015af2d4 nt!KiFastCallEntry+0x12a
015af290 77c44a1c 75dd9cc1 015af330 00100080 ntdll!KiFastSystemCallRet
015af294 75dd9cc1 015af330 00100080 015af2d4 ntdll!NtCreateFile+0xc
015af338 76a10ba7 00404028 00100080 00000007 KERNELBASE!CreateFileW+0x35e
015af364 6e54a4ce 02f9dff8 00000080 00000007 kernel32!CreateFileWImplementation+0x69
WARNING: Stack unwind information not available. Following frames may be wrong.
015af394 6e594d2a 00000080 00000007 00000003 mpengine!rsignal+0xa126e
015af3bc 6e594d8d 00000000 00000000 7695e04b mpengine!rsignal+0xebaca
015af408 6e59677a 035baca8 e07a18d4 019123b8 mpengine!rsignal+0xebb2d
015af47c 6e5966ac 019123f8 00000001 035baca8 mpengine!rsignal+0xed51a
015af494 6e59666f 02f9ddf0 035baca8 00000000 mpengine!rsignal+0xed44c
015af4bc 6e597103 02f9ddf0 0308f948 015af4e0 mpengine!rsignal+0xed40f
015af4f0 6e596dc0 02f9ddf0 015af584 015af548 mpengine!rsignal+0xedea3
015af5a4 6e595f6a 005babb0 02f9ddf0 e07a1974 mpengine!rsignal+0xedb60
015af644 6e595424 00f60dc8 00000000 00000000 mpengine!rsignal+0xecd0a
015af6dc 6e5aa3df 00000000 0224f4a0 00000000 mpengine!rsignal+0xec1c4
015af88c 6e5a9298 02ffcd88 00f60c68 00000000 mpengine!rsignal+0x10117f
015af8ec 6e5a8e61 00f60c68 00000000 00f60c68 mpengine!rsignal+0x100038
015af9d8 6e4a614c 00004026 00f60c68 00000044 mpengine!rsignal+0xffc01
015af9f4 6e4a61ba 00004026 00f60c68 00000044 mpengine+0x1614c
015afa88 6e4a6209 00f60918 00004026 00f60c68 mpengine+0x161ba
015afaa0 6ef5537a 00f60918 00004026 00f60c68 mpengine!_rsignal+0x37
015afae8 6ef5e3a4 00f608c0 00004026 00f60c68 mpsvc!rsignal_wrapper+0x77
015afb10 6ef59b41 00f6b698 00d90e20 00000000 mpsvc!OnDemandScanWorker+0x11a
015afb20 6ef59c24 00f6bf1c 015afb5c 6f378b87 mpsvc!MpWorkItemIsComplete+0x81
015afb2c 6f378b87 00f6bf1c e206ee11 77c57e08 mpsvc!MpWorkItemIsComplete+0x164
015afb5c 6f378c03 015afb70 6f37b3b6 00d90e20 MpClient!MpUpdateStart+0x11bfb
015afb64 6f37b3b6 00d90e20 015afb94 77c16cf5 MpClient!MpUpdateStart+0x11c77
015afb70 77c16cf5 015afbd0 00d9e150 00110198 MpClient!MpUpdateStart+0x1442a
015afb94 77c2e8d1 015afbd0 001101f8 7695e8ef ntdll!TppWorkpExecuteCallback+0x10f
015afcf4 76a11174 0010f4b0 015afd40 77c5b3f5 ntdll!TppWorkerThread+0x572
015afd00 77c5b3f5 0010f4b0 7695e95b 00000000 kernel32!BaseThreadInitThunk+0xe
015afd40 77c5b3c8 77c2d63e 0010f4b0 00000000 ntdll!__RtlUserThreadStart+0x70
015afd58 00000000 77c2d63e 0010f4b0 00000000 ntdll!_RtlUserThreadStart+0x1b


STACK_COMMAND:  kb

SYMBOL_STACK_INDEX:  0

SYMBOL_NAME:  nt!ObpIncrementHandleCountEx+2a4

FOLLOWUP_NAME:  MachineOwner

MODULE_NAME: nt

IMAGE_NAME:  ntkrpamp.exe

DEBUG_FLR_IMAGE_TIMESTAMP:  4a5bc007

FAILURE_BUCKET_ID:  ACCESS_VIOLATION_nt!ObpIncrementHandleCountEx+2a4

BUCKET_ID:  ACCESS_VIOLATION_nt!ObpIncrementHandleCountEx+2a4

Followup: MachineOwner
I really can't explain why this is happening since what I'm doing is very simple, initially there is no callback for OpenProcedure so I'm not running into a race condition. Also I never touch ObpIncrementHandleCountEx o_O Any help/ideas will be much appreciated.
 #9785  by xqrzd
 Sun Nov 20, 2011 11:59 pm
OpenProcedure returns NTSTATUS, maybe that is your problem? Also, I think your OpenProcedure signature is wrong for Windows 7, between OpenReason and Process, there should be a char. I don't know what it represents.

NTSTATUS myOpenProcedure(IN OB_OPEN_REASON OpenReason, char something, IN PEPROCESS Process OPTIONAL, IN PVOID Object, IN ACCESS_MASK GrantedAccess, IN ULONG HandleCount )
 #9791  by lorddoskias
 Mon Nov 21, 2011 1:58 am
I managed to install my hook - the problem was indeed with a wrong signature of my function - no more blindly believing of structures, will start to use symboltypeviewer from now on :). But I have another problem:
Code: Select all
NTSTATUS myOpenProcedure(OB_OPEN_REASON OpenReason, CHAR Unknown1, PEPROCESS Process, PVOID Object, ACCESS_MASK GrantedAccess, ULONG32 HandleCount) {

	DbgPrint("Our openProcedure routine has been invoked\n");

	if(Process != NULL) {
		DbgPrint("Process with name: %s is requesting file opening\n", getName(Process));
		//DbgPrint("A handle for %Z has been opened \n", ((PFILE_OBJECT)Object)->FileName);
	}
	
	return STATUS_SUCCESS;
}
With this function I can't get the commented out DbgPrint statement to execute it bugchecks with "page fault in non paged area" which probbaly means that the Object is not of type FILE_OBJECT, but since I have hooked the OpenProcedure for OBJECT_TYPE "File" doesn't this mean that Object should be FILE_OBJECT?
 #9792  by nullptr
 Mon Nov 21, 2011 7:34 am
See if this works (untested)
Code: Select all
DbgPrint("A handle for %wZ has been opened \n", &((PFILE_OBJECT)Object)->FileName);
rkhunter wrote:Why do you need to hook OpenProcedure for file object type? What purposes?
I'd also be curious to know.
 #9794  by lorddoskias
 Mon Nov 21, 2011 9:33 am
Works like charm nullptr ! And as far as to "Why you are doing this" - I simply want to see this into action, I believe it can be used for a lot of good or bad things - rootkit detective uses it to protect itself (I'm assuming it is not the only mechanism).