BASH SCRIPTS HAS the inherit property of script languages of being readable by the users.
Sometimes it is desireable to at least attempt to hide the inner details of a script.
There are a few possibilities to do at least a bit of scrambling of the contents of a script for the viewing end user.
The examples shown here are not real content hiding measures, but at first glance the end user will not have a clue of the content, and will have to do a bit of non-total-n00b work to get its contents descrambled.
Suppose we have a function that rolls the dice and if you hit a three, the scripts exits.
function roll_dice() {
local sample_space=6
local number=${RANDOM}
let "number %= ${sample_space}"
if [[ $number == 3 ]]; then
echo
echo "Better luck next time! Game over - you loose :-P"
echo
exit ${number}
fi
}
roll_dice
For this first example base64 is used. It has the nice properties of converting any
input to a sequence that contains only plain ascii characters.
If the above is saved in a script roll_dice.txt
, the following command will base-64 encode it
cat roll_dice.txt | base64
As output from this command is printed the base64 encoded data:
ZnVuY3Rpb24gcm9sbF9kaWNlKCkgewogICAgbG9jYWwgc2FtcGxlX3NwYWNlPTYKICAgIGxvY2Fs IG51bWJlcj0ke1JBTkRPTX0KICAgIGxldCAibnVtYmVyICU9ICR7c2FtcGxlX3NwYWNlfSIKCiAg ICBpZiBbWyAkbnVtYmVyID09IDMgXV07IHRoZW4KICAgICAgICBlY2hvCiAgICAgICAgZWNobyAi QmV0dGVyIGx1Y2sgbmV4dCB0aW1lISBHYW1lIG92ZXIgLSB5b3UgbG9vc2UgOi1QIgogICAgICAg IGVjaG8KICAgICAgICBleGl0ICR7bnVtYmVyfQogICAgZmkKfQpyb2xsX2RpY2U=
The data can now be used in a script and evaluated. To descramble the data
back to its original bash content, the base64 command is used again, but in reverse.
This makes it nothing but data though, so to have it evaluated (executed), the
eval
command is used to runtime evaluate the code loaded to the dice
variable.
#!/bin/bash
dice=$(base64 -d <<'EOF'
ZnVuY3Rpb24gcm9sbF9kaWNlKCkgewogICAgbG9jYWwgc2FtcGxlX3NwYWNlPTYKICAgIGxvY2Fs
IG51bWJlcj0ke1JBTkRPTX0KICAgIGxldCAibnVtYmVyICU9ICR7c2FtcGxlX3NwYWNlfSIKCiAg
ICBpZiBbWyAkbnVtYmVyID09IDMgXV07IHRoZW4KICAgICAgICBlY2hvCiAgICAgICAgZWNobyAi
QmV0dGVyIGx1Y2sgbmV4dCB0aW1lISBHYW1lIG92ZXIgLSB5b3UgbG9vc2UgOi1QIgogICAgICAg
IGVjaG8KICAgICAgICBleGl0ICR7bnVtYmVyfQogICAgZmkKfQpyb2xsX2RpY2U=
EOF
)
eval "${dice}"
echo "Welcome, you lucky one"
There are several reasons why this is more a fun/prank trick, than an actual
security measure. But if you want, the same trick can be used with gpg. This
will disallow users to run or decode the scrambled script lines unless the passphrase is known.
Firstly create a gpg encoded script snippet. When run, gpg will prompt for encoding passphrase.
» gpg -ac -o- <<'EOF' | xclip -selection clipboard
echo "I am encrypted"
EOF
As the key is required for executing the encrypted parts, the bash script needs the passphrase.
Therefore there is no way to hide the key, which eventually means that the end user will always
have a means to decode the script before executing. Alternatively, let gpg ask for the passphrase
and anyone knowing the correct passphrase will be able to run its hidden content.
In the script below the user will be prompted for the decoding passphrase before being able to execute the encoded section.
#!/bin/bash
echo "To learn the secret, you must know the passphrase"
secret_message=$(gpg -d <<'EOF'
-----BEGIN PGP MESSAGE-----
Version: GnuPG v1
jA0EBwMCJ+zlMDPCUlBg0ksBUQm4AstVcHFIluhT8Og0RA83X5s6p54JWisJz/mk
xgdBFTcMXYto0fHgT2N4vC0BFog39IFDp6oMXRjtI1Quv1YQx4HTmVaRYeA=
=z7wJ
-----END PGP MESSAGE-----
EOF
)
eval "${secret_message}"