How to minify/obfuscate a bash script

Of course a bash file cannot be truly obfuscated and will always be readable. And I don't want to wrap them in some binary package. And renaming local variables wouldn't be worth the trouble.

But is there a reliable simple bash obfuscator or minifier which at least removes all the indentation, all the empty lines and all whitespace without breaking anything? And especially the comments and commented out portions of the script which might contain sensitive documents or information?

I would be afraid of simple grep/sed-lines to do this because "HEREDOCs" must not be modified of course, so a little bit of real parsing is necessary.

Maybe there's a tool to do this, that would be great!

Answers


Here is a tool that I created for bash scripts minification: https://github.com/precious/bash_minifier – it tries to remove all comments and as many spaces/tabs/newlines as possible. It is also available as a service here https://bash-minifier.appspot.com/.

To minify your bash script run this command:

python minifier.py /path/to/shell/script.sh

:P here is something funny.

say your script is named origin and the obfuscated one is named obsf.

here is origin:

#!/bin/sh
echo "fooo"

here is obsf

$ echo "echo $(base64 origin)" > obsf
$ cat obsf
echo IyEvYmluL3NoCmVjaG8gImZvb28iCg==
$ chmod +x obsf

now rm origin and run obsf like this:

$ sh obsf | base64 -d | sh
fooo

heh :3


Even though this is an old question, it seems to be popular on Google. I was also looking for a bash minifer/obfuscator, and didn't like the one in the answer.

I didn't want to add gibberish either, or compile the script. So I wrote one that did what I wanted in Perl, and put it on GitHub at https://github.com/Aralhach/bashobfus/tree/master It can:

  • Flatten indentation
  • Remove full-line comments (except the initial hashbang (#!)) and blank lines
  • Renames all lowercase variables in basic declarations (to avoid renaming variables like PATH), for loops, array access, and 'read' statements.

There might be some case where it fails, but I tested it with a fairly big bash script, and the listed cases of variable replacing popped up. It also leaves variables within single quotes (') alone --this popped up when printing an AWK script-- but replaces between single quotes (') when the statement is already inside double quotes (") --this popped up when printing an MySQL statement.

This makes me think I've covered all the big use cases, but I've been wrong before. If you find any bugs, feel free to report them (or fix them! :D). I was also thinking of adding a feature to join short lines into one with ";" but the cases were too many to analyze while making my deadline.

I hope people find it useful!


A Tool to obfuscate shell scripts: http://www.comp.eonworks.com/scripts/obfuscate_shell_script-20011012.html

Sort of silly to do, but that's up to you. There are also ways to "compile" your shell script into an executable. This post's accepted answer gives several links with tools to do that.


Minification and Obfuscation of a shell script are two different things.

Minification means reducing the size of a script by removing all unnecessary characters from source code without changing its functionality. Obfuscation on the other hand means making the script difficult, if not impossible, to read.

Minification:

To minify a big script, you can run the following code against the actual script you want to minify:

#!/bin/sh
Script=${1}
if [ ! -z "${Script}" ] && [ -f ${Script} ] ; then
        CurrenTime=$(date | sed -e 's~ ~_~g' -e 's~:~~g')
        cp ${Script} ${Script}_${CurrenTime}
        #### Remove all empty lines
        #### Remove lines that begin with spaces and a comment sign #
        #### Remove all comment lines (meaning, lines that begin with a "#")
        awk '
                (/.*/ || /#!/) && (!/^#$/) &&
                (!/^#[[:blank:]]/) && (!/^#[a-z]/) && 
                (!/^#[A-Z]/) && (!/^##/) &&
                (!/^\t#/) && (!/^[[:space:]]*$/) &&
                ( /^#.*!/ || !/^[[:space:]]*#/)
        ' ${Script} | sed 's_^[[:space:]]*__g' > ${Script}.tmp 2>/dev/null
        #' ${Script} > ${Script}.tmp 2>/dev/null (comment out the above line and uncomment this line if your HEREDOCS are affected)
        ExitCode=$?
        if [ ${ExitCode} -eq 0 ] && [ -s ${Script}.tmp ] ; then
                echo
                echo "SUCCESS: Your newly [ minified ] script can be found here [ ${Script}.tmp ]."
                echo "Review the script [ ${Script}.tmp ] and if happy with it, replace your original script with it!"
                echo "NOTE: Your original script [ ${Script} ] was backed up as [ ${Script}_${CurrenTime} ]!"
                echo
                exit 0
        else
                echo
                echo "FAILURE: Unable to [ minify ] the specified script [ ${Script} ]!!!"
                echo
                exit 2
        fi
else
        echo
        echo "USAGE: ${0}  <your-script>"
        echo
        exit 3
fi

Note, minification tends to make a difference only if the script being minified is big...with several hundred or even thousands of lines. I was able to trim off a few Megabytes from a script using the above code.

Obfuscation:

After the above minification is completed, you can just stop right there if size reduction is what you're going for. If however, after the minification, you also wish to obfuscate your script as well, you have options.

The simplest way to obfuscate your script is through the use of encryption tools such as as Openssl.

To encrypt your script using Openssl:

    1. cat <your-script> | openssl aes-128-cbc -a -salt -k "specify-a-password" > yourscript.enc

    OR

    2. openssl aes-128-cbc -a-salt -in <path-to-your-script> -k "yourpassword"

To decrypt a script using Openssl (notice the '-d'):

    1. cat yourscript.enc | openssl aes-128-cbc -a -d -salt -k "specify-a-password" > yourscript.dec

    OR

    2. openssl aes-128-cbc -a -d -salt -in <path-to-your-script> -k "yourpassword" > yourscript.dec

Encryption/Obfuscation:

  1. If your ultimate goal is to make it difficult to others to read your script, try pasting it here to have an encrypted copy generated for you.
  2. In case you change your mind about SHC, the latest version can be downloaded here.

Original file script.sh:

#!/usr/bin/env bash
echo "foo"

Create other.sh

$ echo '#!/usr/bin/env bash' > other.sh
$ echo "echo '$(base64 script.sh)' | base64 -d | sh" >> other.sh
$ chmod +x other.sh

Result (cat other.sh):

#!/usr/bin/env bash
echo 'IyEvdXNyL2Jpbi9lbnYgYmFzaAplY2hvICJmb28iCg==' | base64 -d | sh

Try:

$ ./other.sh
foo

Based on c00kiemon5ter idea, here you have THE script

Your twisted recursive minds will love it, since this is not the original script, but the obfuscated(obfuscated(original))

#!/bin/bash
#
# Usage:
#     obfuscate scrript.sh > script_obfuscated.sh
#
PIXIE=$(mktemp)
base64 -d  >${PIXIE}<<DIXIE
IyEvYmluL2Jhc2ggClBJWElFPSQobWt0ZW1wKQpiYXNlNjQgLWQgID4ke1BJWElFfTw8RElYSUUK
SXlFdlltbHVMMkpoYzJnS2FXWWdXeUFnTFdZZ0lpUXhJaUJkSUFwMGFHVnVDbU5oZENBOFBGQkpX
RWxGSUFvaklTOWlhVzR2WW1GegphQ0FLVUVsWVNVVTlYQ1FvYld0MFpXMXdLUXBpWVhObE5qUWdM
V1FnSUQ1Y0pIdFFTVmhKUlgwOFBFUkpXRWxGQ2lRb1ltRnpaVFkwCklDUXhLUXBFU1ZoSlJRcHpi
M1Z5WTJVZ1hDUjdVRWxZU1VWOUNuSnRJQzF5WmlCY0pIdFFTVmhKUlgwS1VFbFlTVVVLWlhocGRD
QXcKQ21acENtTmhkRHc4VGtWU1JBb2dJQ0IxYzJGblpUb2diMkoxYzJOaGRHVWdjMk55YVhCMENn
b2dJQ0JYYVd4c0lHZGxibVZ5WVhSbApJQ0p6WTNKcGNIUXViMkp6YUNJS1RrVlNSQW89CkRJWElF
CnNvdXJjZSAke1BJWElFfQpybSAtcmYgJHtQSVhJRX0K
DIXIE
source ${PIXIE}
rm -rf ${PIXIE}

Need Your Help

Mongoose findOneAndUpdate and runValidators not working

node.js mongodb validation mongoose

I am having issues trying to get the 'runValidators' option to work. My user schema has an email field that has required set to true but each time a new user gets added to the database (using the '...

What's the difference between Future and FutureTask in Java?

java executorservice callable futuretask

Since use ExecutorService can submit a Callable task and return a Future, why need to use FutureTask to wrap Callable task and use the method execute? I feel they both do the same thing.