Sandbox I. Sandboxie. Aislamiento de procesos mediante control de acceso a objetos en kernel.

Ver el tema anterior Ver el tema siguiente Ir abajo

Sandbox I. Sandboxie. Aislamiento de procesos mediante control de acceso a objetos en kernel.

Mensaje  r32 el Sáb Oct 15, 2011 8:32 pm

0. Indice:

    1. Introducción.
    2. Diseño de Sandboxie.
    3. Control de acceso a recursos.
    3.1. El hookeo en objectos de \ObjectTypes.
    3.2. Los hookeos en la ssdt y la shadow ssdt.
    4. Los io controles.
    5. Seguridad de Sandboxie.
    5.1. Fuzzing de io controls.
    5.2. Envío de mensajes a Shell_TrayWnd (ventana excluída por Sandboxie).
    5.3. Nombres largos.
    5.4. Parseo de formatos complejos.
    5.5. Conclusión.

1. Introducción:

En este artículo voy a hablar de Sandboxie, una sandbox que realiza aislamiento de procesos y cuyos pilares son:

-El control de acceso a objetos en kernel mediante hooks directos en las estructuras de los mismos objetos.
-Algunos hookeos en la ssdt y la shadow ssdt para control de mensajes a ventanas de procesos no sandboxeados.
-Algunos callbacks registrados en el sistema para control de creación de procesos, imágenes cargadas, etc…

Hablaré un poco del diseño de la sandbox, las técnicas que usa para “construir la celda”, y lo fiable o no que, bajo mi punto de vista, pueden llegar a ser este tipo de sandbox.

2. Diseño de Sandboxie:

Aunque sandboxie consta de la aplicación que hace de interfaz, un servicio, etc… Y otros componentes, en relación con la sandbox sólo nos interesan el driver (sbiedrv.sys) y la dll que inyecta en todos los procesos sandboxeados (sbiedll.dll).



A grandes rasgos Sandboxie funciona de la siguiente manera:

El driver de Sandboxie hookea todo lo necesario en kernel para proteger los recursos que quiere proteger de los procesos sandboxeados.
Pone además un callback con PsLoadImageNotifyRoutine y PsCreateProcessNotifyRoutine para ser notificado cuando se carga una imagen en un proceso y cuando se crea un proceso. El driver mantiene una lista de procesos sandboxeados en kernel, y gracias a estos callbacks puede mantener actualizadas las listas de los procesos sanboxeados. Lo que hace es comprobar si el padre del proceso creado es sandboxeado, y si lo es, el hijo pasa a la lista también (también es posible mediante io controles indicar que un proceso debe pasar a considerarse sandboxeado. Esto es necesario para lanzar procesos sandboxeados desde la interfaz de usuario de Sandboxie).

El driver no se complica la vida en el control de acceso a recursos protegidos: si es un proceso sandboxeado deniega el acceso a cualquier recurso protegido, si no es sandboxeado, lo permite.

Sin embargo cuando manejamos Sandboxie vemos que permite el acceso a algunos recursos protegidos desde los procesos sandboxeados. Además
crea un sistema de archivos, entradas de registro, etc… paralelos para cada sandbox manejada.

Para controlar esto el driver de Sandboxie exporta una serie de io controls. Exporta mucha funcionalidad mediante estos io controls, y algunos de ellos sirven para acceder a los recursos protegidos desde los procesos sandboxeados, pero de una manera controlado (discriminando a qué tiene acceso y a qué no, el proceso sandboxeado).

Aquí es donde entra en juego la dll SbieDll que entre otras cosas hookea todas las exports en todas las dlls de cada proceso sandboxeado.

Esta dll es fundamental para que el proceso sandboxeado funcione correctamente ya que en el hook de ciertas apis conocidas (ZwCreateFile, ZwCreateProcess, ZwOpenKey, etc…) la dll corta el flujo normal hacía kernel para redirigirlo hacía los io controles del driver donde se realizará un acceso a los recursos protegidos de manera controlada (una pequeña prueba que demuestra esto es que si quitamos con HookShark por ejemplo todos los hooks de modo usuario se nos queda un proceso sandboxeado sin acceso a nada, porque el driver lo deniega todo).

3. Control de acceso a recursos:

No se si se me ha escapado algo de lo que SbieDrv intercepta en kernel. Los principales hookeos que he visto que realiza son:

En los objetos token, process, thread, event, section, port y semaphore, de tipo Type, que cuelgan de \ObjectTypes, hookean el puntero a función de tipo OB_OPEN_METHOD para controlar el acceso a este tipo de objetos:

OBJECT_TYPE ->OBJECT_TYPE_INITIALIZER-> OpenProcedure

Sólo con esto puede controlar el acceso a disco, registro, etc…

Pero todavía necesita controlar todo el tema de ventanas, que lo maneja win32k.sys: debe cortar el envío de mensajes de las ventanas de aplicaciones sandboxeadas a las ventanas de las no sandboxeadas, debe evitar que las aplicaciones sandboxeadas puedan registrar Windows hooks, etc…

Para poder hacer esto SbieDrv necesita interceptar algunas funciones de la ssdt y la shadow ssdt:

Código:

[b][color=#888888][b]win32k_NtUserCallHwndParamLock
[/b][b]win32k_NtUserDestroyWindow
[/b][b]win32k_NtUserShowWindow
[/b][b]win32k_NtUserSendInput
[/b][b]win32k_NtUserBlockInput
[/b][b]win32k_NtUserSystemParametersInfo
[/b][b]win32k_NtUserSetSysColors
[/b][b]win32k_NtUserSetSystemCursor
[/b][b]win32k_NtUserMessageCall
[/b][b]win32k_NtUserPostMessage
[/b][b]win32k_NtUserPostThreadMessage
[/b][b]win32k_NtUserSetWindowsHookEx
[/b][b]win32k_NtUserSetWinEventHook
[/b][b]nt_NtRequestPort
[/b][b]nt_NtRequestWaitReplyPort
[/b][b]nt_NtTraceEvent[/b][/color][/b]

3.1. El hookeo en objectos de \ObjectTypes:

Vamos a ver primero como son estos objetos que cuelgan del directorio ObjectTypes. Tomamos para el ejemplo el objeto \ObjectTypes\Token:

Código:

[b][color=#888888][b]WINDBG>!object \ObjectTypes
[/b]Object: e1000548  Type: (819f1418) [b]Directory
[/b]ObjectHeader: e1000530 (old version)
HandleCount: 0  PointerCount: 25
Directory Object: e1001520  Name: ObjectTypes
Hash Address  Type          Name
—- ——-  —-          —-
00  819f1418 Type          Directory
01  819ccca0 Type          Thread
819c95e0 Type          Mutant
03  8198cca0 Type          FilterCommunicationPort
05  819b8e70 Type          Controller
07  819c8ca0 Type          Profile
819c9980 Type          Event
819f15e8 Type          Type
09  819c8560 Type          Section
819c97b0 Type          EventPair
819f1248 Type          SymbolicLink
10  819c8730 Type          Desktop
11  819c8e70 Type          Timer
12  819b8730 Type          File
819c8900 Type          WindowStation
16  819b8ad0 Type          Driver
18  819eb910 Type          WmiGuid
819c8ad0 Type          KeyedEvent
[b] 19  819cc040 Type          Token
[/b]819b8ca0 Type          Device
20  819cc408 Type          DebugObject
21  819b8900 Type          IoCompletion
22  819cce70 Type          Process
24  819f0300 Type          Adapter
26  819c5980 Type          Key
28  819ccad0 Type          Job
31  819f0708 Type          WaitablePort
819f08d8 Type          Port
32  819c9410 Type          Callback
33  8198ce70 Type          FilterConnectionPort
34  819c8040 Type          Semaphore

[b]WINDBG>!object 819cc040
[/b]Object: 819cc040  Type: (819f15e8) [b]Type
[/b]ObjectHeader: 819cc028 (old version)
HandleCount: 0  PointerCount: 1
Directory Object: e1000548  Name: [b]Token
[/b]

[b]WINDBG>dt _OBJECT_TYPE 819cc040
[/b]ntdll!_OBJECT_TYPE
+0×000 Mutex            : _ERESOURCE
+0×038 TypeList        : _LIST_ENTRY [ 0x819cc078 - 0x819cc078 ]
+0×040 Name            : _UNICODE_STRING “Token”
+0×048 DefaultObject    : 0x80558cc0
+0x04c Index            : 4
+0×050 TotalNumberOfObjects : 0x1a
+0×054 TotalNumberOfHandles : 0×10
+0×058 HighWaterNumberOfObjects : 0x1d
+0x05c HighWaterNumberOfHandles : 0×14
[b] +0×060 TypeInfo        : _OBJECT_TYPE_INITIALIZER
[/b]+0x0ac Key              : 0x656b6f54
+0x0b0 ObjectLocks      : [4] _ERESOURCE
Como vemos de \ObjectTypes cuelgan varios objetos de tipo Type. La estructura de estos objetos es de tipo _OBJECT_TYPE.
[/color][/b]

Dentro de esta estructura _OBJECT_TYPE nos interesa especialmente OBJECT_TYPE_INITIALIZER
porque dentro de esta subestructura vamos a tener los punteros a los
callbacks que son llamados cuando se abre, cierra, etc… los objetos de
este tipo.

Código:
[b][color=#888888]typedef struct _OBJECT_TYPE_INITIALIZER {
USHORT Length;  2 bytes
BOOLEAN UseDefaultObject; 1 byte
BOOLEAN Reserved; 1 byte
ULONG InvalidAttributes; 4 bytes
GENERIC_MAPPING GenericMapping; 16 bytes
ULONG ValidAccessMask; 4 bytes
BOOLEAN SecurityRequired; 1 byte
BOOLEAN MaintainHandleCount; 1 byte
BOOLEAN MaintainTypeList; 1 byte
POOL_TYPE PoolType; 1 byte
ULONG ObjectTypeCode; 4 bytes //-> depende de la versión del sistema operativo,
//de esto depende que se acceda a +30h
//o a +34h para buscar el puntero para hookear
ULONG DefaultPagedPoolCharge; 4 bytes
ULONG DefaultNonPagedPoolCharge; 4 bytes
//——
OB_DUMP_METHOD DumpProcedure; 4 bytes
[b] OB_OPEN_METHOD OpenProcedure; 4 bytes
[/b]OB_CLOSE_METHOD CloseProcedure; 4 bytes
OB_DELETE_METHOD DeleteProcedure; 4 bytes
OB_PARSE_METHOD ParseProcedure; 4 bytes
OB_SECURITY_METHOD SecurityProcedure; 4 bytes
OB_QUERYNAME_METHOD QueryNameProcedure; 4 bytes
OB_OKAYTOCLOSE_METHOD OkayToCloseProcedure; 4 bytes
//——
} OBJECT_TYPE_INITIALIZER, *POBJECT_TYPE_INITIALIZER;[/color][/b]


Dependiendo de la versión del sistema operativo esta estructura tiene un campo más o no (el campo ObjectTypeCode). SbieDrv tiene en cuenta
este detalle para hookear correctamente el puntero OpenProcedure en todas las versiones que soporta.

Este puntero es de tipo OB_OPEN_METHOD:
Código:

[b][color=#888888][b]typedef NTSTATUS
[/b][b](NTAPI *OB_OPEN_METHOD)(
[/b][b] IN OB_OPEN_REASON Reason,
[/b][b] IN PEPROCESS Process OPTIONAL,
[/b][b] IN PVOID ObjectBody,
[/b][b] IN ACCESS_MASK GrantedAccess,
[/b][b] IN ULONG HandleCount
[/b][b]);[/b][/color][/b]


Este callback es llamado cuando se abre un objeto del tipo en el que se hookea. En este caso cuando se abra un objeto de tipo Token se
llamará a este callback, y aquí es posible controlar la apertura de dicho objeto.

Como hemos dicho SbieDrv hookea el callback OpenProcedure para los objetos de tipo token, process, thread, event, section, port y semaphore. Aquí vemos como SbieDrv llama a la función que realiza todo el hookeo con el nombre de cada objeto y el puntero para el hook de éste:



Vemos como comprueba la versión y el build del sistema operativo para calcular los offsets dentro de las estructuras del objeto donde encontrar el OpenProcedure.

Código:

[b][color=#888888]——
Si version < 4:
Si BuildNumber <= 1770h:
OpenProcedureOffset = pTypeObjHeader+30h+60h
Sino:
OpenProcedureOffset = pTypeObjHeader+30h+28h
Sino:
Si BuildNumber <= 1770h:
OpenProcedureOffset = pTypeObjHeader+30h+60h
Sino:
OpenProcedureOffset = pTypeObjHeader+34h+28h
——[/color][/b]



Para el hookeo utiliza una pieza de código que escribe en memoria del sistema operativo, seguramente porque el sistema operativo controla que
estos punteros apunten a memoria suya. Las piezas de código con las que hookea son siempre así:



Esta función que he nombrado “ComprobarProcessIdEnListaDeSandboxeadosObtenerEstructura” busca en las listas de procesos sandboxeados el processid que se le pasa. Si se le pasa cero busca el current process. Como vemos en el trozo que usa para hookear siempre comprueba si el proceso actual es sandboxeado. Si no lo es, deja acceder. Si lo es, pasa a llamar a una función específica del tipo de objeto accedido (una para Token, otra para Process, etc…), pero en este punto ya ha decidido cortar el acceso al objeto (el proceso tendrá que acceder a estos objetos usando los io controles de SbieDrv).

En la imagen a continuación vemos el punto donde SbieDrv compone el bloque de código para el hookeo y el punto donde escribe el puntero en
la estructura de kernel.



3.2. Los hookeos en la ssdt y la shadow ssdt:

Como hemos dicho antes Sandboxie hookea las siguientes apis:

Código:

[b][color=#888888][b]win32k_NtUserCallHwndParamLock
[/b][b]win32k_NtUserDestroyWindow
[/b][b]win32k_NtUserShowWindow
[/b][b]win32k_NtUserSendInput
[/b][b]win32k_NtUserBlockInput
[/b][b]win32k_NtUserSystemParametersInfo
[/b][b]win32k_NtUserSetSysColors
[/b][b]win32k_NtUserSetSystemCursor
[/b][b]win32k_NtUserMessageCall
[/b][b]win32k_NtUserPostMessage
[/b][b]win32k_NtUserPostThreadMessage
[/b][b]win32k_NtUserSetWindowsHookEx
[/b][b]win32k_NtUserSetWinEventHook
[/b][b]nt_NtRequestPort
[/b][b]nt_NtRequestWaitReplyPort
[/b][b]nt_NtTraceEvent[/b][/color][/b]


La mayoría están relacionadas con el control de mensajes de ventana a
las aplicaciones sandboxeadas. Vamos a analizar por ejemplo el hook a
win32k_NtUserMessageCall:



En varias de las apis interceptadas hay que gestionar un mensaje de ventana enviado a una ventana concreta. SbieDrv tiene una función común que hace esta gestión, la que he nombrado Hook_Win32k_Gestiona_MensajeDeVentana:



Esta función va comprobando el mensaje y sus parámetros para decidir qué mensajes permite enviar a las aplicaciones sandboxeadas y cuáles no.
La función Hook_Win32k_Gestiona_MensajeDeVentana actúa de esta manera:

-Primero obtiene el id del proceso que envía y el que recibe el mensaje. Si el proceso que envía y el que recibe es el mismo, deja pasar el msg.
-Sino, comprueba si el receptor es un sandboxeado. Si lo es, deja pasar el mensaje.
-A continuación comprueba si el msg es 0x3e4 y si lo es lo deja pasar.
- Luego obtiene el nombre de la clase de la ventana objetivo. Tiene una lista de nombres de clases de ventanas que deben ser tratadas como excepciones para las cuales se permiten algunos mensajes adicionales:

Código:
[b][color=#888888][b]TrayNotifyWnd
[/b][b]SystemTray_Main
[/b][b]Connections Tray
[/b][b]MS_WebcheckMonitor
[/b][b]PrintTray_Notify_WndClass
[/b][b]CicLoaderWndClass
[/b][b]CicMarshalWndClass
[/b][b]Logitech Wingman Internal Message Router
[/b][b]devldr
[/b][b]CTouchPadSynchronizer
[/b][b]Type32_Main_Window
[/b][b]TForm_AshampooFirewall
[/b][b]WinVNC desktop sink
[/b][b]Afx:400000:0
[/b][b]NVIDIA TwinView Window
[/b][b]Shell_TrayWnd[/b][/color][/b]


Seguramente necesite meter estas excepciones para el funcionamiento correcto de algunas aplicaciones típicas: explorer, navegadores, etc…



-Si el mensaje no es para un proceso de la sandbox, y el que envía sí es un proceso de la sandbox, si la ventana objetivo no es una de las dichas anteriormente, sale directamente prohibiendo el envío del mensaje.

-Para todas las clases de ventanas que son excepciones primero comprueba si el mensaje es de tipo WM_USER (0×400) o mayor. Si es por debajo de 0×400, comprueba contra la siguiente lista de mensajes inválidos para estas clases de ventanas conocidas:

Código:
[b][color=#888888][b]2h – WM_DESTROY
[/b][b]0Bh – WM_SETREDRAW
[/b][b]10h – WM_CLOSE
[/b][b]11h – WM_QUERYENDSESSION
[/b][b]12h – WM_QUIT
[/b][b]16h – WM_ENDSESSION
[/b][b]3Bh -
[/b][b]4Eh – WM_NOTIFY
[/b][b]82h – WM_NCDESTROY
[/b][b]111h – WM_COMMAND
[/b][b]112h – WM_SYSCOMMAND
[/b][b]319h[/b][/color][/b]


-Si no es ninguno de los anteriores ids, sale dejando pasar el mensaje.

-Si es un mensaje por arriba de 0×400, según la clase de ventana que sea, deja pasar unos u otros. Por ejemplo
para Shell_TrayWnd deja pasar el id de msg 0x4ec.

4. Los io controles:

Sandboxie crea el siguiente device:

\device\SandboxieDriverApi

Para enviar io controles a Sandboxie él espera que sean:

DeviceType = FILE_DEVICE_UNKNOWN = 0×00000022

Function = 0×801

Method = METHOD_NEITHER

Access = 0

CTL_CODE(0×00000022, 0×801, METHOD_NEITHER, 0);


Por lo tanto el driver accede desde kernel a un buffer en user mode para recuperar los parámetros del io control. El formato de dicho buffer
depende de la operación que se le solicite. Este buffer en zona de usuario tiene que tener un tamaño entre 0×8 y 0×40 bytes. El primer
DWORD siempre es un valor 0x123400XX, que son los ids de las distintas operaciones que ofrece SbieDrv a través de sus io controles. SbieDrv
tiene asociada una función a cada id soportado para gestionar el io control.

A continuación los io controles soportados.



Código:
[b][color=#888888][b]0×12340001:
[/b][b][0x12340001][XXXXXXXX][ptr zona mem usuario out]
[/b]Este ioctl guarda en el puntero en zona de usuario la cadena de versión de sandboxie.
[b]0×12340002:
[/b][b][0x12340002][XXXXXXXX][XXXXXXXX][XXXXXXXX][ptr zona mem usuario out] [XXXXXXXX][XXXXXXXX][XXXXXXXX][XXXXXXXX]
[/b]Pedir lista de procesos sandboxeados.
[b]0×12340003:
[/b]Petición de escritura de fichero.
[b]0×12340007:
[/b][b][0x12340007][XXXXXXXX][XXXXXXXX][XXXXXXXX][XXXXXXXX][XXXXXXXX][ptr zona mem usuario]
[/b][b]0×12340008:
[/b][b][0x12340008][XXXXXXXX][XXXXXXXX][XXXXXXXX][XXXXXXXX][XXXXXXXX]
 [XXXXXXXX][XXXXXXXX][XXXXXXXX][XXXXXXXX][ptr mem usr][XXXXXXXX][ptr mem
 usr][XXXXXXXX][ptr mem usr]
[/b][b]0×12340009: [/b]Obtener objecto proceso a partir de pid
[b]0x1234000a
[/b][b]0x1234000b: [/b]Parece que sirve para pedir información de procesos sandboxeados.

El proceso sbiectrl.exe está constantemente mandando los códigos 0x1234000b, 0x1234000c y 0×12340002 al driver.
[b]0x1234000c: [/b]Parece que pregunta al driver la fecha y hora.
[b]0x1234000d:[/b] Con este iocontrol se pide que el driver
desproteja una dirección en modo usuario para luego meterle el jump del
hook. Así hookea sbiedll (en la rva 0xe7a9) en modo usuario.
[b][0x1234000D][XXXXXXXX][ptr funcion modo usuario][XXXXXXXX][ptr memoria usuario info hook]
[/b][b]0x1234000f[/b]: Sirve para consultar una opción de una sandbox. Algunas opciones de sandboxie:
DisableBoxedWinSxS
InjectDll
AutoExec
OpenProtectedStorage
OpenCredentials
OpenWinClass
NoRenameWinClass
BoxNameTitle
ClsidTrace
OpenClsid
StartService
StartProgram
AutoRecover
RecoverFolder -> para recuperar todas las carpetas de autorecover
AutoRecoverIgnore
[b]0×12340010: [/b]Con este iocontrol se le pide al driver que
 se actualice con los datos de los ini: sandboxie.ini y templates.ini.
El propio driver se pone a parsear los ini.
[b]0×12340011
[/b][b]0×12340015
[/b][b]0×12340016: [/b]En este iocontrol se hookean las funciones de ntoskrnl.exe y de win32k.sys (de la ssdt y la shadow).
[b]0×12340019
[/b][b]0x1234001e
[/b][b]0x1234001f: [/b]Relacionado con los accesos a disco.
[b]0×12340021
[/b][b]0×12340024
[/b][b]0×12340025
[/b][b]0×12340026
[/b][b]0×12340028
[/b][b]0x1234002b: [/b]Obtener handle a proceso.[/color][/b]


5. Seguridad de Sandboxie:

Primero vamos a ver algunos detalles y a hacer algunas pruebas relacionadas con este tema.

5.1. Fuzzing de io controls:

SandBoxie exporta varios io controles con mucha funcionalidad necesaria para su funcionamiento, tanto a procesos sandboxeados como no
sandboxeados.

No he entrado muy en detalle en el fuzzing de los io controles, sólo una pequeña prueba realizada con Kartoffel (kartoffel.reversemode.com). Llamamos a Kartoffel con esta línea de comandos:

Código:
[b][color=#888888]FOR %%A IN (0 1 2) DO FOR %%B IN
(0 1 2 3 4 5 6 7 8 9 A B C D E F) DO Kartoffel -d
\device\SandboxieDriverApi -n 0×40 -o 0×40 -z 0×40 -Z 0×40 -I 0×222007
-u CUSTOM,”[P=0x123400%%A%%B::*0][B=0x41::*0x3c$4][!!]“[/color][/b]
Con esta orden vamos a enviar a io controles con id desde 0×12340001
hasta 0x1234002f, seguidos por un buffer lleno de ‘A’. Todo junto tiene
un tamaño de 0×40 (el máximo soportado por Sandboxie).
Código:

[b][color=#888888][0x123400XX][AAAAAAAAAAAAAAAAAAAAAAA…][/color][/b]
Al lanzar este simple fuzzeo, cuando llega al id 0×12340027 salta un bug check:
Código:

[b][color=#888888]WINDBG>!analyze -v
*******************************************************************************
* *
* Bugcheck Analysis *
* *
*******************************************************************************
DRIVER_CORRUPTED_MMPOOL (d0)
Arguments:
[b]Arg1: 6b757a74, memory referenced
[/b][b]Arg2: 00123400, IRQL
[/b][b]Arg3: 00000000, value 0 = read operation, 1 = write operation
[/b][b]Arg4: 12340027, address which referenced memory
[/b]An attempt was made to access a pageable (or completely invalid) address at an
interrupt request level (IRQL) that is too high. This is
caused by drivers that have corrupted the system pool. Run the driver
verifier against any new (or suspect) drivers, and if that doesn’t turn up
the culprit, then use gflags to enable special pool. You can also set
HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Memory Management\ProtectNonPagedPool
to a DWORD 1 value and reboot. Then the system will unmap freed nonpaged pool,
preventing drivers (although not DMA-hardware) from corrupting the pool.
Debugging Details:
——————
*************************************************************************
*** ***
*** ***
*** Your debugger is not using the correct symbols ***
*** ***
*** In order for this command to work properly, your symbol path ***
*** must point to .pdb files that have full type information. ***
*** ***
*** Certain .pdb files (such as the public OS symbols) do not ***
*** contain the required information. Contact the group that ***
*** provided you with these symbols if you need this command to ***
*** work. ***
*** ***
*** Type referenced: kernel32!pNlsUserInfo ***
*** ***
*************************************************************************
*************************************************************************
*** ***
*** ***
*** Your debugger is not using the correct symbols ***
*** ***
*** In order for this command to work properly, your symbol path ***
*** must point to .pdb files that have full type information. ***
*** ***
*** Certain .pdb files (such as the public OS symbols) do not ***
*** contain the required information. Contact the group that ***
*** provided you with these symbols if you need this command to ***
*** work. ***
*** ***
*** Type referenced: kernel32!pNlsUserInfo ***
*** ***
*************************************************************************
[b]READ_ADDRESS: 6b757a74  (kuzt -> tzuk -> el nombre del autor)
[/b]CURRENT_IRQL: 123400
FAULTING_IP:
+5c1952f0012c4f0
12340027 ?? ???
DEFAULT_BUCKET_ID: DRIVER_FAULT
BUGCHECK_STR: 0xD0
PROCESS_NAME: Kartoffel.exe
LAST_CONTROL_TRANSFER: from 804f7b27 to 8052716c
STACK_TEXT:
f7642750 804f7b27 00000003 f7642aac 00000000 nt!RtlpBreakWithStatusInstruction
f764279c 804f8714 00000003 c0000005 00000000 nt!KiBugCheckDebugBreak+0×19
f7642b7c 804f8c3f 000000d0 6b757a74 00123400 nt!KeBugCheck2+0×574
f7642b9c f7cce31f 000000d0 6b757a74 00123400 nt!KeBugCheckEx+0x1b
WARNING: Stack unwind information not available. Following frames may be wrong.
f7642c34 804ee0ef 81740340 817398a0 806d12d0 SbieDrv+0x131f
f7642c44 80574032 81739910 818b2b88 817398a0 nt!IopfCallDriver+0×31
f7642c58 80574ec1 81740340 817398a0 818b2b88 nt!IopSynchronousServiceTail+0×60
f7642d00 8056d81e 000007b4 00000000 00000000 nt!IopXxxControlFile+0x5e7
f7642d34 8053cbc8 000007b4 00000000 00000000 nt!NtDeviceIoControlFile+0x2a
f7642d34 7c91eb94 000007b4 00000000 00000000 nt!KiFastCallEntry+0xf8
0012eca4 7c91d8ef 7c8016be 000007b4 00000000 ntdll!KiFastSystemCallRet
0012eca8 7c8016be 000007b4 00000000 00000000 ntdll!ZwDeviceIoControlFile+0xc
0012ed08 0040617d 000007b4 00222007 003b0808 kernel32!DeviceIoControl+0×78
0012fee4 0040a9cd 0000000f 003b0b40 003b0c10 Kartoffel+0x617d
0012ffc0 7c816ff7 0000001a 00000000 7ffdd000 Kartoffel+0xa9cd
0012fff0 00000000 0040a85a 00000000 78746341 kernel32!BaseProcessStart+0×23
STACK_COMMAND: kb
FOLLOWUP_IP:
SbieDrv+131f
f7cce31f 8bf7 mov esi,edi
SYMBOL_STACK_INDEX: 4
SYMBOL_NAME: SbieDrv+131f
FOLLOWUP_NAME: MachineOwner
MODULE_NAME: SbieDrv
IMAGE_NAME: SbieDrv.sys
DEBUG_FLR_IMAGE_TIMESTAMP: 4d8b29aa
FAILURE_BUCKET_ID: 0xD0_SbieDrv+131f
BUCKET_ID: 0xD0_SbieDrv+131f
Followup: MachineOwner
———
Sorting ‘Functions window’… ok[/color][/b]


KeBugCheck es llamado por el propio SbieDrv porque detecta algo raro, así que es un simple DoS no muy peligroso. Pero que un fuzzeo
tan simple nos provoque un DoS en kernel nos hace pensar que el código de SbieDrv tiene varios cabos sueltos.


5.2. Envío de mensajes a Shell_TrayWnd (ventana excluída por Sandboxie):

Como ya vimos en el análisis de los hooks para controles de mensajes a ventanas hay una serie de ventanas excluídas para las que se permiten
algunos mensajes adicionales. Entre ellas está Shell_TrayWnd, la ventana de la barra de aplicaciones.

El siguiente script demuestra que estos mensajes permitidos a Shell_TrayWnd nos permiten movernos por el menú inicio y lanzar
aplicaciones linkadas desde él:


Código:
[color=#000000]import random[/color]
[color=#000000]random.seed()[/color]
[color=#000000]VK_LEFT=0x25
VK_UP=0x26
VK_RIGHT=0x27
VK_DOWN=0x28
VK_RETURN=0x0d
VK_TAB=0x09
VK_SHIFT=0x10
VK_CONTROL=0x11
VK_MENU=0x12[/color]

[color=#000000]import ctypes
import time
from ctypes.wintypes import DWORD, HWND, HANDLE, LPCWSTR, WPARAM, LPARAM, RECT, POINT
trayRect=RECT(0,0,0,0)
trayWindow = ctypes.windll.user32.FindWindowExA(0,0,"Shell_TrayWnd",0)
trayNotifyWindow = ctypes.windll.user32.FindWindowExA(trayWindow,0,"TrayNotifyWnd",0)[/color]
def PressKey(hwin,key):
msgkeydown=0x100
msgkeyup=0x101
ctypes.windll.user32.PostMessageA(hwin, msgkeydown, key, 0) #KEYDOWN
time.sleep(0.1)
ctypes.windll.user32.PostMessageA(hwin, msgkeyup, key, 0) #KEYUP
time.sleep(0.1)
ctypes.windll.user32.PostMessageA(trayWindow, 0xa1, 1, 0x200020) #WM_NCLBUTTONDOWN
ctypes.windll.user32.PostMessageA(trayWindow, 0xa2, 0, 0x200020) #WM_NCLBUTTONUP
PressKey(trayWindow, VK_UP)
PressKey(trayWindow, VK_UP)
PressKey(trayWindow, VK_UP)
PressKey(trayWindow, VK_UP)
PressKey(trayWindow, VK_UP)
PressKey(trayWindow, VK_UP)
PressKey(trayWindow, VK_UP)
PressKey(trayWindow, VK_RIGHT)
PressKey(trayWindow, VK_RIGHT)
PressKey(trayWindow, VK_DOWN)
PressKey(trayWindow, VK_DOWN)
PressKey(trayWindow, VK_DOWN)
PressKey(trayWindow, VK_DOWN)
PressKey(trayWindow, VK_DOWN)
PressKey(trayWindow, VK_DOWN)
PressKey(trayWindow, VK_RETURN

(Las pulsaciones de teclas son las necesarias para lanzar la calculadora tal como yo tenía colocado el menú inicio cuando hice la prueba).
No es un problema de seguridad grave pero pienso que tampoco es el comportamiento que espera el usuario de la sandbox.

5.3. Nombres largos:

Sandboxie tiene problemas con nombres de ficheros largos (más largos que MAX_PATH y hasta 32 mil y pico caracteres) porque en su callback
LoadImageNotifyRoutine llega el nombre a NULL.
No he visto problemas de seguridad aquí pero sí que se obtienen mensajes de error y comportamientos que sin Sandboxie no ocurrirían (tanto en procesos sandboxeados como no sandboxeados).
Sin embargo este detalle nos vuelve a hacer pensar que es difícil interceptar demasiadas cosas en el sistema operativo, en puntos muy
delicados, y tener en cuenta todos los posibles casos.

5.4. Parseo de formatos complejos:

En mi opinión el driver de Sandboxie tiene código bastante arriesgado en kernel.

Por ejemplo, en el callback LoadImageNotifyRoutine se hace un parseo a fondo de la cabecera PE de la imagen cargada en modo usuario. A continuación vemos el comienzo de dicho parseo en el que más adelante profundiza en los recursos, etc…



También abre y parsea los ficheros de configuración .ini desde kernel:



En otros puntos desensambla instrucciones a la entrada de funciones (tanto de kernel como de modo usuario) para saber
que tipo de hook debe meter y guardarse las instrucciones sobrescritas.
Cuando por ejemplo se va a pinchar algo en modo usuario es el driver el que va a salvar en un buffer de usuario las instrucciones que se van a
sobreescribir.
En definitiva, mi opinión es que Sandboxie mete bastante código complejo y arriesgado en kernel. Ya vimos en el sencillo fuzzeo de io controles que SbieDrv deja más de un cabo suelto. No me he metido a fuzzear en profundida: ficheros ini, cabeceras pe, etc… pero tengo la impresión de que saltaría la liebre por más de un sitio.

5.5. Conclusión:

En general mi opinión es que las sandbox por aislamiento de proceso llevan una inseguridad intrínseca:

-Es difícil interceptar todo lo peligroso a lo que puede acceder un proceso.
-Se va a introducir código (los hooks) en puntos muy delicados del sistema por lo que hay que confiar mucho en ese código.
-Se van a tocar cosas muy dependientes de la versión del sistema operativo para interceptar todo lo necesario.
-Muchos de los hooks necesarios no van a ser muy limpios ni documentados, ni soportados por el sistema, más
propios de un rootkit que de una herramienta de seguridad.
-Seguramente vas a necesitar meter algunas excepciones a lo que prohibes en la sandbox para que funcionen algunas aplicaciones típicas, como hace Sandboxie.
-En el caso de Sandboxie además se meten en kernel muchos bloques de código complejos que en mi opinión podrían
estar en modo usuario: parseo de ficheros sandboxie.ini y templates.ini,parseo de cabeceras PE, etc…
-También en el caso de Sandboxie, por su diseño, necesita exportar mucha funcionalidad compleja a través de io controles.

Mi conclusión respecto a Sandboxie es que es una herramienta útil en la que sí lanzaría un navegador o un pdf reader para ayudar a
protegerme contra vulnerabilidades, pero si fuera a lanzar malware dentro de Sandboxie, lanzaría Sandboxie dentro de una vmware, bochs u otra máquina virtual.


Autor: 48bits
avatar
r32
Admin
Admin

Mensajes : 81
Puntos : 1696
Fecha de inscripción : 21/02/2011

https://www.elhacker.net/

Volver arriba Ir abajo

Ver el tema anterior Ver el tema siguiente Volver arriba

- Temas similares

 
Permisos de este foro:
No puedes responder a temas en este foro.