SHC转换的shell可执行文件系统重启后运行失效输出乱码问题
故障根因
这是SHC的固有缺陷,和AWS公共AMI的默认系统配置直接相关:
- SHC不会把Shell脚本真正编译为独立的本地机器码,它输出的
.x文件本质是个简易C加载器:真正的脚本逻辑被加密后存在二进制段中,运行时必须先在系统临时目录(默认路径/tmp)解密写出一份临时可执行脚本片段,再调用系统shell执行这份片段才能正常运行。 - AWS官方提供的Amazon Linux 2/2023、Ubuntu等常用公共AMI,默认配置了两项规则:一是重启后自动清空
/tmp目录下的所有用户文件,二是默认将/tmp目录挂载为*noexec模式*,禁止该目录下的任何文件获取可执行权限。 - 你在镜像制作阶段第一次执行
./test.sh.x时,要么当时实例还没加载/tmp的noexec挂载参数,要么SHC写出的临时文件还没被清理,所以运行正常;实例重启后,旧临时文件被清空,noexec权限阻止SHC写入新的可执行临时片段,加载器执行流异常,会直接把内存中存储的加密二进制内容打印到标准输出,就是你看到的乱码。
SHC方案修复方法
如果坚持用SHC,改下编译和运行配置就能解决重启失效的问题:
- 提前在镜像内创建一个不会被自动清理、不会被挂载为
noexec的固定临时目录,比如/opt/shc_runtime,设置全局可写权限:mkdir -p /opt/shc_runtime chmod 1777 /opt/shc_runtime - 编译SHC二进制时,不要直接用默认的
shc -f test.sh命令,手动修改生成的C源文件里的硬编码临时路径,再自行编译:# 先生成.x和.x.c文件 shc -f test.sh # 替换硬编码的/tmp路径为你自建的目录 sed -i 's|"/tmp"|"/opt/shc_runtime"|g' test.sh.x.c # 手动编译为独立二进制,去掉无用的调试符号减小体积 gcc -s -o test_bin test.sh.x.c - (可选)如果不想改源码,也可以在镜像的全局环境变量配置(比如
/etc/profile、/etc/environment)里加一行export TMPDIR=/opt/shc_runtime,SHC运行时会优先读这个环境变量选择临时目录,避开/tmp的权限限制。
更稳定的轻量隐藏替代方案
SHC本身已经多年没有核心功能更新,坑点较多,如果只需要满足普通用户无法直接cat查看原脚本的轻量隐藏需求,下面几个方案无额外依赖、不会出现重启失效问题,稳定性远高于SHC:
- 方案1:Base64自解压包装
纯Shell实现,无二进制依赖,所有Linux环境通用,普通用户打开文件只能看到Base64字符串,无法直接读原脚本逻辑:
如果要提升混淆度,可以把Base64字符串拆成多段、插入无意义的干扰变量,足够应付普通的随意查看。# 先把原脚本编码为单行Base64字符串 B64_PAYLOAD=$(base64 -w0 test.sh) # 生成可执行包装脚本 cat > test_bin <<'EOF' #!/bin/bash PAYLOAD="这里替换成上一步得到的B64_PAYLOAD字符串" echo "$PAYLOAD" | base64 -d | bash EOF chmod +x test_bin - 方案2:gzexe压缩包装
所有Linux发行版默认自带gzexe工具,原本用于压缩可执行脚本减小体积,压缩后的文件是自解压格式,直接运行即可,普通用户打开看到的是压缩后的二进制乱码,满足轻量隐藏需求:
这个方案生成的文件本质还是Shell脚本,不依赖临时目录可执行权限,跨环境兼容性极强,不会因为系统配置变化失效。# 压缩原脚本 gzexe test.sh # 删除自动生成的原文件备份 rm -f test.sh~ # 压缩后的test.sh就是可直接执行的文件,重命名即可 mv test.sh test_bin - 方案3:独立二进制打包
写一个极简C加载器把脚本内容嵌入二进制,运行时直接通过管道传给Shell执行,不落地写临时文件,使用体验和SHC生成的二进制一致但没有临时目录依赖:- 新建
loader.c文件,内容如下:#include <stdlib.h> #define PAYLOAD "这里替换成base64 -w0 test.sh生成的字符串" int main() { char cmd[2048000]; // 缓冲区大小根据脚本长度调整,足够存下解码命令即可 snprintf(cmd, sizeof(cmd), "echo \"%s\" | base64 -d | bash", PAYLOAD); return system(cmd); } - 编译为静态独立二进制:
gcc -static -s -o test_bin loader.c
/tmp怎么配置都能正常运行,逆向难度和SHC相当,完全满足轻量隐藏需求。 - 新建
内容的提问来源于stack exchange,提问作者Vinny Pem
相关产品推荐
相关产品推荐

