Добрый день хабр. В статье я расскажу, как используя синтаксис php, можно написать функцию, для вывода переданной ей строковой переменной, не использующую в своем теле символы «a-zA-Z0-9<>?»
Вообще на хабре уже проскальзывали ссылки на статьи об использовании undefined variable, так что ничего нового я скорее всего не открою.
В php, как и в любом языке с динамической типизацией, есть моменты скрытые от конечного разработчика, на них мы и сыграем.
Начнем с конца. Мы всегда можем обратится к любому callable- была бы строка для вызова. Функции из SPL не исключение, хоть это и крайне редко применяется.
$v="print_r";
$v([1,2,3,4]);
Array
(
[0] => 1
[1] => 2
[2] => 3
[3] => 4
)
Но обратится таким способом ни к echo ни к print мы не можем, ибо они являются конструкциями языка, а не функциями. Можно было бы использовать printf например, но мне такой подход не понравился. Поэтому мы будем использовать для вывода функцию assert.
assert("print someShit");
Кстати заменить print на echo в выражении выше не выйдет, они оба не функции, но print хотя бы старается таковой казаться.
Строку для вывода нам передадут при вызове. Осталось самая малость. Получить строки «assert» и «print» используя доступный нам набор символов.
Для этого мы используем ряд особенностей языка.
1) В php мы можем обратится к undefined variable через _ (underscore). Нетрудно добится сужения типа и получить 0
var_dump(+_);
int(0)
2) При приведении массива к строке, он будет преобразован в строку со значением Array
//инициализируем пустой массив
$_[]++;
// В данном случае _ приводится к строке "_"
$_[]=$_._;
var_dump($_);
array(2) {
[0]=>
int(1)
[1]=>
string(6) "Array_"
}
3) Как и в большинстве других языков, строка фактически является массивом символов. Символы можно инкрементировать.
Скомбинировав все вышеперечисленное получаем такой код.
<?
error_reporting(E_ALL^E_NOTICE);
crazyOutput("было нечего");
function crazyOutput($__________){
$_[]++;
$_[]=$_._;
$_=$_[$_[+_]];
$___=$__=$_[++$__[]];
$____=$_=$_[+_];
$_++;$_++;$_++;
$_=$____.++$___.$___.++$_.$__.++$___;
$__=+_;$__=++$__+(++$__);
$____=$_[$__];
$____++;$____++;$____++;
$______=$____;
$____++;$____++;$____++;$____++;$____++;$____++;$____++;$____++;
$___=$____;
$____++;$____++;
$______++;
$___.=$____.$______;
$______++;$______++;$______++;$______++;$______++;
$___.=$______;
$__=+_;$__++;
$______=$___[$__];
$______++;$______++;
$___.=$______;
$_($___." '".$__________."'");
}
?>
/usr/bin/php /var/www/garbage/brainfuck.php
было нечего
Process finished with exit code 0
Практической пользы 0 в принципе… но что-то в этом есть =)
Автор: sl4mmer