shell加密 与 二进制

shell加密 与 二进制
shell脚本中嵌入二进制文件

20120911

http://hi.baidu.com/coolrainbow/item/ef918856724b4a9e08be1771
【原创】shell脚本中嵌入二进制文件

最近有人问我,一个集群监控软件的安装文件特别“诡异”,说脚本里有“乱码”却能执行,是怎么回事?我看了才发现这个东西原来是典型的脚本嵌套代码的模式,这里就讲讲吧。反正好久没写东西了。

某些比较“拽”的单位在发布Linux软件时以一种特殊的形式发布,即在shell脚本中嵌入二进制字符,从而使脚本变得极其诡异,让某些初学者感觉惊奇。其实,这个原理戳穿了非常简单,就是在运行脚本时将二进制代码导出成一个程序,再执行之就可以。(不过这种行为其实,是违反Linux社区的精神的,像我这种人, 看到什么软件第一反应都是想搞到其源码)

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

例:下面的这个源码:

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 ?EFLB
...
18 ....AMIC@data_start@__libc_csu_fini^@_sta

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

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

C调用shell指令

20120910 chenxin
1.自己编写的调用测试程序
cat server.c
/*

  • server.c
  • Created on: 2012-9-9
  • Author: uadmin

*/

include<stdlib.h>

include<stdio.h>

main()
{
system("pwd");
printf("%s\n","show the system passwd file and shadow file!");
system("./Debug/test.sh");
}
eclipse默认的工作环境是/home/uadmin/workspace/command/,如果--system("./Debug/test.sh");--输入为system("./test.sh");的话,编译可以通过,但run的时候会提示找不到二进制可执行文件;

2.网上的例子,测试是否可以将整个脚本的文本文件赋予一个数组变量

include <stdio.h>

include <string.h>

include<unistd.h>

int main(int argc ,char *argv[])
{
char arg[300]="/tmp/testDir/tsh.sh ";
if ( argv[1] != NULL )
{
strcat(arg,argv[1]);

system(arg);
    printf("\ndone message in program\n");
    return 1;
}
else
{
    printf("Error: Empty input\n");
    return 0;
}

}

shell加密
20121008Chenxin
shc是一个加密shell脚本的工具.它的作用是把shell脚本转换为一个可执行的二进制文件.

一、安装:
wget http://www.datsi.fi.upm.es/~frosal/sources/shc-3.8.9.tgz
tar zxvf shc-3.8.9.tgz
cd shc-3.8.9
make && make install
make报错处理
make: *** No rule to make target shc.c‘, needed by shc‘. Stop.
cat makefile
shc: shc.c
$(CC) $(CFLAGS) -o
找不到shc.c文件,处理方法:
mv shc-3.8.9.c shc.c

二、使用
shc -r -f script-name 注意:要有-r选项, -f 后跟要加密的脚本名.
运行后会生成两个文件,script-name.x 和 script-name.x.c
script-name.x是加密后的可执行的二进制文件.
./script-name 即可运行.
script-name.x.c是生成script-name.x的原文件(c语言)
shc Version 3.8.9, Generic Script Compiler
shc Copyright (c) 1994-2012 Francisco Rosales
shc Usage: shc [-e date] [-m addr] [-i iopt] [-x cmnd] [-l lopt] [-rvDTCAh] -f script
-e %s Expiration date in dd/mm/yyyy format [none] #设置过期时间
-m %s Message to display upon expiration ["Please contact your provider"] #过期信息提示
-f %s File name of the script to compile #加密脚本名称
-i %s Inline option for the shell interpreter i.e: -e
-x %s eXec command, as a printf format i.e: exec(‘%s‘,@ARGV);
-l %s Last shell option i.e: --
-r Relax security. Make a redistributable binary #在系统通用
-v Verbose compilation #详细汇编
-D Switch ON debug exec calls [OFF]
-T Allow binary to be traceable [no]
-C Display license and exit #显示许可证并退出
-A Display abstract and exit #显示摘要和退出
-h Display help and exit #显示帮助和退出

三、实例
shc -e 31/8/2012 -m ExpireTime:31/8/2012 -v -r -f test.sh
测试脚本每次都自动放入后台,且提示stoped;
通过以下方式可以成功:
shc -T -f test.sh

四、静态编译
4.1动态库
查看
file scriptname.x
scriptname.bash.x: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.18, stripped
注意:dynamically linked(uses shared libs)使用的是动态链接库,不能跨平台使用
可以使用ldd查看具体使用的库
ldd scriptname.x
如:ldd mysql_backup.bash.x
linux-vdso.so.1 => (0x00007fff019ff000)
libc.so.6 => /lib64/libc.so.6 (0x0000003a3c200000)
/lib64/ld-linux-x86-64.so.2 (0x0000003a3ba00000)
普通动态编译:
shc -T -vrf test.sh

4.2静态库编译方式
CFLAGS=... shc -r -f scriptname
CFLAGS中指定:-static选项等
CFLAGS=-static shc -T -f test.sh
执行静态编译无法通过,报错如下:
CFLAGS=-static shc -T -f test.sh
/usr/bin/ld: cannot find -lc
collect2: ld returned 1 exit status
解决方法:
yum install -y glibc-static libstdc++-static
之后,运行编译命令,生成的test.sh.x文件由原先的9K变为671K;
虽然静态编译成功,但放到其他机器上运行,运行结果仍然不正常,本机输出正常,其他机器上输出结果乱码(这种情况有概率发生,不是每次都这样)

解决方法:利用 CFLAGS=-static shc -T -vrf test.sh 生成的test.sh.c源码文件,再手动通过gcc编译:
gcc -static -o static_test test.sh.x.c
生成的static_test 文件,则可以放到其他系统上执行;

正常情况执行如下:
CFLAGS=-static shc -T -vrf test.sh
就会生成可执行文件,在Centos6.2下编译后,在ubuntu11.10上执行没有问题,在SUSE上不行(提示 FATAL: kernel too old Segmentation fault ),模式版本太低;

相关推荐