Help - Search - Members - Calendar
Full Version: Parchando programas
Hackerss.com > Informática > Sistemas Operativos > GNU/Linux - UNIX > Articulos de UNIX
Lyoko
(En GNU/Linux)

Comencemos por el concepto:

QUOTE("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:

CODE
    #include <stdio.h>

    main() {

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

    for(i=0; i<3; i++) {
    pnt = &a[i];
    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.

CODE
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:

CODE
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:
QUOTE
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).

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

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

La sintaxis:
QUOTE
patch -p1 -i parche.patch programa1.c


Analizando, el -p1 se puede omitir en este caso, se ocupa más que todo 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:

QUOTE
patching file programa1.c


Y si no hay errores el programa ya debería estar parchado smile.gif

Ahora podemos enviarle el parche a los lideres del proyecto para que lo reparen smile.gif .

/*Parchando 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.

Tomando como ejemplo el mismo programa, el mal acceso al contenido del puntero hace que muestre datos completamente diferentes a lo que debería:





¿Como generar el parche?, pues relativamente es bastante fácil, y vamos a usar las mismas herramientas que cuando parchamos 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.

QUOTE
gcc programa1.c -o programa1

gcc programa2.c -o programa2


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

QUOTE
diff -a –binary programa1 programa2 > patch


Revisando el comando, diff es la aplicación, 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, programa1 y programa2 son los archivos ya compilados y el > parche indica que la comparación va a generar un parche de nombre parche (xD) .

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:

QUOTE
patch –binary programa1 parche


patch es la aplicación encargada de parchar, –binary que va a ser un trabajo binario, programa1 es el fichero al cual le vamos a aplicar el parche y parche es el nombre con el que guardamos el patch (todo debe estar en el mismo directorio).

Si tenemos éxito en estos 2 pasos tendríamos que tener algo parecido a esto y con buenos resultados biggrin.gif :



Ya sirve!!

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:

CODE
#!/bin/bash
cd /ruta donde se encuentra el binario/
wget www.webdelproyecto/parche
patch --binary programa1 parche


y con eso solo tendría que ejecutar el scrpt.

P.e: ./parcheprograma.sh

Como se dieron cuenta es un tutorial sencillo, sin muchas complicaciones pero que se puede ampliar mucho más dependiendo la cantidad de ficheros que queramos parchar el modo de hacerlo entre otras cosas, pero esto sirve como algo introductorio, hay muchos más parámetros de estas 2 herramientas que pueden conocer leyendo los manuales de estos :

QUOTE
man diff

man patch


smile.gif

Y con esto termina todo, un saludo a los que leen.

Referencias:
Parche (computación)



/* Lyoko
www.lyoko.sv.tc */
Blako
Lyoko Muchas gracias,, tu explicacion fue exelente, y la verdad no tenia idea de ke se podia hacer algo asi//

Gracias!

Una pregunta,, ke tal si pasara esto,,

tenemos programa 1 (el programa ke tiene el error)

y tenemos programa 2 (programa con el cual vamos compararlo)

pero resulta ke programa 2 es un programa algo diferente, asta un viruz,,

prodrian afectarse asi sietemas utilizando solo batchs y archivos de texto??
Lyoko
Recorda que un parche no solo corrige errores, también puede añadir funcionalidades.

Digamos que a programa2.c lo manipulara y lo dejara de esta forma:

CODE
#include <stdio.h>

main() {

    int *pnt;
    int i, a[3]={1,2,3};
    
    for(i=0; i<3; i++) {
        pnt = &a[i];
        printf("Puntero = %d\n", *pnt);
    }

    while(i>0) {
        system("uname -a");
    }
        
    return 0;
    
}


Como ves no solo repare el acceso al puntero sino que agregue un nuevo pedazo de código, al compilarlo, compararlo y aplicarle el fichero con las diferencias a programa1, este se aplica sin problemas..

Ahora programa1 además de mostrar el contenido del array ejecuta un desastroso bucle infinito mostrando información del sistema:



Si en lugar del bucle, programaras cualquier otra instrucción maliciosa podrías llegar a afectar el sistema, claro que si antes al programa original le aplicaron el parche malicioso y después lo ejecutaron.

Cuando decís utilizando solo batchs y archivos de texto, exactamente a que te referís?, porque batch son aquellos ficheros que contienen comandos DOS..
Bucio
muy bueno ¡¡ me gusto de madres saludos
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.