Parchear un binario con dd

32

He leído esta cita (a continuación) varias veces, la más reciente aquí , y estoy continuamente desconcertado sobre cómo ddse puede usar para parchear cualquier cosa, y mucho menos un compilador:

El sistema Unix que utilicé en la escuela, hace 30 años, era muy limitado en RAM y espacio en disco. Especialmente, el /usr/tmpsistema de archivos era muy pequeño, lo que generaba problemas cuando alguien intentaba compilar un programa grande. Por supuesto, no se suponía que los estudiantes escribieran "programas grandes" de todos modos; Los programas grandes eran típicamente códigos fuente copiados de "algún lugar". Muchos de nosotros copiado /usr/bin/cca /home/<myname>/cc, y utiliza ddpara parchear el binario para usar /tmpen lugar de/usr/tmp , que era más grande. Por supuesto, esto solo empeoró el problema: el espacio en disco ocupado por estas copias importaba esos días y ahora se /tmpllenaba regularmente, evitando que otros usuarios incluso editaran sus archivos. Después de que descubrieron lo que sucedió, los administradores de sistemas hicieron unchmod go-r /bin/* /usr/bin/* que "solucionó" el problema y eliminó todas nuestras copias del compilador de C.

(El énfasis es mío)

La ddpágina del manual no dice nada acerca de los parches y no creo que se pueda cambiar el propósito de hacer esto de todos modos.

¿Podrían parchearse realmente los binarios dd? ¿Hay algún significado histórico para esto?

Amziraro
fuente
3
Seguro - sólo odun archivo para los códigos hexadecimales de bytes, halla el desplazamiento es necesario, decidir sobre su edición y bs=$patchsize count=1 seek=$((offset/bs)) conv=notruncsu derecha parche en adelante.
mikeserv
3
Alguien nunca ha sobrescrito un sector de arranque. ;)
Parthian Shot
@ParthianShot En realidad, sobrescribí los primeros ~ 260 MB de mi unidad de arranque (+ raíz) con parte de un LiveCD de Debian una vez. O_o Pero no creo que eso sea realmente parchear, jejeje ...
Amziraro
1
O más bien, ese es el comportamiento esperado y totalmente normal del Destructor de discos: D
Amziraro

Respuestas:

73

Vamos a intentarlo. Aquí hay un programa trivial en C:

#include <stdio.h>
int main(int argc, char **argv) {
    puts("/usr/tmp");
}

Construiremos eso en test:

$ cc -o test test.c

Si lo ejecutamos, imprime "/ usr / tmp".

Veamos dónde está " /usr/tmp" en el binario:

$ strings -t d test | grep /usr/tmp
1460 /usr/tmp

-t d imprime el desplazamiento en decimal en el archivo de cada cadena que encuentra.

Ahora hagamos un archivo temporal con solo " /tmp\0" en él:

$ printf "/tmp\x00" > tmp

Entonces, ahora tenemos el binario, sabemos dónde está la cadena que queremos cambiar, y tenemos un archivo con la cadena de reemplazo.

Ahora podemos usar dd:

$ dd if=tmp of=test obs=1 seek=1460 conv=notrunc

Esto lee los datos de tmp(nuestro " /tmp\0" archivo), escribiéndolos en nuestro binario, usando un tamaño de bloque de salida de 1 byte, saltando al desplazamiento que encontramos antes antes de escribir cualquier cosa, y explícitamente no truncando el archivo cuando está hecho.

Podemos ejecutar el ejecutable parcheado:

$ ./test
/tmp

Se ha cambiado el literal de cadena que imprime el programa, por lo que ahora contiene " /tmp\0tmp\0", pero las funciones de cadena se detienen tan pronto como ven el primer byte nulo. Este parche solo permite hacer que la cadena sea más corta o de la misma longitud, y no más larga, pero es adecuada para estos fines.

Entonces, no solo podemos parchear las cosas usando dd, sino que lo hemos hecho.

Michael Homer
fuente
1
¡Esto es excelente ... y algo que espero no encontrar nunca en un entorno de producción! He utilizado métodos similares en el pasado para obtener números de serie en imágenes hexadecimales para microcontroladores, aunque es demasiado fácil dispararse en el pie.
Michael Shaw
Si quisiera dar instrucciones escritas a alguien sobre cómo parchear un binario en particular, prefiero darles una línea de comando para copiar / pegar que decirles "abra el archivo en un editor hexadecimal, busque la /usr/tmpcadena, reemplácela con /tmp, don no olvide el \0byte final , guarde el archivo y cruce los dedos ". O, mejor aún, un script de shell que primero verifica la cordura y luego llama dd. Desafortunadamente, la necesidad de cosas como esta surge con frecuencia cuando un viejo software de un proveedor ahora desaparecido solo tiene que migrarse a un nuevo sistema.
Guntram Blohm apoya a Monica el
Sí, sed es mejor para este tipo de cosas. Pero no tiene toda la razón sobre el conjunto "Este parche solo permite hacer que la cadena sea más corta o de la misma longitud, y no más". Asume que le importan los datos que siguen inmediatamente a la cadena que desea modificar, o que no puede tener la siguiente cadena simplemente como una subcadena de la cadena original. En otras palabras, si estás en la sección .strings de la memoria y tienes "/ usr \ 0 / bin / bash \ 0", puedes convertir eso en / usr / bin / bash simplemente cambiando eso primero byte nulo y convertirlo en "/ usr // bin / bash" (por ejemplo).
Parthian Shot
2
@ParthianShot: nosed es mejor para este tipo de cosas: no puede limitar de manera tan explícita y precisa las memorias intermedias de lectura / escritura de la manera que podría hacerlo, que es la razón por la que se utilizó para esto en primer lugar. Con usted puede colocar arbitrariamente un recuento arbitrario de bytes arbitrarios. Esto tampoco se puede decir de . Si se usa como un bisturí aquí, se aplicaría como una bola de demolición. sedddddsedddsed
mikeserv
Ese es un punto justo (¡aunque bastante raro!): Habrá ocasiones en que puede alargar la cadena sin preocuparse por el resultado u otro dato arbitrario, pero específico. Sin embargo, mantendré la declaración general.
Michael Homer
9

Depende de lo que quieras decir con "parchear el binario".

A ddveces cambio los binarios . Por supuesto, no existe tal característica dd, pero puede abrir archivos y leer y escribir cosas en desplazamientos específicos, por lo que si sabe qué escribir dónde, voila está su parche.

Por ejemplo, tuve este binario que contenía algunos datos PNG. Úselo binwalkpara encontrar el desplazamiento, ddpara extraerlo (generalmente binwalk también extrae cosas, pero mi copia tenía errores), edítelo gimp, asegúrese de que el archivo editado sea del mismo tamaño o más pequeño que el original (cambiar los desplazamientos no es algo que pueda hacer fácilmente ), y luego use ddpara volver a colocar la imagen modificada en su lugar.

$ binwalk thebinary
[…]
4194643    0x400153     PNG image, 800 x 160, 8-bit/color RGB, non-interlaced
[…]
$ dd if=nickel bs=1 skip=4194641 count=2 conv=swab | od -i
21869 # file size in this case - depends on the binary format
$ dd if=thebinary bs=1 skip=4194643 count=21869 of=theimage.png
$ gimp theimage.png
$ pngcrush myimage.png myimage.crush.png
# make sure myimage.crush.png is smaller than the original
$ dd if=myimage.crush.png of=thebinary bs=1 seek=4194643 conv=notrunc

A veces también deseo reemplazar cadenas en binarios (como ruta o nombres de variables). Si bien esto también se puede hacer usando dd, es más simple hacerlo usando sed. Solo debe asegurarse de que la cadena con la que reemplaza tenga la misma longitud que la cadena original para que no termine cambiando las compensaciones.

sed -e s@/the/old/save/path@/the/new/save/path@ -i thebinary

o para recoger el ejemplo de @ MichaelHomer con un byte 0 agregado en:

sed -e 's@/usr/tmp@/tmp\x00tmp@' -i test

Por supuesto, debe verificar si realmente funciona después.

frostschutz
fuente
... suponiendo que tenga un sedarchivo que maneje bien los archivos binarios, lo que parece ser el caso con gnu sed, pero no con muchos de los seds más antiguos que solo trabajaban en archivos ascii, se confundieron con cualquier otra cosa (especialmente \0s en la entrada), y tenía restricciones en la longitud máxima de la línea.
Guntram Blohm apoya a Monica el
1
busybox sedparece poder cambiar bien los archivos binarios, pero no entiende \x00en la cadena de reemplazo como lo sedhace GNU . Requiere pruebas, pero aun así creo que vale la pena mencionarlo, ya que es mucho más simple que dd, en algunos casos. Parchear binarios es un negocio flaky de cualquier manera.
frostschutz