Hay un búfer binario con tamaño fijo en un programa que se utiliza para almacenar datos. Y memcpy se usa para copiar el buffer de uno a otro. Dado que el buffer de origen puede ser más grande que el buffer de destino. ¿Cómo puedo detectar si hay un desbordamiento del búfer?¿Cómo prevenir el desbordamiento del búfer memcpy?
Respuesta
Debe saber cuántos datos hay en el búfer fuente y cuánto espacio hay disponible en el búfer de destino.
No llame al memcpy()
si no hay suficiente espacio en el búfer de destino para todos los datos que desea copiar del búfer de origen. (Debe decidir si está bien truncar los datos si la fuente es más grande que el destino.)
Si no sabe, reescriba el código para saber cuánto espacio hay; de lo contrario, no es seguro.
Tenga en cuenta que si existe la posibilidad de que los almacenamientos intermedios de origen y de destino se superpongan, debe usar memmove()
en lugar de memcpy()
.
En C++, mira primero el uso de memcpy()
; esa es una operación estilo C en lugar de C++.
Gracias. ¿Cuál es la forma correcta de hacer la copia de la memoria en C++? –
@MichaelD: almacene sus datos en un 'std :: vector <>', y simplemente use 'vector2 = vector1'. – MSalters
¿Cómo puedo insertar datos en el vector? usar push_back para insertar byte de fecha por byte? –
¡Siempre debe conocer y verificar el tamaño de los buffers de src y dest!
void *memcpy(void *dest, const void *src, size_t n);
n
nunca debe ser mayor que src
o dest
tamaño.
Por ejemplo, si usted tiene:
destino tamaño de 4 bytes
fuente tamaño de 5 bytes
Puede asegurarse de que la copia, como máximo, 4 bytes al búfer de destino:
size_t getCopySize(size_t sourceSize, size_t destSize)
{
return (destSize <= sourceSize ? destSize : sourceSize);
}
memcpy(destination, source, getCopySize(sizeof(source),sizeof(destination)));
Según su aplicación, también podría asegurarse de que los datos restantes se copiarán más adelante, o puede omitirlos si se pueden ignorar algunos datos.
¿Cómo puedo detectar si hay un desbordamiento del búfer?
Creo que tiene tres o cuatro opciones (dar o recibir).
La primera opción es la de proporcionar una función de "seguro" para memcpy
. Esto es lo que requiero en el código bajo mi competencia, y regularmente audito para ello. También requiero que todos los parámetros estén validados y que todos los parámetros estén confirmados.
Las aserciones crean código de auto depuración. Quiero que los desarrolladores escriban código; y no quiero que pierdan tiempo depurando. Por lo tanto, les solicito que escriban código que se depure a sí mismo. ASSERT también documenta las cosas bastante bien, por lo que pueden escatimar en la documentación. En las compilaciones de lanzamiento, los ASSERT son eliminados por las macros de preporcesor.
errno_t safe_memcpy(void* dest, size_t dsize, void* src, size_t ssize, size_t cnt)
{
ASSERT(dest != NULL);
ASSERT(src != NULL);
ASSERT(dsize != 0);
ASSERT(ssize != 0);
ASSERT(cnt != 0);
// What was the point of this call?
if(cnt == 0)
retrn 0;
if(dest == NULL || src == NULL)
return EINVALID;
if(dsize == 0 || ssize == 0)
return EINVALID;
ASSERT(dsize <= RSIZE_MAX);
ASSERT(ssize <= RSIZE_MAX);
ASSERT(cnt <= RSIZE_MAX);
if(dsize > RSIZE_MAX || ssize > RSIZE_MAX || cnt > RSIZE_MAX)
return EINVALID;
size_t cc = min(min(dsize, ssize), cnt);
memmove(dest, src, cc);
if(cc != cnt)
return ETRUNCATE;
return 0;
}
Si sus safe_memcpy
devuelve un valor no 0, entonces no fue un error como un parámetro incorrecto o potencial desbordamiento de búfer.
La segunda opción es utilizar funciones "más seguras" proporcionadas por el estándar C. C tiene funciones "más seguras" a través del ISO/IEC TR 24731-1, Bounds Checking Interfaces. En plataformas conformes, simplemente puede llamar al gets_s
y sprintf_s
. Ofrecen un comportamiento constante (como garantizar siempre que una cadena esté terminada en NULL
) y valores de retorno consistentes (como 0 en caso de éxito o errno_t
).
errno_t err = memcpy_s(dest, dsize, src, cnt);
...
Lamentablemente, gcc y glibc no cumplen con la norma C. Ulrich Drepper (uno de los mantenedores de glibc) denominó interfaces de comprobación de límites "horribly inefficient BSD crap", y nunca se agregaron.
La tercera opción es utilizar las interfaces "más seguros" de la plataforma, si está presente. En Windows, que es el mismo que en ISO/IEC TR 24731-1, Bounds Checking Interfaces. También tiene la biblioteca String Safe.
En Apple y BSD, no tiene una función "más segura" para memcpy
. Pero tiene funciones de cadena más seguras como strlcpy
, strlcat
y amigos.
En Linux, su cuarta opción es usar FORTIFY_SOURCE. FORTIFY_SOURCE utiliza variantes "más seguras" de funciones de alto riesgo como memcpy
, strcpy
y gets
. El compilador usa las variantes más seguras cuando puede deducir el tamaño del búfer de destino. Si la copia excede el tamaño del búfer de destino, el programa llama al abort()
. Si el compilador no puede deducir el tamaño del búfer de destino, entonces las variantes "más seguras" no se utilizan.
Para deshabilitar FORTIFY_SOURCE para probar, debe compilar el programa con -U_FORTIFY_SOURCE
o -D_FORTIFY_SOURCE=0
.
- 1. ¿Cómo puedo invocar el desbordamiento del búfer?
- 2. Prevenir el desbordamiento de pila Excepción del proceso de bloqueo
- 3. Dillema con desbordamiento de búfer
- 4. ¿Cómo prevenir scanf causando un desbordamiento de buffer en C?
- 5. Es posible el desbordamiento/desbordamiento del búfer en la aplicación web asp.net C# completamente administrada
- 6. ejemplo de desbordamiento de búfer del libro Art of Exploitation
- 7. Cómo desactivar la optimización del compilador gcc para habilitar el desbordamiento del búfer
- 8. dbms_output desbordamiento de búfer de tamaño
- 9. Consecuencias de este desbordamiento de búfer?
- 10. ¿Es posible el desbordamiento de búfer de PHP?
- 11. C# creación de desbordamiento de búfer
- 12. ¿Cómo llevar a cabo el desbordamiento del búfer en PHP/Python?
- 13. ¿Cómo prevenir el envío del formulario?
- 14. Cómo prevenir el restablecimiento del formulario HTML
- 15. ¿Son posibles exploits de desbordamiento de búfer en C#?
- 16. memcpy con startIndex?
- 17. La declaración codificada std :: string provoca desbordamiento de búfer
- 18. Abortar trampa en lugar de desbordamiento de búfer
- 19. ¿Cómo usar memcpy?
- 20. Programa de explotación de desbordamiento de búfer intencional
- 21. ¿Cómo prevenir un desbordamiento de pila al monitorear el tamaño de la pila?
- 22. ¿Cómo prevenir el error de desbordamiento aritmético al usar SUM en la columna INT?
- 23. Cómo prevenir el evento ListBox.SelectedIndexChanged?
- 24. ¿Por qué recibo un error de desbordamiento del búfer con esta línea de código?
- 25. Ejemplo de desbordamiento de búfer que provoca una fuga de seguridad
- 26. memcpy(), ¿cuál debería ser el valor del parámetro de tamaño?
- 27. Tamaño del búfer en el servicio WCF
- 28. ¿Cómo puedo prevenir o recuperar un desbordamiento de pila en un subproceso de trabajador?
- 29. optimizado memcpy
- 30. ¿Cómo prevenir el cierre de la ventana del navegador?
Detect? ¿Conoces el tamaño del búfer de destino? Luego escriba un código como este memcpy (src, dst, sizeof (dst)) – BSen
Compare el tamaño del búfer de origen y el búfer de destino y vea cuál es más grande? – SingerOfTheFall
@BSen que '' sizeof'' simplemente dará el tamaño de un puntero. – juanchopanza