Sí, esto se puede hacer. En realidad, es bastante similar en concepto a su artículo vinculado. El truco es usar uuencode
para codificar el binario en formato de texto y luego virarlo al final de su script.
Su secuencia de comandos se escribe de tal manera que ejecuta uudecode
en sí mismo para crear un archivo binario, cambiar los permisos y luego ejecutarlo.
uuencode
y uudecode
se crearon originalmente para cambiar el contenido binario en el precursor de internet, que no manejaba bien la información binaria. La conversión en texto significa que también se puede enviar como un script de shell. Si, por alguna razón, su distribución se queja cuando intenta ejecutar uuencode
, probablemente signifique que debe instalarlo. Por ejemplo, en Debian Squeeze:
sudo aptitude install sharutils
obtendrá los archivos ejecutables relevantes para usted. Este es el proceso por el que pasé. En primer lugar crear y compilar el programa C hello.c
:
pax> cat hello.c
#include <stdio.h>
int main (void) {
printf ("Hello\n");
return 0;
}
pax> gcc -o hello hello.c
A continuación, cree un script de shell testEmbed.sh
, que se descodificarlo en:
pax> cat testEmbed.sh
#!/bin/bash
rm -f hello
uudecode $0
./hello
rm -f hello
exit
La primera rm
declaración demuestra que el ejecutable hello
está siendo creado de nuevo por esta secuencia de comandos, no se queda fuera de su compilación.Ya que se necesita la carga útil en el archivo, así, adjuntar el archivo ejecutable codificada al final de la misma:
pax> uuencode hello hello >>testEmbed.sh
Posteriormente, cuando se ejecuta la secuencia de comandos testEmbed.sh
, extrae el ejecutable y lo ejecuta.
La razón por la que esto funciona es porque uudecode
busca ciertas líneas de marcador en su entrada (begin
y end
) que se ponen allí por uuencode
, por lo que sólo intenta descodificar el programa codificado, no toda la secuencia de comandos:
pax> cat testEmbed.sh
#!/bin/bash
rm -f hello
uudecode $0
./hello
rm -f hello
exit
begin 755 hello
M?T5,[email protected]$!`0````````````(``P`!````$(,$"#0```#`[email protected]```````#0`(``'
M`"@`'@`;``8````T````-(`$"#2`!`[email protected]````X`````4````$`````P```!0!
: : :
M:&%N9&QE`%]?1%1/4E]%3D1?7P!?7VQI8F-?8W-U7VEN:70`7U]B<W-?<W1A
M<G0`7V5N9`!P=71S0$!'3$E"0U\R+C``7V5D871A`%]?:38X-BYG971?<&-?
4=&AU;[email protected]`;6%I;@!?:6YI=```
`
end
Hay otras cosas de las que probablemente debería preocuparse, como la posibilidad de que su programa requiera bibliotecas compartidas que no existen en el sistema de destino, pero el proceso anterior es básicamente lo que necesita.
El proceso para un archivo JAR es muy similar, excepto que la forma de ejecutarlo es diferente. Es todavía un solo archivo, pero es necesario para reemplazar la línea:
./hello
con algo capaz de ejecutar archivos JAR, tales como:
java -jar hello.jar
También podría ser una buena idea agregar un 'trap 'rm -f hello' SIGINT' al script del shell para que el archivo temporal se limpie en caso de que el usuario Ctrl-C sea el programa. –
Sí, no dudo de que haya una gran cantidad de mejoras que pueda hacer en ese código y que _es_ una buena. No quiero complicarlo demasiado, ya que solo intento transmitir el concepto. – paxdiablo
Una muy buena explicación. Gracias – Ankit