Cómo evitar el desbordamiento (computadora)
Si el campo de entrada contiene más datos de los necesarios, provocará un problema de desbordamiento de datos y los datos sobrantes se utilizarán como instrucciones para ejecutar en la computadora de acuerdo con la seguridad relevante. organizaciones, la operación Más de 50 vulnerabilidades de seguridad en el sistema son causadas por desbordamientos de memoria, la mayoría de los cuales están relacionados con la tecnología de Microsoft
El software de Microsoft está desarrollado para computadoras de escritorio, pero los desbordamientos de memoria no causarán problemas graves. Hoy en día, las computadoras de escritorio generalmente están conectadas a Internet y los desbordamientos de memoria brindan comodidad para los ataques de piratas informáticos.
Cómo resolver el problema de desbordamiento de memoria
Las soluciones y medidas preventivas para la memoria. El problema de desbordamiento se analiza a continuación. p>
1. Cambiar código controlado
En febrero y marzo de 2002, Microsoft lanzó la campaña de seguridad de Microsoft Windows. Durante este período, mi grupo trabajó en cómo diseñar, prueba, y más de 8.500 personas fueron capacitadas durante el proceso de documentación para abordar los problemas de seguridad. Las recomendaciones para todos los programadores incluyen seguir las políticas de desarrollo de software de Microsoft y convertir ciertas aplicaciones y herramientas desde código C nativo controlado allí. Hay muchas razones para esto, pero una de las más fundamentales es resolver problemas de desbordamiento de memoria. El código basado en código controlado no puede acceder directamente a los punteros, registros o memoria del sistema. Como desarrollador, debería considerar (o al menos intentar) reescribir ciertas aplicaciones o herramientas en código controlado y, por supuesto, debería comprender claramente que es imposible reescribir todo el software desarrollado en C de la noche a la mañana en un lenguaje de código controlado como este. como C#
2. Siga la regla de oro
Al escribir código en C/C, siempre debe prestar atención a cómo se manejan los datos del usuario si es la fuente de datos. de la función no es confiable y se utiliza un búfer de memoria, se deben seguir estrictamente las siguientes reglas:
Debe conocer la longitud total del búfer de memoria
Verificar el búfer de memoria.
Echemos un vistazo más de cerca a estas "reglas de oro":
(1) Debe conocer la longitud total del búfer de memoria.
Código como este puede causa errores:
void Function(char *szName) {
char szBuff[MAX_NAME]
//Copiar y usar szName
strcpy(szBuff, szName);
(szBuff, szName);
Copiar y usar szName.}
El problema es que la función no lo sabe. cuál es la longitud de szName, por lo que no es seguro copiar los datos en este momento. El enfoque correcto es obtener la longitud de szName antes de copiar los datos:
void Function(char *szName, DWORD cbName) {
char szBuff[MAX_NAME]
;// Copiar y usar szName
if (cbName lt; MAX_NAME)
strcpy(szBuff, szName
}
<); p> Esto es una mejora, pero parece confiar demasiado en cbName. Todavía es posible que un atacante falsifique los parámetros czName y szName, informando así falsamente la longitud de los datos y la longitud del búfer de memoria.Por lo tanto, aún debes verificar estos dos parámetros.
(2) Verifique el búfer de memoria
¿Cómo saber si la longitud del búfer de memoria pasada por el parámetro es real? ¿Confiarías completamente en los datos provenientes de tus usuarios? La respuesta suele ser no. De hecho, existe una forma sencilla de comprobar si un búfer de memoria se ha desbordado. Mire el siguiente fragmento de código:
void Function(char *szName, DWORD cbName) {
char szBuff[MAX_NAME]
//Detectar memoria;
p>szBuff[cbName] = 0x42
//
// Copiar y usar szName
if (cbName lt; MAX_NAME) p>
strcpy(szBuff, szName);
}
Este código intenta escribir 0x42 al final del búfer en la memoria que se va a detectar. Quizás estés pensando: esto es una pérdida de tiempo, ¿por qué no simplemente copiar el búfer de memoria? De hecho, escribir un valor constante en un búfer de memoria cuando ya se ha desbordado provocará que el código del programa genere un error y finalice. De esta manera, los errores en el código se pueden detectar en las primeras etapas del proceso de desarrollo. Piénselo, si cancela el programa a tiempo, en lugar de dejar que el atacante tenga éxito, probablemente no quiera que el atacante copie los datos en el búfer de memoria como le plazca.
(3) Manténgase alerta
Aunque comprobar el búfer de memoria puede ayudar a minimizar el riesgo de problemas de desbordamiento de memoria, no puede prevenir fundamentalmente la aparición de ataques de desbordamiento de memoria. Sólo estando atentos desde el código fuente en adelante se puede eliminar verdaderamente el peligro de ataques de desbordamiento de memoria. Sí, el código anterior ha mantenido un alto nivel de vigilancia sobre los datos del usuario. Garantiza que la longitud total de los datos copiados en el búfer de memoria no exceda la longitud de szBuff. Sin embargo, algunas funciones también pueden ser vulnerables a vulnerabilidades de desbordamiento de memoria al usar o copiar datos no confiables. Para verificar su código en busca de vulnerabilidades de desbordamiento de memoria, debe intentar rastrear el flujo de datos de entrada y cuestionar cada suposición en el código. Una vez que hagas esto, te darás cuenta de que algunas de estas suposiciones están equivocadas y luego te sorprenderás: ¡cuántas están equivocadas!
Por supuesto, debes tener cuidado al llamar a funciones clásicas como strcpy, strcat, gets; pero para las llamadas n versiones de strcpy o strcat, como strncpy o strncat (donde n = 1, 2, 3). 2, 3...)—todos son indignos de confianza. Es cierto que estas versiones mejoradas de funciones son más seguras y confiables porque limitan la longitud de los datos que ingresan al búfer de memoria; sin embargo, ¡también pueden causar problemas de desbordamiento de la memoria! Mire el código a continuación. ¿Puede señalar el error?
#define TAMAÑO(b) (tamañode(b))
char buff[128]
strncpy(buff, szSomeData, TAMAÑO(buff))
strncat(buff, szMoreData.SIZE(buff));
strncat(buff, szEvenMoreData, SIZE(buff)); a estos El último parámetro de la función de cadena. ¿Qué, abstenerse? Lo que quiero decir es que si decides abandonar las funciones de cadena clásicas "inseguras" y utilizar las n versiones "relativamente seguras", ¡pasarás el resto de tu vida solucionando nuevos errores provocados por estas nuevas funciones! Estoy bromeando. Es una broma.
¿Por qué? En primer lugar, su último parámetro no representa la longitud total del búfer de memoria, sino solo la longitud del espacio restante. No es difícil ver que después de ejecutar cada función strn..., la longitud del búfer de memoria; será igual a la longitud del búfer de memoria. Misma longitud. Una vez ejecutada la función, se reducirá la longitud del búfer. En segundo lugar, la longitud del búfer de memoria pasado a la función inevitablemente se desviará de la unidad. ¿Crees que el carácter nulo al final de la cadena se incluye al calcular la longitud del búfer? Cuando le planteo esta pregunta a mi audiencia, normalmente obtengo una respuesta mixta. Es decir, aproximadamente la mitad pensó que se contaría el carácter nulo al final de la cadena, mientras que la otra mitad pensó que se ignoraría. Finalmente, las cadenas devueltas por estas funciones de n versiones no necesariamente terminan en nulo, así que asegúrese de leer atentamente su documentación antes de usar estas funciones.
3. Opción de compilación /GS
"/GS" es una nueva opción de compilación en Visual C. Le indica al compilador que inserte datos específicos en el marco de la pila de ciertas funciones para ayudar a eliminar la posibilidad de problemas de desbordamiento de memoria específicos de la pila. Tenga en cuenta que el uso de esta opción no elimina las vulnerabilidades de desbordamiento de memoria en su código ni elimina ningún error. Simplemente soluciona el problema para que algunos peligros de desbordamiento de memoria no se conviertan en desbordamientos de memoria reales, es decir, evita que los atacantes inserten y ejecuten código malicioso en el proceso en caso de un desbordamiento de memoria; De todos modos, esto es sólo una pequeña medida de seguridad. Tenga en cuenta que en las nuevas versiones de Win32 C esta opción está activada de forma predeterminada al crear nuevos proyectos utilizando el Asistente de aplicaciones Win32. Asimismo, los entornos Windows .NET Server también tienen esta opción activada de forma predeterminada. Para obtener más información sobre la opción /GS, consulte el libro Compiler Security Checks Deep de Brandon Bray.
Desbordamiento de punto fijo significa que el valor absoluto del resultado de una operación de punto específico es mayor que el valor absoluto del número más grande que puede representar la computadora. El desbordamiento de números de punto flotante se puede dividir en "desbordamiento" y "desbordamiento". "Desbordamiento" tiene el mismo significado que los números enteros y de punto fijo. "Desbordamiento" significa que el valor absoluto del resultado de la operación del número de punto flotante. es menor que el valor mínimo que la máquina puede representar El valor absoluto del número, en este momento el resultado de la operación se procesará a la posición cero de la máquina. Si se encuentra un desbordamiento (desbordamiento), el operador generará un indicador de desbordamiento o emitirá una solicitud de interrupción. Cuando la interrupción de desbordamiento no está enmascarada, la aparición de la señal de interrupción de desbordamiento interrumpirá la ejecución del programa y la transferirá al controlador de interrupciones de desbordamiento.
Por ejemplo, si sumas dos números 0.1001111 y 0.1101011, el resultado debería ser 1.0111010. Dado que las computadoras de punto fijo solo pueden representar números menores que 1, si la longitud de la palabra es de solo 8 bits, el 1 antes del punto decimal se perderá debido a la falta de un flip-flop. De esta forma, el resultado de los dos números anteriores en la computadora será 0.0111010. Para otro ejemplo, si se multiplican dos números 0.0001001 y 0.00001111, el resultado debe ser 0.00000000111111. Si la longitud de la palabra es de solo 8 bits, el resultado se muestra como 0.0000000 y los siguientes 0 y 6 1 se pierden. el resultado es incorrecto. No se permite el desbordamiento en ninguna operación de la computadora, a menos que el desbordamiento se use específicamente para juzgar sin usar el resultado. Por lo tanto, cuando ocurre un desbordamiento pero no se permite que ocurra, es necesario detenerse o recurrir al programa de inspección para descubrir la causa del desbordamiento y manejarlo en consecuencia.