SHC Shell Compiler
Wrapped
ByThe Bash Shell Script Compiler converts shell scripts directly into binaries. Compiling your scripts provides protection against accidental changes, but you will have to contend with some quirks.
The Shell Script Compiler tool (SHC) brings one advantage of compiled scripts to Bash: the ability to hide source code and prevent future modifications.
Other advantages of compiled scripts include speed and portability, but in this case, portability and faster run time are not the focus. In fact, programs that you compile with SHC still require Bash, and speed gains are hardly noticeable.
If you have a need to protect your Bash scripts from prying eyes, though, SHC might be your best option. It is currently the most popular free tool for converting (Bash) shell scripts into executable programs (see the “Installation” section).
Installation |
On Ubuntu: The PPAs for many versions and variants (Xubuntu, Mint, etc.) of this distribution have more-or-less recent versions of SHC. On Arch Linux: The current version of the package is available from the AUR (user repositories). You will have to navigate two obstacles during installation. The first issue relates to an incorrect checksum in the PKGBUILD file (Listing 1). The correct checksum is computed by the specified tool (sha256sums) and inserted during the install (Listing 2). If you answer y to Edit PKGBUILD?, an editor opens in which you can make the necessary changes. Listing 1: Checksum ... source=("http://www.datsi.fi.upm.es/~frosal/sources/${pkgname}-${pkgver}.tgz") sha256sums=('\textbf{ef7bbf1252c9c791f711782870d00d6f19c42c08e0ee57e9a04d0e2b3d114d40}') ... Listing 2: Unsupported Package ... ( Unsupported package: Potentially dangerous ! ) ==> Edit PKGBUILD ? [Y/n] ("A" to abort) ==> ------------------------------------ Textbf {Y} ... Additionally, the SHC package includes a series of test scripts (pru.sh, test.bash) that are not installed on Arch Linux, even though the original archive contains them. These scripts are used to make sure that SHC works properly and should therefore always be compiled before using the compiler to verify the results. Alternatively, you could always build SHC directly from source code and then install. After unpacking the archive, a simple make handles the compilation; make install installs the program below /usr/local/. The make test command no longer works in version 3.8.9; instead, you can use shc -f test.bash (Listing 3). Listing 3: Test SHC Install # ./shc -f test.bash # ./test.bash.x + echo '$@ is ' $@ is + echo 'command line: ./test.bash.x ' command line: ./test.bash.x + echo 'hello world' hello world + echo '[24010] PAUSED... Hit return!' [24010] PAUSED... Hit return! + read DUMMY + exit 0 |
Understanding SHC
SHC uses a two-step process (Figure 1): SHC generates fairly extensive, highly specialized C source code from the shell script, which is then subsequently compiled using the C compiler to create a binary program.
In the first step, SHC generates a file with the extension .x.c; this is then compiled in the second step by the C compiler defined in the $CC environment variable to create a file with the extension .x.
Obfuscation of the shell script source code in the C code relies on the use of an array that contains the contents of the script. During the build, SHC progressively accesses the (encrypted) entries of the array and integrates them into the executable program.
How arrays are processed in detail and how the binary program is implemented is described online, where you can also learn something about password security in scripts. The very informative blog also discusses the options for subsequently decrypting programs created by SHC.
Hands On
To begin, I take the classic “Hello World” script and output Hello SHC. The command
shc -f hello.sh
will refuse to compile and will output the message: shc: invalid first line in script:… if the first line of your script is not the shebang line:
#! /bin/sh
If you include this line, the build proceeds without complaint. Adding -v to the shc command outputs compilation comments. Table 1 lists some of the most important command-line options.
Table 1:SHC Options and Variables |
||
Option/Variable | Meaning | Function |
---|---|---|
Options |
||
-e <date> |
Expire |
Limits the time in which the program can be run up to the specified date. The date is expected in the format <dd>/<mm>/<yyyy>. After the deadline expires, the following warning is output: …: has expired! |
-m <message> |
Message |
Specifies the message that appears after the expiration set by -e. |
-f <script> |
File |
A mandatory option that references the script SHC needs to build in the argument. |
-i <shell options> |
Inline |
Options passed into Bash and enabled by the binary program when Bash starts. |
-x <command> |
Exec |
The binary program starts the script using an exec, followed by $@ (all command-line options and arguments) by default. |
-l <Option> |
Last |
Defines the last command-line option, normally --, which is also the default. |
-r |
Relax |
Loosens the security settings for compiling so that the binary program will also run on other computers with the same operating system. |
-v |
Verbose |
Displays extensive messages while compiling, which is useful for fault diagnosis. |
-d |
Debug |
Enables debug mode in the binary program. This creates a large amount of additional information about the command-line options, arguments, paths, external programs, and so on. |
-T |
Traceable |
Creates a program that can be traced with strace or the like. |
-h |
Help |
Displays the short help -h message. |
-C |
Copyright license |
Displays the copyright license. |
-A |
Abstract |
Displays brief abstract information and terminates processing without compiling the script. |
Environment Variables |
||
$CC |
C compiler |
Contains the C compiler (cc by default). |
$CFLAGS |
C Flags |
Defines compiler options. |
The source code produced in Listing 4, hello.sh.x.c, is almost 9KB and largely incomprehensible at first glance, but the greater part of it has to do with encrypting the script. The executable program (.x) weighs in at 11KB; this is not exactly small and can cause problems on various platforms.
Listing 4: Hello SHC
# shc -v -f hello.sh shc shll=bash shc [-i]=-c shc [-x]=exec '%s' "$@" shc [-l]= shc opts= shc: cc hello.sh.x.c -o hello.sh.x shc: strip hello.sh.x shc: chmod go-r hello.sh.x
Shell scripts have some special properties that the compiler needs to “understand” and implement, or at least keep. For example, arguments can be passed in to scripts that are used within the scripts as position parameters. SHC has no trouble handling them. This is true even if set -- … reassigns the position parameters.For example, programs generated in Arch Linux and Ubuntu only run on Arch Linux if they are created with the -T option set, which ensures that program flow can be monitored by external diagnostic programs such as strace. On Ubuntu, this option is not required. Binaries generated on either system run on Ubuntu without problems.
The next important point that needs to be clarified in shell scripts is the evaluation of return values (exit codes), which are produced by both internal and external commands and are supported by SHC. In Bash, $? contains the exit code for the last command executed in the foreground; to display this value, type echo $?.
With shell scripts in particular, return values are often used for conditional linking of commands (Listing 5). Short circuit logic is a special case: && connects two commands, the second of which is only evaluated if the first runs without error (i.e., it terminates with a return value of 0). Alternatively, the command that follows the || is only evaluated if the previous command produces an error (i.e., returns a value other than zero). Short circuit tests can be used easily with SHC.
Listing 5: Conditional Logic
true && echo "OK" # OK false && echo "OK" # no output true || echo "OK" # no output false || echo "OK" # OK true || echo "no" && echo "yes" # yes true && echo "yes" || echo "no" # yes
Another cause of concern involves inputs and outputs. Without the addition of dialog programs, the shell provides only very limited options directly associated with the terminal. For example, what happens if the Zenity dialog tool (or the newer variant YAD) is used to accept input – and perhaps also to produce output? As the example below shows, this is no problem:
INPUT=$(yad --entry "input" --editable) ; yad --entry $INPUT
The environment variable $INPUT is set by YAD. The input dialog is initialized in YAD with the string "input", which can be modified or replaced by the user (--editable allows this to happen). Then, the second call to YAD shows the current content of the $INPUT environment variable.
Note that when using external programs, SHC does not integrate them into the binary program but still calls the programs like a script; in other words, the external programs need to exist in $PATH. Absolute paths are also considered when executing the script, and the same applies to calling Bash, which should exist below the expected path.
Alternatives
A web search for shell script encrypt or shell script obfuscate reveals a number of alternatives for concealing the content of shell scripts – aptly implemented as shell scripts in part – that use a variety of ways to make the script code unreadable (e.g., obfsh or ShellCrypt)
Whereas obfsh makes the source illegible by inserting or removing spaces and lines and adding extra “garbage,” ShellCrypt take things a step further: The program creates a truly encrypted program with a .bin extension that only becomes executable again after decryption.
The program needed for decrypting is used as an interpreter (Figure 2). The disadvantage of this method is that the ShellCrypt package always needs to be installed on the executing system. You could use gpg-encrypted scripts in a similar way; they would first need to be symmetrically encrypted (using -c), then they can be decrypted with the -d option and passed to the executing shell.
Conclusions
SHC ranks somewhere between a gadget and a useful tool. Binary programs generated by the compiler are not genuinely secure (i.e., NSA-proof): For one thing, they only work if all the external programs needed in the script are available on the executing computer; for another, you can still reconstruct the original source code with some effort.
The benefits lie in ease of use and the ability to provide protection against accidental changes to scripts. The alternatives to SHC also have special requirements or are even less portable.
Subscribe to our Linux Newsletters
Find Linux and Open Source Jobs
Subscribe to our ADMIN Newsletters
Support Our Work
Linux Magazine content is made possible with support from readers like you. Please consider contributing when you’ve found an article to be beneficial.
News
-
Latest Cinnamon Desktop Releases with a Bold New Look
Just in time for the holidays, the developer of the Cinnamon desktop has shipped a new release to help spice up your eggnog with new features and a new look.
-
Armbian 24.11 Released with Expanded Hardware Support
If you've been waiting for Armbian to support OrangePi 5 Max and Radxa ROCK 5B+, the wait is over.
-
SUSE Renames Several Products for Better Name Recognition
SUSE has been a very powerful player in the European market, but it knows it must branch out to gain serious traction. Will a name change do the trick?
-
ESET Discovers New Linux Malware
WolfsBane is an all-in-one malware that has hit the Linux operating system and includes a dropper, a launcher, and a backdoor.
-
New Linux Kernel Patch Allows Forcing a CPU Mitigation
Even when CPU mitigations can consume precious CPU cycles, it might not be a bad idea to allow users to enable them, even if your machine isn't vulnerable.
-
Red Hat Enterprise Linux 9.5 Released
Notify your friends, loved ones, and colleagues that the latest version of RHEL is available with plenty of enhancements.
-
Linux Sees Massive Performance Increase from a Single Line of Code
With one line of code, Intel was able to increase the performance of the Linux kernel by 4,000 percent.
-
Fedora KDE Approved as an Official Spin
If you prefer the Plasma desktop environment and the Fedora distribution, you're in luck because there's now an official spin that is listed on the same level as the Fedora Workstation edition.
-
New Steam Client Ups the Ante for Linux
The latest release from Steam has some pretty cool tricks up its sleeve.
-
Gnome OS Transitioning Toward a General-Purpose Distro
If you're looking for the perfectly vanilla take on the Gnome desktop, Gnome OS might be for you.