Простите за мат в заголовке, это намёк на развлечение, начало которому дал язык «Брейнфак» — написать на каком-либо языке код, выполняющий что-то разумное, не используя букв и цифр. Мы уже видели JSFuck, PHPFuck, теперь я вам хочу представить Bashfuck:
__=${_##*/};____=<(:);___=${__#???};_____=$((${#___}<<${#___}))
__=${__::-${#___}}${____:$_____:${#___}}
__=$__$((${#__}|$_____))$((${#__}));___=$___${__:${#___}:${#___}};____=$($__<<<$_____|$__)
_____=${____:$((${#__}-${#___})):${#?}};___=$___$_____$_____;____=$($__<<<$____|$__|$__)
___=$___${____:$((${#?}+${#__})):${#?}};___=$___' '${____:$((${#___}+${#___})):${#?}}
___=$___${__:$((${#____}/${#___}-${#?})):${#?}};___=$___${____:$((${#____}#$_____-${#___})):${#?}}
___=$___ ${____:$((${#__}+${#?})):${#?}}${__:$((${#__}>>${#?})):${#?}}${__:${#_____}:${#?}}
___=$___${____:$((${#___}-${#?}-${#?})):${#?}};___=${___,,}
____=${____:$((${#___}+${#__}-${#?})):$((${#?}+${#?}))}
____=${____::${#?}}${__:${#_____}:${#?}}${____:${#?}};${____,,}<<<${___^}
Для запуска потребуется «Баш» четвёртой версии. Ничего вредоносного скрипт не делает смело запускайте из-под «рута», просто выведет надпись «Happy new year». Исходник надо скопировать в файл и запустить.
Теперь немного о принципе работы.
«Баш», к счастью, богат на разнообразные закорюки, но имена переменных, в условиях наших ограничений, могут состоять только из разного количество символов подчёркивания, их хорошо видно в коде — в них я собираю нужные последовательности букв. Откуда же берутся сами буквы?
О, тут мне пришлось поломать голову!
Чтобы начать получать буквы в промышленных количествах, мне сначала нужно получить в какой-то переменной имя команды base64 — передавая ей на вход всякий бред, можно получить на выходе весь алфавит.
Первые три буквы я взял из имени командного интерпретатора («bash», благо путь к нему передаётся на входе в переменной «$_»), а четвёртую — из имени специального файла, который используется, если некая программа не умеет принимать данные на стандартный вход. Имя файла всегда начинается с «/dev/fd», отсюда и берётся недостающая «e».
Цифры получить проще.
Во-первых, «баш» (как и многие шеллы) позволяет измерить длину переменной через конструкцию «${#имя}» (например, получить единицу проще простого — это просто длина значения переменной кода возврата предыдущей команды, так как у меня это значение всегда ноль, её длина всегда один).
Во-вторых, конструкция $((…)) позволяет делать вычисления, комбинируя длины разных переменных с операциями, я получаю недостающие цифры. Операций много, что даёт довольно большую свободу, из экзотики мне пришлось один раз применить операцию смены системы исчисления — решётку.
После того как я получил команду «base64», подставляя ей на вход (иногда через цепочку вызовов) имеющиеся у меня данные, можно выудить из возвращаемого мусора оставшиеся буквы. Их я выкусываю при помощи операции удаления символов или выделения подстроки — эти операции в «шеллах» так же делаются «закорюками».
Ближе к концу пригождаются новые операции с переменными в четвёртом «баше» — там теперь можно менять регистр буквы, без этого пришлось бы куда тяжелее.
Так в конце получается команда «cat<<<'Happy new year'», которую я и запускаю. Почему не «echo» или «printf»? Они просто длиннее — каждая лишняя буква это морока с переменными и операциями.
Happy new year!
Автор: bolk