白彩恋
总主编2025 年 9 月 6 日 星期六
前言
Shell 作为有举足轻重地位的解释型语言,安全防护必然是少不了的一个内容,可以怎么防护是一个需要深入的问题常见混淆加密方案
过于简单或过于复杂的不在此提起
明文混淆加密
gzexe
gzexe 的原理较为简单,本质就是通过 gzip 将源码压缩,放置于脚本文件的尾部,然后解压执行
如果要变种也很简单,比如说多层压缩、多层编码嵌套,但是并没有什么实质作用
gzexe 的优点
- 由于是把处理后的二进制数据直接放在脚本文件内,通过文本编辑器无法直接编辑
gzexe 的缺点
- 由于是把处理后的二进制数据直接放在脚本文件内,执行时需要获取
$0(也就是自身),从而导致兼容性较差,无法通过./source执行 - 只是单纯把源码处理,可读性极强,解密非常简单
gzexe 的解密
看执行逻辑,然后直接执行对应的解压/解码就可以了变量混淆
这种混淆的出处暂未找到,本质是将源码中出现的每一个字符都替换成可读性差的变量变量混淆的优点
- 源码被替换成变量,可读性较差
- 不需要获取
$0,兼容性优秀
变量混淆的缺点
- 出发点是较好的,但是将源码替换变量后直接使用
eval执行,极易解密 - 对于较为复杂的源码,可能无法加密
变量混淆的解密
直接把eval 改成 echo 然后执行,源码就会直接输出出来了
可执行混淆加密
shc
shc 的实现也不复杂,将字符串加密后调用 sh -c 执行
特征也很明显,反编译后看伪代码可以很明显地看出调用 sh -c 执行的这一过程
shc 的优点
- 有字符串加密,如果要直接在二进制层面解密,并非易事
- 通过
sh -c执行,兼容性尚可
shc 的缺点
- 通过
sh -c执行,极易解密 - 获取到的
$0不是其真实名称
shc 的解密
执行后读取cmdline 即可
shellc/xbash
shellc 是一个强度较高的项目,xbash 的强度更是更上一层楼
shellc/xbash 的优点
shellc的兼容性较高,支持shell、perl、python、node、Rscript、php等语言shellc的功能多,可用性强xbash实现了内置解释器,交给其他解释器和直接内置解释器是完全不一样的强度
shellc/xbash 的缺点
- 反调试不够多,但是由于
xbash闭源,不知道其具体手段
shellc/xbash 的解密
作者已写,只不过xbash 的话,没有一些技术手段是弄不出来的
玉龙加密
有这么个东西,但是我没有看到有谁在用,但也说说吧,它还叫什么 XXC 加密?
upx 压缩传入,成功则视为二进制,失败则视为脚本
然后处理 upx 特征,并将其加密存放于事先编译好的可执行的尾部
执行的时候是将其解密至 /data/data 内的随机目录,然后如果是可执行就直接执行,如果是脚本则调用 sh 执行
执行后会立即删除解密后的文件
玉龙加密的优点
没有任何优点,可能就是看起来唬人吧?玉龙加密的缺点
- 本身的实现就很抽象
- 获取到的工作目录不是其真实目录
玉龙加密的解密
要直接在二进制层面解密较为简单,找到尾部标志的位置读取出其尾部数据,然后进行异或解密即可 如果是通过执行来解密,只需要给/data/data 设置 chattr +a,然后把 chattr 指令直接干掉即可(因为执行的时候会调用 chattr -a 来防止破解)
进阶混淆加密方案
只提大概方向,不提具体实现
进阶混淆加密大纲
- 不留任何中间文件
- 做好反调试
- 做好真实性校验
- 开头固然重要,执行时更重要
明文进阶混淆加密
明文实际上非常不安全,因为执行完全受到执行者的掌控,所以只能做到尽可能地降低可读性,这里以 AW 加密举例外层壳
中层壳
内层壳(由于换行非常影响可读性,故已去除)
... 是随机名称,其他的则是具体的处理后内容
AW 加密是一个较为简单的多层壳混淆加密,其主要目的是提供艺术性较强的混淆加密,主要防的是低技术人群
AW 加密主要实现了多层壳、低可读性、反调试,由于项目性质,其中并没有添加例如更强的混淆、源码分割、真实性校验、更强的反调试等
并且基于纯 POSIX Shell 实现,在 set -e 情况下也可正常运行,兼容性极佳
AW 加密实现原理
简单来说,就是把eval 等关键代码去特征化,并且尽可能写不规范但是可正常运行的语句,引号几乎不用,绝大部分都是基于转义连接字符串
这种方案并不保险,不过要增加强度,增强反调试策略、验证解释器/指令真实性、混淆封装指令、分隔处理后的源码、添加伪源码即可,就目前的强度而言,拿来做案例绰绰有余
更强的内容自然是机密
可执行进阶混淆加密
由于强度偏高,不提供实际案例
外置解释器方案
为了不重蹈覆辙shc 直接 sh -c 带来的后果,可以采用管道执行,还可以通过多线程来确保解释器真实性(如果执行者做了管道转发那就很难说了),但是切忌一次性执行,逐行执行更稳妥
缺点是必须手动执行 exit,不过这只是个小问题,需要注意的是 $0 需要通过 exec -a 加上一点小手段才能解决,命令行传入则是使用 set -- 解决
内置解释器方案
都做到这个地步了,要做的就是反调试和防内存了,要去掉解释器内一切可能暴露源码的内容当然,有混淆加密的编译器、静态编译、符号剥离同样也相当重要
总结
能别写解释型语言就别写解释型语言啊!
