Windows System Call Table Retrieval

366 views
Skip to first unread message

hakim

unread,
Aug 10, 2017, 5:59:18 PM8/10/17
to vmitools
I am trying to retrieve system call table and associated function pointers from a Windows VM. In Windows system, an instance(KeServiceDescriptorTable) of SystemServiceDescriptorTable structure holds the number of system call in the system and the base pointer to the system call table. The data structure looks like below.

struct SystemServiceDescriptorTable {
        PULONG_PTR
ServiceTableBase;
        PULONG
ServiceCounterTableBase;
        ULONG
NumberOfServices;
        PUCHAR
ParamTableBase;
};




This is the approach I am trying to implement: 

  • Get KeServiceDescriptorTable using vmi_translate_ksym2v.
  • Read the number of system calls from the structure using vmi_read_32_va.
  • Get the ServiceTableBase address using vmi_read_64_va
  • use vmi_read_32_va to read all system call function pointers starting from ServiceTableBase

 Is this approach correct? I am getting incorrect system call function pointers and the address doesn't look like a valid kernel address.


Here is the code segment I wrote.

    uint64_t KeServiceDescriptorTableAddress = vmi_translate_ksym2v(vmi, "KeServiceDescriptorTable");     // The address received matches with rekall profile

    uint32_t NumberOfServices = 0;
    vmi_read_32_va(vmi, KeServiceDescriptorTableAddress + 16, 0, &NumberOfServices);
    printf("Number of System calls = %u\n", NumberOfServices);                                            // NumberOfServices = 450 in my system.

    uint64_t ServiceTableBaseAddress = 0;
    vmi_read_64_va(vmi, KeServiceDescriptorTableAddress + 0, 0, &ServiceTableBaseAddress);
    printf("ServiceTableBaseAddress = %p\n", ServiceTableBaseAddress);                                   // Matched with rekall profile


    for (int i=0; i<NumberOfServices; i++) {
      uint64_t syscallAddress = 0;
      vmi_read_64_va(vmi, ServiceTableBaseAddress + (8 * i), 0, &syscallAddress);
      printf("Syscall#%d = %p\n", i, syscallAddress);                                                   // None of them matches with rekall profile
    }



Here is a section of output I am getting.
Syscall#0 = 0xfd43f900fd3c7c04
Syscall#1 = 0x370df400158eb42
Syscall#2 = 0xfe5e58000193bb00
Syscall#3 = 0x19e4906019dc205
Syscall#4 = 0x1e4d401019cb405
Syscall#5 = 0x133ab0001fe1000
Syscall#6 = 0x1f1430001fd8900
Syscall#7 = 0x1aa7c000193ae00
Syscall#8 = 0x19f250101271401
Syscall#9 = 0x18b0e02013d1280


Is there anything wrong with my approach?

Tamas K Lengyel

unread,
Aug 11, 2017, 6:14:06 PM8/11/17
to vmit...@googlegroups.com
Try KiServiceTable instead as the location for the table. See https://github.com/tklengyel/drakvuf/blob/master/src/plugins/ssdtmon/ssdtmon.cpp for some more hints.

--
You received this message because you are subscribed to the Google Groups "vmitools" group.
To unsubscribe from this group and stop receiving emails from it, send an email to vmitools+unsubscribe@googlegroups.com.
To post to this group, send email to vmit...@googlegroups.com.
Visit this group at https://groups.google.com/group/vmitools.
For more options, visit https://groups.google.com/d/optout.

hakim

unread,
Aug 11, 2017, 6:59:43 PM8/11/17
to vmitools
Using KiServiceTable and KeServiceDescriptorTable gives me the same address for table location. I double checked it with Rekall profile. Do you think the last for loop in my code has something wrong? May be I am missing some theoretical aspect of the Windows architecture?


To unsubscribe from this group and stop receiving emails from it, send an email to vmitools+u...@googlegroups.com.

hakim

unread,
Aug 14, 2017, 2:02:20 PM8/14/17
to vmitools
I did some debugging using WinDBG. The result says my output is correct. Using WinDBG I get same content in KiServiceTable. Does it mean Windows 10 handles the system call differently?

hakim

unread,
Aug 14, 2017, 4:25:41 PM8/14/17
to vmitools
This is the output of WinDBG. The content doesn't look like a valid kernel address.

kd> d KiServiceTable
fffff802
`202f2050  fd3c7c04
fffff802`
202f2054  fd43f900
fffff802
`202f2058  0158eb42
fffff802`
202f205c  0370df40
fffff802
`202f2060  0193bb00
fffff802`
202f2064  fe5e5800
fffff802
`202f2068  019dc205
fffff802`
202f206c  019e4906
fffff802
`202f2070  019cb405
fffff802`
202f2074  01e4d401
fffff802
`202f2078  01fe1000

Tamas K Lengyel

unread,
Aug 14, 2017, 10:35:13 PM8/14/17
to vmit...@googlegroups.com
Maybe the table only holds rva's instead of full virtual adresses?

To unsubscribe from this group and stop receiving emails from it, send an email to vmitools+unsubscribe@googlegroups.com.

hakim

unread,
Aug 15, 2017, 10:22:14 AM8/15/17
to vmitools
I found the following WinDBG command to print the system call using KiServiceTable. [reference]

.for(r $t0=0; @$t0<dwo(nt!KiServiceLimit); r $t0=@$t0+1){.printf "%y\n", nt!KiServiceTable+(dwo(nt!KiServiceTable+@$t0*4)>>4)}


Looks like it is indeed rva, starting from KiServiceTable instead of kernel base address. Confused why they did it this way though.
Reply all
Reply to author
Forward
0 new messages