counter

View My Stats

Sunday, October 23, 2011

Enumerating a DRIVER_OBJECT using Driver Code

 

A Driver Object has the Following structure.

typedef struct _DRIVER_OBJECT
{
SHORT Type;
SHORT Size;
PDEVICE_OBJECT DeviceObject;
ULONG Flags;
PVOID DriverStart;
ULONG DriverSize;
PVOID DriverSection;
PDRIVER_EXTENSION DriverExtension;
UNICODE_STRING DriverName;
PUNICODE_STRING HardwareDatabase;
PFAST_IO_DISPATCH FastIoDispatch;
LONG * DriverInit;
PVOID DriverStartIo;
PVOID DriverUnload;
LONG * MajorFunction[28];
} DRIVER_OBJECT, *PDRIVER_OBJECT;

Looking at  a driver in DeviceTree utility


Following is the Driver related to keyboard


image


Using Windbg we can see the Structure of the Driver.

kd> !drvobj kbdclass
Driver object (8186aae8) is for:
 \Driver\Kbdclass
Driver Extension List: (id , addr)
Device Object list:
81798a58  81864860  

Lets see the DevObject at 81864860

kd> !devobj 81864860 
Device object (81864860) is for:
 KeyboardClass0 \Driver\Kbdclass DriverObject 8186aae8
Current Irp 00000000 RefCount 1 Type 0000000b Flags 00002044

Now lets see the DriverObject at 8186aae8 which is KeyboardClass0

kd> !drvobj 8186AAE8 7
Driver object (8186aae8) is for:
 \Driver\Kbdclass
Driver Extension List: (id , addr)
Device Object list:
81798a58  81864860  
DriverEntry:   f9cb0610	
DriverStartIo: 00000000	
DriverUnload:  00000000	
AddDevice:     f9cafb02	
Dispatch routines:
[00] IRP_MJ_CREATE                      f9cacdd8	+0xf9cacdd8
[01] IRP_MJ_CREATE_NAMED_PIPE           804f320e	nt!IopInvalidDeviceRequest
[02] IRP_MJ_CLOSE                       f9cacfe8	+0xf9cacfe8
[03] IRP_MJ_READ                        f9cadc82	+0xf9cadc82
[04] IRP_MJ_WRITE                       804f320e	nt!IopInvalidDeviceRequest
[05] IRP_MJ_QUERY_INFORMATION           804f320e	nt!IopInvalidDeviceRequest
[06] IRP_MJ_SET_INFORMATION             804f320e	nt!IopInvalidDeviceRequest
[07] IRP_MJ_QUERY_EA                    804f320e	nt!IopInvalidDeviceRequest
[08] IRP_MJ_SET_EA                      804f320e	nt!IopInvalidDeviceRequest
[09] IRP_MJ_FLUSH_BUFFERS               f9cacd50	+0xf9cacd50
[0a] IRP_MJ_QUERY_VOLUME_INFORMATION    804f320e	nt!IopInvalidDeviceRequest
[0b] IRP_MJ_SET_VOLUME_INFORMATION      804f320e	nt!IopInvalidDeviceRequest
[0c] IRP_MJ_DIRECTORY_CONTROL           804f320e	nt!IopInvalidDeviceRequest
[0d] IRP_MJ_FILE_SYSTEM_CONTROL         804f320e	nt!IopInvalidDeviceRequest
[0e] IRP_MJ_DEVICE_CONTROL              f9caea44	+0xf9caea44
[0f] IRP_MJ_INTERNAL_DEVICE_CONTROL     f9cae386	+0xf9cae386
[10] IRP_MJ_SHUTDOWN                    804f320e	nt!IopInvalidDeviceRequest
[11] IRP_MJ_LOCK_CONTROL                804f320e	nt!IopInvalidDeviceRequest
[12] IRP_MJ_CLEANUP                     f9cacd0c	+0xf9cacd0c
[13] IRP_MJ_CREATE_MAILSLOT             804f320e	nt!IopInvalidDeviceRequest
[14] IRP_MJ_QUERY_SECURITY              804f320e	nt!IopInvalidDeviceRequest
[15] IRP_MJ_SET_SECURITY                804f320e	nt!IopInvalidDeviceRequest
[16] IRP_MJ_POWER                       f9caf196	+0xf9caf196
[17] IRP_MJ_SYSTEM_CONTROL              f9cae844	+0xf9cae844
[18] IRP_MJ_DEVICE_CHANGE               804f320e	nt!IopInvalidDeviceRequest
[19] IRP_MJ_QUERY_QUOTA                 804f320e	nt!IopInvalidDeviceRequest
[1a] IRP_MJ_SET_QUOTA                   804f320e	nt!IopInvalidDeviceRequest
[1b] IRP_MJ_PNP                         f9cad798	+0xf9cad798

Now lets write a kernel mode driver code to do the same thing

/*
kd> !drvobj kbdclass
Driver object (8186aae8) is for:
 \Driver\Kbdclass
Driver Extension List: (id , addr)
Device Object list:
81798a58  81864860  
kd> !devobj 81864860 
Device object (81864860) is for:
 KeyboardClass0 \Driver\Kbdclass DriverObject 8186aae8
Current Irp 00000000 RefCount 1 Type 0000000b Flags 00002044
Dacl e13ae02c DevExt 81864918 DevObjExt 818649f8 
ExtensionFlags (0000000000)  
AttachedTo (Lower) 81864a58*** ERROR: Module load completed but symbols could not be loaded for nmfilter.sys
 \Driver\nmfilter
Device queue is not busy.
kd> !drvobj 8186AAE8
Driver object (8186aae8) is for:
 \Driver\Kbdclass
Driver Extension List: (id , addr)
Device Object list:
81798a58  81864860 
//out of the code
addr of drivr=8186AAE8 
addr of device =81798A58 
addr of irp =F9CACDD8 
*/
#include <ntddk.h> 
VOID DriverUnload(IN PDRIVER_OBJECT DriverObject);
NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
{
	PDRIVER_OBJECT drvcopy;
	PDEVICE_OBJECT devcopy;
	UNICODE_STRING DeviceName;
	PDEVICE_OBJECT device;
	PFILE_OBJECT file;
	NTSTATUS s;
	DbgPrint("driver 7\n");//variables should be declared before
	RtlInitUnicodeString(&DeviceName,L"\\Device\\KeyboardClass0");
	s = IoGetDeviceObjectPointer(&DeviceName,FILE_ALL_ACCESS,&file,&device);
		if (!NT_SUCCESS(s))
		{
			DbgPrint("Get Device error!");
			return s;
		}
	drvcopy = device->DriverObject;//device is pointer
	DbgPrint("addr of driver=%p \n",drvcopy);
	devcopy = drvcopy->DeviceObject;
	DbgPrint("addr of device =%p \n",devcopy);
	DbgPrint("addr of irp =%p \n",drvcopy->MajorFunction[IRP_MJ_CREATE] );
	
	DriverObject->DriverUnload = DriverUnload;
	
	return STATUS_SUCCESS;
}
VOID DriverUnload(IN PDRIVER_OBJECT DriverObject)
{
	DbgPrint("Driver Unload! \n");
}

We can see the output in DebugView


image


Well “addr of irp” in the figure is address IRP_MJ_CREATE


Thats it…..

Sunday, October 16, 2011

Reversing the Aurora Vulnerability CVE-2010-0249:

Well this is a year old vulnerability but I thought of documenting it as was quite famous.

and was over television news. Here are some links

http://indiatoday.intoday.in/story/Chinese+hackers+target+PMO/1/79215.html

http://www.wired.com/threatlevel/2010/01/operation-aurora/.

Enough of stories.

Lets move on to technical analysis.

I picked up a POC from internet and tested on my XP SP2.

I opened IE in windbg and opened the POC html with IE. IE crashed at following location.

image

Looking at the disassembly of the location:

image

We see the the Crash happens at the GetDocPtr

image

It looks like the address pointed by ecx register has invalid data which causes the access violation.

Looking at the stack trace

image

Looking at the function mshtml!CEventObj::GenericGetElement

image

It looks like ecx value is derived from the value at address pointed by esi.

restart windbg and set breapoint

bp mshtml!CEventObj::GenericGetElement+0x97

the press g. when internet explorer comes up open the html page.


We break at the point and view the contents of address pointed by esi.

0:000> dds poi(esi) l1
036f7b30  7d4c1850 mshtml!CImgElement::`vftable'
0:000> dds ecx l1
036f7b30  7d4c1850 mshtml!CImgElement::`vftable'

We see that the  that the ecx points CImgElement Vtable is


Looking at the Vtable

0:000> dds 7d4c1850 l10
7d4c1850  7d6de377 mshtml!CImgElement::PrivateQueryInterface
7d4c1854  7d4f43c9 mshtml!CElement::PrivateAddRef
7d4c1858  7d4f4cdd mshtml!CElement::PrivateRelease
7d4c185c  7d519a0e mshtml!C1DElement::`vector deleting destructor'
7d4c1860  7d56c685 mshtml!CImgElement::Init
7d4c1864  7d56c5e0 mshtml!CImgElement::Passivate
7d4c1868  7d63ba1f mshtml!CBase::GetEnabled
7d4c186c  7d63ba1f mshtml!CBase::GetEnabled
7d4c1870  7d63b1f2 mshtml!CBase::GetPages
7d4c1874  7d63b644 mshtml!CBase::InterfaceSupportsErrorInfo
7d4c1878  7d6df0f8 mshtml!CImgElement::QueryStatus
7d4c187c  7d6dff5f mshtml!CImgElement::Exec
7d4c1880  7d4fad5c mshtml!CRect::CRect
7d4c1884  7d4f4e9d mshtml!CElement::SecurityContext
7d4c1888  7d4f7c1c mshtml!CBase::SecurityContextAllowsAccess
7d4c188c  7d5e71d8 mshtml!CElement::DesignMode

We can use the following winbg command to automate to see what all variables are created at esi at the address

bp mshtml!CEventObj::GenericGetElement+0x93 ".printf \"esi = [%08x] \",esi;dds poi(esi) l1;gc"

I press g in windbg and see the following

esi = [036f7f20] 036f7b30  7d4c1850 mshtml!CImgElement::`vftable'
esi = [036f7f20] 036f7b30  7d4c1850 mshtml!CImgElement::`vftable'
ModLoad: 75c50000 75cbe000   C:\WINDOWS\system32\jscript.dll
esi = [036f6b60] aaaaaaaa  ????????
(8b8.768): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=036f7bc0 ebx=aaaaaaaa ecx=aaaaaaaa edx=03703cd0 esi=036f6b60 edi=ffffffff
eip=7d4f2531 esp=0013e154 ebp=0013e174 iopl=0         nv up ei pl nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00010206
mshtml!CElement::GetDocPtr:
7d4f2531 8b01            mov     eax,dword ptr [ecx]  ds:0023:aaaaaaaa=????????

We see that esi always points the CImgElement  is created at the place.

Restart windbg clear all the old breakpoints using bc *.

Let us find which all function cause the exception and

I set another breapoint

bp mshtml!CEventObj::GenericGetElement+0x97

and run windbg. Windbg breaks at the following location

Breakpoint 0 hit
eax=0013e4c8 ebx=036f7b30 ecx=036f7b30 edx=0013dfc0 esi=036f7f20 edi=ffffffff
eip=7d6d5250 esp=0013df7c ebp=0013df98 iopl=0         nv up ei pl nz na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202
mshtml!CEventObj::GenericGetElement+0x97:
7d6d5250 e8dcd2e1ff      call    mshtml!CElement::GetDocPtr (7d4f2531)

Lets set breakpoint at the address pointed by ecx and see which function write on the address ecx=036f7b30

After the breakpoint is hit I clear all the breakpoints and set breakpoint on write

ecx=036f7b30

0:000> bc *
0:000> ba w4 036f7b30 ".printf \"eip=[%08x] \n\n \",eip;u eip l1;gc"
0:000> g
eip=[7d519a43]    mshtml!CElement::~CElement+0x10:
7d519a43 7406            je      mshtml!CElement::~CElement+0x18 (7d519a4b)
ModLoad: 75c50000 75cbe000   C:\WINDOWS\system32\jscript.dll
eip=[7d4f2c22]    mshtml!CStr::Set+0x3e:
7d4f2c22 83c004          add     eax,4
(464.960): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=036f8a50 ebx=aaaaaaaa ecx=aaaaaaaa edx=03703df0 esi=036f7fc0 edi=ffffffff
eip=7d4f2531 esp=0013e154 ebp=0013e174 iopl=0         nv up ei pl nz na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00010206
mshtml!CElement::GetDocPtr:
7d4f2531 8b01            mov     eax,dword ptr [ecx]  ds:0023:aaaaaaaa=????????

It looks like some of the functions which write the address are


shtml!CElement::~CElement
mshtml!CStr::Set

 


To be continued. . .

Tuesday, October 11, 2011

Unpacking Custom Packers

 

There are several articles on internet about unpacking Packed Executables. Most demonstrate the ESP trick. This trick may not work in most packers. These days most malwares use custom packers which are created using some toolkit. You can find lot of malwares of such type like Zbot, SpyeEye, Cycbot.

How PE Packers work

PE Packers compress the PE sections or some other data using some compression algorithms like LZMA ,LZSS,APLIB etc. So to before the running the actual malicious code the packer would

1)Decompress the compressed code:

To do this usually it allocates some space using VirtualAlloc(),ZwAllocateVirtualMemory().Then it will decompress the data to the allocated memory.

2)Fixes the imports:

The imports are fixed so the malware can use the imported API’s . To resolve the import addresses it will use the API’ GetProcAddress() .

3)Jump to OEP:

Finally jumps to the OEP where the the actual malware code begins. Many malwares use multilevel packers.

How to Unpack:

We can set breakpoint on VirtualAlloc() first then after the breakpoint is hit we can remove the breakpoint on VirtualAlloc() and set breakpoint GetProcAddress().

We see that GetProcAddress() would be called repetedly in the loop. This loop is used to resolve all the API’s in the dll. We bypass the loop after that continue debugging.

After few lines of codes we will reach the OEP.

DEMO:

I have taken a sample of SpyEye for the demo.

I had set breakpoint on VirtualAlloc()

image

Then I set breakpoint on GetProcAddress() and break at the following

image

 

We see that getProcAddress is called in loop. We bypass the loop and little below u can see a jump seems like jump to OEP.

image

I follow the jump

image

 

This is another layer of packer .

The trick applies to most packers. May not work in case packers combined with protectors like asprotect.

Feel free to comment