четверг, 13 июля 2017 г.

win32k calls filtering on w10

Lets see on some functions from W32pServiceTableFilter on w10 build 16215:
stub_UserSetSensorPresence:
  push    ebp
  mov     ebp, esp
  push    2 ; call index
  call    _IsWin32KSyscallFiltered@4    ; IsWin32KSyscallFiltered(x)
  test    al, al
  jz      short loc_1361D
  lea     ecx, aNtusersetsenso          ; "NtUserSetSensorPresence"
  mov     edx, 2
  call    @NtUserWin32kSysCallFilterStub@8 ; NtUserWin32kSysCallFilterStub(x,x)
  call    _PsIsWin32KFilterEnabled@0    ; PsIsWin32KFilterEnabled()
  test    al, al
  jz      short loc_1361D
  lea     edx, _W32pServiceTableFilter
  mov     ecx, cs:_W32pServiceLimitFilter
  mov     eax, 2 ; call index
  lea     edx, [edx+ecx*4]
  movsx   eax, byte ptr [eax+edx]
  or      eax, eax
  jle     short loc_13619
  mov     eax, 0C000001Ch ;
STATUS_INVALID_SYSTEM_SERVICE
loc_13619:
  mov     esp, ebp
  pop     ebp
  retn
loc_1361D: ; call original function
  mov     esp, ebp
  pop     ebp
  jmp     _NtUserSetSensorPresence@4    ; NtUserSetSensorPresence(x)


In some case this stub just pass control to original function (NtUserSetSensorPresence in this case) if IsWin32KSyscallFiltered or PsIsWin32KFilterEnabled returned 0, returns STATUS_INVALID_SYSTEM_SERVICE or just do nothing. Last condition depends from byte stored with call index behind W32pServiceTableFilter, so we can write simple idc script to dump all functions which will return STATUS_INVALID_SYSTEM_SERVICE:
#include

static main(void)
{
  auto  cnt, addr, tab, ftab, i, fp, name;
  addr = LocByName("_W32pServiceLimitFilter");
  if ( addr == BADADDR )
  {
    Warn("Cannot find W32pServiceLimitFilter");
    return;
  }
  cnt = Dword(addr);
  tab = LocByName("_W32pServiceTableFilter");
  if ( tab == BADADDR )
  {
    Warn("Cannot find W32pServiceTableFilter");
    return;
  }
  ftab = cnt * 4 + tab;
  fp = fopen("wf32.dmp", "w");
  for ( i = 0; i < cnt; i++, tab = tab + 4, ftab = ftab + 1 )
  {
    if ( Byte(ftab) )
    {
      addr = Dword(tab);
      name = Name(addr);
      fprintf(fp, "[%d] \"%s\",\n", i, name);
    }
  }
  fclose(fp);
}


Just short cut from output file wf32.dmp:
[3] "__stub_GdiWidenPath@4",
[4] "__stub_GdiUpdateColors@4",
[5] "__stub_GdiUnrealizeObject@4",


Now lets look at IsWin32KSyscallFiltered function from win32kbase.sys:
callIdx= dword ptr  8

  mov     edi, edi
  push    ebp
  mov     ebp, esp
  call    ds:__imp__PsGetWin32KFilterSet@0 ; PsGetWin32KFilterSet()
  cmp     eax, 6
  jb      short loc_CCD70
  mov     al, 1
  jmp     short loc_CCD96

loc_CCD70: 

  push    esi
  mov     esi, ?gaWin32KFilterBitmap@@3PAPAEA[eax*4] ; uchar * * gaWin32KFilterBitmap
  test    esi, esi
  jz      short loc_CCD93
  mov     edx, [ebp+callIdx]
  mov     al, 1
  mov     ecx, edx
  shr     edx, 3
  and     ecx, 7
  shl     al, cl
  test    [edx+esi], al
  setnz   al
  jmp     short loc_CCD95

loc_CCD93:
  xor     al, al

loc_CCD95: 

  pop     esi

loc_CCD96:
  pop     ebp
  retn    4


If PsGetWin32KFilterSet returned more than 5 then this call will be filtered. In other case we have 6 bitmaps in gaWin32KFilterBitmap where each bit responsible for filtering some call. Pseudocode looks like:

DWORD bitmap_index = PsGetWin32KFilterSet();
if ( bitmap_index > 6 )
  return 1; 
PBYTE mask_array = gaWin32KFilterBitmap[bitmap_index];
if ( NULL == mask_array )
  return 0;
DWORD mask_idx = callidx >> 3;
return (mask_array[mask_idx] & (1 << (callidx & 7));

Sample of content for one of Win32KFilterBitmap:
Win32KFilterBitmap[1] at 8F974D08
00000000  FF 6C F9 47-6D FF 9A C6|C3 3B DC 55-FC A1 1E C9  яlщGmяљЖГ;ЬUьЎ.Й
00000010  DD 6E 06 94-46 54 30 4E|6B 4D C0 27-53 FA 91 FE  Эn.”FT0NkMА'Sъ‘ю
00000020  5E 71 E0 59-80 8C 20 04|BC D4 20 46-52 10 48 00  ^qаYЂЊ .јФ FR.H.
00000030  17 A0 63 B0-7D EB C3 43|1C 71 A8 5F-5B B0 BF D8  . c°}лГC.qЁ_[°їШ
00000040  49 AD 38 F8-E8 1B C4 8A|A6 E9 E5 FF-C7 38 DA E0  I­8ши.ДЉ¦йеяЗ8Ъа
00000050  FF FF 7F 73-AB A8 01 F5|FF FF FF FF-9F 3F E8 1F  яяs«Ё.хяяяяџ?и.
00000060  80 21 80 A0-E1 F0 B9 FD|CF FF 21 40-84 DE FF F7  Ђ!Ђ бр№эПя!@„Юяч
00000070  F1 FF F3 FF-FF BF FF FF|5F F2 FD E6-DF FE 9F 04  сяуяяїяя_тэжЯюџ.
00000080  00 D2 DF 38-FE FF BD BD|13 FC FF FF-FF F1 9F FF  .ТЯ8юяЅЅ.ьяяясџя
00000090  EF FB                                            пы

 [0] NtUserGetOwnerTransformedMonitorRect
 [1] NtUserYieldTask
 [2] NtUserSetSensorPresence
 [3] NtGdiWidenPath
 [4] NtGdiUpdateColors
 [5] NtGdiUnrealizeObject
 [6] NtGdiUnmapMemFont
 [7] NtGdiUnloadPrinterDriver
 [10] NtGdiScaleRgn


On more old builds of windows 10 there are 3 exported bitmaks arrays: gWin32KFilterBitArraySet1, gWin32KFilterBitArraySet2 and gWin32KFilterBitArraySet3. Sample of content from build 15058:
gWin32KFilterBitArraySet1 at 8F527248
00000000  FF 6C F9 47-6D FF 9A C6|C3 3B DC 55-FC A1 1E C9  яlщGmяљЖГ;ЬUьЎ.Й
00000010  DD 6E 06 94-46 54 30 4E|6B 4D C0 27-53 FA 91 FE  Эn.”FT0NkMА'Sъ‘ю
00000020  5E 71 E0 59-80 8C 20 04|BC D4 20 92-14 04 12 C0  ^qаYЂЊ .јФ ’...А
00000030  05 E8 18 6C-DF FA F0 10|47 1C EA D7-16 EC 2F 3B  .и.lЯър.G.кЧ.м/;
00000040  A9 15 83 8F-BE 41 56 34|4D 2F FF 3F-C6 D1 06 FF  ©.ѓЏѕAV4M/я?ЖС.я
00000050  FF FF 9B 5B-45 0D A8 FF|FF FF FF FF-FC 41 FF 01  яя›[E.ЁяяяяяьAя.
00000060  18 02 08 1A-0E 9F DB FF|FC 9F 02 46-E8 FD EF E3  .....џЫяьџ.Fиэпг
00000070  FF E7 FF FE-FF BF EC FB|CD BF FD 3F-09 00 A4 BF  язяюяїмыНїэ?..¤ї
00000080  71 FC FF 7B-7B 27 FC FF|FF FF F8 CF-FF F7        qья{{'ьяяяшПяч

 [0] NtUserGetOwnerTransformedMonitorRect
 [1] NtUserYieldTask
 [2] NtUserSetSensorPresence
 [3] NtGdiWidenPath
 [4] NtGdiUpdateColors
 [5] NtGdiUnrealizeObject
 [6] NtGdiUnmapMemFont
 [7] NtGdiUnloadPrinterDriver
 [10] NtGdiScaleRgn

Комментариев нет:

Отправить комментарий