#!/bin/bash
###################
# Author: Luiz Otavio Duarte a.k.a. (LOD)
# 11/03/08 - v.0.1
# Updated: Yann CAM v0.2 - yann.cam@gmail.com | www.asafety.fr
# 06/27/13 - v.0.2
# -- Adding new objdump format (2.22) to retrieve data (especially on Ubuntu distribution)
# -- Patch few regex with sorted address list
# Updated: Yann CAM v0.3 - yann.cam@gmail.com | www.asafety.fr
# 18/11/15 - v.0.3
# -- Adapt script for new architecture
# -- Clean and optimize functions
# -- Add an (unsigned long) cast in shc C source code
# Updated: Yann CAM v0.3 - yann.cam@gmail.com | www.asafety.fr
# 14/12/15 - v.0.4
# -- Comment specific return statement in C source
# Updated: Yann CAM v0.5 - yann.cam@gmail.com | www.asafety.fr
# 15/12/15 - v.0.5
# -- Patch extract arc4 function to keep the latest offset only
# Updated: Yann CAM v0.5 - yann.cam@gmail.com | www.asafety.fr
# 16/12/15 - v.0.6
# -- Add bash script options (getopts)
###################
# Tested on :
# Ubuntu 14.04.3 LTS x86_64
# Linux server 3.13.0-61-generic #100-Ubuntu SMP Wed Jul 29 11:21:34 UTC 2015 x86_64 x86_64 x86_64 GNU/Linux
# Linux version 3.13.0-61-generic (buildd@lgw01-50) (gcc version 4.8.2 (Ubuntu 4.8.2-19ubuntu1) ) #100-Ubuntu SMP Wed Jul 29 11:21:34 UTC 2015
#
# CentOS release 6.6 (Final) x86_64
# Linux server 2.6.32-504.23.4.el6.x86_64 #1 SMP Tue Jun 9 20:57:37 UTC 2015 x86_64 x86_64 x86_64 GNU/Linux
# Linux version 2.6.32-504.23.4.el6.x86_64 (mockbuild@c6b9.bsys.dev.centos.org) (gcc version 4.4.7 20120313 (Red Hat 4.4.7-11) (GCC) ) #1 SMP Tue Jun 9 20:57:37 UTC 2015
#
# Debian 7.8 i686
# Linux server 3.2.0-4-686-pae #1 SMP Debian 3.2.68-1+deb7u2 i686 GNU/Linux
# Linux version 3.2.0-4-686-pae (debian-kernel@lists.debian.org) (gcc version 4.6.3 (Debian 4.6.3-14) ) #1 SMP Debian 3.2.68-1+deb7u2
###################
VERSION="0.5"
OBJDUMP=`whichobjdump`
GREP=`whichgrep`
CUT=`whichcut`
SHRED=`whichshred`
UNIQ=`whichuniq`
SORT=`whichsort`
GCC=`whichgcc`
WC=`whichwc`
AWK=`whichawk`
SED=`whichsed`
TR=`whichtr`
HEAD=`whichhead`
BINARY=""
TMPBINARY=$(mktemp/tmp/XXXXXX)
DUMPFILE=""
STRINGFILE=""
CALLFILE=$(mktemp/tmp/XXXXXX)
CALLADDRFILE=$(mktemp/tmp/XXXXXX)
CALLSIZEFILE=$(mktemp/tmp/XXXXXX)
declare-ALISTOFCALL
# Variable to know the index of variables.
# This var is to loop on each 14 arc4() call with ordered args.
j=0
# Simple usage help / man
functionusage(){
printf"[*] Usage : $0 [OPTIONS] <file.sh.x>\n"
printf"\t -h | --help : print this help message\n"
printf"\t -a OFFSET | --arc4 OFFSET : specify the arc4() offset arbitrarily (without 0x prefix)\n"
printf"\t -d DUMPFILE | --dumpfile DUMPFILE : provide an object dump file (objdump -D script.sh.x > DUMPFILE)\n"
printf"\t -s STRFILE | --stringfile STRFILE : provide a string dump file (objdump -s script.sh.x > STRFILE)\n"
printf"\t -o OUTFILE | --outputfile OUTFILE : indicate the output file name\n\n"
printf"[*] e.g : \n"
printf"\t$0 script.sh.x\n"
printf"\t$0 script.sh.x -o script_decrypted.sh\n"
printf"\t$0 script.sh.x -a 400f9b\n"
printf"\t$0 script.sh.x -d /tmp/dumpfile -s /tmp/strfile\n"
printf"\t$0 script.sh.x -a 400f9b -d /tmp/dumpfile -s /tmp/strfile -o script_decrypted.sh\n"
}
# Clean all temp file created for this script
functionclean(){
$SHRED-zu-n1$DUMPFILE$CALLFILE$CALLADDRFILE$CALLSIZEFILE$STRINGFILE$TMPBINARY${TMPBINARY}.c>/dev/null2>&1
}
# Clean error exit function after cleaning temp file
functionexit_error(){
clean
exit1;
}
# Check the availability of basic commands usefull for this script
functioncheck_binaries(){
if[!-x${OBJDUMP}];then
echo"[-] Error, cannot execute or find objdump binary"
exit_error
fi
if[!-x${GREP}];then
echo"[-] Error, cannot execute or find grep binary"
exit_error
fi
if[!-x${CUT}];then
echo"[-] Error, cannot execute or find cut binary"
exit_error
fi
if[!-x${SHRED}];then
echo"[-] Error, cannot execute or find shred binary"
exit_error
fi
if[!-x${UNIQ}];then
echo"[-] Error, cannot execute or find uniq binary"
exit_error
fi
if[!-x${SORT}];then
echo"[-] Error, cannot execute or find sort binary"
exit_error
fi
if[!-x${GCC}];then
echo"[-] Error, cannot execute or find gcc binary"
exit_error
fi
if[!-x${WC}];then
echo"[-] Error, cannot execute or find wc binary"
exit_error
fi
}
# Create dump files of encrypted script
functiongenerate_dump(){
# DUMPFILE dump to retrive arc4 address, address and size of each arc4 arguments and pwd
$OBJDUMP-D$BINARY>"$DUMPFILE"
# STRINGFILE dump to retrieve pwd and arc4 argument
$OBJDUMP-s$BINARY>"$STRINGFILE"
}
# Find out the most called function. This function is arc4() and there are 14 calls.
# Update 27/06/2013 : Regexps updated to match new objdump format and retrieve the $CALLADDR from his number of call (bug initial with "sort")
# Update 16/11/2015 : Adding new architecture support
functionextract_arc4_call_addr(){
CALLADDR=$($GREP-Eo"call.*[0-9a-f]{6,}"$DUMPFILE|$GREP-Eo"[0-9a-f]{6,}"|$SORT|$UNIQ-c|$SORT|$GREP-Eo"(14).*[0-9a-f]{6,}"|$GREP-Eo"[0-9a-f]{6,}"|tail-n1)
if[-z"$CALLADDR"];then
echo"[-] Unable to define arc4() call address..."
exit_error
fi
echo"[+] ARC4 address call defined : [0x$CALLADDR]"
}
# Extract each args values of arc4 calls
functionextract_variables_from_binary(){
echo"[*] Extracting each args address and size for the 14 arc4() calls..."
# Initialize the number of line before CALLADDR to looking for addresses of args
i=2
# Retrieve ordered list of address var and put it to $CALLADDRFILE
while[[$($WC-l<$CALLADDRFILE)-ne14]];do
$GREP-B$i"call.*$CALLADDR"$DUMPFILE|$GREP-v"$CALLADDR"|$GREP-Eo"(0x[0-9a-f]{6,})">$CALLADDRFILE
i=$(($i+1))
if[$i-eq10];then
echo"[-] Unable to extract addresses of 14 arc4 args..."
exit_error
fi
done
# Initialize the number of line before CALLADDR to looking for sizes of args
i=3
# Retrieve ordered list of size var and append it to $CALLSIZEFILE
while[[$($WC-l<$CALLSIZEFILE)-ne14]];do
$GREP-B$i"call.*$CALLADDR"$DUMPFILE|$GREP-v"$CALLADDR"|$GREP-Eo"(0x[0-9a-f]+,)"|$GREP-Eo"(0x[0-9a-f]+)"|$GREP-Ev"0x[0-9a-f]{6,}">$CALLSIZEFILE
i=$(($i+1))
if[$i-eq10];then
echo"[-] Unable to extract sizes of 14 arc4 args..."
exit_error
fi
done
#cat $CALLADDRFILE
#cat $CALLSIZEFILE
# For each full address in $CALLADDRFILE and corresponding size in $CALLSIZEFILE
IFS=$'\n'read-d''-r-aLISTOFADDR<$CALLADDRFILE
IFS=$'\n'read-d''-r-aLISTOFSIZE<$CALLSIZEFILE
for((x=0;x<${#LISTOFADDR[*]};x=x+1))
do
i=${LISTOFADDR[$x]}
NBYTES=${LISTOFSIZE[$x]}
echo-e"\t[$x] Working with var address at offset [$i] ($NBYTES bytes)"
# Some diferences in assembly.
# We can have:
# mov <adr>,%eax
# push 0x<hex>
# push %eax
# call $CALLADDR
#
# or
#
# push 0x<hex>
# push 0x<adr>
# call $CALLADDR
#
# UPDATE 27/06/2013 :
# Adding support of objdump format
# New format supported (Debian 7 x86) :
#
# movl $0x<hex>,0x4(%esp)
#
# movl $0x<adr>,(%esp)
# call $CALLADDR
#
# UPDATE 18/11/2015 :
# Adding support of objdump format
# Ubuntu 14.04 LTS x86_64
#
# mov $0x<hex>,%esi
# mov $0x<adr>,%edi
# callq $CALLADDR <fork@plt+0x23b>
#
# Key is the address with the variable content.
KEY=$(echo$i|$CUT-d'x'-f2)
# A 2 bytes variable (NBYTES > 0) can be found like this: (in STRINGFILE)
# ---------------X
# X---------------
#
# So we need 2 lines from STRINGFILE to make it all correct. So:
NLINES=$((($NBYTES/16)+2))
# All line in STRINGFILE starts from 0 to f. So LASTBIT tells me the index in the line to start recording.
letLASTBYTE="0x${KEY:$((${#KEY}-1))}"
# Grep all lines needed from STRINGFILE, merge lines.
STRING=$($GREP-A$(($NLINES-1))-E"^ ${KEY:0:$((${#KEY}-1))}0 "$STRINGFILE|$AWK'{ print $2$3$4$5}'|$TR'\n''T'|$SED-e"s:T::g")
# Change string to begin in the line index.
STRING=${STRING:$((2*$LASTBYTE))}
# Cut the string to the number off bytes of the variable.
STRING=${STRING:0:$(($NBYTES*2))}
# We need to convert to a \x??\x?? structure so:
FINALSTRING=""
for((i=0;i<$((${#STRING}/2));i++));do
FINALSTRING="${FINALSTRING}\x${STRING:$(($i * 2)):2}"
done
define_variable
done
}
# arc4 function is called 14 times in the C code.
# Each call is done with the same args sequence even if their declaration is randomized :
# msg1, date, shll, inlo, xecc, lsto, tst1, chk1, msg2, rlax, opts, text, tst2 and chk2.
functiondefine_variable(){
case"$j"in
0) VAR_MSG1=$FINALSTRING
VAR_MSG1_Z=$NBYTES;;
1) VAR_DATE=$FINALSTRING
VAR_DATE_Z=$NBYTES;;
2) VAR_SHLL=$FINALSTRING
VAR_SHLL_Z=$NBYTES;;
3) VAR_INLO=$FINALSTRING
VAR_INLO_Z=$NBYTES;;
4) VAR_XECC=$FINALSTRING
VAR_XECC_Z=$NBYTES;;
5) VAR_LSTO=$FINALSTRING
VAR_LSTO_Z=$NBYTES;;
6) VAR_TST1=$FINALSTRING
VAR_TST1_Z=$NBYTES;;
7) VAR_CHK1=$FINALSTRING
VAR_CHK1_Z=$NBYTES;;
8) VAR_MSG2=$FINALSTRING
VAR_MSG2_Z=$NBYTES;;
9) VAR_RLAX=$FINALSTRING
VAR_RLAX_Z=$NBYTES;;
10) VAR_OPTS=$FINALSTRING
VAR_OPTS_Z=$NBYTES;;
11) VAR_TEXT=$FINALSTRING
VAR_TEXT_Z=$NBYTES;;
12) VAR_TST2=$FINALSTRING
VAR_TST2_Z=$NBYTES;;
13) VAR_CHK2=$FINALSTRING
VAR_CHK2_Z=$NBYTES;;
esac
j=$(($j+1))
}
# The password is used in the key function right before first call to arc4.
# So we need the previous call just before the first "call ARC4_CALLADDR" and its args.
# Update 27/06/2013 : Add new objdump format
# Update 18/11/2015 : Simplify extraction
functionextract_password_from_binary(){
echo"[*] Extracting password..."
KEY_ADDR=""
KEY_SIZE=""
# Initialize the number of line before CALLADDR to watch
i=5
while[[(-z"$KEY_ADDR")||(-z"$KEY_SIZE")]];do
$GREP-B$i-m1"call.*$CALLADDR"$DUMPFILE|$GREP-v$CALLADDR>$CALLFILE
#cat $CALLFILE
# Adjust these two next line to grep right addr & size value (depending on your architecture)
KEY_ADDR=$($GREP-B3-m1"call"$CALLFILE|$GREPmov|$GREP-oE"0x[0-9a-z]{6,}+"|$HEAD-n1)
KEY_SIZE=$($GREP-B3-m1"call"$CALLFILE|$GREPmov|$GREP-v$KEY_ADDR|$GREP-oE"0x[0-9a-z]+"|$HEAD-n1)
i=$(($i+1))
if[$i-eq10];then
echo"[-] Error, function call previous first call of arc4() hasn't been identified..."
exit_error
fi
done
echo-e"\t[+] PWD address found : [$KEY_ADDR]"
echo-e"\t[+] PWD size found : [$KEY_SIZE]"
# Defining the address without 0x.
KEY=$(echo$KEY_ADDR|$CUT-d'x'-f2)
# Like the other NLINES
NLINES=$((($KEY_SIZE/16)+2))
# Like the other LASTBYTE
LASTBYTE="0x${KEY:$((${#KEY}-1))}"
# Extract PWD from STRINGFILE
STRING=$($GREP-A$(($NLINES-1))-E"^ ${KEY:0:$((${#KEY}-1))}0 "$STRINGFILE|$AWK'{ print $2$3$4$5}'|$TR'\n''T'|$SED-e"s:T::g")
STRING=${STRING:$((2*$LASTBYTE))}
STRING=${STRING:0:$(($KEY_SIZE*2))}
# Encode / rewrite PWD in the \x??\x?? format
FINALSTRING=""
for((i=0;i<$((${#STRING}/2));i++));do
FINALSTRING="${FINALSTRING}\x${STRING:$(($i * 2)):2}"
done
VAR_PSWD=$FINALSTRING
}
# This function append a generic engine for decrypt from shc project. With out own new variables extracted.
# Rather than execute the source code decrypted, it's printed in stdout.
functiongeneric_file(){
cat>${TMPBINARY}.c<<EOF
#define msg1_z $VAR_MSG1_Z
#define date_z $VAR_DATE_Z
#define shll_z $VAR_SHLL_Z
#define inlo_z $VAR_INLO_Z
#define xecc_z $VAR_XECC_Z
#define lsto_z $VAR_LSTO_Z
#define tst1_z $VAR_TST1_Z
#define chk1_z $VAR_CHK1_Z
#define msg2_z $VAR_MSG2_Z
#define rlax_z $VAR_RLAX_Z
#define opts_z $VAR_OPTS_Z
#define text_z $VAR_TEXT_Z
#define tst2_z $VAR_TST2_Z
#define chk2_z $VAR_CHK2_Z
#define pswd_z $KEY_SIZE
staticcharmsg1[]="$VAR_MSG1";
staticchardate[]="$VAR_DATE";
staticcharshll[]="$VAR_SHLL";
staticcharinlo[]="$VAR_INLO";
staticcharxecc[]="$VAR_XECC";
staticcharlsto[]="$VAR_LSTO";
staticchartst1[]="$VAR_TST1";
staticcharchk1[]="$VAR_CHK1";
staticcharmsg2[]="$VAR_MSG2";
staticcharrlax[]="$VAR_RLAX";
staticcharopts[]="$VAR_OPTS";
staticchartext[]="$VAR_TEXT";
staticchartst2[]="$VAR_TST2";
staticcharchk2[]="$VAR_CHK2";
staticcharpswd[]="$VAR_PSWD";
#define hide_z 4096
/*rtc.c*/
#include <sys/stat.h>
#include <sys/types.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h>
/*'Alleged RC4'*/
staticunsignedcharstte[256],indx,jndx,kndx;
/*
*Resetarc4stte.
*/
voidstte_0(void)
{
indx=jndx=kndx=0;
do{
stte[indx]=indx;
}while(++indx);
}
/*
*Setkey.Canbeusedmorethanonce.
*/
voidkey(void*str,intlen)
{
unsignedchartmp,*ptr=(unsignedchar*)str;
while(len>0){
do{
tmp=stte[indx];
kndx+=tmp;
kndx+=ptr[(int)indx%len];
stte[indx]=stte[kndx];
stte[kndx]=tmp;
}while(++indx);
ptr+=256;
len-=256;
}
}
/*
*Cryptdata.
*/
voidarc4(void*str,intlen)
{
unsignedchartmp,*ptr=(unsignedchar*)str;
while(len>0){
indx++;
tmp=stte[indx];
jndx+=tmp;
stte[indx]=stte[jndx];
stte[jndx]=tmp;
tmp+=stte[indx];
*ptr^=stte[tmp];
ptr++;
len--;
}
}
/*EndofARC4*/
/*
*Keywithfileinvariants.
*/
intkey_with_file(char*file)
{
structstatstatf[1];
structstatcontrol[1];
if(stat(file,statf)<0)
return-1;
/*Turnonstablefields*/
memset(control,0,sizeof(control));
control->st_ino=statf->st_ino;
control->st_dev=statf->st_dev;
control->st_rdev=statf->st_rdev;
control->st_uid=statf->st_uid;
control->st_gid=statf->st_gid;
control->st_size=statf->st_size;
control->st_mtime=statf->st_mtime;
control->st_ctime=statf->st_ctime;
key(control,sizeof(control));
return0;
}
voidrmarg(char**argv,char*arg)
{
for(;argv&&*argv&&*argv!=arg;argv++);
for(;argv&&*argv;argv++)
*argv=argv[1];
}
//Update18/11/2015:Update"mask"castingfrom"unsigned"to"unsigned long".
intchkenv(intargc)
{
charbuff[512];
unsignedmask,m;
intl,a,c;
char*string;
externchar**environ;
mask =(unsignedlong)chkenv;
mask^=(unsigned)getpid()*~mask;
sprintf(buff,"x%x",mask);
string=getenv(buff);
l=strlen(buff);
if(!string){
/*1st*/
sprintf(&buff[l],"=%u %d",mask,argc);
putenv(strdup(buff));
return0;
}
c=sscanf(string,"%u %d%c",&m,&a,buff);
if(c==2&&m==mask){
/*3rd*/
rmarg(environ,&string[-l-1]);
return1+(argc-a);
}
return-1;
}
char*xsh(intargc,char**argv)
{
char*scrpt;
intret,i,j;
char**varg;
stte_0();
key(pswd,pswd_z);
arc4(msg1,msg1_z);
arc4(date,date_z);
//if(date[0]&&date[0]<time(NULL))
// returnmsg1;
arc4(shll,shll_z);
arc4(inlo,inlo_z);
arc4(xecc,xecc_z);
arc4(lsto,lsto_z);
arc4(tst1,tst1_z);
key(tst1,tst1_z);
arc4(chk1,chk1_z);
if((chk1_z!=tst1_z)||memcmp(tst1,chk1,tst1_z))
returntst1;
ret=chkenv(argc);
arc4(msg2,msg2_z);
if(ret<0)
returnmsg2;
varg=(char**)calloc(argc+10,sizeof(char*));
if(!varg)
return0;
if(ret){
arc4(rlax,rlax_z);
if(!rlax[0]&&key_with_file(shll))
returnshll;
arc4(opts,opts_z);
arc4(text,text_z);
printf("%s",text);
return0;
/*arc4(tst2,tst2_z);
key(tst2,tst2_z);
arc4(chk2,chk2_z);
if((chk2_z!=tst2_z)||memcmp(tst2,chk2,tst2_z))
returntst2;
if(text_z<hide_z){
scrpt=malloc(hide_z);
if(!scrpt)
return0;
memset(scrpt,(int)' ',hide_z);
memcpy(&scrpt[hide_z-text_z],text,text_z);
}else{
scrpt=text;
}*/
}else{
if(*xecc){
scrpt=malloc(512);
if(!scrpt)
return0;
sprintf(scrpt,xecc,argv[0]);
}else{
scrpt=argv[0];
}
}
j=0;
varg[j++]=argv[0]; /*Myownnameatexecution*/
if(ret&&*opts)
varg[j++]=opts; /*Optionson1stlineofcode*/
if(*inlo)
varg[j++]=inlo; /*Optionintroducinginlinecode*/
varg[j++]=scrpt; /*Thescriptitself*/
if(*lsto)
varg[j++]=lsto; /*Optionmeaninglastoption*/
i=(ret>1)?ret:0; /*Argsnumberingcorrection*/
while(i<argc)
varg[j++]=argv[i++]; /*Mainrun-timearguments*/
varg[j]=0; /*NULLterminatedarray*/
execvp(shll,varg);
returnshll;
}
intmain(intargc,char**argv)
{
argv[1]=xsh(argc,argv);
return1;
}
EOF
}
##########################################
## Starting
echo" _ _ _____ _ _ "
echo"| | | | / ___| | | | "
echo"| | | |_ __ \ `--.| |_| | ___ "
echo"| | | | '_ \ `--. \ _ |/ __|"
echo"| |_| | | | /\__/ / | | | (__ "
echo" \___/|_| |_\____/\_| |_/\___|"
echo
echo"--- UnSHc - The shc decrypter."
echo"--- Version: $VERSION"
echo"------------------------------"
echo"UnSHc is used to decrypt script encrypted with SHc"
echo"Original idea from Luiz Octavio Duarte (LOD)"
echo"Updated and modernized by Yann CAM"
echo"- SHc : [http://www.datsi.fi.upm.es/~frosal/]"
echo"- UnSHc : [https://www.asafety.fr/unshc-the-shc-decrypter/]"
echo"------------------------------"
echo
if[$# -lt 1 ]; then
echo"[?] Type -h or --help for how to use it"
clean
exit0
fi
# Check the availability of each command needed in this script.
check_binaries
OPTS=$(getopt-oh,a:,d:,s:,o:-lhelp,arc4:,dumpfile:,stringfile:,outputfile:--"$@")
if[$?!=0];then
exit_error;
fi
while["$#"-gt0];do
case"$1"in
-h|--help)
usage;
clean;
exit0;;
-a|--arc4)
echo"[+] ARC4() offset function call address specified [0x$2]";
CALLADDR=$2;
shift2;;
-d|--dumpfile)
echo"[+] Object dump file specified [$2]";
DUMPFILE=$2;
shift2;;
-s|--stringfile)
echo"[+] String dump file specified [$2]";
STRINGFILE=$2;
shift2;;
-o|--outputfile)
echo"[+] Output file name specified [$2]";
OUTPUTFILE=$2;
shift2;;
-*)
echo"[-] Unknown option: [$1]">&2;
exit_error;;
--)
shift;
break;;
*)
echo"[*] Input file name to decrypt [$1]";
BINARY=$1
shift1;;
esac
done
if[!-e$BINARY];then
echo"[-] Error, File [$BINARY] not found."
exit_error
fi
if[-z"$DUMPFILE"];then
DUMPFILE=$(mktemp/tmp/XXXXXX)
else
if[!-e$DUMPFILE];then
echo"[-] Object dump file [$DUMPFILE] not found."
exit_error;
fi
fi
if[-z"$STRINGFILE"];then
STRINGFILE=$(mktemp/tmp/XXXXXX)
else
if[!-e$STRINGFILE];then
echo"[-] String dump file [$STRINGFILE] not found."
exit_error;
fi
fi
# Fill DUMPFILE and STRINGFILE from objdump of the *.sh.x encrypted script
generate_dump
# Find out the most called function. This function is arc4() and there are 14 calls.
if[-z"$CALLADDR"];then
extract_arc4_call_addr
fi
# Retrieve the data used in each CALLADDR call
extract_variables_from_binary
# Retrieve PWD from function call just before the first CALLADDR call
extract_password_from_binary
# Create a C source code to decrypt *.sh.x file with previously extracted data
generic_file
# Compile C source code to decrypt *.sh.x file
$GCC-o$TMPBINARY${TMPBINARY}.c>/dev/null2>&1
echo"[*] Executing [$TMPBINARY] to decrypt [${BINARY}]"
if[-z"$OUTPUTFILE"];then
echo"[*] Retrieving initial source code in [${BINARY%.x}]"
$TMPBINARY>${BINARY%.x}
else
echo"[*] Retrieving initial source code in [$OUTPUTFILE]"
$TMPBINARY>$OUTPUTFILE
fi
echo"[*] All done!"
clean
exit0