Parchear un binary con dd

He leído esta cita (abajo) varias veces, la más reciente aquí , y estoy continuamente desconcertado sobre cómo dd se puede usar para parchar algo, y mucho less un comstackdor:

El sistema Unix que utilicé en la escuela, hace 30 años, era muy limitado en RAM y espacio en disco. Especialmente, el sistema de files /usr/tmp era muy pequeño, lo que ocasionaba problemas cuando alguien intentaba comstackr un progtwig grande. Por supuesto, no se suponía que los estudiantes escribieran "progtwigs grandes" de todos modos; los progtwigs grandes generalmente eran códigos fuente copydos de "algún lugar". Muchos de nosotros copymos /usr/bin/cc a /home/<myname>/cc , y usamos dd para parchar el binary para usar /tmp lugar de /usr/tmp , que era más grande. Por supuesto, esto solo empeoró el problema: el espacio en disco ocupado por estas copys sí importaba en esos días, y ahora /tmp llena regularmente, lo que impide que otros usuarios editen sus files. Después de que descubrieron lo que sucedió, los administradores del sistema hicieron un chmod go-r /bin/* /usr/bin/* que "corrigió" el problema y borró todas nuestras copys del comstackdor de C.

(Énfasis mío)

La página de manual de dd no dice nada sobre el parcheo y no creo que se pueda volver a utilizar para hacer esto de todos modos.

¿Los binarys realmente podrían ser parcheados con dd ? ¿Hay algún significado histórico para esto?

Vamos a intentarlo. Aquí hay un progtwig trivial de C:

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

Vamos a build eso en test :

 $ cc -o test test.c 

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

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

 $ strings -td test | grep /usr/tmp 1460 /usr/tmp 

-td imprime el desplazamiento en decimal en el file de cada cadena que encuentra.

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

 $ printf "/tmp\x00" > tmp 

Entonces ahora tenemos el binary, sabemos dónde está la cadena que queremos cambiar, y tenemos un file con la cadena de reemploop en él.

Ahora podemos usar dd :

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

Esto lee los datos de tmp (nuestro file " /tmp\0 "), escribiéndolos en nuestro binary, usando un tamaño de bloque de salida de 1 byte, salteando al desplazamiento que encontramos antes antes de que escriba algo y explícitamente no trunque el file cuando está hecho.

Podemos ejecutar el ejecutable parcheado:

 $ ./test /tmp 

El literal de cadena que el progtwig imprime ha sido cambiado, 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 acortar la cadena o la misma longitud, y no más, pero es adecuada para estos fines.

Entonces no solo podemos parchar cosas usando dd , simplemente lo hemos hecho.

Depende de lo que quiere decir con "parchear el binary".

Cambio los binarys usando dd veces. Por supuesto, no hay tal característica en dd , pero puede abrir files, y leer y escribir cosas en desplazamientos específicos, de modo que si sabe qué escribir dónde, allí está su parche.

Por ejemplo, tenía este binary que contenía algunos datos PNG. Use binwalk para encontrar el desplazamiento, dd para extraerlo (generalmente binwalk también extrae cosas pero mi copy tenía fallas), gimp con gimp , asegúrese de que el file editado sea del mismo tamaño o más pequeño que el original (cambiar los desplazamientos no es algo que puede hacerlo fácilmente), y luego use dd para volver a colocar la image 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 replace cadenas en binarys (como nombres de routes o variables). Si bien esto también se puede hacer usando dd , es más simple hacerlo usando sed . Solo tienes que asegurarte de que la cadena con la que reemplazas tenga la misma longitud que la cadena original para que no acabes cambiando los desplazamientos.

 sed -es@/the/old/save/path@/the/new/save/path@ -i thebinary 

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

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

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