Self Extracting Shell Scripts

A shell script can have a binary payload attached to it, that it can extract from itself.

Say for example that you have the following shell script format:

<some shell commands>

PAYLOAD:

<some payload>

The “PAYLOAD:” is a line, with ONLY that written on it. This is a marker, used to find the binary payload later on.

Imagine that we create the following script to append binary payloads to a shell script:


cat install.sh.in > install.sh

echo "PAYLOAD:" >> install.sh

cat $1 >> install.sh

The above script will create a new file install.sh from the install.sh.in template (makes it easier to test the script, because you do not have to rewrite install.sh everytime :))

Then the PAYLOAD: line is appended, and finally, whatever was given as an argument ($1 is the first argument to the script. $0 is the script itself) is appended.

Now we can create the install.sh.in script:


#First we find the linenumber which holds the marker-text

#We do this by grepping in text mode (-a) and we want line numbers printed (-n)

#and we grep on the script itself ($0). We then pipe this to the cut command, which splits #the output from grep on the ':' character. Then we extract the first entry from the split (-f #1). This should give us the line number.

match=$(grep -a -n '^PAYLOAD:$' $0 | cut -d ':' -f 1)

#The payload starts AFTER the PAYLOAD marker

payload_start=$((match+1))

#Now we can extract the binary part of the script itself, using the tail command.

#'-n +' means "start from line number. As a demo we pipe the binary data

#to tar to show the files inside. (given that the binary payload was a tar to begin

#with!)

tail -n +$payload_start $0 | tar -zt

#remember to exit before the payload! Otherwize the binary payload will be

#interpreted as script.

exit 0