пятница, 24 ноября 2017 г.

wincheck rc8.59

  • add support of numerous versions of windows 10 insider preview - up to ~17025
  • add -dsip option to dump SIPs from crypt32.dll
  • add -dac & -dsac options to dump activation contexts and system activation contexts. based on this code from @deroko
  • add dumping of rpcrt4 security providers
  • add dumping of ETW private loggers (-wmi option)
  • add lots of WNF IDs names
  • add dumping of registered with winnsi!NsiRpcRegisterChangeNotification notifications

четверг, 16 ноября 2017 г.

crypt32.dll SIPs

in cool paper "subverting windows trust" was described mechanism of subject interface package (SIP)
Lets see how we can extract and dump them
Unfortunately list of SIPs inside crypt32.dll don't have name in .pdb. One way is to find it with help of IDA Pro from function FindDll:

  push    [ebp+nSize]                   ; nSize
  push    ebx                           ; lpDst
  push    [ebp+lpSrc]                   ; lpSrc
  call    ds:__imp__ExpandEnvironmentStringsW@12
  test    eax, eax
  jz      short loc_5CF28F50
  push    offset dll_cs

  call    ds:__imp__EnterCriticalSection@4
  mov     edi, dll_list ; linked list of SIPs
  test    edi, edi
  jz      short loc_5CF28F89

  push    0FFFFFFFFh                    ; cchCount2
  push    dword ptr [edi+8]             ; lpString2
  push    0FFFFFFFFh                    ; cchCount1
  push    ebx                           ; lpString1
  push    1                             ; dwCmpFlags
  push    409h                          ; Locale
  call    ds:__imp__CompareStringW@24
  dec     eax
  sub     eax, 1
  jz      short loc_5CF28F41
  mov     edi, [edi+4]
  test    edi, edi
  jnz     short next_item

this address (I named it dll_list) contains head of linked list to SIPs structures like this:
struct sip_item
  sip_item *next;
  PVOID unk4;        // ptr to crypto32_dll_list_item
  const char *fname; // actually ends to end of sip_item
  PVOID pfn; // if function was resolved, else NULL

struct crypto32_dll_list_item
  PVOID unk;
  crypto32_dll_list_item *next;
  const wchar_t *dll_name;

  HANDLE base; // if dll was loaded - load base else NULL
  DWORD unk10;
  DWORD unk14;
  sip_item *func_items_list;
  PVOID unk20;
  PVOID unk24;
  PVOID unk28;

вторник, 7 ноября 2017 г.

rpcrt4 security providers

Count of loaded providers stored in rpcrt4!LoadedProviders and list in rpcrt4!ProviderList
Structure of each provider can be partially recovered from function FindSecurityPackage:
struct _rpc_loaded_provider
  DWORD unk1;
  PVOID unk2;
  PSecurityFunctionTable table; 
  PVOID unk3;
  PVOID unk4;
}; // size of struct 0x14 for x86 and 0x28 for x64

It's interesting that the function of InitSecurityFunctionTable patches the contents of SECURITY_FUNCTION_TABLE. Sample of output from w8.1:

четверг, 2 ноября 2017 г.

how to find rpcrt4!GlobalRpcServer

I looked through sources of rpcview and found that they used some kind of brute-force in file RpcCore.c in function GetRpcServerAddressInProcess. It looks very strange and slow - they already has some code for pdb reading, so why not just ask address of ?GlobalRpcServer@@3PEAVRPC_SERVER@@EA ?

Anyway there is better way. Lets run my exref.pl in IDA Pro on rpcrt4.dll from windows 10 build 16278:
_I_RpcServerUseProtseq2W@20: 4EFACEB0 addr 4EFACEED
_RpcServerInqBindings@4: 4EFADA90 addr 4EFADAAC
_RpcServerRegisterIfEx@24: 4EFADCB0 addr 4EFADCCC
_RpcMgmtIsServerListening@4: 4EFAE470 addr 4EFAE48D
_RpcServerInterfaceGroupActivate@4: 4EFAE5B0 addr 4EFAE5C2
_RpcServerInterfaceGroupDeactivate@8: 4EFAE5E0 addr 4EFAE5F2
_I_RpcServerUseProtseqEp2W@24: 4EFB33E0 addr 4EFB33FF
_RpcServerUnregisterIf@12: 4EFB50B0 addr 4EFB50C5
_RpcServerRegisterIf3@32: 4EFB51F0 addr 4EFB5222
_RpcServerRegisterIf2@28: 4EFDFF40 addr 4EFDFF5C
_RpcServerInqBindingsEx@8: 4EFE0080 addr 4EFE0098
_RpcServerRegisterIf@12: 4EFE02E0 addr 4EFE02F5
_I_RpcServerRegisterForwardFunction@4: 4EFE03E0 addr 4EFE03F2
_RpcServerInterfaceGroupInqBindings@8: 4F0070D0 addr 4F0070E7
_RpcServerUseAllProtseqsEx@12: 4F007150 addr 4F00722C

wow, it seems that this will be easy
Lets look at exported function I_RpcServerRegisterForwardFunction:

пятница, 1 сентября 2017 г.

ETW private loggers

as you know ordinary etw loggers can be checked in compmgmt.msc\performance\data collector sets\event trace sessions
But private etw sessions cannot be showed in compmgmt.msc
Actually all private sessions stored in ntdll!EtwpLoggerArray. This array has size of 0x40 items (see allocation in function EtwpGetNextAvailableLoggerId) and looks like:

EtwpLoggerArray: 000000000524D380
00000000  01 00 00 00-00 00 00 00|01 00 00 00-00 00 00 00  ................
00000010  01 00 00 00-00 00 00 00|01 00 00 00-00 00 00 00  ................
00000020  01 00 00 00-00 00 00 00|01 00 00 00-00 00 00 00  ................
00000030  01 00 00 00-00 00 00 00|01 00 00 00-00 00 00 00  ................
00000040  80 6D 2B 05-01 00 00 00|01 00 00 00-00 00 00 00  Ђm+.............
00000050  01 00 00 00-00 00 00 00|01 00 00 00-00 00 00 00  ................
00000060  01 00 00 00-00 00 00 00|01 00 00 00-00 00 00 00  ................
00000070  01 00 00 00-00 00 00 00|01 00 00 00-00 00 00 00  ................
00000080  01 00 00 00-00 00 00 00|01 00 00 00-00 00 00 00  ................
00000090  01 00 00 00-00 00 00 00|01 00 00 00-00 00 00 00  ................
000000A0  01 00 00 00-00 00 00 00|01 00 00 00-00 00 00 00  ................

среда, 9 августа 2017 г.

wincheck rc8.58

  • add support of numerous versions of windows 10 insider preview - up to 16257
  • add -j option to dump jobs
  • add -dwf option to dump win32k filtering bitmaps
  • add support of DelegatedNtdll
  • add dumping of kprocess.LdtBaseAddress &LdtTableLength (based on this paper)

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

win32k calls filtering on w10

Lets see on some functions from W32pServiceTableFilter on w10 build 16215:
  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 ;
  mov     esp, ebp
  pop     ebp
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:

static main(void)
  auto  cnt, addr, tab, ftab, i, fp, name;
  addr = LocByName("_W32pServiceLimitFilter");
  if ( addr == BADADDR )
    Warn("Cannot find W32pServiceLimitFilter");
  cnt = Dword(addr);
  tab = LocByName("_W32pServiceTableFilter");
  if ( tab == BADADDR )
    Warn("Cannot find W32pServiceTableFilter");
  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);

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


It seems that since est. w10 build 15007 you can have more than one loaded 32bit ntdll.dll
Function LdrpLoadDelegatedNtdll query key DelegatedNtdll via LdrQueryImageFileKeyOption then appends this value to \\SystemRoot\\system32\\ and loads it. Sure this required changes in callbacks propagation logic

There is table LdrpDelegatedNtdllExports which just hold pairs of exported symbol and offset to it "delegated" ptr:
  • LdrInitializeThunk -> LdrDelegatedLdrInitializeThunk
  • RtlUserThreadStart -> LdrDelegatedRtlUserThreadStart
  • RtlDispatchAPC -> LdrDelegatedRtlDispatchAPC
  • KiUserExceptionDispatcher -> LdrDelegatedKiUserExceptionDispatcher
  • KiUserApcDispatcher -> LdrDelegatedKiUserApcDispatcher
  • KiUserCallbackDispatcher -> LdrDelegatedKiUserCallbackDispatcher
  • KiRaiseUserExceptionDispatcher -> LdrDelegatedKiRaiseUserExceptionDispatcher
  • LdrSystemDllInitBlock -> LdrDelegatedSystemDllInitBlock
  • LdrpChildNtdll -> LdrpChildNtdllPointer
  • LdrParentInterlockedPopEntrySList -> LdrpParentInterlockedPopEntrySListPointer
  • LdrParentRtlInitializeNtUserPfn -> LdrpParentRtlInitializeNtUserPfnPointer
  • LdrParentRtlResetNtUserPfn -> LdrpParentRtlResetNtUserPfnPointer
  • LdrParentRtlRetrieveNtUserPfn -> LdrpParentRtlRetrieveNtUserPfnPointer

Lets see how this "delegated" pfns works

пятница, 16 июня 2017 г.

EPROCESS.MitigationFlags in w10 build 16215

Lets see EPROCESS.Flags3 in w10 build 16193:
unsigned long Flags3;
unsigned long Minimal:0:1;
unsigned long ReplacingPageRoot:1:1;
unsigned long DisableNonSystemFonts:2:1;
unsigned long AuditNonSystemFontLoading:3:1;
unsigned long Crashed:4:1;
unsigned long JobVadsAreTracked:5:1;
unsigned long VadTrackingDisabled:6:1;
unsigned long AuxiliaryProcess:7:1;
unsigned long SubsystemProcess:8:1;
unsigned long IndirectCpuSets:9:1;
unsigned long InPrivate:a:1;
unsigned long ProhibitRemoteImageMap:b:1;
unsigned long ProhibitLowILImageMap:c:1;
unsigned long SignatureMitigationOptIn:d:1;
unsigned long DisableDynamicCodeAllowOptOut:e:1;
unsigned long EnableFilteredWin32kAPIs:f:1;
unsigned long AuditFilteredWin32kAPIs:10:1;
unsigned long PreferSystem32Images:11:1;
unsigned long RelinquishedCommit:12:1;
unsigned long Reserved:13:1;
unsigned long HighGraphicsPriority:14:1;
unsigned long CommitFailLogged:15:1;
unsigned long ReserveFailLogged:16:1;
unsigned long DisableDynamicCodeAllowRemoteDowngrade:17:1;
unsigned long LoaderIntegrityContinuityEnabled:18:1;
unsigned long LoaderIntegrityContinuityAudit:19:1;
unsigned long ControlFlowGuardExportSuppressionEnabled:1a:1;
unsigned long FatalAccessTerminationRequested:1b:1;
unsigned long DisableSystemAllowedCpuSet:1c:1;
unsigned long ControlFlowGuardStrict:1d:1;

and compare it with EPROCESS.Flags3 in w10 build 16215:
unsigned long Flags3;
unsigned long Minimal:0:1;
unsigned long ReplacingPageRoot:1:1;
unsigned long Crashed:2:1;
unsigned long JobVadsAreTracked:3:1;
unsigned long VadTrackingDisabled:4:1;
unsigned long AuxiliaryProcess:5:1;
unsigned long SubsystemProcess:6:1;
unsigned long IndirectCpuSets:7:1;
unsigned long RelinquishedCommit:8:1;
unsigned long HighGraphicsPriority:9:1;
unsigned long CommitFailLogged:a:1;
unsigned long ReserveFailLogged:b:1;
unsigned long SystemProcess:c:1;

dramatic difference

понедельник, 5 июня 2017 г.

how to find PspUniqueJobIdTable

In his cool presentation Alex Ionescu said:
PspUniqueJobIdTable - no way to open/enumerate
Sure there are always some ways. Lets see xrefs to PspUniqueJobIdTable:
  • PspJobDelete
  • NtCreateJobObject
  • PspInitializeJobStructures
no exported functions in this list (well, NtCreateJobObject can be considered as such). Looks deep in PspJobDelete: 

loc_14001B6B4:                          ; CODE XREF: PspJobDelete+2A3
                                        ; PspJobDelete+17FEA8
  test    dword ptr [rbx+518h], 40000000h ; EJOB.JobFlags
  jnz     loc_14019B3AD

loc_14001B6C4:                          ; CODE XREF: PspJobDelete+17FEB6

  mov     rax, gs:188h
  dec     word ptr [rax+1E4h]
  mov     eax, [rbx+4C4h]               ; EJOB.JobId
  test    eax, eax
  jz      short loc_14001B701
  mov     rcx, cs:PspUniqueJobIdTable
  mov     edx, eax
  call    ExMapHandleToPointer

There is very long and noticeable signature for testing of EJOB.JobFlags with value 0x40000000: 18 05 00 00 00 00 00 40
If you searching it in .text section you get only 5-6 matches. Now question is how to get offset to EJOB.JobFlags. It can be done from exported function PsGetCurrentSilo:
PsGetCurrentSilo proc near
  mov     rax, gs:188h
  cmp     qword ptr [rax+7C8h], 0FFFFFFFFFFFFFFFDh
  jnz     short loc_1400B61BF
  mov     rax, [rax+220h]               ; KTHREAD.Process
  mov     rax, [rax+3B0h]               ; EPROCESS.Job
  test    rax, rax
  jz      short locret_1400B61BE

loc_1400B61A6:                          ; CODE XREF: PsGetCurrentSilo+3Cj
  test    dword ptr [rax+518h], 40000000h ; EJOB.JobFlags

And few words about enumerating - it`s just good old HANDLE_TABLE, so we can use ExEnumHandleTable and get all Jobs IDs

понедельник, 29 мая 2017 г.

wincheck rc8.57


среда, 24 мая 2017 г.

wnf kernelmode callbacks

I already described how to enum usermode wnf callbacks
Now it`s time to enum WNF callbacks in kernel
It is not surprising that they stored in EPROCESS.WnfContext, this struct is undocumented but can be partially recovered from function ExpWnfCreateProcessContext:
offset 0 - WORD signature 0x906
offset 4 - WORD - size 0x88 (0x44 for x86)
offset 8 - eprocess
offset 0x10 - linked list for WNF contexts
offset 0x28 - push lock
offset 0x40 - linked list
offset 0x58 - linked list
offset 0x70 - linked list

Lets see at this struct in windbg

среда, 3 мая 2017 г.

kernel etw traces in windows 10

In windows 10 there is no good old EtwpGuidHashTable and all registered Etw stored in SILO. Let`s see how we can extract them

Check first function exported function EtwRegister:
  call    _PsGetCurrentServerSiloGlobals@0 ; PsGetCurrentServerSiloGlobals()
  push    [ebp+arg_C]
  mov     edx, [ebp+arg_0]
  push    dword ptr [ebp+4]
  mov     ecx, [eax+1F0h]               ; ESERVERSILO_GLOBALS.EtwSiloState
  push    [ebp+arg_8]
  push    [ebp+arg_4]
  push    3
  call    _EtwpRegisterProvider@28      ; EtwpRegisterProvider(x,x,x,x,x,x,x)

Function PsGetCurrentServerSiloGlobals returns processes SILO or default SILO PspHostSiloGlobals stored in kernel which has type ESERVERSILO_GLOBALS. Field EtwSiloState has type ETW_SILODRIVERSTATE:
  /*   0x0 */ /*|0x4|*/ struct _ESERVERSILO_GLOBALS* SiloGlobals;
  /*   0x8 */ /*|0x168|*/ struct _ETW_GUID_ENTRY EtwpSecurityProviderGuidEntry;
  /* 0x170 */ /*|0x100|*/ struct _EX_RUNDOWN_REF_CACHE_AWARE* EtwpLoggerRundown[64];
  /* 0x270 */ /*|0x100|*/ struct _WMI_LOGGER_CONTEXT* WmipLoggerContext[64];
  /* 0x370 */ /*|0x700|*/ struct _ETW_HASH_BUCKET EtwpGuidHashTable[64];
  /* 0xa70 */ /*|0x10|*/ unsigned short EtwpSecurityLoggers[8];
  /* 0xa80 */ /*|0x1|*/ unsigned char EtwpSecurityProviderEnableMask;
  /* 0xa84 */ /*|0x4|*/ long EtwpShutdownInProgress;
  /* 0xa88 */ /*|0x4|*/ unsigned long EtwpSecurityProviderPID;
  /* 0xa8c */ /*|0x10|*/ struct _ETW_PRIV_HANDLE_DEMUX_TABLE PrivHandleDemuxTable;
  /* 0xa9c */ /*|0x10|*/ struct _ETW_COUNTERS EtwpCounters;
  /* 0xab0 */ /*|0x8|*/ union _LARGE_INTEGER LogfileBytesWritten;
  /* 0xab8 */ /*|0x4|*/ struct _ETW_SILO_TRACING_BLOCK* ProcessorBlocks;

пятница, 21 апреля 2017 г.

etwex - ida plugin for Etw traces IIDs searching

For example you may need to find which Etw providers located in some module. There are lots of functions can be used to register provider and manual searching is very boring
So I commited today code for Ida Pro plugin for Etw traces IIDs searching. It currently supports only 32bit PE files (much better if you load appropriate PDB file) and processing following functions:
  • TraceLoggingRegister
  • TraceLoggingRegisterEx
  • EtwRegister from import
  • EtwEventRegister from import
  • EventRegister from import
Samples of using:

четверг, 6 апреля 2017 г.

ntdll ProtectedPolicies

It seems that since windows 10 ntdll has security feature called "ProtectedPolicies" - you can query it with RtlQueryProtectedPolicy function. Prototype of this function is:
NTAPI NTSTATUS RtlQueryProtectedPolicy(GUID *, PDWORD out_flag);

Lets see how it works:
loc_6A277EFB:   ; CODE XREF: RtlQueryProtectedPolicy(x,x)+12 j
  push    edi
  mov     edi, offset _RtlpProtectedPoliciesSRWLock
  push    edi
  call    _RtlAcquireSRWLockShared@4    ; RtlAcquireSRWLockShared(x)
  push    offset _RtlpSearchProtectedPolicyEntry ; PtFuncCompare
  push    14h                           ; SizeOfElements
  push    ds:_RtlpProtectedPoliciesActiveCount ; NumOfElements
  push    ds:_RtlpProtectedPolicies     ; Base
  push    [ebp+Key]                     ; Key
  call    _bsearch

That policies stored in array RtlpProtectedPolicies, count located in RtlpProtectedPoliciesActiveCount and size of each policy is 0x14 bytes (0x18 under x64), so each policy looks like struct:
struct protected_policy
  IID guid;
  DWORD flag;

Lets see from where RtlQueryProtectedPolicy called

четверг, 2 марта 2017 г.

ida plugin for RFG fixups processing

I commited today code for Ida Pro plugin for RFG fixups processing - for both version 1 & 2

It seems that by default during automatic loading of pe files Ida don`t load .reloc section (where usually located RFG fixups). In such case I ask if you want to add new segment:
Sure it works only if original input file (you can extract it with get_input_file_path function) is still available. Also I used dirty hack - I am too lazy to parse PE file by hand, and it seems that node "$ PE header" keeps all sections (even not loaded in base !) in supvals


Update: it seems that buggy ida sdk don`t contains doCode function and auto_mark_range actually does not take into account end argument, so body of prologs looks ugly

среда, 1 марта 2017 г.


it seems that around since w10 build 15007 format of rfg relocs was changed and field IMAGE_DYNAMIC_RELOCATION_TABLE.Version now has value 2. So lets install platform SDK for 15003 and see what was changed

First remarkable thing is that IMAGE_LOAD_CONFIG_DIRECTORY now has two additional fields:
    WORD       DynamicValueRelocTableSection;
    WORD       Reserved2;
    // since w10 build 15003 ?
    ULONGLONG  GuardRFVerifyStackPointerFunctionPointer; // VA
    DWORD      HotPatchTableOffset;

so sizeof(IMAGE_LOAD_CONFIG_DIRECTORY64) is now 0xf4

вторник, 7 февраля 2017 г.

apisetschema.dll from windows 10 build 15025

lots of new modules was added:
  • win-core-registry-fromapp
  • win-gaming-expandedresources
  • win-gaming-gamemonitor
  • win-ngc-serialization
  • win-security-isolatedcontainer
  • win-shcore-path
  • onecore-appmodel-tdlmigration 
  • onecore-hcap-svf
  • onecore-hnetcfg
  • onecore-mpc-input
  • onecore-shlwapi
  • onecore-spectrumsyncclient
  • win-adsi-activeds
  • win-appcompat-aepic
  • win-appmodel-restrictedappcontainer-internal
  • win-audiocore-spatial
  • win-base-rstrtmgr
  • win-core-iuri
  • win-core-winsrv
  • win-deployment-productenumerator
  • win-dx-dinput8
  • win-eventing-pdh
  • win-fs-cscapi
  • win-gaming-gamechatoverlay
  • win-gdi-gdiplus
  • win-hyperv-compute
  • win-kernel32-process
  • win-kioskmode-config
  • win-mapi-mapi32
  • win-mininput-inputhost
  • win-mm-wmvcore
  • win-net-netbios
  • win-net-netshell
  • win-net-nfdapi
  • win-nfc-semgr
  • win-ntuser-rawinput
  • win-odbc-odbc32
  • win-parentalcontrols-setup
  • win-resources-deployment
  • win-rtcore-ntuser-winevent
  • win-security-appinfoext
  • win-security-certpoleng
  • win-security-slc
  • win-shell-aclui
  • win-shell-comctl32
  • win-shell-efsadu
  • win-shell-ntshrui
  • win-shell-shdocvw
  • win-wnv