Lets see on some functions from W32pServiceTableFilter on w10 build 16215:
stub_UserSetSensorPresence:
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:
Just short cut from output file wf32.dmp:
Now lets look at IsWin32KSyscallFiltered function from win32kbase.sys:
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:
Sample of content for one of Win32KFilterBitmap:
On more old builds of windows 10 there are 3 exported bitmaks arrays: gWin32KFilterBitArraySet1, gWin32KFilterBitArraySet2 and gWin32KFilterBitArraySet3. Sample of content from build 15058:
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 I8ши.ДЉ¦йеяЗ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