c++ assembly reverse-engineering compiler-optimization buffer-overflow

"Xor eax, ebp" se usa en la salida del compilador C++



assembly reverse-engineering (1)

Solo intenté compilar un par de fragmentos de C ++ en VS2010 y analicé los ejecutables en IDA Pro. Algo que noté es que la mayoría de ellos tienen algo como lo siguiente al inicio (poco después de una llamada a __security_check_cookie)

xor eax, ebp

y algo así como

xor ecx, ebp

en el fondo. ¿Por qué pasó esto? La optimización del compilador estaba desactivada.


Estos son métodos de protección de desbordamiento de búfer y no tienen nada que ver con la optimización del compilador. MSVC (si especifica el /GS ) insertará una cookie de seguridad en la pila cerca de la dirección de retorno para que pueda detectar un caso común de corrupción de la pila.

La corrupción de la pila puede ser causada por un código incorrecto a lo largo de las líneas de:

char buff[5]; strcpy (buff, "Man, this string is waaay too long!!");

o por usuarios malintencionados que aprovechan las malas prácticas de codificación, como el uso de scanf ("%s", myBuff) para la entrada del usuario. Los ataques cuidadosamente diseñados como ese pueden socavar su programa para hacer cosas que probablemente no desee.

Al colocar una cookie cerca de la dirección de retorno, se puede evitar una gran cantidad de errores (y vectores de ataque), simplemente debido al hecho de que la corrupción de la memoria tiende a ser de naturaleza secuencial. En otras palabras, si sobrescribió la dirección de devolución, es probable que haya comenzado a escribir en un lado de la cookie y en la memoria corrupta hasta la dirección de devolución en el otro lado de la cookie (de ahí que se sobrescriba la cookie) también).

No detecta todos los errores ya que puede tener algún código como:

char buff[5]; buff[87] = ''x'';

que podría dañar la dirección de retorno sin tocar la cookie. Pero detectará todos los maliciosos que dependen de ingresar una cadena más larga de lo esperado, que se corrompe hasta la dirección de devolución (incluida la cookie).

La secuencia que probablemente veas en el código es algo así como:

mov eax, dword ptr ds:___sec_cookie ; fixed value. xor eax, ebp ; adjust based on base pointer. mov [ebp+SOMETHING], eax ; store adjusted value.

que está personalizando la cookie, dependiendo del puntero base actual.

Esto cambiará lo que en realidad se coloca en la pila en cada nivel de pila (y también dependiendo del recuento y tamaño de los parámetros) y es probablemente un intento de proteger aún más el código de intenciones maliciosas, asegurando que una firma variable se escriba en la pila en lugar de un valor fijo (de lo contrario, el atacante podría ingresar caracteres que incluyen una cookie válida).

Y la secuencia al final se ejecutará algo así:

mov ecx, [ebp+SOMETHING] ; get the adjusted cookie. xor ecx, ebp ; un-adjust it, since ; ((N xor X) xor X) == N. call @__sec_check_cookie ; check the cookie.

Básicamente es solo el proceso inverso al descrito anteriormente. La llamada @__sec_check_cookie solo volverá si ecx se establece en el valor correcto de la cookie. De lo contrario, generará una falla, como se confirma here :

La rutina __security_check_cookie() es sencilla: si la cookie no se modificó, ejecuta la instrucción RET y finaliza la llamada a la función. Si la cookie no coincide, la rutina invoca report_failure() .

La función __security_error_handler() llama a __security_error_handler() . Ambas funciones están definidas en el archivo seccook.c de los archivos fuente en tiempo de ejecución C (CRT).

Se necesita soporte de CRT para hacer que estas comprobaciones de seguridad funcionen. Cuando se produce una falla en la comprobación de seguridad, el control del programa se pasa a __security_error_handler() , que se resume aquí:

void __cdecl __security_error_handler(int code, void *data) { if (user_handler != NULL) { __try { user_handler(code, data); } __except (EXCEPTION_EXECUTE_HANDLER) {} } else { //...prepare outmsg... __crtMessageBoxA( outmsg, "Microsoft Visual C++ Runtime Library", MB_OK|MB_ICONHAND|MB_SETFOREGROUND|MB_TASKMODAL); } _exit(3); }

De forma predeterminada, una aplicación que falla una comprobación de seguridad muestra un cuadro de diálogo que indica "¡Desbordamiento del búfer detectado!". Cuando se cierra el diálogo, la aplicación finaliza.