Como crear y aplicar parches a binarios o codigo fuente de programas

En esta ocasión vamos a hablar de como aplicar parches o comúnmente llamado en ingles Patch, que tan usado es por ejemplo para actualizar el kernel.

Comencemos por el concepto:

Cita wikipedia:

En informática, un parche es una sección de código que se introduce a un programa. Dicho código puede tener varios objetivos; sustituir código erróneo, agregar funcionalidad al programa, aplicar una actualización, etc.

Ahora vamos a aclarar que el patching se pueden aplicar a 2 tipos de cosas:

* Al código fuente del programa
* Al archivo binario (ya compilado)

Por ahora vamos a concentrarnos en el primer tipo.

 

Parcheando un código fuente

Supongamos que entramos a una web de algún proyecto open source, el código fuente de la aplicación que se esta creando en el proyecto esta disponible desde allí, nos ponemos a revisar el código y vemos algo como esto:

#include <stdio.h>

main() {

int *pnt;
int i, a[3]={1,2,3};

for(dato=0; i<3; i++) {
pnt = &a[dato];
printf(«Puntero = %d\n», pnt);
}

return 0;

}

Obviamente no es un programa real ni parte de ningún otro, solo un ejemplo que escribí que va a servir para demostrar el uso de los parches.

Ohh, ahí hay un error en una linea, si se compila de esa forma el programa no va a funcionar como debe.

printf(«Puntero = %d\n», pnt);

En esa parte, hay un error en el acceso del contenido del puntero, falta el «*«.

Un error mínimo que no va a dar ninguna clase de problemas en la compilación pero que haría que el programa fuera inútil, sabiendo esto ¿que podríamos hacer?.

Pues una opción seria aplicarle un parche que corrija el error.

¿Como hacerlo?

En GNU/Linux disponemos de dos herramientas que hacen el trabajo extremadamente fácil.

* diff
* patch

Lo primero seria guardar el código fuente, como es un ejemplo, que tenga de nombre programa1.c , ahí tendríamos el programa tal cual esta con el error incluido, ahora creo otro archivo con el mismo código pero cambiado la linea del error por esta:

printf(«Puntero = %d\n», *pnt);

De hecho ese seria el único cambio (en este caso agregar el «*«), el código reparado lo guardamos como programa2.c

Ahora viene la magia, diff es un programa que compara 2 archivos y muestra las diferencias de este, en este caso eso es justo lo que necesitamos.

La sintaxis:

$> diff programa1.c programa2.c > parche.patch

Analizando la linea notamos que compara los dos programas y las diferencias las escribe en un nuevo archivo parche.patch.

Ya tenemos el parche, ahora solo falta aplicarlo, esto lo vamos a hacer con otra aplicación de los sistema Lunix que se llama patch.

Lo que hace este es que toma las diferencias de 2 programas (el parche.patch) y esta diferencia la aplica al archivo original.

La sintaxis:

$> patch -p1 -i parche.patch programa1.c

Analizando:
El -p1 se puede omitir en este caso, se usa más que nada para cuando hay parches en directorios diferentes, y sirve para omitir los slash y la ruta superior.
El -i viene de input y lee el archivo parche.patch

Si todo salio bien el sistema arroja este mensaje:

patching file programa1.c

Y si no hay errores el programa ya debería estar parchado.
Ahora podemos enviarle el parche para que sea aplicado al resto de los usuarios que lo precisen.

 

Parcheando un archivo binario

Ahora vamos al segundo caso, que pasa si el código fuente del proyecto ya fue compilado (aun con el error) y también ya fue distribuido.

Primero seria sustituir el archivo de la descarga de la web por el correcto, pero.. ¿y los usuarios? , cuando son programas muy grandes no se les puede decir que desinstalen todo y vuelvan a bajar el programa y después volver a instalarlo, en este caso es mejor aplicarle un parche que solucione el error.

¿Como generar el parche?, pues fácil, usando las mismas herramientas que cuando parcheamos el código fuente.

Como anteriormente teníamos el código fuente original (con el error) programa1.c y el código reparado programa2.c, vamos a compilar los 2 código para generar 2 binarios.

$> gcc programa1.c -o programa1

$> gcc programa2.c -o programa2

Ahora vamos a compararlos de esta manera y a generar el nuevo parche:

$> diff -a –binary programa1 programa2 > parchebin.patch

Revisando el comando, diff tenemos:
El -a indica que va a tratar los archivos como texto y va a comparar linea por linea.
El –binary que va a ser una comparación binaria y el parche va a ser de la misma forma.
El programa1 y programa2 son los archivos ya compilados.
parchebin.patch el archivo a usar resultante de la comparación para parchear.

Con eso ya tenemos todo listo, ¿como lo aplicamos?.
Pues bastante parecido al ejemplo anterior y siempre usando patch.

La sintaxis del comando en este caso resulta bastante simple:

$> patch –binary programa1 parchebin.patch

El –binary que el parche se va aplicar de forma binaria y programa1 es el fichero al cual le vamos a aplicar el parche. Todos los archivos deben estar en el mismo directorio.

Si tenemos éxito en estos 2 pasos tendríamos en resultado siguiente:

patching file programa1

En caso de que quisiéramos facilitarle aun más el trabajo al usuario y evitar que se ponga a ejecutar comandos podríamos hacer todo automáticamente con un pequeño script en bash.

 

 

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *