Дело было вечером, echo «было нечего»

в 20:11, , рубрики: php, ненормальное программирование, особенности, метки: , ,

Добрый день хабр. В статье я расскажу, как используя синтаксис 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

Источник

Поделиться

* - обязательные к заполнению поля