0

I am looking into getting the address of a dispatch routine. For example, I can get it with windbg easily like so:

0: kd> !drvobj HEVD 2
Driver object (ffffa70752fdbe30) is for:
 \Driver\HEVD

DriverEntry:   fffff8066262a134 HEVD
DriverStartIo: 00000000 
DriverUnload:  fffff80662625000 HEVD
AddDevice:     00000000 

Dispatch routines:
[00] IRP_MJ_CREATE                      fffff80662625058    HEVD+0x85058
--snipped--
[0e] IRP_MJ_DEVICE_CONTROL              fffff80662625078    HEVD+0x85078
--snipped--

The IRP_MJ_DEVICE_CONTROL is the routine I am interested in getting and I am not having any luck finding a way to do so. Any knudges or help is much appreciated.

Thank you in advance!

Edit: I would like to get by either Python or CPP

  • in memory or from file on disk? – Igor Skochinsky Oct 4 at 22:34
  • windbg just reads a struct and formats it DRIVER_OBJECT->MajorFunction[IRP_MJ_DEVICE_CONTROL] – blabb Oct 5 at 0:46
  • @IgorSkochinsky I would like to get it from memory if possible but both ways will work. Basically what I'm trying to do is locate the dispatch table to scrape IOCTL's. If I am unable to find it by programming, I will just add the address to the dispatch table as a parameter to my project. – Jon Oct 5 at 0:54
1

As Commented Windbg Just Reads A Structure and Formats it

you can simply use the #FIELD_OFFSET macro (wdm.h)

kd> ?? #FIELD_OFFSET( ntkrpamp!_DRIVER_OBJECT , MajorFunction[0])
long 0n56

kd> ?? #FIELD_OFFSET( ntkrpamp!_DRIVER_OBJECT , MajorFunction[0xe])  <<<<<
0xe == IRP_MJ_DEVICE_CONTROL
long 0n112

kd> dd 0x85ded260+0n112 l1
85ded2d0  8df7d116

kd> u 8df7d116
Beep!BeepDeviceControl:
8df7d116 8bff            mov     edi,edi
8df7d118 55              push    ebp
8df7d119 8bec            mov     ebp,esp
8df7d11b 8b4d0c          mov     ecx,dword ptr [ebp+0Ch]
8df7d11e 8b4160          mov     eax,dword ptr [ecx+60h]
8df7d121 8b500c          mov     edx,dword ptr [eax+0Ch]
8df7d124 81ea00000100    sub     edx,10000h
8df7d12a 56              push    esi

Windbg gets all the driverObjects / or any object for that matter from the RootObjectDirectory

use ReadDebuggerData() Method in IDebugDataSpaces Interface to get
nt!obpRootDirectoryObject
then cast the Address properly to their types and dereference the members of Structure

a small javascript that gets the First Level Driver names is as below
Please note this is a hack using hardcoded 36th HashBucket For Driver DirectoryObject
this can bomb anytime one needs to get The TypeIndex and Compare With _OBJECT_TYPE for robustness
also note TypeIndex in latest windows releases undergo a xorring routine and Do not point directly to the UnderLying TypeNames

it is Xorred with nt!ObHeaderCookie and another Byte From Object Header Address

an emulated demo for the disassembly of that routine below

0: kd> r $t0 = 0xffffe00e255187a0
0: kd> r $t1 = @$t0-30
0: kd> r $t2 = @$t0-18
0: kd> r $t3 = by(@$t0-18)
0: kd> r $t4 = @$t1>>8 &0xff
0: kd> r $t5 = @$t4 ^ @$t3 ^ by(nt!ObHeaderCookie)
0: kd> ? @$t0;? @$t1;? @$t2;? @$t3;?@$t4;? @$t5

Evaluate expression: -35123616446560 = ffffe00e`255187a0
Evaluate expression: -35123616446608 = ffffe00e`25518770
Evaluate expression: -35123616446584 = ffffe00e`25518788
Evaluate expression: 246 = 00000000`000000f6
Evaluate expression: 135 = 00000000`00000087
Evaluate expression: 3 = 00000000`00000003

0: kd> dt nt!_OBJECT_TYPE poi(nt!ObTypeIndexTable + 3 *8) 

   +0x000 TypeList         : _LIST_ENTRY [ 0xffff920c`896b9900 - 0xffff920c`896b9900 ]
   +0x010 Name             : _UNICODE_STRING "Directory"  <<<<
xxxxxxxxxxxxxxxxxxxxxxxx


0: kd> uf nt!ObGetObjectType
nt!ObGetObjectType:
fffff805`1abcbff0 488d41d0        lea     rax,[rcx-30h]
fffff805`1abcbff4 0fb649e8        movzx   ecx,byte ptr [rcx-18h]
fffff805`1abcbff8 48c1e808        shr     rax,8
fffff805`1abcbffc 0fb6c0          movzx   eax,al
fffff805`1abcbfff 4833c1          xor     rax,rcx
fffff805`1abcc002 0fb60dcf75f8ff  movzx   ecx,byte ptr [nt!ObHeaderCookie (fffff805`1ab535d8)]
fffff805`1abcc009 4833c1          xor     rax,rcx
fffff805`1abcc00c 488d0d4d7cf8ff  lea     rcx,[nt!ObTypeIndexTable (fffff805`1ab53c60)]
fffff805`1abcc013 488b04c1        mov     rax,qword ptr [rcx+rax*8]
fffff805`1abcc017 c3              ret

Source Code For Javascript

/// <reference path="JSProvider.d.ts" />

function log(x) {
    host.diagnostics.debugLog(x + "\n")
}

function getobroot() {
    var obroot = host.getModuleSymbol("ntkrnlmp", "ObpRootDirectoryObject", "_OBJECT_DIRECTORY *");
    var ObHeadFields = host.getModuleType("nt", "_OBJECT_HEADER").fields
    var drvdirheadaddr = obroot.HashBuckets[36].ChainLink.Object.address
    var drvdirobj = host.createPointerObject(drvdirheadaddr, "nt", "_OBJECT_DIRECTORY *")
    //looping only Hasbuckets 
    for (i = 0; i < 37; i++) {
        var drvobj1 = drvdirobj.HashBuckets[i].Object.address
        //loop all the 37 HashBucket's Objects and Chainlinks->Objects for drivers x,y,z,...
        var drvobj = host.createPointerObject(drvobj1, "nt", "_DRIVER_OBJECT *")
        try {
            var dname = host.memory.readWideString(drvobj.DriverName.Buffer.address)
        } catch (error) {
            log(error)
        }
        log(dname)
    }
}
  • Thank you for that! I didn't know that was a thing. I was leaning more towards using either Python or Cpp to get the dispatch routines for a project I'm working on. As I mentioned in the previous comments, I'm trying to locate the dispatch table to scrape IOCTL's. If not, I will just add the address manually to my project as a parameter. Thanks again, @blabb! – Jon Oct 5 at 0:58
  • @Jon you've to dig into the driver binary to get the ioctl value. – Biswapriyo Oct 5 at 8:08
  • @Biswapriyo, I can get the IOCTL's easily. So right now, I can give it the address of the dispatch table and from there, itll get the IOCTL's. So right now, I have this: project.exe driver address I would like to just give it the driver and do something to find the dispatch table rather than actually specifying the address as a parameter. This is being a pain in the ass, so I might just stick to that. I would still like to do it. If windbg can do it, I'm pretty sure there is a way – Jon Oct 5 at 19:47
  • added details of how windbg gets it – blabb Oct 7 at 19:22
  • thank you blabb! Sorry, I am just now seeing it but this was quite helpful – Jon Oct 30 at 3:46

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.