当前位置:   article > 正文

Linux shell加密解密方法(gzexe、shc)_shell脚本解密

shell脚本解密

一、系统自带gzexe

gzexe无需安装任何软件,是linux自带的功能,只需要执行命令即可,我们可以利用wget将文件放在root目录下,也可以通过sftp放在root目录,也可以直接利用cd命令选择任意目录

加密方法

假如说我们当前目录下有个脚本名字叫test.sh
那我们就执行下面的方法进行加密

gzexe test.sh

此时在目录下就会产生一个test.sh~文件,该文件是源文件,test.sh是加密后的文件
(注意:执行加密的文件跟执行源文件没有区别)

解密方法

假如说我们这个脚本名字叫test.sh
那我们就执行如下命令进行解密

gzexe -d test.sh

同上,在目录下就会产生一个test.sh~文件,该文件是源文件,test.sh是解密后的文件

二、shc加密软件

shc是linux的一款加密脚本的插件,东西比较安全,shc官网:http://www.datsi.fi.upm.es/%7Efrosal/

安装方法

执行如下脚本安装shc

  1. wget https://www.datsi.fi.upm.es/%7Efrosal/sources/shc-3.8.9.tgz
  2. tar vxf shc-3.8.9.tgz
  3. cd shc-3.8.9
  4. mkdir -p /usr/local/man/man1
  5. make install

如果不执行mkdir -p /usr/local/man/man1将会报如下错误

*** Installing shc and shc.1 on /usr/local *** ?Do you want to continue? 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

shc常用参数:

-e date (指定过期日期)

-m message (指定过期提示的信息)

-f script_name(指定要编译的shell的路径及文件名)

-r Relax security. (可以相同操作系统的不同系统中执行)

-v Verbose compilation(编译的详细情况)

加密方法

假如说我们这个脚本名字叫test.sh

那我们就执行如下命令进行加密

shc -v -f test.sh

-v 是现实加密过程

-f 后面跟需要加密的文件

abc.sh.x为加密后的二进制文件,赋予执行权限后,可直接执行。更改名字mv vpsps.sh.x vpspscom.sh

abc.sh.x.c 是c源文件。基本没用,可以删除

过期加密法

另shc还提供了一种设定有效执行期限的方法,过期时间,如:

# shc -e 14/09/2016 -m -f test.sh

选项“-e”指定过期时间,格式为“日/月/年”;选项“-m”指定过期后执行此Shell程序的提示信息。

如果在过期后执行,则会有如下提示:

  1. # ./abc.sh.x
  2. ./abc.sh.x: has expired!(文件已经过期)

使用以上方法要注意,需防止用户更改系统时间,可以通过在程序中加入自动更新系统时间的命令来解决此问题。测试都已通过!

解密方法

利用unshc来解密
网址:https://github.com/yanncam/UnSHc/

unshc使用方法

将unshc wget或者上传到任意目录
然后可执行如下命令查看帮助

./unshc.sh -h

执行下面的命令进行解密(此过程可能耗时有点长,需耐心等待)

./unshc.sh script.sh.x -o script_decrypted.sh

script.sh.x文件为经过加密的二进制文件 script_decrypted.sh文件为解密后shell脚本

github.com/yanncam/UnSHc/blob/master/release/0.8/unshc-v0.8.sh

可以将下面的代码保存成unshc.sh文件即可,给可执行权限后(chmod 777 unshc.sh),直接使用

  1. #!/bin/bash
  2. ###################
  3. # Author: Luiz Otavio Duarte a.k.a. (LOD)
  4. # 11/03/08 - v0.1
  5. # Updated: Yann CAM v0.2 - yann.cam@gmail.com | www.asafety.fr
  6. # 06/27/13 - v0.2
  7. # -- Adding new objdump format (2.22) to retrieve data (especially on Ubuntu distribution)
  8. # -- Patch few regex with sorted address list
  9. # Updated: Yann CAM v0.3 - yann.cam@gmail.com | www.asafety.fr
  10. # 18/11/15 - v0.3
  11. # -- Adapt script for new architecture
  12. # -- Clean and optimize functions
  13. # -- Add an (unsigned long) cast in shc C source code
  14. # Updated: Yann CAM v0.4 - yann.cam@gmail.com | www.asafety.fr
  15. # 14/12/15 - v0.4
  16. # -- Comment specific return statement in C source
  17. # Updated: Yann CAM v0.5 - yann.cam@gmail.com | www.asafety.fr
  18. # 15/12/15 - v0.5
  19. # -- Patch extract arc4 function to keep the latest offset only
  20. # Updated: Yann CAM v0.6 - yann.cam@gmail.com | www.asafety.fr
  21. # 16/12/15 - v0.6
  22. # -- Add bash script options (getopts)
  23. # Updated: Yann CAM v0.7 - yann.cam@gmail.com | www.asafety.fr
  24. # 07/28/16 - v0.7
  25. # -- Add support of multiple ARC4 offsets auto-retrieved by script (iterate over each one), specialy for huge bash file encrypted
  26. # -- Force .sh extension to decrypted file, for initial file without extension (prevent rewrite of original file)
  27. # Updated: Yann CAM v0.8 - yann.cam@gmail.com | www.asafety.fr
  28. # 01/23/17 - v0.8
  29. # -- Adjust grep for retrieve PWD_SIZE in OBJDUMP to ignore movb instruction (https://github.com/yanncam/UnSHc/issues/12)
  30. ###################
  31. # Tested on :
  32. # Ubuntu 14.04.3 LTS x86_64
  33. # 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
  34. # 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
  35. #
  36. # CentOS release 6.6 (Final) x86_64
  37. # 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
  38. # 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
  39. #
  40. # Debian 7.8 i686
  41. # Linux server 3.2.0-4-686-pae #1 SMP Debian 3.2.68-1+deb7u2 i686 GNU/Linux
  42. # 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
  43. ###################
  44. VERSION="0.8"
  45. OBJDUMP=`which objdump`
  46. GREP=`which grep`
  47. CUT=`which cut`
  48. SHRED=`which shred`
  49. UNIQ=`which uniq`
  50. SORT=`which sort`
  51. GCC=`which gcc`
  52. WC=`which wc`
  53. AWK=`which awk`
  54. SED=`which sed`
  55. TR=`which tr`
  56. HEAD=`which head`
  57. TAIL=`which tail`
  58. BINARY=""
  59. TMPBINARY=$(mktemp /tmp/XXXXXX)
  60. DUMPFILE=""
  61. STRINGFILE=""
  62. CALLFILE=$(mktemp /tmp/XXXXXX)
  63. CALLADDRFILE=$(mktemp /tmp/XXXXXX)
  64. CALLSIZEFILE=$(mktemp /tmp/XXXXXX)
  65. declare -A LISTOFCALL
  66. # Variable to know the index of variables.
  67. # This var is to loop on each 14 arc4() call with ordered args.
  68. j=0
  69. # Simple usage help / man
  70. function usage(){
  71. printf "[*] Usage : $0 [OPTIONS] <file.sh.x>\n"
  72. printf "\t -h | --help : print this help message\n"
  73. printf "\t -a OFFSET | --arc4 OFFSET : specify the arc4() offset arbitrarily (without 0x prefix)\n"
  74. printf "\t -d DUMPFILE | --dumpfile DUMPFILE : provide an object dump file (objdump -D script.sh.x > DUMPFILE)\n"
  75. printf "\t -s STRFILE | --stringfile STRFILE : provide a string dump file (objdump -s script.sh.x > STRFILE)\n"
  76. printf "\t -o OUTFILE | --outputfile OUTFILE : indicate the output file name\n\n"
  77. printf "[*] e.g : \n"
  78. printf "\t$0 script.sh.x\n"
  79. printf "\t$0 script.sh.x -o script_decrypted.sh\n"
  80. printf "\t$0 script.sh.x -a 400f9b\n"
  81. printf "\t$0 script.sh.x -d /tmp/dumpfile -s /tmp/strfile\n"
  82. printf "\t$0 script.sh.x -a 400f9b -d /tmp/dumpfile -s /tmp/strfile -o script_decrypted.sh\n"
  83. }
  84. # Clean all temp file created for this script
  85. function clean(){
  86. $SHRED -zu -n 1 $DUMPFILE $CALLFILE $CALLADDRFILE $CALLSIZEFILE $STRINGFILE $TMPBINARY ${TMPBINARY}.c >/dev/null 2>&1
  87. }
  88. # Clean error exit function after cleaning temp file
  89. function exit_error(){
  90. clean
  91. exit 1;
  92. }
  93. # Check the availability of basic commands usefull for this script
  94. function check_binaries() {
  95. if [ ! -x ${OBJDUMP} ]; then
  96. echo "[-] Error, cannot execute or find objdump binary"
  97. exit_error
  98. fi
  99. if [ ! -x ${GREP} ]; then
  100. echo "[-] Error, cannot execute or find grep binary"
  101. exit_error
  102. fi
  103. if [ ! -x ${CUT} ]; then
  104. echo "[-] Error, cannot execute or find cut binary"
  105. exit_error
  106. fi
  107. if [ ! -x ${SHRED} ]; then
  108. echo "[-] Error, cannot execute or find shred binary"
  109. exit_error
  110. fi
  111. if [ ! -x ${UNIQ} ]; then
  112. echo "[-] Error, cannot execute or find uniq binary"
  113. exit_error
  114. fi
  115. if [ ! -x ${SORT} ]; then
  116. echo "[-] Error, cannot execute or find sort binary"
  117. exit_error
  118. fi
  119. if [ ! -x ${GCC} ]; then
  120. echo "[-] Error, cannot execute or find gcc binary"
  121. exit_error
  122. fi
  123. if [ ! -x ${WC} ]; then
  124. echo "[-] Error, cannot execute or find wc binary"
  125. exit_error
  126. fi
  127. }
  128. # Create dump files of encrypted script
  129. function generate_dump() {
  130. # DUMPFILE dump to retrive arc4 address, address and size of each arc4 arguments and pwd
  131. $OBJDUMP -D $BINARY > "$DUMPFILE"
  132. # STRINGFILE dump to retrieve pwd and arc4 argument
  133. $OBJDUMP -s $BINARY > "$STRINGFILE"
  134. }
  135. # Find out the most called function. This function is arc4() and there are 14 calls.
  136. # Update 27/06/2013 : Regexps updated to match new objdump format and retrieve the $CALLADDR from his number of call (bug initial with "sort")
  137. # Update 16/11/2015 : Adding new architecture support
  138. # Update 28/07/2016 : Adding multiple ARC4 offsets support (loop on each candidate)
  139. function extract_arc4_call_addr(){
  140. TAILNUMBER=$1
  141. CALLADDRS=$($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,}")
  142. TAILMAX=`wc -l <<< "$CALLADDRS"`
  143. CALLADDR=$(echo $CALLADDRS | $SED "s/ /\n/g" | $TAIL -n $TAILNUMBER | $HEAD -n 1)
  144. if [[ -z "$CALLADDR" || $TAILNUMBER -gt $TAILMAX ]]; then
  145. echo "[-] Unable to define arc4() call address..."
  146. exit_error
  147. fi
  148. echo "[+] ARC4 address call candidate : [0x$CALLADDR]"
  149. }
  150. # Extract each args values of arc4 calls
  151. function extract_variables_from_binary(){
  152. echo "[*] Extracting each args address and size for the 14 arc4() calls with address [0x$CALLADDR]..."
  153. # Initialize the number of line before CALLADDR to looking for addresses of args
  154. i=2
  155. # Retrieve ordered list of address var and put it to $CALLADDRFILE
  156. while [[ $($WC -l < $CALLADDRFILE) -ne 14 ]]; do
  157. $GREP -B $i "call.*$CALLADDR" $DUMPFILE | $GREP -v "$CALLADDR" | $GREP -Eo "(0x[0-9a-f]{6,})" > $CALLADDRFILE
  158. i=$(($i + 1))
  159. if [ $i -eq 10 ]; then
  160. echo "[-] Unable to extract addresses of 14 arc4 args with ARC4 address call [0x$CALLADDR]..."
  161. return;
  162. fi
  163. done
  164. # Initialize the number of line before CALLADDR to looking for sizes of args
  165. i=3
  166. # Retrieve ordered list of size var and append it to $CALLSIZEFILE
  167. while [[ $($WC -l < $CALLSIZEFILE) -ne 14 ]]; do
  168. $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
  169. i=$(($i + 1))
  170. if [ $i -eq 10 ]; then
  171. echo "[-] Unable to extract sizes of 14 arc4 args with ARC4 address call [0x$CALLADDR]..."
  172. return;
  173. fi
  174. done
  175. # For each full address in $CALLADDRFILE and corresponding size in $CALLSIZEFILE
  176. IFS=$'\n' read -d '' -r -a LISTOFADDR < $CALLADDRFILE
  177. IFS=$'\n' read -d '' -r -a LISTOFSIZE < $CALLSIZEFILE
  178. for (( x = 0; x < ${#LISTOFADDR[*]}; x = x+1 ))
  179. do
  180. i=${LISTOFADDR[$x]}
  181. NBYTES=${LISTOFSIZE[$x]}
  182. echo -e "\t[$x] Working with var address at offset [$i] ($NBYTES bytes)"
  183. # Some diferences in assembly.
  184. # We can have:
  185. # mov <adr>,%eax
  186. # push 0x<hex>
  187. # push %eax
  188. # call $CALLADDR
  189. #
  190. # or
  191. #
  192. # push 0x<hex>
  193. # push 0x<adr>
  194. # call $CALLADDR
  195. #
  196. # UPDATE 27/06/2013 :
  197. # Adding support of objdump format
  198. # New format supported (Debian 7 x86) :
  199. #
  200. # movl $0x<hex>,0x4(%esp)
  201. #
  202. # movl $0x<adr>,(%esp)
  203. # call $CALLADDR
  204. #
  205. # UPDATE 18/11/2015 :
  206. # Adding support of objdump format
  207. # Ubuntu 14.04 LTS x86_64
  208. #
  209. # mov $0x<hex>,%esi
  210. # mov $0x<adr>,%edi
  211. # callq $CALLADDR <fork@plt+0x23b>
  212. #
  213. # Key is the address with the variable content.
  214. KEY=$(echo $i | $CUT -d 'x' -f 2)
  215. # A 2 bytes variable (NBYTES > 0) can be found like this: (in STRINGFILE)
  216. # ---------------X
  217. # X---------------
  218. #
  219. # So we need 2 lines from STRINGFILE to make it all correct. So:
  220. NLINES=$(( ($NBYTES / 16) +2 ))
  221. # All line in STRINGFILE starts from 0 to f. So LASTBIT tells me the index in the line to start recording.
  222. let LASTBYTE="0x${KEY:$((${#KEY}-1))}"
  223. # Grep all lines needed from STRINGFILE, merge lines.
  224. 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")
  225. # Change string to begin in the line index.
  226. STRING=${STRING:$((2*$LASTBYTE))}
  227. # Cut the string to the number off bytes of the variable.
  228. STRING=${STRING:0:$(($NBYTES * 2))}
  229. # We need to convert to a \x??\x?? structure so:
  230. FINALSTRING=""
  231. for ((i = 0; i < $((${#STRING} /2 )); i++)); do
  232. FINALSTRING="${FINALSTRING}\x${STRING:$(($i * 2)):2}"
  233. done
  234. define_variable
  235. done
  236. }
  237. # arc4 function is called 14 times in the C code.
  238. # Each call is done with the same args sequence even if their declaration is randomized :
  239. # msg1, date, shll, inlo, xecc, lsto, tst1, chk1, msg2, rlax, opts, text, tst2 and chk2.
  240. function define_variable() {
  241. case "$j" in
  242. 0) VAR_MSG1=$FINALSTRING
  243. VAR_MSG1_Z=$NBYTES;;
  244. 1) VAR_DATE=$FINALSTRING
  245. VAR_DATE_Z=$NBYTES;;
  246. 2) VAR_SHLL=$FINALSTRING
  247. VAR_SHLL_Z=$NBYTES;;
  248. 3) VAR_INLO=$FINALSTRING
  249. VAR_INLO_Z=$NBYTES;;
  250. 4) VAR_XECC=$FINALSTRING
  251. VAR_XECC_Z=$NBYTES;;
  252. 5) VAR_LSTO=$FINALSTRING
  253. VAR_LSTO_Z=$NBYTES;;
  254. 6) VAR_TST1=$FINALSTRING
  255. VAR_TST1_Z=$NBYTES;;
  256. 7) VAR_CHK1=$FINALSTRING
  257. VAR_CHK1_Z=$NBYTES;;
  258. 8) VAR_MSG2=$FINALSTRING
  259. VAR_MSG2_Z=$NBYTES;;
  260. 9) VAR_RLAX=$FINALSTRING
  261. VAR_RLAX_Z=$NBYTES;;
  262. 10) VAR_OPTS=$FINALSTRING
  263. VAR_OPTS_Z=$NBYTES;;
  264. 11) VAR_TEXT=$FINALSTRING
  265. VAR_TEXT_Z=$NBYTES;;
  266. 12) VAR_TST2=$FINALSTRING
  267. VAR_TST2_Z=$NBYTES;;
  268. 13) VAR_CHK2=$FINALSTRING
  269. VAR_CHK2_Z=$NBYTES;;
  270. esac
  271. j=$(($j + 1))
  272. }
  273. # The password is used in the key function right before first call to arc4.
  274. # So we need the previous call just before the first "call ARC4_CALLADDR" and its args.
  275. # Update 27/06/2013 : Add new objdump format
  276. # Update 18/11/2015 : Simplify extraction
  277. # Update 23/01/2017 : Ignore movb instruction
  278. function extract_password_from_binary(){
  279. echo "[*] Extracting password..."
  280. KEY_ADDR=""
  281. KEY_SIZE=""
  282. # Initialize the number of line before CALLADDR to watch
  283. i=5
  284. while [[ ( -z "$KEY_ADDR" ) || ( -z "$KEY_SIZE" ) ]]; do
  285. $GREP -B $i -m 1 "call.*$CALLADDR" $DUMPFILE | $GREP -v $CALLADDR > $CALLFILE
  286. #cat $CALLFILE
  287. # Adjust these two next line to grep right addr & size value (depending on your architecture)
  288. KEY_ADDR=$($GREP -B 3 -m 1 "call" $CALLFILE | $GREP mov | $GREP -oE "0x[0-9a-z]{6,}+" | $HEAD -n 1)
  289. KEY_SIZE=$($GREP -B 3 -m 1 "call" $CALLFILE | $GREP mov | $GREP -v $KEY_ADDR | $GREP -v movb | $GREP -oE "0x[0-9a-z]+" | $HEAD -n 1)
  290. i=$(($i + 1))
  291. if [ $i -eq 10 ]; then
  292. echo "[-] Error, function call previous first call of arc4() hasn't been identified..."
  293. exit_error
  294. fi
  295. done
  296. echo -e "\t[+] PWD address found : [$KEY_ADDR]"
  297. echo -e "\t[+] PWD size found : [$KEY_SIZE]"
  298. # Defining the address without 0x.
  299. KEY=$(echo $KEY_ADDR | $CUT -d 'x' -f 2)
  300. # Like the other NLINES
  301. NLINES=$(( ($KEY_SIZE / 16) +2 ))
  302. # Like the other LASTBYTE
  303. LASTBYTE="0x${KEY:$((${#KEY}-1))}"
  304. # Extract PWD from STRINGFILE
  305. 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")
  306. STRING=${STRING:$((2*$LASTBYTE))}
  307. STRING=${STRING:0:$(($KEY_SIZE * 2))}
  308. # Encode / rewrite PWD in the \x??\x?? format
  309. FINALSTRING=""
  310. for ((i=0;i<$((${#STRING} /2 ));i++)); do
  311. FINALSTRING="${FINALSTRING}\x${STRING:$(($i * 2)):2}"
  312. done
  313. VAR_PSWD=$FINALSTRING
  314. }
  315. # This function append a generic engine for decrypt from shc project. With out own new variables extracted.
  316. # Rather than execute the source code decrypted, it's printed in stdout.
  317. function generic_file(){
  318. cat > ${TMPBINARY}.c << EOF
  319. #define msg1_z $VAR_MSG1_Z
  320. #define date_z $VAR_DATE_Z
  321. #define shll_z $VAR_SHLL_Z
  322. #define inlo_z $VAR_INLO_Z
  323. #define xecc_z $VAR_XECC_Z
  324. #define lsto_z $VAR_LSTO_Z
  325. #define tst1_z $VAR_TST1_Z
  326. #define chk1_z $VAR_CHK1_Z
  327. #define msg2_z $VAR_MSG2_Z
  328. #define rlax_z $VAR_RLAX_Z
  329. #define opts_z $VAR_OPTS_Z
  330. #define text_z $VAR_TEXT_Z
  331. #define tst2_z $VAR_TST2_Z
  332. #define chk2_z $VAR_CHK2_Z
  333. #define pswd_z $KEY_SIZE
  334. static char msg1 [] = "$VAR_MSG1";
  335. static char date [] = "$VAR_DATE";
  336. static char shll [] = "$VAR_SHLL";
  337. static char inlo [] = "$VAR_INLO";
  338. static char xecc [] = "$VAR_XECC";
  339. static char lsto [] = "$VAR_LSTO";
  340. static char tst1 [] = "$VAR_TST1";
  341. static char chk1 [] = "$VAR_CHK1";
  342. static char msg2 [] = "$VAR_MSG2";
  343. static char rlax [] = "$VAR_RLAX";
  344. static char opts [] = "$VAR_OPTS";
  345. static char text [] = "$VAR_TEXT";
  346. static char tst2 [] = "$VAR_TST2";
  347. static char chk2 [] = "$VAR_CHK2";
  348. static char pswd [] = "$VAR_PSWD";
  349. #define hide_z 4096
  350. /* rtc.c */
  351. #include <sys/stat.h>
  352. #include <sys/types.h>
  353. #include <errno.h>
  354. #include <stdio.h>
  355. #include <stdlib.h>
  356. #include <string.h>
  357. #include <time.h>
  358. #include <unistd.h>
  359. /* 'Alleged RC4' */
  360. static unsigned char stte[256], indx, jndx, kndx;
  361. /*
  362. * Reset arc4 stte.
  363. */
  364. void stte_0(void)
  365. {
  366. indx = jndx = kndx = 0;
  367. do {
  368. stte[indx] = indx;
  369. } while (++indx);
  370. }
  371. /*
  372. * Set key. Can be used more than once.
  373. */
  374. void key(void * str, int len)
  375. {
  376. unsigned char tmp, * ptr = (unsigned char *)str;
  377. while (len > 0) {
  378. do {
  379. tmp = stte[indx];
  380. kndx += tmp;
  381. kndx += ptr[(int)indx % len];
  382. stte[indx] = stte[kndx];
  383. stte[kndx] = tmp;
  384. } while (++indx);
  385. ptr += 256;
  386. len -= 256;
  387. }
  388. }
  389. /*
  390. * Crypt data.
  391. */
  392. void arc4(void * str, int len)
  393. {
  394. unsigned char tmp, * ptr = (unsigned char *)str;
  395. while (len > 0) {
  396. indx++;
  397. tmp = stte[indx];
  398. jndx += tmp;
  399. stte[indx] = stte[jndx];
  400. stte[jndx] = tmp;
  401. tmp += stte[indx];
  402. *ptr ^= stte[tmp];
  403. ptr++;
  404. len--;
  405. }
  406. }
  407. /* End of ARC4 */
  408. /*
  409. * Key with file invariants.
  410. */
  411. int key_with_file(char * file)
  412. {
  413. struct stat statf[1];
  414. struct stat control[1];
  415. if (stat(file, statf) < 0)
  416. return -1;
  417. /* Turn on stable fields */
  418. memset(control, 0, sizeof(control));
  419. control->st_ino = statf->st_ino;
  420. control->st_dev = statf->st_dev;
  421. control->st_rdev = statf->st_rdev;
  422. control->st_uid = statf->st_uid;
  423. control->st_gid = statf->st_gid;
  424. control->st_size = statf->st_size;
  425. control->st_mtime = statf->st_mtime;
  426. control->st_ctime = statf->st_ctime;
  427. key(control, sizeof(control));
  428. return 0;
  429. }
  430. void rmarg(char ** argv, char * arg)
  431. {
  432. for (; argv && *argv && *argv != arg; argv++);
  433. for (; argv && *argv; argv++)
  434. *argv = argv[1];
  435. }
  436. // Update 18/11/2015 : Update "mask" casting from "unsigned" to "unsigned long".
  437. int chkenv(int argc)
  438. {
  439. char buff[512];
  440. unsigned mask, m;
  441. int l, a, c;
  442. char * string;
  443. extern char ** environ;
  444. mask = (unsigned long)chkenv;
  445. mask ^= (unsigned)getpid() * ~mask;
  446. sprintf(buff, "x%x", mask);
  447. string = getenv(buff);
  448. l = strlen(buff);
  449. if (!string) {
  450. /* 1st */
  451. sprintf(&buff[l], "=%u %d", mask, argc);
  452. putenv(strdup(buff));
  453. return 0;
  454. }
  455. c = sscanf(string, "%u %d%c", &m, &a, buff);
  456. if (c == 2 && m == mask) {
  457. /* 3rd */
  458. rmarg(environ, &string[-l - 1]);
  459. return 1 + (argc - a);
  460. }
  461. return -1;
  462. }
  463. char * xsh(int argc, char ** argv)
  464. {
  465. char * scrpt;
  466. int ret, i, j;
  467. char ** varg;
  468. stte_0();
  469. key(pswd, pswd_z);
  470. arc4(msg1, msg1_z);
  471. arc4(date, date_z);
  472. //if (date[0] && date[0]<time(NULL))
  473. // return msg1;
  474. arc4(shll, shll_z);
  475. arc4(inlo, inlo_z);
  476. arc4(xecc, xecc_z);
  477. arc4(lsto, lsto_z);
  478. arc4(tst1, tst1_z);
  479. key(tst1, tst1_z);
  480. arc4(chk1, chk1_z);
  481. if ((chk1_z != tst1_z) || memcmp(tst1, chk1, tst1_z))
  482. return tst1;
  483. ret = chkenv(argc);
  484. arc4(msg2, msg2_z);
  485. if (ret < 0)
  486. return msg2;
  487. varg = (char **)calloc(argc + 10, sizeof(char *));
  488. if (!varg)
  489. return 0;
  490. if (ret) {
  491. arc4(rlax, rlax_z);
  492. if (!rlax[0] && key_with_file(shll))
  493. return shll;
  494. arc4(opts, opts_z);
  495. arc4(text, text_z);
  496. printf("%s",text);
  497. return 0;
  498. /*arc4(tst2, tst2_z);
  499. key(tst2, tst2_z);
  500. arc4(chk2, chk2_z);
  501. if ((chk2_z != tst2_z) || memcmp(tst2, chk2, tst2_z))
  502. return tst2;
  503. if (text_z < hide_z) {
  504. scrpt = malloc(hide_z);
  505. if (!scrpt)
  506. return 0;
  507. memset(scrpt, (int) ' ', hide_z);
  508. memcpy(&scrpt[hide_z - text_z], text, text_z);
  509. } else {
  510. scrpt = text;
  511. }*/
  512. } else {
  513. if (*xecc) {
  514. scrpt = malloc(512);
  515. if (!scrpt)
  516. return 0;
  517. sprintf(scrpt, xecc, argv[0]);
  518. } else {
  519. scrpt = argv[0];
  520. }
  521. }
  522. j = 0;
  523. varg[j++] = argv[0]; /* My own name at execution */
  524. if (ret && *opts)
  525. varg[j++] = opts; /* Options on 1st line of code */
  526. if (*inlo)
  527. varg[j++] = inlo; /* Option introducing inline code */
  528. varg[j++] = scrpt; /* The script itself */
  529. if (*lsto)
  530. varg[j++] = lsto; /* Option meaning last option */
  531. i = (ret > 1) ? ret : 0; /* Args numbering correction */
  532. while (i < argc)
  533. varg[j++] = argv[i++]; /* Main run-time arguments */
  534. varg[j] = 0; /* NULL terminated array */
  535. execvp(shll, varg);
  536. return shll;
  537. }
  538. int main(int argc, char ** argv)
  539. {
  540. argv[1] = xsh(argc, argv);
  541. return 1;
  542. }
  543. EOF
  544. }
  545. ##########################################
  546. ## Starting
  547. echo " _ _ _____ _ _ "
  548. echo "| | | | / ___| | | | "
  549. echo "| | | |_ __ \ \`--.| |_| | ___ "
  550. echo "| | | | '_ \ \`--. \ _ |/ __|"
  551. echo "| |_| | | | /\__/ / | | | (__ "
  552. echo " \___/|_| |_\____/\_| |_/\___|"
  553. echo
  554. echo "--- UnSHc - The shc decrypter."
  555. echo "--- Version: $VERSION"
  556. echo "------------------------------"
  557. echo "UnSHc is used to decrypt script encrypted with SHc"
  558. echo "Original idea from Luiz Octavio Duarte (LOD)"
  559. echo "Updated and modernized by Yann CAM"
  560. echo "- SHc : [http://www.datsi.fi.upm.es/~frosal/]"
  561. echo "- UnSHc : [https://www.asafety.fr/unshc-the-shc-decrypter/]"
  562. echo "------------------------------"
  563. echo
  564. if [ $# -lt 1 ]; then
  565. echo "[?] Type -h or --help for how to use it"
  566. clean
  567. exit 0
  568. fi
  569. # Check the availability of each command needed in this script.
  570. check_binaries
  571. OPTS=$( getopt -o h,a:,d:,s:,o: -l help,arc4:,dumpfile:,stringfile:,outputfile: -- "$@" )
  572. if [ $? != 0 ]; then
  573. exit_error;
  574. fi
  575. while [ "$#" -gt 0 ] ; do
  576. case "$1" in
  577. -h|--help)
  578. usage;
  579. clean;
  580. exit 0;;
  581. -a|--arc4)
  582. echo "[+] ARC4() offset function call address specified [0x$2]";
  583. CALLADDR=$2;
  584. shift 2;;
  585. -d|--dumpfile)
  586. echo "[+] Object dump file specified [$2]";
  587. DUMPFILE=$2;
  588. shift 2;;
  589. -s|--stringfile)
  590. echo "[+] String dump file specified [$2]";
  591. STRINGFILE=$2;
  592. shift 2;;
  593. -o|--outputfile)
  594. echo "[+] Output file name specified [$2]";
  595. OUTPUTFILE=$2;
  596. shift 2;;
  597. -*)
  598. echo "[-] Unknown option: [$1]" >&2;
  599. exit_error;;
  600. --)
  601. shift;
  602. break;;
  603. *)
  604. echo "[*] Input file name to decrypt [$1]";
  605. BINARY=$1
  606. shift 1;;
  607. esac
  608. done
  609. if [ ! -e $BINARY ]; then
  610. echo "[-] Error, File [$BINARY] not found."
  611. exit_error
  612. fi
  613. if [ -z "$DUMPFILE" ]; then
  614. DUMPFILE=$(mktemp /tmp/XXXXXX)
  615. else
  616. if [ ! -e $DUMPFILE ]; then
  617. echo "[-] Object dump file [$DUMPFILE] not found."
  618. exit_error;
  619. fi
  620. fi
  621. if [ -z "$STRINGFILE" ]; then
  622. STRINGFILE=$(mktemp /tmp/XXXXXX)
  623. else
  624. if [ ! -e $STRINGFILE ]; then
  625. echo "[-] String dump file [$STRINGFILE] not found."
  626. exit_error;
  627. fi
  628. fi
  629. # Fill DUMPFILE and STRINGFILE from objdump of the *.sh.x encrypted script
  630. generate_dump
  631. # Find out the most called function. This function is arc4() and there are 14 calls.
  632. # Then retrieve the data used in each CALLADDR call
  633. c=1
  634. if [ -z "$CALLADDR" ]; then
  635. # Case when ARC4 offset is unknown and there are multiple candidate
  636. while [[ $($WC -l < $CALLSIZEFILE) -ne 14 ]]; do
  637. extract_arc4_call_addr "$c"
  638. extract_variables_from_binary
  639. c=$(($c + 1))
  640. done
  641. else
  642. # Case when the ARC4 address is already defined and passed throught args
  643. extract_variables_from_binary
  644. fi
  645. # Retrieve PWD from function call just before the first CALLADDR call
  646. extract_password_from_binary
  647. # Create a C source code to decrypt *.sh.x file with previously extracted data
  648. generic_file
  649. # Compile C source code to decrypt *.sh.x file
  650. $GCC -o $TMPBINARY ${TMPBINARY}.c >/dev/null 2>&1
  651. echo "[*] Executing [$TMPBINARY] to decrypt [${BINARY}]"
  652. chmod +x $TMPBINARY
  653. if [ -z "$OUTPUTFILE" ]; then
  654. echo "[*] Retrieving initial source code in [${BINARY%.sh.x}.sh]"
  655. $TMPBINARY > ${BINARY%.sh.x}.sh
  656. else
  657. echo "[*] Retrieving initial source code in [$OUTPUTFILE]"
  658. $TMPBINARY > $OUTPUTFILE
  659. fi
  660. echo "[*] All done!"
  661. clean
  662. exit 0

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Gausst松鼠会/article/detail/361498
推荐阅读
相关标签
  

闽ICP备14008679号