programa - Código C que se comprueba a sí mismo*en ram*
generar.hex en ccs (5)
¿Se puede actualizar el cargador para realizar la prueba de suma de comprobación en la imagen binaria residente en flash, antes de que se copie a la RAM?
Estoy tratando de obtener una imagen de residente de RAM para la suma de comprobación, lo que está resultando más fácil decirlo que hacerlo.
El código se compila primero en una plataforma de desarrollo cruzado, generando una salida .elf. Se utiliza una utilidad para eliminar la imagen binaria, y esa imagen se graba para parpadear en la plataforma de destino, junto con el tamaño de la imagen. Cuando se inicia el objetivo, copia el binario a la región correcta de ram, y salta a él. La utilidad también calcula una suma de comprobación de todas las palabras en el elfo que están destinadas a ram, y eso también se quema en el flash. Por lo tanto, en teoría, mi imagen podría sumar su propia imagen de RAM utilizando la dirección de inicio a priori y el tamaño guardado en flash, y compararla con la suma guardada en flash.
Esa es la teoría de todos modos. El problema es que una vez que la imagen comienza a ejecutarse, hay un cambio en la sección .data
medida que se modifican las variables. En el momento en que se realiza la suma, la imagen que se ha sumado ya no es la imagen para la cual la utilidad calculó la suma.
He eliminado el cambio debido a las variables definidas por mi aplicación, moviendo la rutina de suma de comprobación por delante de todas las otras inicializaciones en la aplicación (lo que tiene sentido b / c, por qué ejecutar cualquiera de ellas si falla una verificación de integridad, ¿no?), Pero asesino es el tiempo de ejecución de C en sí. Parece que hay algunos elementos relacionados con malloc
y puntero de fundición y otras cosas que se modifican antes de que incluso se ingrese main()
.
¿Es la idea completa de auto-checkumming C code cojo? Si hubiera una forma de forzar la aplicación y los datos de CRT en diferentes secciones, podría evitar el golpe de CRT, pero se podría argumentar que si el objetivo es verificar la integridad de la imagen antes de ejecutarla (la mayoría de ellos), los datos de CRT inicializados deberían ser parte de eso ¿Hay alguna forma de hacer que la suma de comprobación de código en RAM sea así?
FWIW, me parece que estoy atascado con un requisito para esto. Personalmente, pensé que el camino a seguir es sumir el binario en el flash , antes de transferirlo al ram, y confiar en el cargador y el ram. La paranoia tiene que terminar en algún lugar ¿no?
Otros detalles: la cadena de herramientas es GNU, la imagen contiene .text
, .rodata
y .data
como un fragmento cargado de forma contigua. No hay sistema operativo, esto es el metal desnudo incrustado. Cargador primario esencialmente memcpy
es mi binario en ram, en una dirección predeterminada. No se producen reubicaciones. VM no se utiliza. Checksum solo necesita pruebas una vez al inicio solo.
actualizado Encontré que al hacer esto ...
__attribute__((constructor)) void sumItUp(void) {
// sum it up
// leave result where it can be found
}
.. que puedo hacer la suma antes de casi todo, excepto la inicialización de las vars malloc
/ sbrk
por el CRT init, y algunas vars propiedad de "impure.o" y "locale.o". Ahora, el valor de malloc
/ sbrk
es algo que sé por el script del enlazador del proyecto. Si se puede mitigar impure.o y locale.o, podría estar en el negocio.
actualizar Ya que puedo controlar el punto de entrada (por lo que se indica en flash para el cargador primario), parece que el mejor ángulo de ataque ahora es usar un código de ensamblador personalizado para configurar los apiladores y los punteros sdata, llame a la rutina de suma de comprobación, y luego se bifurca en el código de inicio "normal".
¿Se puede usar el script del vinculador para colocar impure.o y locale.o antes o después de todo lo demás, permitiéndole sumar todo, excepto esos y el material de malloc / sbrk? Supongo que se llama a malloc y sbrk en el gestor de arranque que carga su aplicación, por lo que no se pueden eliminar los problemas causados por esos problemas.
No es una respuesta simplemente decirte que luches contra este requisito, pero estoy de acuerdo en que esto parece estar sobre pensado. Estoy seguro de que no puede entrar en detalles, pero supongo que los autores de las especificaciones están preocupados por los usuarios / piratas informáticos maliciosos, en lugar de la corrupción de memoria normal debida a los rayos cósmicos, etc. En este caso, si es un malicioso el usuario / hacker puede cambiar lo que está cargado en la RAM, solo puede cambiar su rutina de suma de comprobación (que se ejecuta desde la RAM, ¿correcto?) para devolver siempre un estado feliz, sin importar qué tan bien esté diseñada la rutina de suma de comprobación que ya no están ejecutando .
Incluso si están preocupados por la corrupción de la memoria normal, esta rutina de suma de comprobación solo detectará que si el error ocurrió durante la copia original en la memoria, que en realidad es el momento más improbable de que ocurra tal error, simplemente porque el sistema no se ha estado ejecutando el tiempo suficiente para tener una alta probabilidad de un evento de corrupción.
En general, lo que quiere hacer es imposible, ya que en muchas plataformas (¿la mayoría?) El cargador de programas puede "reubicar" algunas constantes de direcciones de programas.
Si la suma de comprobación se realiza con suficiente antelación, puede usar SOLO las variables de la pila, y no escribir en ninguna de las variables de la sección de datos, es decir, hacer TODO lo que necesita para realizar la suma de comprobación [y todos los pasos anteriores para llegar a ese punto] SOLAMENTE use local variables para almacenar cosas en [puedes leer datos globales por supuesto].
Estoy bastante convencido de que la forma correcta es confiar en el flash y el cargador para cargar lo que está en el flash. Si desea verificar la suma de comprobación del código, asegúrese, vaya y haga eso [asumiendo que el cargador no lo está modificando, por ejemplo, la carga en tiempo de ejecución de bibliotecas compartidas o la reubicación del ejecutable en sí mismo, como los espacios de direcciones virtuales aleatorias y demás]. Pero no se puede confiar en los datos cargados desde flash una vez que la ejecución comience correctamente.
Si hay un requisito de alguien más para que hagas esto, entonces explícales que esto no es factible de implementar y que "el requisito, tal como está" está "roto".
Yo sugeriría acercarse a esto como un empaquetador ejecutable, como upx .
Hay varias cosas en las otras respuestas y en tu pregunta que, por falta de un término mejor, me ponen nervioso.
- No confiaría en el cargador ni en nada en flash que no me fuera forzado.
- Existe un código fuente flotando en la red que se usó para proteger uno de los teléfonos recientes de HTC, creo. Mire a su alrededor en forum.xda-developers.com y vea si puede encontrarlo y usarlo como ejemplo.
- Yo rechazaría este requisito. Los fabricantes de teléfonos celulares dedican mucho tiempo a mantener sus imágenes bloqueadas y, eventualmente, todos son golpeados. Esto parece un círculo vicioso.