The immediate use of bash scripting is to automate tasks, but there are a lot of applications and tools in the commandline that are powerful enough and easy to use to have the need to use other languages such as python, perl, etc. that are harder to learn just to implement workflows of other tools.
When you try to make these scripts to be usable for third parties, its complexity increases as the amount of code that makes checks, verifications, etc. grows. At the end, you have created scripts that are reasonably big. Moreover, when you want to transfer these applications to others, you may want to avoid its re-distribution.
So this time I explored…
How to create compressed and/or encrypted bash scripts
TL;DR: An extended version of a code that gzips and encodes a script, that is run depending on a password (or license) is in the repository named LSC – License Shell Code.
Bash scripting is a powerful language to develop applications that manage servers, but also to automate processes in Linux, to execute batch tasks, or to other tasks that can be executed in the Linux commandline e.g. implement workflows in scientific applications (processing the output from one application to prepare it for other application).
But if your script grows a lot, maybe you want to compress it. Moreover, compressing the code is like somehow obfuscating the code. So it reduces the chance of re-using your code for other applications without permission (for the case of common end-users that do not master bash scripting).
Compressing the script and running it
Having a bash script in file example, compressing it is very simple. You can just see the next commands that create the example script and generates a gzipped version:
$ cat > example <<EOT #!/bin/bash echo "hello world" EOT $ cat > compressedscript <<EOT #!/bin/bash eval "\$(echo "$(cat example | gzip | base64)" | base64 -d | gunzip)" EOT
Now the compressed script looks like this one:
#!/bin/bash eval "$(echo "H4sIAOMSmVsAA1NW1E/KzNNPSizO4EpNzshXUMpIzcnJVyjPL8pJUeICAFeChBYfAAAA" | base64 -d | gunzip)"
And executing it is as simple as chmodding it and running it:
$ chmod +x compressedscript $ ./compressedscript hello world
As you can see, the process is very simple. We just embedded the gzipped source code (*) in a new script and took profit from the ability of the eval function.
(*) We needed to uuencode the gzipped file to be able to embed it in a plain text file.
Encrypting the script
Now that we know that the eval function works for our purposes, we can generalize the function of our proof of concept, to embed more complex things. For example, we can encrypt our script…
To encrypt things, we can use openssl as shown in this post. Briefly, we can encrypt a file with a command like the next one:
$ openssl enc -aes-256-cbc -salt -in file.txt -out file.txt.enc
And decode a encoded file with a command like the next one:
$ openssl enc -aes-256-cbc -d -in file.txt.enc -out file.txt
We apply encryption to our case, appart from gzipping our script. The resulting code is very similar to the previous case, but adding the encryption step:
$ cat > compressedscript <<EOT #!/bin/bash read -p "Please provide a password: " PASSWORD eval "\$(echo "$(cat example | gzip | openssl enc -aes-256-cbc -in /dev/stdin -out /dev/stdout -k "mypasswd" | base64 | tr -d '\n')" | base64 -d | openssl enc -d -aes-256-cbc -in /dev/stdin -out /dev/stdout -k "\$PASSWORD" | gunzip)" EOT
The resulting content for the new compressedscript file is the next one:
#!/bin/bash read -p "Please provide a password: " PASSWORD eval "$(echo "U2FsdGVkX18gnaQ3jFPBfhalu0/riWaRirtWHcFWgFqGFuzf3s98T/Y65Km2oe4jqGaAXlDCBX6+oWwWgqMIOBfG/O3P7qgmLTRpkzvShwc=" | base64 -d | openssl enc -d -aes-256-cbc -in /dev/stdin -out /dev/stdout -k "$PASSWORD" | gunzip)"
If we run that script, it will prompt for a password to decode de script (in our case it is “mypasswd”), and then it will be ran:
$ ./compressedscript Please provide a password: mypasswd hello world $ ./compressedscript Please provide a password: otherpasswd bad decrypt 140040196646552:error:06065064:digital envelope routines:EVP_DecryptFinal_ex:bad decrypt:evp_enc.c:529: gzip: stdin: not in gzip format
As shown in the code above, if other password is introduced, the code will not be ran.
An extended version of the code of this post is included in LSC – License Shell Code. LSC is an application that generate shell applications (from existing ones) that need a license code to be run.
NOTES: Providing your users with a LICENSE code give them a more professional distribution, and a more tailored solution. Getting the code also implies a knowledge of what they are doing and so it also includes a first barrier (both from the point of the knowledge and from the ethics).