пятница, 27 июля 2012 г.

Ocaml 4.00

  • Microsoft-based native Win32 port. No binary distribution available yet; download the source distribution and compile it.
  • Microsoft-based native Win64 port. Same features as the Microsoft-based native Win32 port, but generates 64-bit code. No binary distribution available yet; download the source distribution and compile it.

вторник, 24 июля 2012 г.

hypervisor callbacks in w8

There are couple of exported functions to set up some hypervisor related callbacks

Set WHEA callback into global variable HvlpWheaErrorNotificationCallback

Set up to 5 (in w8 release preview up to 8) callbacks in global array HvlpInterruptCallback. This callbacks are called in HvlRouteInterrupt:
  • index 0 - from KiHvInterrupt
  • index 1 - from KiVmbusInterrupt0
  • index 2 - from KiVmbusInterrupt1
  • index 3 - from KiVmbusInterrupt2
  • index 4 - from KiVmbusInterrupt3

понедельник, 16 июля 2012 г.


In windows 8 there is some another undocumented function to set callback inside netio.sys. Check it in disasm:

    mov edi, _gWfpGlobal
    xor edx, edx
    lea ecx, [edi+2B8h]
    lea esp, [esp+0Ch+var_C]
    cmp dword ptr [ecx], 0
    jnz short loc_32397
    mov eax, [ebp+callback]
    lea ecx, [edx+edx*2] ; * 3
    mov [edi+ecx*4+2B8h], eax ; * 12
    movzx ecx, [ebp+arg_4]
    mov eax, _gWfpGlobal
    lea edx, [edx+edx*2]
    add edx, edx
    add edx, edx
    mov [edx+eax+2B4h], ecx
    mov ecx, [ebp+arg_0]
    mov eax, _gWfpGlobal
    mov [edx+eax+2B0h], ecx

    inc edx
    add ecx, 0Ch
    cmp edx, 5
    jb  loc_32314

We can see here that gWfpGlobal contains at offset 0x2B8 5 elements with size 0xC (0x10 on x64) where stored pointer to callback function. Both gWfpGlobal and offset can be obtained with static analysis

пятница, 13 июля 2012 г.

callback tables in Fwpkclnt.sys on w8

It seems that under w8 there are couple of undocumented exported functions called to set some callback tables - FwpsL2DispatchTableAndGlobalsSet0 & FwpsTcpIpDispatchTableAndGlobalsSet0:

Check for example FwpsTcpIpDispatchTableAndGlobalsSet0 in disasm:
    mov edi, edi
    push ebp
    mov ebp, esp
    mov eax, [ebp+arg_4]
    push esi
    mov esi, [ebp+arg_0]
    push edi
    mov edi, TcpIpDispatchTable
    push 2Ah
    pop ecx
    rep movsd

We see here that arg_0 are copied to some variable which I named as TcpIpDispatchTable. It can easy be obtained with static analysis. FwpsL2DispatchTableAndGlobalsSet0 looks identical

Sample of output from w8 release preview:

Fwpkclnt.sys exports on w8

to compare with

среда, 11 июля 2012 г.

вторник, 10 июля 2012 г.

wincheck rc8.21

Download mirror


This undocumented function set some callback for NSI providers. I`ll show how to find this registered callbacks. Quick look in disasm shows that this callbacks are stored somewhere deeply in structures linked in list with head in NsiNmpList, so lets check it with debugger:

kd> ? netio!NsiNmpList
Evaluate expression: -6184740751232 = fffffa60`00b97880
kd> dt _LIST_ENTRY fffffa60`00b97880
 [ 0xfffffa60`00b974e8 - 0xfffffa80`03240408 ]
   +0x000 Flink            : 0xfffffa60`00b974e8 _LIST_ENTRY [ 0xfffffa80`0168e018 - 0xfffffa60`00b97880 ]
   +0x008 Blink            : 0xfffffa80`03240408 _LIST_ENTRY [ 0xfffffa60`00b97880 - 0xfffffa80`018ec738 ]
kd> dp fffffa60`00b974e8
fffffa60`00b974e8  fffffa80`0168e018 fffffa60`00b97880
fffffa60`00b974f8  fffffa60`00b8b530 00000000`00000001
fffffa60`00b97508  00000000`00000000 fffffa60`00b8ee28
fffffa60`00b97518  00000000`00000000 00000000`00000000
fffffa60`00b97528  00000000`00000000 00000001`000e0002
fffffa60`00b97538  fffffa60`00b97538 fffffa60`00b97538
fffffa60`00b97548  00000000`00000000 00000000`00000000
fffffa60`00b97558  00000000`00000000 00000000`00000100
kd> u fffffa60`00b8b530 l1
fffffa60`00b8b530 1800            sbb     byte ptr [rax],al
kd> u fffffa60`00b8ee28 l1
fffffa60`00b8ee28 0000            add     byte ptr [rax],al

It seems that first 2 pointers are LIST_ENTRY. Lets see some more samples:

kd> !pool fffffa80`0168e018 2
Pool page fffffa800168e018 region is Nonpaged pool
*fffffa800168e000 size:   d0 previous size:    0  (Allocated) *NMpc
        Owning component : Unknown (update pooltag.txt)

kd> dp fffffa80`0168e018
fffffa80`0168e018  fffffa80`0189f3f8 fffffa60`00b974e8
fffffa80`0168e028  fffffa60`00b8b548 00000000`00000002
fffffa80`0168e038  fffffa80`0168d270 fffffa60`00b8ffc0
fffffa80`0168e048  00000000`00000000 fffffa80`0168d30c
fffffa80`0168e058  00000000`00000000 00000001`000e0002
fffffa80`0168e068  fffffa80`0168e068 fffffa80`0168e068
fffffa80`0168e078  00000000`00000000 00000000`00000000
fffffa80`0168e088  00000000`00000000 00000000`00000100
kd> u fffffa60`00b8b548 l1
fffffa60`00b8b548 1800            sbb     byte ptr [rax],al

kd> !pool fffffa80`0168d270 2
Pool page fffffa800168d270 region is Nonpaged pool
*fffffa800168d260 size:   50 previous size:   40  (Allocated) *RMcc
        Owning component : Unknown (update pooltag.txt)
kd> u fffffa60`00b8ffc0 l1
fffffa60`00b8ffc0 0000            add     byte ptr [rax],al
kd> !pool fffffa80`0168d30c 2
Pool page fffffa800168d30c region is Nonpaged pool
*fffffa800168d2b0 size:   80 previous size:   50  (Allocated) *NMRb
        Pooltag NMRb : Network Module Registrar Bindings, Binary : tcpip.sys

kd> dp fffffa80`018d9d48
fffffa80`018d9d48  fffffa80`018e0cc8 fffffa80`018adde8
fffffa80`018d9d58  fffffa60`00f26f28 00000000`00000006
fffffa80`018d9d68  fffffa80`018d9c60 fffffa60`00f2b5f0
fffffa80`018d9d78  00000000`00000000 fffffa80`018d43fc
fffffa80`018d9d88  fffffa80`032f2b60 00000001`000e0002
fffffa80`018d9d98  fffffa80`018d9d98 fffffa80`018d9d98
fffffa80`018d9da8  fffffa80`029784c0 fffffa80`018d9de0
fffffa80`018d9db8  00000000`00000000 00000000`00000100
kd> u fffffa60`00f26f28 l1
fffffa60`00f26f28 1800            sbb     byte ptr [rax],al
kd> u fffffa60`00f2b5f0 l1
fffffa60`00f2b5f0 0000            add     byte ptr [rax],al
kd> !pool fffffa80`032f2b60 2
Pool page fffffa80032f2b60 region is Unknown
*fffffa80032f2b50 size:  280 previous size:  270  (Allocated) *NSIr
        Pooltag NSIr : NSI Generic Buffers, Binary : nsi.dll

пятница, 6 июля 2012 г.

NPI clients & providers

Some good introduction about NPI can be found here
The main question is how to enumerate all registered NPI clients & providers ? It seems that windbg does not have any plugin for netio.sys support

Lets check some code in disasm - function NmrpFindOrAddRegisteredNpiId called from NmrpGetModule & NmrpRegisterModuleAndGetBindableCandidates:

    mov esi, [ebp+arg_0]
    mov ebx, [esi]
    and ebx, 1                          ; 2 items
    imul ebx, 30h                       ; with length 0x30
    add ebx, offset _NmrRegisteredNpiIdTable
    push esi
    lea eax, [ebx+4]                    ; offset 4 - NpiId
    push eax
    call _NmrpIsEqualNpiId@8
    test al, al
    jnz short loc_1D6BE
    mov [ebp+arg_0], ebx
    mov ebx, [ebx]
    test ebx, ebx
    jnz short loc_1D65B
    cmp [ebp+arg_4], bl
    jz  short loc_1D6BE
    push 6E524D4Eh                      ; Tag - 'nRMN'
    push 30h                            ; NumberOfBytes
    push ebx                            ; PoolType
    call ds:__imp__ExAllocatePoolWithTag@12
    mov ebx, eax
    test ebx, ebx
    jz  short loc_1D6BE
    push edi
    push 30h                            ; size_t
    push 0                              ; int
    push ebx                            ; void *
    call _memset
    lea edi, [ebx+4]                    ; offset 4 - GUID NpiId
    lea eax, [ebx+14h]                  ; offset 14 - list_entry
    mov [eax+4], eax
    mov [eax], eax
    lea eax, [ebx+1Ch]                  ; offset 1C - list_entry
    mov [eax+4], eax
    mov [eax], eax
    lea eax, [ebx+24h]                  ; offset 24 - list_entry
    mov [eax+4], eax
    mov [eax], eax

We (o`k, at least I) can see here that non exported data NmrRegisteredNpiIdTable used as hash table with 2 slots and store linked list to some other structure with size 0x30 byte. netio.pdb does not contain any usefull info besides names but recovering of this structure is easy:

struct NpiIdItem
/* win32 win64 offsets */
/*   0x0   0x0 */  NpiIdItem *Next;
/*   0x4   0x8 */  GUID       Id;
/*  0x14  0x18 */  LIST_ENTRY clients;
/*  0x1c  0x28 */  LIST_ENTRY providers;
/*  0x24  0x38 */  LIST_ENTRY filters;
/*  0x2c  0x48 */  DWORD      flags;

So now we can traverse all NpiIdItem from both NmrRegisteredNpiIdTable slots and for each NpiIdItem also traverse clients & providers linked list.
Example from vista 32bit:

четверг, 5 июля 2012 г.

rdbss registered devices

In exported function rdbss!RxRegisterMinirdr there is such code:

    mov esi, offset mutex
    mov ecx, esi
    call ds:__imp_@ExAcquireFastMutexUnsafe@4
    mov eax, [ebp+DeviceObject]
    mov ecx, dword_23B50
    add eax, 0D4h
    mov dword ptr [eax], offset minidrd_list
    mov [eax+4], ecx
    mov [ecx], eax
    inc minidrd_cnt

Freshly created device object was inserted in some unnamed LIST_ENTRY minidrd_list at offset 0xd4 and before was obtained fast mutex (also unnamed). All this data can be obtained with static analysis

Sample on w7 32bit:
rbdss registered devs count: 3
 [0] DevObj 85248020 DrvObj 8524F458 - \SystemRoot\system32\drivers\csc.sys
 [1] DevObj 851D3A68 DrvObj 85C3D740 - \SystemRoot\system32\DRIVERS\mrxsmb.sys
 [2] DevObj 851D2A68 DrvObj 85C3D740 - \SystemRoot\system32\DRIVERS\mrxsmb.sys

вторник, 3 июля 2012 г.

wincheck rc8.20

Download irusmirror
  • add -kshims option to show registered kernel shims
  • add checking of IoRegisterPriorityCallback callbacks
  • add checking of PoRegisterCoalescingCallback callbacks (with -pofx option)
  • add checking of http.sys!UlIoctlTable
  • Add checking of TLS callbacks (in user mode)
  • some other bugs was fixed