Un resumen muy rápido para ayudarte a responder mis preguntas:
- Aprendizaje del desensamblador interactivo IDA, la antigua edición gratuita (demasiado cara para un aficionado)
- Sysadmin Linux de 15 años & Experiencia DBA
- codificador de aficionados (C / ASM / Fortran / ...)
- No tiene mucho conocimiento sobre Windows & Microsoft en general
- no es un experto en seguridad, pero lo suficiente como para ser un administrador de sistemas
Después de un montón de desmontaje aleatorio de cosas aquí y allá, rápidamente noté que tienen muchos códigos comunes. Y al comienzo de muchos ejecutables hay algo que se parece a esto:
lea eax, [ebp+SystemTimeAsFileTime]
push eax ; lpSystemTimeAsFileTime
call ds:GetSystemTimeAsFileTime
mov eax, [ebp+SystemTimeAsFileTime.dwHighDateTime]
xor eax, [ebp+SystemTimeAsFileTime.dwLowDateTime]
Está literalmente en casi todos los binarios y rápidamente se encontró que es algo llamado por microsoft: "Buffer Security Check". Y el compilador lo agrega automáticamente mediante el indicador / GS.
Es un pila canaria que se usa para detectar el desbordamiento del búfer de la pila:
Este método funciona colocando un entero pequeño, cuyo valor se elige aleatoriamente al inicio del programa, en la memoria justo antes del puntero de retorno de pila. La mayoría de los desbordamientos de búfer sobrescriben la memoria de las direcciones de memoria inferiores a las más altas, por lo que para sobrescribir el puntero de retorno (y, por lo tanto, tomar el control del proceso), el valor canario también debe sobrescribirse. Este valor se verifica para asegurarse de que no haya cambiado antes de que una rutina use el puntero de retorno en la pila
Y de la documentación de Microsoft :
En las funciones que el compilador reconoce como sujetas a problemas de saturación del búfer, el compilador asigna espacio en la pila antes de la dirección de retorno. En la entrada de la función, el espacio asignado se carga con una cookie de seguridad que se calcula una vez en la carga del módulo. Al salir de la función y durante el desenrollado de cuadros en sistemas operativos de 64 bits, se llama a una función auxiliar para asegurarse de que el valor de la cookie sigue siendo el mismo. Un valor diferente indica que puede haberse producido una sobrescritura de la pila. Si se detecta un valor diferente, el proceso finaliza.
Todo está bien y todos vivirán felices para siempre.
Sin embargo , estoy confundido acerca de la implementación en sí. Es un montón de XOR de: tiempo del sistema, processId, ThreadId, tiempo de actividad, más tiempo (contador de rendimiento) en la creación del proceso.
No estoy diciendo que sea una implementación terriblemente mala (pero a primera vista lo estoy pensando) ya que es una gran cantidad de XOR y un solo bit equivocado estropeará la cookie por completo (a menos que haya un ataque, estoy no se tiene en cuenta) y el forzado bruto se evita al 100% (o no se sabe) ya que el proceso finalizará cuando la suposición sea incorrecta y se genere una nueva cookie en el siguiente proceso.
Ahora tengo un montón de preguntas:
- ¿Por qué una implementación de generación pseudoaleatoria tan extraña? ¿El sistema operativo no tiene una fuente de entropía confiable? ¿Está relacionada la portabilidad? ¿Es posible que alguna variante de Windows no tenga una fuente de entropía?
- ¿no se conoce processId y threadId a todos en el sistema de todos modos? entonces, ¿por qué usarlo como fuente de entropía?
- Todo el tiempo está relacionado y se inicia al inicio del proceso, no se garantiza que los servicios no se inicien (lo que necesita la mayor protección) tiene un tiempo de funcionamiento y amp; ¿Contador de resultados y una hora del sistema conocida y, por lo tanto, la entropía más débil?
- ¿Por qué esta generación de cookies no es una llamada al sistema de todos modos? Ahora es irreparable sin recompilación.
Aquí está mi desmontaje comentado:
push ebp ; prolog
mov ebp, esp ; prolog
sub esp, 14h ; prolog
and [ebp+SystemTimeAsFileTime.dwLowDateTime], 0
and [ebp+SystemTimeAsFileTime.dwHighDateTime], 0
mov eax, __security_cookie
push esi
push edi
mov edi, 0BB40E64Eh ; a global constant thingy for security cookie
mov esi, 0FFFF0000h
cmp eax, edi ; compare local security cookie
; with global security cookie.
; if security_cookie == 0BB40E64Eh then it's not initialized
; and it need to be initialized
jz short generate_security_cookie
La generación se realiza solo si se compara con una constante mundial conocida "0BB40E64Eh". ¿No hay un vector de ataque potencial? ¿No podría ser un valor local para el sistema?
- ¿Por qué molestarse en condicionar la generación?
- ¿Es incluso una característica de seguridad? o simplemente un medio de depuración para detectar que algo salió mal con la pila?
Son muchas preguntas, es mi primer paso en este tipo de cosas, pero esto es muy confuso. Pero principalmente: ¿por qué no llamar simplemente a una fuente de entropía del SO? Estoy tan confundido ...
Pregunta de bonificación: si uno tiene un medio para modificar el binario (¿un solo bit en la constante mundial conocida?), no se podría pasar por alto todo / GS? y si es un servicio de red abierta, ahora tiene un servicio con un potencial de desbordamiento de búfer abierto al mundo, ¿no?