It's hilarious how this new code has the exact same Windows security bug I gave 
a talk about at BlackHat 2-3 years ago (which Microsoft fixed in Vista).

It's sad how this code ignores the exported PsSetProcessWindowStation API and 
relevant EPROCESS field.

It's awesome how nothing changes whenever I prop up to see the "progress".

--
Best regards,
Alex Ionescu

On 2011-03-22, at 5:19 AM, gadamopou...@svn.reactos.org wrote:

> Author: gadamopoulos
> Date: Tue Mar 22 09:19:26 2011
> New Revision: 51115
> 
> URL: http://svn.reactos.org/svn/reactos?rev=51115&view=rev
> Log:
> [ntoskrnl]
> - Implement calling OkayToCloseProcedure callouts to win32k for desktop and 
> window station objects
> - Fix a bug that caused ObpCloseHandle to return success even when 
> OkayToCloseProcedure failed
> 
> [win32k]
> - Rewrite SetProcessWindowStation to actually set the current window station 
> and close the previous one
> - Implement OkayToCloseProcedure callouts from the kernel to prevent closing 
> the current desktop or window station
> 
> Modified:
>    trunk/reactos/ntoskrnl/ex/win32k.c
>    trunk/reactos/ntoskrnl/ob/obhandle.c
>    trunk/reactos/ntoskrnl/ps/win32.c
>    trunk/reactos/subsystems/win32/win32k/include/desktop.h
>    trunk/reactos/subsystems/win32/win32k/include/win32.h
>    trunk/reactos/subsystems/win32/win32k/include/winsta.h
>    trunk/reactos/subsystems/win32/win32k/main/dllmain.c
>    trunk/reactos/subsystems/win32/win32k/ntuser/desktop.c
>    trunk/reactos/subsystems/win32/win32k/ntuser/winsta.c
> 
> Modified: trunk/reactos/ntoskrnl/ex/win32k.c
> URL: 
> http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ex/win32k.c?rev=51115&r1=51114&r2=51115&view=diff
> ==============================================================================
> --- trunk/reactos/ntoskrnl/ex/win32k.c [iso-8859-1] (original)
> +++ trunk/reactos/ntoskrnl/ex/win32k.c [iso-8859-1] Tue Mar 22 09:19:26 2011
> @@ -37,9 +37,45 @@
> 
> PKWIN32_PARSEMETHOD_CALLOUT ExpWindowStationObjectParse = NULL;
> PKWIN32_DELETEMETHOD_CALLOUT ExpWindowStationObjectDelete = NULL;
> +PKWIN32_OKTOCLOSEMETHOD_CALLOUT ExpWindowStationObjectOkToClose = NULL;
> +PKWIN32_OKTOCLOSEMETHOD_CALLOUT ExpDesktopObjectOkToClose = NULL;
> PKWIN32_DELETEMETHOD_CALLOUT ExpDesktopObjectDelete = NULL;
> 
> /* FUNCTIONS ****************************************************************/
> +
> +NTSTATUS
> +NTAPI
> +ExpDesktopOkToClose( IN PEPROCESS Process OPTIONAL,
> +                     IN PVOID Object,
> +                     IN HANDLE Handle,
> +                     IN KPROCESSOR_MODE AccessMode)
> +{
> +    WIN32_OKAYTOCLOSEMETHOD_PARAMETERS Parameters;
> +
> +    Parameters.Process = Process;
> +    Parameters.Object = Object;
> +    Parameters.Handle = Handle;
> +    Parameters.PreviousMode = AccessMode;
> +
> +    return ExpDesktopObjectOkToClose(&Parameters);
> +}
> +
> +NTSTATUS
> +NTAPI
> +ExpWindowStationOkToClose( IN PEPROCESS Process OPTIONAL,
> +                     IN PVOID Object,
> +                     IN HANDLE Handle,
> +                     IN KPROCESSOR_MODE AccessMode)
> +{
> +    WIN32_OKAYTOCLOSEMETHOD_PARAMETERS Parameters;
> +
> +    Parameters.Process = Process;
> +    Parameters.Object = Object;
> +    Parameters.Handle = Handle;
> +    Parameters.PreviousMode = AccessMode;
> +
> +    return ExpWindowStationObjectOkToClose(&Parameters);
> +}
> 
> VOID
> NTAPI
> @@ -114,6 +150,7 @@
>     ObjectTypeInitializer.PoolType = NonPagedPool;
>     ObjectTypeInitializer.DeleteProcedure = ExpWinStaObjectDelete;
>     ObjectTypeInitializer.ParseProcedure = ExpWinStaObjectParse;
> +    ObjectTypeInitializer.OkayToCloseProcedure = ExpWindowStationOkToClose;
>     ObCreateObjectType(&Name,
>                        &ObjectTypeInitializer,
>                        NULL,
> @@ -124,6 +161,7 @@
>     ObjectTypeInitializer.GenericMapping = ExpDesktopMapping;
>     ObjectTypeInitializer.DeleteProcedure = ExpDesktopDelete;
>     ObjectTypeInitializer.ParseProcedure = NULL;
> +    ObjectTypeInitializer.OkayToCloseProcedure = ExpDesktopOkToClose;
>     ObCreateObjectType(&Name,
>                        &ObjectTypeInitializer,
>                        NULL,
> 
> Modified: trunk/reactos/ntoskrnl/ob/obhandle.c
> URL: 
> http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ob/obhandle.c?rev=51115&r1=51114&r2=51115&view=diff
> ==============================================================================
> --- trunk/reactos/ntoskrnl/ob/obhandle.c [iso-8859-1] (original)
> +++ trunk/reactos/ntoskrnl/ob/obhandle.c [iso-8859-1] Tue Mar 22 09:19:26 2011
> @@ -1752,7 +1752,6 @@
> 
>         /* Detach and return success */
>         if (AttachedToProcess) KeUnstackDetachProcess(&ApcState);
> -        Status = STATUS_SUCCESS;
>     }
>     else
>     {
> 
> Modified: trunk/reactos/ntoskrnl/ps/win32.c
> URL: 
> http://svn.reactos.org/svn/reactos/trunk/reactos/ntoskrnl/ps/win32.c?rev=51115&r1=51114&r2=51115&view=diff
> ==============================================================================
> --- trunk/reactos/ntoskrnl/ps/win32.c [iso-8859-1] (original)
> +++ trunk/reactos/ntoskrnl/ps/win32.c [iso-8859-1] Tue Mar 22 09:19:26 2011
> @@ -20,6 +20,8 @@
> PGDI_BATCHFLUSH_ROUTINE KeGdiFlushUserBatch = NULL;
> extern PKWIN32_PARSEMETHOD_CALLOUT ExpWindowStationObjectParse;
> extern PKWIN32_DELETEMETHOD_CALLOUT ExpWindowStationObjectDelete;
> +extern PKWIN32_OKTOCLOSEMETHOD_CALLOUT ExpWindowStationObjectOkToClose;
> +extern PKWIN32_OKTOCLOSEMETHOD_CALLOUT ExpDesktopObjectOkToClose;
> extern PKWIN32_DELETEMETHOD_CALLOUT ExpDesktopObjectDelete;
> extern PKWIN32_POWEREVENT_CALLOUT PopEventCallout;
> 
> @@ -116,6 +118,8 @@
>     PspW32ThreadCallout = CalloutData->ThreadCallout;
>     ExpWindowStationObjectParse = CalloutData->WindowStationParseProcedure;
>     ExpWindowStationObjectDelete = CalloutData->WindowStationDeleteProcedure;
> +    ExpWindowStationObjectOkToClose = 
> CalloutData->WindowStationOkToCloseProcedure;
> +    ExpDesktopObjectOkToClose = CalloutData->DesktopOkToCloseProcedure;
>     ExpDesktopObjectDelete = CalloutData->DesktopDeleteProcedure;
>     PopEventCallout = CalloutData->PowerEventCallout;
>     KeGdiFlushUserBatch = CalloutData->BatchFlushRoutine;
> 
> Modified: trunk/reactos/subsystems/win32/win32k/include/desktop.h
> URL: 
> http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/win32k/include/desktop.h?rev=51115&r1=51114&r2=51115&view=diff
> ==============================================================================
> --- trunk/reactos/subsystems/win32/win32k/include/desktop.h [iso-8859-1] 
> (original)
> +++ trunk/reactos/subsystems/win32/win32k/include/desktop.h [iso-8859-1] Tue 
> Mar 22 09:19:26 2011
> @@ -69,6 +69,9 @@
> VOID APIENTRY
> IntDesktopObjectDelete(PWIN32_DELETEMETHOD_PARAMETERS Parameters);
> 
> +NTSTATUS NTAPI 
> +IntDesktopOkToClose(PWIN32_OKAYTOCLOSEMETHOD_PARAMETERS Parameters);
> +
> LRESULT CALLBACK
> IntDesktopWindowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
> 
> 
> Modified: trunk/reactos/subsystems/win32/win32k/include/win32.h
> URL: 
> http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/win32k/include/win32.h?rev=51115&r1=51114&r2=51115&view=diff
> ==============================================================================
> --- trunk/reactos/subsystems/win32/win32k/include/win32.h [iso-8859-1] 
> (original)
> +++ trunk/reactos/subsystems/win32/win32k/include/win32.h [iso-8859-1] Tue 
> Mar 22 09:19:26 2011
> @@ -166,6 +166,7 @@
>   PCLS pclsPrivateList;
>   PCLS pclsPublicList;
>   INT cThreads;
> +  HDESK hdeskStartup;
>   DWORD dwhmodLibLoadedMask;
>   HANDLE ahmodLibLoaded[CLIBS];
>   struct _WINSTATION_OBJECT *prpwinsta;
> 
> Modified: trunk/reactos/subsystems/win32/win32k/include/winsta.h
> URL: 
> http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/win32k/include/winsta.h?rev=51115&r1=51114&r2=51115&view=diff
> ==============================================================================
> --- trunk/reactos/subsystems/win32/win32k/include/winsta.h [iso-8859-1] 
> (original)
> +++ trunk/reactos/subsystems/win32/win32k/include/winsta.h [iso-8859-1] Tue 
> Mar 22 09:19:26 2011
> @@ -82,6 +82,9 @@
> APIENTRY
> IntWinStaObjectParse(PWIN32_PARSEMETHOD_PARAMETERS Parameters);
> 
> +NTSTATUS NTAPI 
> +IntWinstaOkToClose(PWIN32_OKAYTOCLOSEMETHOD_PARAMETERS Parameters);
> +
> NTSTATUS FASTCALL
> IntValidateWindowStationHandle(
>    HWINSTA WindowStation,
> @@ -106,4 +109,7 @@
> 
> PWINSTATION_OBJECT FASTCALL IntGetWinStaObj(VOID);
> 
> +BOOL FASTCALL
> +UserSetProcessWindowStation(HWINSTA hWindowStation);
> +
> /* EOF */
> 
> Modified: trunk/reactos/subsystems/win32/win32k/main/dllmain.c
> URL: 
> http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/win32k/main/dllmain.c?rev=51115&r1=51114&r2=51115&view=diff
> ==============================================================================
> --- trunk/reactos/subsystems/win32/win32k/main/dllmain.c [iso-8859-1] 
> (original)
> +++ trunk/reactos/subsystems/win32/win32k/main/dllmain.c [iso-8859-1] Tue Mar 
> 22 09:19:26 2011
> @@ -119,6 +119,7 @@
>     {
>         DPRINT("Destroying W32 process PID:%d at IRQ level: %lu\n", 
> Process->UniqueProcessId, KeGetCurrentIrql());
>         Win32Process->W32PF_flags |= W32PF_TERMINATED;
> +
>         if (Win32Process->InputIdleEvent)
>         {
>            EngFreeMem((PVOID)Win32Process->InputIdleEvent);
> @@ -144,6 +145,9 @@
>         {
>             LogonProcess = NULL;
>         }
> +
> +        UserSetProcessWindowStation(NULL);
> +
>     }
> 
>     RETURN( STATUS_SUCCESS);
> @@ -220,25 +224,14 @@
>         {
>             if(hWinSta != NULL)
>             {
> -                if(Process != CsrProcess)
> +                if(!UserSetProcessWindowStation(hWinSta))
>                 {
> -                    HWINSTA hProcessWinSta = 
> (HWINSTA)InterlockedCompareExchangePointer((PVOID)&Process->Win32WindowStation,
>  (PVOID)hWinSta, NULL);
> -                    if(hProcessWinSta != NULL)
> -                    {
> -                        /* our process is already assigned to a different 
> window station, we don't need the handle anymore */
> -                        NtClose(hWinSta);
> -                    }
> -                }
> -                else
> -                {
> -                    NtClose(hWinSta);
> +                    DPRINT1("Failed to set process window station\n");
>                 }
>             }
> 
>             if (hDesk != NULL)
>             {
> -                Win32Thread->rpdesk = NULL;
> -                Win32Thread->hdesk = NULL;
>                 if (!IntSetThreadDesktop(hDesk, FALSE))
>                 {
>                         DPRINT1("Unable to set thread desktop\n");
> @@ -441,6 +434,8 @@
>     CalloutData.ProcessCallout = Win32kProcessCallback;
>     CalloutData.ThreadCallout = Win32kThreadCallback;
>     CalloutData.BatchFlushRoutine = NtGdiFlushUserBatch;
> +    CalloutData.DesktopOkToCloseProcedure = IntDesktopOkToClose;
> +    CalloutData.WindowStationOkToCloseProcedure = IntWinstaOkToClose;
> 
>     /* Register our per-process and per-thread structures. */
>     PsEstablishWin32Callouts((PWIN32_CALLOUTS_FPNS)&CalloutData);
> 
> Modified: trunk/reactos/subsystems/win32/win32k/ntuser/desktop.c
> URL: 
> http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/win32k/ntuser/desktop.c?rev=51115&r1=51114&r2=51115&view=diff
> ==============================================================================
> --- trunk/reactos/subsystems/win32/win32k/ntuser/desktop.c [iso-8859-1] 
> (original)
> +++ trunk/reactos/subsystems/win32/win32k/ntuser/desktop.c [iso-8859-1] Tue 
> Mar 22 09:19:26 2011
> @@ -166,6 +166,29 @@
>    RemoveEntryList(&Desktop->ListEntry);
> 
>    IntFreeDesktopHeap(Desktop);
> +}
> +
> +NTSTATUS NTAPI 
> +IntDesktopOkToClose(PWIN32_OKAYTOCLOSEMETHOD_PARAMETERS Parameters)
> +{
> +    PTHREADINFO pti;
> +
> +    pti = PsGetCurrentThreadWin32Thread();
> +
> +    if( pti == NULL)
> +    {
> +        /* This happens when we leak desktop handles */
> +        return TRUE;
> +    }
> +
> +    /* Do not allow the current desktop or the initial desktop to be closed 
> */
> +    if( Parameters->Handle == pti->ppi->hdeskStartup ||
> +        Parameters->Handle == pti->hdesk)
> +    {
> +        return FALSE;
> +    }
> +
> +    return TRUE;
> }
> 
> /* PRIVATE FUNCTIONS 
> **********************************************************/
> 
> Modified: trunk/reactos/subsystems/win32/win32k/ntuser/winsta.c
> URL: 
> http://svn.reactos.org/svn/reactos/trunk/reactos/subsystems/win32/win32k/ntuser/winsta.c?rev=51115&r1=51114&r2=51115&view=diff
> ==============================================================================
> --- trunk/reactos/subsystems/win32/win32k/ntuser/winsta.c [iso-8859-1] 
> (original)
> +++ trunk/reactos/subsystems/win32/win32k/ntuser/winsta.c [iso-8859-1] Tue 
> Mar 22 09:19:26 2011
> @@ -187,6 +187,21 @@
>     return STATUS_OBJECT_TYPE_MISMATCH;
> }
> 
> +NTSTATUS NTAPI 
> +IntWinstaOkToClose(PWIN32_OKAYTOCLOSEMETHOD_PARAMETERS Parameters)
> +{
> +    PPROCESSINFO ppi;
> +
> +    ppi = PsGetCurrentProcessWin32Process();
> +
> +    if(Parameters->Handle == ppi->hwinsta)
> +    {
> +        return FALSE;
> +    }
> +
> +    return TRUE;
> +}
> +
> /* PRIVATE FUNCTIONS 
> **********************************************************/
> 
> /*
> @@ -915,6 +930,57 @@
>    return WinStaObj;
> }
> 
> +BOOL FASTCALL
> +UserSetProcessWindowStation(HWINSTA hWindowStation)
> +{
> +    PPROCESSINFO ppi;
> +    NTSTATUS Status;
> +    HWINSTA hwinstaOld;
> +    PWINSTATION_OBJECT NewWinSta = NULL, OldWinSta;
> +
> +    ppi = PsGetCurrentProcessWin32Process();
> +
> +    if(hWindowStation !=NULL)
> +    {
> +        Status = IntValidateWindowStationHandle( hWindowStation,
> +                                                 KernelMode,
> +                                                 0,
> +                                                 &NewWinSta);
> +       if (!NT_SUCCESS(Status))
> +       {
> +          DPRINT("Validation of window station handle (0x%X) failed\n",
> +                 hWindowStation);
> +          SetLastNtError(Status);
> +          return FALSE;
> +       }
> +    }
> +
> +   OldWinSta = ppi->prpwinsta;
> +   hwinstaOld = ppi->hwinsta;
> +
> +   /*
> +    * FIXME - don't allow changing the window station if there are threads 
> that are attached to desktops and own gui objects
> +    */
> +
> +   InterlockedExchangePointer(&PsGetCurrentProcess()->Win32WindowStation, 
> hWindowStation);
> +
> +   ppi->prpwinsta = NewWinSta;
> +   ppi->hwinsta = hWindowStation;
> +
> +
> +   if(OldWinSta != NULL)
> +   {
> +       ObDereferenceObject(OldWinSta);
> +   }
> +
> +   if(hwinstaOld != NULL)
> +   {
> +       ZwClose(hwinstaOld);
> +   }
> +
> +   return TRUE;
> +}
> +
> /*
>  * NtUserSetProcessWindowStation
>  *
> @@ -934,44 +1000,15 @@
> BOOL APIENTRY
> NtUserSetProcessWindowStation(HWINSTA hWindowStation)
> {
> -   PWINSTATION_OBJECT NewWinSta;
> -   NTSTATUS Status;
> -
> -   DPRINT("About to set process window station with handle (0x%X)\n",
> -          hWindowStation);
> -
> -   if(PsGetCurrentProcess() == CsrProcess)
> -   {
> -      DPRINT1("CSRSS is not allowed to change it's window station!!!\n");
> -      EngSetLastError(ERROR_ACCESS_DENIED);
> -      return FALSE;
> -   }
> -
> -   Status = IntValidateWindowStationHandle(
> -               hWindowStation,
> -               KernelMode,
> -               0,
> -               &NewWinSta);
> -
> -   if (!NT_SUCCESS(Status))
> -   {
> -      DPRINT("Validation of window station handle (0x%X) failed\n",
> -             hWindowStation);
> -      SetLastNtError(Status);
> -      return FALSE;
> -   }
> -
> -   /*
> -    * FIXME - don't allow changing the window station if there are threads 
> that are attached to desktops and own gui objects
> -    */
> -
> -   /* FIXME - dereference the old window station, etc... */
> -   InterlockedExchangePointer(&PsGetCurrentProcess()->Win32WindowStation, 
> hWindowStation);
> -
> -   DPRINT("PsGetCurrentProcess()->Win32WindowStation 0x%X\n",
> -          PsGetCurrentProcess()->Win32WindowStation);
> -
> -   return TRUE;
> +    BOOL ret;
> +
> +    UserEnterExclusive();
> +
> +    ret = UserSetProcessWindowStation(hWindowStation);
> +
> +    UserLeave();
> +
> +    return ret;
> }
> 
> /*
> 
> 


_______________________________________________
Ros-dev mailing list
Ros-dev@reactos.org
http://www.reactos.org/mailman/listinfo/ros-dev

Reply via email to