320 likes | 535 Views
Fermín J. Serna – MSRC Engineering @ Microsoft. Windows SECURE RING0 DEVELOPMENT. Fermín J. Serna – MSRC @ Microsoft. Agenda. Introduction Common mistakes in kernel mode MSRC case history Yes, you will see Windows Kernel Source Code Detect / Protect QA.
E N D
Fermín J. Serna – MSRC Engineering @ Microsoft Windows SECURE RING0 DEVELOPMENT
Fermín J. Serna – MSRC @ Microsoft Agenda • Introduction • Commonmistakes in kernelmode • MSRC case history • Yes, youwillsee Windows KernelSourceCode • Detect/Protect • QA
Fermín J. Serna – MSRC @ Microsoft Introduction • Who am I? • Security Engineer at MSRC EngineeringReact (former SWI). • Technicalbackground of MSRC forexternallyreportedsecurityissues: MSo8-67, … • HPUX PA-RISC, Solaris SPARC: assembly, shellcode and exploitlover. • Publishedseveraldocs and exploits: Phrack (58-9) HP-UX PA-RISC exploitationtechniqueslong time ago, … • Developer of a PAX implementationon win32 long time ago…
Fermín J. Serna – MSRC @ Microsoft Introduction • Purpose of thetalk • Kernelmodeisnotthatobscure and it shares the similar problemswithusermode • Willdemonstratethiswith real MSRC cases. • Evangelizationonkernelmodesecurityawareness • Providetools and techniquesforkernelmodedevelopers and testers
Fermín J. Serna – MSRC @ Microsoft Introduction • Kernelmode vs usermode (Win32 - x86) • Twoexecutionmodes: privilegedmode and non privilegedone • 2Gb forkernel – 2Gb forusermode (/3GB) • Protectedmode, paging and segmentationprotectskernelspace • Kernelmodeneedstovalidateusermoderequests and their data (untrusted)
Fermín J. Serna – MSRC @ Microsoft Introduction
Fermín J. Serna – MSRC @ Microsoft Introduction • Kernelentrypoints (Win32) • Software interrupts (Sysenter, int 2eh, etc) • Device IO (read, write, IO, etc) • UsermodeCallbacks • Networking • Hardware • Others
Fermín J. Serna – MSRC @ Microsoft Introduction • Entrypointexample: ZwFake_GetMeColorAtPixel(Ulong x, Ulong y, Ulong* buffer) • Whatdoesit do? • Executed in kernelmodewithusermodeparams • Wewillwritetothesupplied buffer • Whatcouldgowrongif buffer pointsto a kernelmodeaddress?
Fermín J. Serna – MSRC @ Microsoft Introduction Request: give me the color at pixel (x,y) and storeit in buffer z KernelSpace Tcpip.sys Driver.sys Win32k.sys Userspace Buffer Z ntdll.dll Kernel32.dll
Fermín J. Serna – MSRC @ Microsoft Introduction Request: give me the color at pixel (x,y) and storeit in buffer z KernelSpace Tcpip.sys Buffer Z Driver.sys Win32k.sys Userspace ntdll.dll Kernel32.dll
Fermín J. Serna – MSRC @ Microsoft Introduction • Whatkernel/drivers should do • Validateallusermode data • ProbeForWrite() • ProbeForRead() • Handlevalidation • Capture data locally in kernelspace • Access usermode data only once. Parallelusermodethreadscouldbechangingthe data. • “Time of Check Time of Use” attacks • Raceconditions
Fermín J. Serna – MSRC @ Microsoft Introduction • ProbeForRead/Write(addr, len,align) • Validatesif a memoryrangeis in usermode • Ifrangeoverlapswithkernelmemorygeneratesanexception • ProbeForWriteprobesallthepagesforWriteaccess. • If ( len == 0 ) continuewith no exception • DuetoLegacycodecompatibility
Fermín J. Serna – MSRC @ Microsoft CommonMistakes • Integeroverflows and oldschoolmistakes • Of course, they do alsoexist in kernelmode void foo(struct bar *x, USHORT len) { USHORT blah; blah=get_actual_counter(); blah+=len; new_entries = ExAllocatePoolWithTag( NonPagedPool,blah*sizeof(struct bar),TAG_NAME); for (USHORT counter=0; counter<get_actual_counter(); counter++) { // Copy old entries } for (USHORT counter=0; counter<len;counter++) { // Copy new entries } blah can overflow size can overflow NULL deref Memorycorruption
Fermín J. Serna – MSRC @ Microsoft CommonMistakes • Trustinguser-supplied pointers • Kernel API, no probing of usermode data • Sameappliesto IOCTL and METHOD_NEITHER void NtUser_giveme_foo(struct bar *x, USHORT len) { for (USHORT counter=0; counter<len;counter++) { // Copy entries to x } } No NULL checkingon X No ProbeForWriteon X No lengthcheck
Fermín J. Serna – MSRC @ Microsoft CommonMistakes • Nulldereferencing (SystemBuffer + more) case IOCTL_FOO_STATS: // METHOD_BUFFERED Stats = Irp->AssociatedIrp.SystemBuffer; Irp->IoStatus.Information = sizeof(*Stats); if (Stats->Version != FOO_STATS_VERSION) { Irp->IoStatus.Status = STATUS_INVALID_PARAMETER; break; } *Stats->data = *FooSt; Usermode Data Derefitwithout NULL checking Ifattackercontrols NULL page….
Fermín J. Serna – MSRC @ Microsoft CommonMistakes • BypassingProbeForRead/Write (zerolen) // lParam and wParam are untrusted DWORDs LARGE_STRING str; try { str.bAnsi = bAnsi; str.MaximumLength = wParam; if (!bAnsi) { str.MaximumLength *= sizeof(WCHAR); } str.Length = 0; str.Buffer = (LPBYTE)lParam; ProbeForWrite((PVOID)str.Buffer, str.MaximumLength,1); } except (StubExceptionHandler(FALSE)) { MSGERROR(0); } [... later write into str.Buffer pointer based on wParam ...] This can overflow and becomezero PFW willsay Ok for a zerolength LateronwewritewParamTchars
Fermín J. Serna – MSRC @ Microsoft CommonMistakes • BypassingProbeForRead/Write (len != usedlen) // Attacker controls OutputBuffer and OutputBufferLength void IOCTL_foo_handler(...) { [...] try { ProbeForWrite(OutputBuffer,OutputBufferLength,sizeof(UCHAR)); RtlCopyMemory(OutputBuffer,context->offset,context->Length ); } except( FOO_EXCEPTION_FILTER(&status) ) { } [...] } Outputbufferlengthcanbezero OutputBuffer can pointtokmode PFW willsayitis OK Wecopybasedonanothersize
Fermín J. Serna – MSRC @ Microsoft CommonMistakes • Casting/Truncation... // lParam and wParam are untrusted DWORDs LARGE_STRING str; try { str.bAnsi = bAnsi; str.MaximumLength = WORD_TRUNCATION(wParam); str.Length = 0; str.Buffer = (LPBYTE)lParam; ProbeForWrite((PVOID)str.Buffer,str.MaximumLength,1); } except (StubExceptionHandler(FALSE)) { MSGERROR(0); } [... later write into str.Buffer pointer based on wParam ...] This can bebecomezero PFW willsay Ok for a zerolength LateronwewritewParamTchars
Fermín J. Serna – MSRC @ Microsoft CommonMistakes • Lack of exceptionhandlingonProbeForRead/Write and data access // lParam and wParam are untrusted DWORDs LARGE_STRING str; str.bAnsi = bAnsi; str.MaximumLength = (ULONG)wParam; str.Length = 0; str.Buffer = (LPBYTE)lParam; ProbeForWrite((PVOID)str.Buffer, str.MaximumLength, 1); *str.Buffer=‘\0’; Weinitialize LARG_STRING PFW can throwanexception Writtingtousermodetoo! Exceptionhandling? bugcheck
Fermín J. Serna – MSRC @ Microsoft CommonMistakes • Trustingusermodestructures (doublefetch) // Attacker controls lParam void win32k_foo_entry_point(...) { // lParam has already passed successfully the ProbeForRead my_struct = (PMY_STRUCT)lParam; if (my_struct ->lpData) { cbCapture = sizeof(MY_STRUCT) + my_struct->cbData; […] if (my_alloc=UserAllocPoolWithQuota(cbCapture,TAG1))!= NULL) { RtlCopyMemory(my_alloc,my_struct->lpData,my_struct->cbData); } } } my_structisalreadyvalidated Butnotcaptured Firstusermodefetch Secondone…
Fermín J. Serna – MSRC @ Microsoft MSRC Cases • MS08-01: IGMP IGMPv3GroupRecord * GetGSIsInRecord(IN IGMPAddr *AddrPtr, IN uint *RecSize) { IGMPSrcAddr *Src, *PrevSrc; IGMPv3GroupRecord *Rec; ushort Count = 0; for (Src=AddrPtr->iga_srclist; Src; Src=Src->isa_next) { if (!IS_SOURCE_ALLOWED(AddrPtr, Src)) continue; if (!Src->isa_csmarked) continue; Count++; } // Allocate record Rec = CTEAllocMemN(RECORD_SIZE(Count,0), 'qICT'); if (Rec == NULL) { *RecSize = 0; return NULL; } Countinitializaed This can overflow 65535 Small allocation Lateron pool overflow
Fermín J. Serna – MSRC @ Microsoft MSRC Cases • MS08-25: Win32k MESSAGECALL(OUTSTRING) { LARGE_STRING str; BEGINRECV_MESSAGECALL(0); try { str.bAnsi = bAnsi; str.MaximumLength = (ULONG)wParam; if (!bAnsi) { str.MaximumLength *= sizeof(WCHAR); } str.Length = 0; str.Buffer = (PVOID)lParam; ProbeForWrite((PVOID)str.Buffer, str.MaximumLength, sizeof(BYTE)); } except (StubExceptionHandler(FALSE)) { MSGERROR(0); } Truncationto 31 bits Alsoanintegeroverflow Length can bezero and PFW Bypass Lateronwehad a RtlCopyMemory
Fermín J. Serna – MSRC @ Microsoft MSRC Cases • MS08-66: AFD.sys try { if (RequestorMode != KernelMode ) { ProbeForWrite (OutputBuffer, OutputBufferLength, sizeof (UCHAR)); RtlCopyMemory( OutputBuffer, (PUCHAR)context+endpoint->Common.VcConnecting.RemoteSocketAddressOffset, endpoint->Common.VcConnecting.RemoteSocketAddressLength ); *Information = endpoint->ContextLength; } except( AFD_EXCEPTION_FILTER (status) ) { ASSERT (NT_ERROR (status)); } Validatewithsuppliedlength Actual usagewithdifferentone Ifkmodeaddr and lengthzero Kernelmemorycorruption
Fermín J. Serna – MSRC @ Microsoft MSRC Cases • MS07-66: ALPC AlpcpIsReplyAllowed( __in PALPC_PORT PortObject,__in PKALPC_MESSAGE Message ) { BOOLEAN Allowed; PALPC_COMMUNICATION_INFO CommunicationInfo; PALPC_PORT OwnerPort; ALPCASSERT_PTR(AlpcpIsLocked(Message) != FALSE, Message); ALPCASSERT_PTR(AlpcpIsCanceled(Message) == FALSE, Message); if (Message->PortQueue != PortObject) { if (Message->PortQueue == NULL) { OwnerPort = AlpcpGetOwnerPortMessage(Message); ALPCASSERT_PTR(OwnerPort != NULL, Message); CommunicationInfo = OwnerPort->CommunicationInfo; Thisfunction can return NULL ASSERT only,notpresent in free build ReadAVfrom NULL page
Fermín J. Serna – MSRC @ Microsoft MSRC Cases • MS08-61: Win32k pcds = (PCOPYDATASTRUCT)lParam; if (pcds->lpData) { cbCapture = sizeof(COPYDATASTRUCT) + pcds->cbData; } else { cbCapture = sizeof(COPYDATASTRUCT); } if (cbCapture && (psms->pvCapture = UserAllocPoolWithQuota (cbCapture, TAG_SMS_CAPTURE)) != NULL) { if (pcds->lpData) { pcdsNew->lpData=(PVOID)((PBYTE)pcdsNew + sizeof(COPYDATASTRUCT)); RtlCopyMemory(pcdsNew->lpData, pcds->lpData, pcds->cbData); } Firstfetchfromusermode Allocationbasedonit Secondfetchfromusermode Copybasedonit
Fermín J. Serna – MSRC @ Microsoft Detect/Protect • Fuzzing: devctl.exe and dc2.exe at the WDK • Devctl.exe: IOCTL fuzzerwrittenbyNeillClift • Dc2.exe: Improvedversion in newest WDK • Lots of switchesfortargetedfuzzing • Itis free, itis simple, use it!
Fermín J. Serna – MSRC @ Microsoft Detect/Protect • DriverVerifier • Part of theOperatingSystem • Dynamicanalysistool • Windows key + R: verifier.exe • Special pool fordetecting pool overflows and underflows. • Handleverification (Usermode vs kernelmodehandles) • Fuzzingwiththesechecksenablediswise
Fermín J. Serna – MSRC @ Microsoft Detect/Protect • Static Driver Verifier • Compile –time tools (build, scan and check) • Staticdv /rule:* • Staticdv /view • Itis free, itis simple, use it!
Fermín J. Serna – MSRC @ Microsoft Detect/Protect • BinaryStaticAnalysisframeworks • Integeroverflowonallocations • ProbeForRead/Write bypass • METHOD_BUFFERED & SystemBuffer • METHOD_NEITHER & UserBuffer | Type3Inputbuffer • […]
Fermín J. Serna – MSRC @ Microsoft Door-Points • What I hope youshouldgetfromthistalk • Itiseasytomakemistakes in kernelmode • Extra validationneeded • Trickytofind… • Butautomatedtools can helpyou • Fuzz… no really… Fuzz!
Fermín J. Serna – MSRC @ Microsoft Greetings • Thankyouguys! • MSRC/MSEC (former SWI): Bruce Dang, Matt Miller, DamianHasse, Andrew Roths and Thomas Garnier • Non-MS people: Sexy Pandas and MatthieuSuiche
Fermín J. Serna – MSRC @ Microsoft Questions Nowor... fermin [_DOT_] serna [_AT_] microsoft [_DOT_] com Twitter: fjserna