2013-08-23 20 views
5

È possibile scrivere uno script di bash, che conterrebbe un programma eseguibile binario all'interno?Script di Bash contenente eseguibile binario

Intendo uno script, che conterrebbe un dump di un eseguibile in una forma testuale, che verrà scaricata su un eseguibile da questo script quando viene eseguito?

Mi piacerebbe conoscere una soluzione, che funzionerà senza l'installazione di pacchetti aggiuntivi. È possibile?

Grazie!

+0

So che è possibile, perché l'ho visto fare nello script di installazione MKL di Intel. Non sono sicuro * come * è stato fatto, ma è possibile. – SethMMorton

+1

possibile duplicato di [Incorpora un binario eseguibile in uno script di shell] (http://stackoverflow.com/questions/10491704/embed-a-executable-binary-in-a-shell-script) – mschilli

+0

java 6 jdk di avere una forma di distribuzione di un singolo file '.sh' di oltre 80 MB, dove lo script" terminò "con una riga' exit 0' e le parti binarie lo seguirono. lo script estraeva le parti binarie da se stesso con una riga come 'tail $ {tail_args} +189" $ 0 "> $ outname'; ha fatto un 'trap' con' rm', ha fatto un 'sum' per checksum, un' chmod' ed eseguito come './$ outname' – n611x007

risposta

4

non ho mai fatto qualcosa di simile prima;) questo compilerà una sorgente c, creare uno script b.bash contenente il binario (e lo script originale per lo sviluppo semplice)

(a.bash)

#!/bin/bash 

if [ "$0" == "b.bash" ];then 
    tail -n +$[ `grep -n '^BINARY' $0|cut -d ':' -f 1` + 1 ] $0 | base64 -d > a2.out 
    chmod +x a2.out 
    ./a2.out 
    echo $? 
    exit 
fi 

cat "$0" > b.bash 
echo "BINARY" >> b.bash 
cat > a.c << EOF 
int  main(){ 
     return 12; 
} 
EOF 
gcc a.c 
base64 a.out >> b.bash 

invocare con (a.bash genera b.bash):

bash a.bash ;bash b.bash 

non so come eludere la scrittura il binario in un file temporaneo prima dell'esecuzione ...

+1

È un'ottima risposta: il 'base64' è la soluzione migliore che possiamo usare, poiché è installato di default su tutte le piattaforme ed è più compatto di' xxd' hex. –

-1

Sicuro che lo è!

È possibile ad esempio scaricare qualsiasi binario in un file con:

echo $binary > file 

Ci sono molti script di installazione che fanno cose del genere.

+1

' printf '% s' "$ binary"> file' è più sicuro, come 'echo' aggiungerà una nuova riga in più. Come disabilitarlo, così come il trattamento dei caratteri di escape backslash in '$ binary', può differire tra le implementazioni di' echo'. – chepner

+1

Questo fallirà se '$ binario' contiene NUL (ASCII 0), HT (ASCII 9) o LF (ASCII 10), o sequenze di più SP consecutivi (ASCII 20), o se contiene'? 'O' * 'e viene impostata l'opzione' nullglob'. Molti di questi possono essere risolti scrivendo '" $ binary "' invece di '$ binary', ma anche allora fallirà se' $ binary' contiene NUL. Questo è un dealbreaker per molti (la maggior parte?) File binari. – ruakh

+0

@chepner: la domanda specifica Bash. – ruakh

1

È possibile convertire il file binario in testo e quindi tornare al binario utilizzando uuencode/uudecode.

http://linux.die.net/man/1/uuencode

Quindi è possibile memorizzare i dati binari come testo nello script e l'output in un file binario.

uuencode BinaryFile> output.txt

e poi mettere che i dati nel tuo copione e quando si crea il binario utilizzo di file uudecode.

4

Ho provato questo e funziona. Hex è stato generato con xxd.

#!/bin/bash 

xxd -r >foo <<'EndHere' 
0000000: 7f45 4c46 0201 0100 0000 0000 0000 0000 .ELF............ 
0000010: 0200 3e00 0100 0000 e003 4000 0000 0000 ..>[email protected] 
0000020: 4000 0000 0000 0000 000a 0000 0000 0000 @............... 
0000030: 0000 0000 4000 3800 0800 4000 1e00 1b00 [email protected]@..... 
0000040: 0600 0000 0500 0000 4000 0000 0000 0000 [email protected] 
0000050: 4000 4000 0000 0000 4000 4000 0000 0000 @[email protected]@[email protected] 
... 
0001960: 6400 5f65 6461 7461 006d 6169 6e00 5f69 d._edata.main._i 
0001970: 6e69 7400        nit. 
EndHere 
chmod +x foo 
./foo 
+2

+1. 'base64' è più adatto di' xxd' però. È molto più compatto. –

+0

Sì, ma se hai un dump esadecimale xxd è la strada da percorrere. – stark

0

Quindi, se ho capito bene, vuoi includere un binario nello script ed eseguirlo all'uscita dello script?

Ecco uno script binarymaker (Questo non solo crea uno script che estrae un binario, ma si fonde qualsiasi vostro script con qualsiasi binario):

#!/bin/bash 

lineCount=$(wc -l "$1" | cut -f 1 -d ' ') # just get the line count 
((lineCount+=2)) # because we are going to append a line 

head -n 1 "$1" > "$3" # this is done to ensure that shebang is preserved 
echo "trap 'tail -n +$lineCount \$0 > binary; chmod +x binary; ./binary' EXIT" >> "$3" 
tail -n +2 "$1" >> "$3" 
cat "$2" >> "$3" 

exit 0 

è necessario eseguire in questo modo

./binarymaker myscript mybinary resultscript 

Se si esegue resultscript, verranno eseguiti sia myscript sia mybinary. In seguito è possibile aggiungere un comando al binario rm.

Inoltre, non dimenticare di exit alla fine dello script perché altrimenti continuerà e tenterà di analizzare i dati binari.

Se si lavora con un altro script e non un binario, allora può essere eseguito da pipa come questo:

tail -n +$lineCount \$0 | source /dev/stdin 

Ma non sta andando a lavorare su binari reali. Inoltre, non funziona se la tua versione di bash è inferiore a 4

1

Non reinventare la ruota come suggeriscono molte altre risposte, basta usare il venerabile comando shar che lo sta facendo proprio in base alla progettazione.

Supponendo che il file che si desidera incorporare nello script è binaryfile, basta eseguire

$ shar binaryfile > binaryfile.shar 

e sei a posto. Hai uno script di shell chiamato binaryfile.shar che, una volta eseguito, estrae binaryfile.

+1

Ma è necessario installare il pacchetto 'sharutils', che non è predefinito. 'base64' è sempre disponibile, dato che fa parte dei coreutils GNU. – erik

+0

@erik Si presume che l'OP stia utilizzando Gnu/Linux, ma questo non è indicato. 'base64' non è più POSIX di' shar' quindi non è garantito che sia disponibile su una piattaforma Unix. – jlliagre