Acerca de la opción del compilador / SAFESEH

Introducción

En esta historia, les contaré sobre una emocionante aventura que me llevó a resolver un acertijo que me planteé. La solución es un pequeño detalle en el mecanismo de carga de aplicaciones de 32 bits en Windows 7 y superior, y el proceso de resolución es un largo viaje de un guerrero que sigue el camino del corazón.





Si llegó a esta página buscando una respuesta a una pregunta, mire el spoiler a continuación, porque el contenido principal puede ser de interés para aquellos que solo están tratando de comprender el mecanismo SEH.





Todo el problema fue que utilicé una descripción incorrecta de la estructura de dataDirectories tomada de Wikipedia. En lugar del campo boundImport, en realidad está el campo loadConfigTable , que apunta a la estructura IMAGE_LOAD_CONFIG_DIRECTORY32. Esta estructura contiene el campo SEHandlerTable. Si es cero, entonces / SAFESEH está deshabilitado. Si es un puntero virtual a la tabla de controladores seguros, solo funcionarán los controladores especificados en la tabla. La tabla es una lista de compensaciones relativas a la dirección virtual de la sección .text. El número de controladores se establece en el campo SEHandlerCount.





Cómo empezó todo

Pensando en una forma de proteger mi programa de copias, recordé el artículo de Chris Kaspersky, en el que aprendí sobre la existencia de técnicas anti-depuración. Intentando en vano implementar el ejemplo que Chris analizó en mi programa, me encontré con un muro de confusión por parte de Windows. El problema fue que Windows se negó a usar mi controlador de excepciones, considerándolo "inseguro".





Más o menos detalles sobre SEH que pude obtener de este artículo . Pero, sin embargo, hasta que yo mismo examiné este mecanismo con lupa y herramientas, tenía ideas muy vagas sobre su estructura. Desenrollé las cadenas de los manejadores, les establecí puntos de interrupción, observé el orden de su ejecución, consideré los valores de retorno, etc.





Llegar al punto

  ( Microsoft Visual C++ )





int main()
{
    __asm
    {
        mov eax, DWORD PTR SS : [0]
    }
}
      
      



, eax 0.





, OllyDbg.





«access violation when reading 0x00000000».





, , 0 - 6 . Eip, ( ). 6 : 36 A1 00 00 00 00.





  , __try, __except .. .





  !





  , - :





    struct _EXCEPTION_RECORD* exceptionRecord,
    void* establisherFrame,
    struct _CONTEXT* contextRecord,
    void* dispatcherContext
      
      



exceptionRecord – , , , contextRecord – ( Eip). - __cdecl, :





typedef enum _EXCEPTION_DISPOSITION
{
    ExceptionContinueExecution,
    ExceptionContinueSearch,
    ExceptionNestedException,
    ExceptionCollidedUnwind
} EXCEPTION_DISPOSITION;
      
      



:





EXCEPTION_DISPOSITION __cdecl ExceptionHanler(
    struct _EXCEPTION_RECORD* exceptionRecord,
    void* establisherFrame,
    struct _CONTEXT* contextRecord,
    void* dispatcherContext
)
{
    contextRecord->Eip += 6;
    MessageBoxA(0, "Exteption was handled", "Success!", 0);
    return ExceptionContinueExecution;
}
      
      



Eip 6 , ! : ExceptionContinueExecution – . , Eip + 6 .





- . , . , , . - , : Next Handler. Next , ( , ). Handler -. TIB (thread information block), , fs:[0]. . 





main:





int main()
{
	__asm
	{
    push ExceptionHanler //    -
		push fs:[0]          //       
		                     //    ,  2 :  
    										 //     

		mov fs:[0] , esp	   //    ,                                                                                                                            
                         //   fs:[0]

		mov eax, DWORD PTR SS:[0] //    0
    
		add esp, 8			          // ,  8  ( )
	}
}

      
      



, - /SAFESEH , , - fs:[0]. , .





– 0 «» !





 , . . /SAFESEH:NO.





 , , :





«» . .





, -, , ? ? , … , , /SAFESEH, , , mov fs:[0], esp, -, , ? , /SAFESEH .





, - « ». , ? ? , , ? …





  , …





, , crt0 ( main), ntdll.dll. , fs:[0]! , , ?





. , /SAFESEH, , , fs:[0] JMP ExceptionHandler ( ). ! ! , «»? , . .





entry point main EXE , /SAFESEH /SAFESEH:NO, , WinApi , . . , , . .





crt0 -. , ! push main, ret. , main, ret «» main main , crt0! ( JMP, )





, ! , : EXE, , , .





  , PE ? - LoaderFlags? … , rdata. rdata , , ? , …





, - , . ! , , , -, , . , . , rdata , importTable, debug boundImport. , /SAFESEH! dataDirectories . , , - , /SAFESEH , « EXE ».





, «» , EXE . - . , 2 , , , . , , , ( 3-) .





, «» , mov eax, DWORD PTR SS : [0] play. . play.





! ntdll.dll.





. 0x1341d20 rdata 0x1be0, , EBX – 0x1000. , imageBase + 0x1000 ! - . 0x1be0, 0x2080 0x2351 . ! !





0x1341d20 0x1be0 0x1000 … !





! Windows, . ntdll.dll, !





, .





, . , - , – 3, .





- -.





! , /SAFESEH , /SAFESEH:NO!





, ?





… - , … Total Commander?!





, PE ? boundImport. Microsoft PE .





… , Microsoft boundImport. - -? ?





, .. , except… .. , .sxdata - . . sxdata? . boundImport, - -.





... , , pdata . , ? , boundImport, , .





... The Load Configuration Structure. ! , IMAGE_LOAD_CONFIG_DIRECTORY - , SEH.





, -. , , boundImport IMAGE_LOAD_CONFIG_DIRECTORY32 . ! , .





Eso es todo, todo el secreto era que boundImport en el encabezado PE (descompuesto según la tabla de Wikipedia) apunta a la estructura IMAGE_LOAD_CONFIG_DIRECTORY32. ¡Esta estructura contiene campos que cambiarán drásticamente el funcionamiento del programa! ¡Ahora podemos crear con confianza nuestra propia tabla de controladores y agregar solo lo que creemos que es necesario!





¿Quizás en algún lugar de la documentación hay información de que boundImport ya se llama incorrectamente en mi plataforma? ¿O información de que su cita ha cambiado? ¿Quizás boundImport fue excluido o cambiado?








All Articles