脚本嵌套代码

典型的脚本嵌套代码的模式,即在shell脚本中嵌入二进制字符。其实,这个原理就是在运行脚本时将二进制代码导出成一个程序,再执行之就可以。

原理:通常程序代码处在脚本的最后位置。脚本运行时,把它写出来执行即可。

例:下面的这个源码:

#include <stdio.h>
#include <stdlib.h>

int main(int argc, char** argv)
{
const char* envtagUSER="USER";
printf("Your Username: %s. This is detected by the program %s.\n", getenv(envtagUSER), argv[0]);
return 0;
}

这段代码可以用来输出用户名。当然这仅仅是个例子,实际编程时用shell就可以得到。现在假设我们想把这段代码嵌入一个名叫dofoo.sh的shell脚本中。首先编译之:

gcc -Os foo.c -o foo

现在把foo追加到dofoo.sh的末尾:

cat foo >> dofoo.sh   # Not > but >> !

打开dofoo.sh,添加代码:

1    #!/bin/sh
2 
3    skip=11
4    prog="/tmp/$0.exe"
5    tail -n +$skip "$0" > $prog
6    chmod u+x $prog
7    $prog
8    rm $prog
9    exit
10
11  ^?EFL^B
...
18  ....AMIC^@data_start^@__libc_csu_fini^@_sta

(11行以后看都是乱码)这代码将脚本中11行以后的东西导入到了/tmp/dofoo.exe这个文件中,添加x权限,执行,然后删除该文件。


加密伪装

有时候一个shell中的乱码并不一定是可执行文件,那些东西可能是某种压缩格式,如bz2,gz等等,或者其他的某种加密形式,程序会先把他们导出来解压在执行然后删除,道理是一样的。有时候,这种解压程序或者解密程序本身就嵌套在shell脚本里。


某黑客在电脑中留下的脚本:

#!/bin/sh
skip=44

tab='	'
nl='
'
IFS=" $tab$nl"

umask=`umask`
umask 77

gztmpdir=
trap 'res=$?
  test -n "$gztmpdir" && rm -fr "$gztmpdir"
  (exit $res); exit $res
' 0 1 2 3 5 10 13 15

if type mktemp >/dev/null 2>&1; then
  gztmpdir=`mktemp -dt`
else
  gztmpdir=/tmp/gztmp$$; mkdir $gztmpdir
fi || { (exit 127); exit 127; }

gztmp=$gztmpdir/$0
case $0 in
-* | */*'
') mkdir -p "$gztmp" && rm -r "$gztmp";;
*/*) gztmp=$gztmpdir/`basename "$0"`;;
esac || { (exit 127); exit 127; }

case `echo X | tail -n +1 2>/dev/null` in
X) tail_n=-n;;
*) tail_n=;;
esac
if tail $tail_n +$skip <"$0" | gzip -cd > "$gztmp"; then
  umask $umask
  chmod 700 "$gztmp"
  (sleep 5; rm -fr "$gztmpdir") 2>/dev/null &
  "$gztmp" ${1+"$@"}; res=$?
else
  echo >&2 "Cannot decompress $0"
  (exit 127); res=127
fi; exit $res