一些不包含数字和字母的webshell理解
前言
前端时间群里大佬发了一个代码询问我们里面的原理,代码如下:
1 |
|
后来在诸位大佬的帮助下找到了这篇文章,顿时眼界打开。
分析
源码理解
第二行的$__ = (‘>’ > ‘<’) + (‘>’ > ‘<’);实际上是true+true也就是1+1(简单地说就是一个大于号>
和一个小于号<
的比较,由于大于号的ASCII码十进制是62
,小于号是60
,因此这里>
大于<
是成立的,返回true)
所以$__=2
第三行的$_ = $__ / $__;
即2/2,所以$_=1
1 | $___ = "瞰"; |
这两行代码的原理是这样的:
将某个汉字转为utf-8编码,然后将其中某个字符取出来。
{}这个括号可以理解为数组里面的[]
~在php里是取反
.这个符号则是添加,类似于python的append
所以这两行代码实际上就是先转为utf-8编码,然后通过{}将里面的字符提取出来,再进行取反,然后就生成a这个字符了。
而这个加密的关键就是在于utf-8编码这里。
下面我们来说明一下相关的原理
原理
我们以“瞰”这个汉字为例。
首先我们这个字要在网络上传播是需要使用二进制来表示电压的。
在unicode编码表中,“瞰”这个字的编码为0x77B0.
转成utf-8模式,对照它的映射表,我们这个0x77B0是在0x000-0xFFFF之间,而utf-8是使用3字节模板(1110xxxx 10xxxxxx 10xxxxxx),所以我们需要将77B0转成二进制
(0111 0111 1011 0000)
在转成二进制后我们用这个比特流一次代替模板中的x,得到
11100111 10011110 10110000即为e7,9e,b0
在源码中我们‘瞰’这个字是提取第一组字符出来进行取反的,因此我们是提取了10011110出来,然后取反为01100001,根据ascill查询可以得到该二进制就是a