随着安全防护技术的不断进步,越来越多的静态分析工具、杀软引擎、入侵检测系统开始对常见的攻击模式建立规则化识别模型,尤其是在 WebShell 检测方面,匹配机制早已从关键词检索、函数组合模式,上升到了结构语义、行为特征的层面。
在这场“攻防猫鼠游戏”中,攻击者始终在寻找新的缝隙与盲点,而本章要讲述的,正是一种看似简单、却非常有效的免杀思路:利用 Unicode 控制字符 \u180B,对 .NET WebShell 进行混淆与绕过处理。
01. Unicode 背景
在介绍技术细节之前,有必要简要回顾一下 Unicode 字符集的相关背景。Unicode 是一种计算机字符编码标准,它为世界上几乎所有的语言、文字、符号、控制字符提供了统一编号。其核心目标是:“一个字符集解决所有文字问题”。
2.1 起源
早期美帝的程序员没有意识到英语只是全世界所有语言中的一种,他们以为26个英文字母再加上一些其它符号就够用了所以就只有ASCII码,但是随着互联网的发展他们终于意识到软件原来还是需要给不同国家不同语言的人来使用的,所以就开始有了其它的编码方法,但因为缺少一个一统天下的标准,所以乱码问题非常严重。
而 Unicode 就是要来解决这个问题,80年代末,Unicode协会成立,该协会成立的目的在于用一个足够大统一的字符集来支持世界上的所有语言,简单的说Unicode是一套通用的字符集,包含世界上的大部分字符。
Unicode协会在1991年首次发布了The Unicode Standard,之后每1-2年发布一个大的版本以增加重大特性。从2013年9月Unicode6.3发布之后,Unicode一直保持一个相对稳定的发布周期,在每年的上半年发布一个新版本。
直至2020年3月,Unicode的版本为Unicode 13.0.0,在最新的Unicode13版本中,包含了大约14万字符,可以支持154种脚本的文本显示,除了定义哪些字符会被涵盖外,它还要定义每个字符所对应的码位。更详细知识点已收录于新书《.NET安全攻防指南》第21.1节,并且有完整的介绍,如下图所示。
2.2 码位
码位英文名为 Code point 或 Code position ,Unicode 字义了字符集合后,需要为每个字符指定一个数字,这样计算机才有办法处理。假如字符集中有 1 万个字符,那就需要 1 万个数字,每个字符对应一个数字,这所有的 1 万个数字就构成了编码空间,而每个数字就是对应的字符的码位。
2.3 UTF-8字符集
UTF-8 应用非常广泛,即使是个刚入行的小白,也应该会经常听到前辈说,“把文件保存成 UTF-8”,“这个讨厌的网站居然用的是 GB2312 编码”,等等。之所以这么流行,是因为 UTF-8 完全兼容 ASCII,对于 ASCII 字符,UTF-8 使用和 ASCII 完全一样的编码方式,同样只使用一个字节,这就意味着,如果被编码的字符仅含 ASCII 字符,那即使是用 UTF-8 进行编码,只支持 ASCII 的旧系统仍然能够准确地解码。
同时,如果被编码的字符大部分是 ASCII 字符,因为只占用一个字节,UTF-8 也最节省空间 .NET 在设计过程中就考虑了对 Unicode 字符的支持,char是 .NET Framework 中的 System.Char