Paranoid Penguin - Limitations of shc, a Shell Encryption Utility

The shell script compiler, shc, obfuscates shell scripts with encryption—but the password is in the encrypted file. Could an intruder recover the original script using objdump?

The first column of the output in listing 3 specifies the starting addresses in hexadecimal, followed by the stored data in the next four columns. The last column represents the stored data in printable characters. So somewhere in the first four columns of the output is the array of characters that form the encryption key (password) and the encrypted shell script. Comparing the original C source code and Listing 3, you can see that the password most likely begins at address 0x804a540. After comparing other executables, I determined that the first address after the zeroes leading the “Please contact your provider” text usually is the starting address. To retrieve these arrays, such as the one depicted in Listing 2, we also need to look at the disassembled code. We use objdump again here, except this time with the -d option, for disassemble, as shown in Listing 4.

The last two columns represent assembly instructions. The movl instruction is used to move data—movl Source, Dest. The Source and Dest are prefixed with $ when referencing a C constant. The push takes a single operand, the data source, and stores it at the top of stack.

Now that we have the basics of objdump, we can proceed to extract the encryption password and eventually the shell code.

In the intermediate C code produced by shc, about nine arrays are referenced by the variables pswd, shll, inlo, xecc, lsto, chk1, opts, txt and chk2. The pswd variable stores the encryption key, and the txt variable stores the encrypted shell text. shc hides the useful information as smaller arrays within these variables. Thus, obtaining the actual array involves two steps. First, identify the length of the array. Second, identify the starting address of the array.

The objdump output needs to be looked at in detail to obtain the actual array length and the starting address. My first hint here is to look for all addresses that are within the data section (Listing 2) of the disassembled object code. Next, seek out all the push and mov commands in Listing 4. Addresses will be different for different scripts, but when you encrypt a few scripts and read the resulting C code, the patterns become familiar.

The 804a540 address seems to correspond to the pswd variable, the encryption key. The length of the useful portion of the encryption key is represented by 0x128, or 296 in decimal form. Similarly, the next variables, shll and inlo, have useful lengths of 0x8 and 0x3 and starting addresses of 804a672 and 804a68a, respectively. This way, we are able to obtain the starting addresses and lengths of all nine variables. Next, we need to be able to decrypt the original shell script using only the binary as input.

In shc, before the shell script itself is encrypted, many other pieces of information are encrypted. Furthermore, the RC4 implementation maintains state between encrypting and decrypting each individual piece of information. This means that the order in which shc encrypts and decrypts information must be maintained. Failure to do so results in illegible text. To extract the original shell script, we need to perform several decryptions. For this step, I wrote a small program called deshc, using the existing code from one of the intermediate C files. The program reads two files as its input, the binary executable and an input file that specifies the array lengths and addresses. deshc executes the following four steps:

  • Reads binary executable.

  • Extracts data section from the disassembled output.

  • Retrieves individual arrays based on input file.

  • Decrypts individual arrays in order, so that the RC4 state is maintained.

Based on the objdump output, I have arrived at the following array lengths and addresses for the pub.sh.x executable:

pswd 0x128 0x804a540
shll 0x8	0x804a672
inlo 0x3 	0x804a68a
xecc 0xf	0x804a68e
lsto 0x1 	0x804a6a4
chk1 0xf 	0x804a6a6
opts 0x1 	0x804a6be
txt  0x76 	0x804a6e0

All of these parameters are used in an input file to deshc, which then decrypts and prints the original shell script.

______________________

Comments

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.

How to work with octave scripts ?

spiriad's picture

How to make it work with octave scripts, knowing the first line in my_octave_script.sh is #! /usr/bin/octave -q
??

Where we can download DESHC

Anonymous's picture

Where we can download DESHC ?

Geek Guide
The DevOps Toolbox

Tools and Technologies for Scale and Reliability
by Linux Journal Editor Bill Childers

Get your free copy today

Sponsored by IBM

Webcast
8 Signs You're Beyond Cron

Scheduling Crontabs With an Enterprise Scheduler
On Demand
Moderated by Linux Journal Contributor Mike Diehl

Sign up and watch now

Sponsored by Skybot