The Complete Magazine on Open Source

SHC Shell Script Compiler: An Introduction

, / 632 3

Bash Shell illustration

The generic shell script compiler (SHC) can hide source code, which is useful in preventing accidental erasures, alterations and deliberate, mischievous and malicious tampering. It also converts shell scripts directly into binaries.

Often, we need to hide shell script code to prevent unintentional modification and hide sensitive information in scripts like passwords. There are tools such as obfsh and shellcrypt available to hide source code.
SHC stands for the generic shell script compiler. Created by Francisco Javier Rosales García, it converts shell scripts directly into binaries, compiles scripts, hides source code, protects against accidental changes and hides sensitive data in script.

How it works
SHC creates a stripped binary executable version of the script specified with -f on the command line. The binary version will get a .x extension appended, and will usually be a bit larger in size than the original ASCII code. Generated C source code is saved in a file with the extension .x.c.

Here, I have chosen the Centos 6.7 version (equivalent: RHEL 6.7) with minimal installation in the virtual box. To install the required packages for compiling SHC from the source code, execute the command below on a terminal with root privileges:

#yum groupinstall “Development Tools”

Or, give the following command:

#yum install make gcc gcc-c++ kernel-devel
Figure 1

Figure 1: How shc works

Download the latest source code tar package for shc, for that first install wget package:

#yum install wget
#cd /usr/local/src
# wget -c

Extract the tar package:

#tar -zvxf shc-3.8.9b.tgz
#cd shc-3.8.9b

To compile SHC, execute the make command, as follows:

[root@test shc-3.8.9b]# make
cc -Wall shc.c -o shc
*** ¿Do you want to probe shc with a test script?
*** Please try... make test

To install the SHC binary, execute the commands below:

[root@test shc-3.8.9b]# make install
*** Installing shc and shc.1 on /usr/local
*** ¿Do you want to continue? y

<<——–Press Y

install -c -s shc /usr/local/bin/
install -c -m 644 shc.1 /usr/local/man/man1/
install: target `/usr/local/man/man1/’ is not a directory: No such file or directory
make: *** [install] Error 1

It will show an error message, as the minimal installation default man package is not installed. You can ignore it, install the man package or create the /usr/local/man/man1/ directory, and again execute the make install command.

[root@test shc-3.8.9b]# make install
*** Installing shc and shc.1 on /usr/local
*** ¿Do you want to continue? y <<--------------Press Y
install -c -s shc /usr/local/bin/
install -c -m 644 shc.1 /usr/local/man/man1/

cross check that shc is installed properly

[root@test shc-3.8.9b]# which shc

It will display the path of the SHC binary.

Table 1

Table 1: SHC options and variables

Hands-on usage of SHC
1. Creating a test shell script
First, create the test shell script that you are going to use to encrypt. Let’s create a script for testing purposes, which will display a simple ‘Welcome to the Linux world’ message, as follows:

echo "Welcome to linux world"

save using: wq

2. Encrypting using SHC
Encrypt the shell scripting using SHC, as shown below:

[root@test src]# shc -v -f
shc shll=sh
shc [-i]=-c
shc [-x]=exec ‘%s’ “$@”
shc [-l]=
shc opts=
shc: cc -o
shc: strip
shc: chmod go-r

This will create two extra files, as shown below:

[root@test src]# ll*
-rw-r--r--. 1 root root 40 Dec 16 04:39
-rwx--x--x. 1 root root 11552 Dec 16 05:23
-rw-r--r--. 1 root root 9236 Dec 16 05:23
  • is the original unencrypted shell script
  • is the encrypted shell script in binary format
  • is the C source code of the file. This C source code is compiled to create the above encrypted file.

3. Executing the encrypted shell script
Now, let us execute the encrypted shell script to make sure it works as expected.

[root@test src]# ./
Welcome to Linux World

Please note that the binary itself is dependent on the shell (the first line provided in, i.e., /bin/sh) is available to execute the script.
4. Setting an expiry date to the encrypted shell script
Using SHC, you can also specify an expiry date. When somebody tries to execute the shell script after this date, they’ll get an error message.
If you don’t want anybody to execute the after December 31, 2014 (I used an earlier year’s date for testing purposes), create a new encrypted shell script using the shc -e option to specify the expiry date, which needs to be specified in the dd/mm/yyyy format.

[root@test src]# shc -e 31/12/2014 -f

In this example, if someone tries to execute after December 31, 2014, they’ll get a default expiry message as shown below:

[root@test src]# ./
./ has expired!
Please contact your provider

To display custom expiration messages, use the -m option (along with the -e option as shown below):

[root@test src]# shc -e 31/12/2014 -m “Contact for new version of this script” -f
[root@test src]# ./
./ has expired!

Contact for new version of this script.

5. Creating redistributable encrypted shell scripts
You can create redistributable encrypted shell scripts using the -r (relax security) and -T (traceable using strace) options:

[root@test src]# shc -v -r -T -f
shc shll=sh
shc [-i]=-c
shc [-x]=exec ‘%s’ “$@”
shc [-l]=
shc opts=
shc: cc -o
shc: strip
shc: chmod go-r


  • Martin Bruchanov

    It is not hiding sensitive data at all!!!

    When you run compiled schell script and get a list of processes with ps xaf, you can see whole source code of script, e. g.:

    ./test.bash.x -x -c #!/bin/bash -x echo “$@ is $@” echo “command line: $0 $*” echo “hello world” # Added echo “[$$] PAUSED… Hit return!” read DUMMY exit 0 ./test.bash.x

    Also /proc/…/cmdline shows the same.

    And memory dump of that process has also shell script clearly visible:

    00007660 23 21 2f 62 69 6e 2f 62 61 73 68 20 2d 78 0a 65 |#!/bin/bash -x.e|
    00007670 63 68 6f 20 22 5c 24 40 20 69 73 20 24 40 22 0a |cho “$@ is $@”.|
    00007680 65 63 68 6f 20 22 63 6f 6d 6d 61 6e 64 20 6c 69 |echo “command li|
    00007690 6e 65 3a 20 24 30 20 24 2a 22 0a 65 63 68 6f 20 |ne: $0 $*”.echo |
    000076a0 22 68 65 6c 6c 6f 20 77 6f 72 6c 64 22 0a 23 20 |”hello world”.# |
    000076b0 41 64 64 65 64 0a 65 63 68 6f 20 22 5b 24 24 5d |Added.echo “[$$]|
    000076c0 20 50 41 55 53 45 44 2e 2e 2e 20 48 69 74 20 72 | PAUSED… Hit r|
    000076d0 65 74 75 72 6e 21 22 0a 72 65 61 64 20 44 55 4d |eturn!”.read DUM|
    000076e0 4d 59 0a 65 78 69 74 20 30 0a 00 00 00 00 00 00 |MY.exit 0

  • sourav

    what if i wanted to compile dependent sh files at the same time. What I mean to say is that two shell script file executed one after another.

  • xdata

    useless easily can be decompile in Ida pro or GDB and can be patched for extended time.