25

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!

Christian
  • 2,903
  • 4
  • 31
  • 34
  • There are many such tools for css/javascript files, maybe you can adapt one of them to your cause. There are quite several bash scripts that can accomplish this task. – Bogdan Emil Mariesan Mar 28 '12 at 12:14
  • http://www.tero.co.uk/scripts/minify.php – Bogdan Emil Mariesan Mar 28 '12 at 12:14
  • Would you consider a ready-made tool that encrypts the script and then wraps it into binary for you ? – louigi600 Feb 09 '17 at 14:05
  • I specifically wrote "And I don't want to wrap them in some binary package". However, somebody else might of course be interessted in that. Please be aware that any encryption is pointless and could be easily reverse engineered. e.g. a simple strace would show the executed script when it is passed to bash for execution – Christian Feb 09 '17 at 19:29

7 Answers7

29

: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

c00kiemon5ter
  • 16,994
  • 7
  • 46
  • 48
  • 2
    I don't understand what this should be. It would be foolish to "base 64 encrypt" a script. I just want to get rid of comments and other helpful stuff in the original script. – Christian May 30 '12 at 21:41
  • Too late to ask, I am getting "Illegal variable name." error while encrypting the original file, any clue ????? –  Jan 09 '15 at 08:55
  • 1
    but it is like you "encrypted" the script, only that you did not use a password? :>, funny indeed xD – Aquarius Power Feb 15 '15 at 00:29
  • The problem is with that you can't pass parameters to the script. Unless you use bash -s – Zibri Dec 13 '16 at 15:19
  • 1
    @Christian The question said "obfuscate". This does that. Obviously it's not real encryption, but if you just want to prevent casual and ill informed snoopers... I like this! – Wowfunhappy Aug 23 '18 at 22:41
14

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
Vsevolod Kulaga
  • 666
  • 7
  • 8
  • 2
    While this link may answer the question, it is better to include the essential parts of the answer here and provide the link for reference. Link-only answers can become invalid if the linked page changes. - [From Review](/review/low-quality-posts/16128568) – hivert May 15 '17 at 16:03
  • @hivert, the command to start minification script has been added (the script itself is big enough to insert it here, it can be found on github) – Vsevolod Kulaga May 15 '17 at 16:29
  • Thanks a lot! You're the first to actually consider heredocs :-) Looks very promising. – Christian May 15 '17 at 20:28
  • Nice work!! It looks much more straightforward and robust than what I hacked together. Keep it up! – Daniel Gray May 16 '17 at 11:56
  • the whole point of this is to make the script unreadable. If the user still sees the source code, then it is not serving the purpose. – raz Sep 02 '20 at 22:08
  • This might have an answer for you .. https://unix.stackexchange.com/questions/90178/how-can-i-either-encrypt-or-render-my-shell-script-unreadable – raz Sep 03 '20 at 12:34
9

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!

Daniel Gray
  • 1,697
  • 1
  • 21
  • 41
  • 2
    Great work! I'll try it soon. One comment so far: It does not look like it supports heredocs. You can write in bash << – Christian Nov 07 '13 at 08:09
  • I didn't know about heredocs!! Thanks for the link! I did try this bash code: `$ test='one' \n $ tr a-z A-Z <<< $test \n ONE $` So it seems the variable replacing should be done. I haven't considered the other << here string case with the delimeters. If the delimeter is quoted, the variable replacement should be skipped right? (I added the \n characters to mark my newline positions) – Daniel Gray Nov 07 '13 at 12:55
8

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
Eduardo Cuomo
  • 17,828
  • 6
  • 117
  • 94
  • 2
    plain and simple, works perfectly. Thanks for sharing – Bogdan Stoica Apr 30 '18 at 22:21
  • It's a bit *too plan* to extent that anyone can just run without `| sh` and get the script's complete code. E,g, `echo 'IyEvdXNyL2Jpbi9lbnYgYmFzaAplY2hvICJmb28iCg==' | base64 -d`. I think if the two later commands were somehow obfuscated, that would be less obvious – Danila Vershinin May 05 '20 at 09:16
3

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.
RoyMWell
  • 199
  • 1
  • 9
2

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.

Community
  • 1
  • 1
linuxnut
  • 58
  • 5
  • 1
    Thanks for finding this. But I don't want to add gibberish, I only want to strip things. The essence of this download seems to be this: sed -e '2,$ {/^ *$/d ; /^ *#/d ; /^[ \t] *#/d ; /*^/d ; s/^[ \t]*// ; s/*[ \t]$// ; s/ $//}' $tmp_2 > $tmp_1 I think this is broken because it doesn't handle HEREDOCS. But thanks anyway! – Christian Apr 18 '12 at 07:55
-1

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}
RSG
  • 384
  • 3
  • 7