Fucky new year!

    Простите за мат в заголовке, это намёк на развлечение, начало которому дал язык «Брейнфак» — написать на каком-либо языке код, выполняющий что-то разумное, не используя букв и цифр. Мы уже видели JSFuck, PHPFuck, теперь я вам хочу представить Bashfuck:

    __=${_##*/};____=<(:);___=${__#???};_____=$((${#___}<<${#___}))
    __=${__::-${#___}}${____:$_____:${#___}}
    __=$__$((${#__}|$_____))$((${#__}));___=$___${__:${#___}:${#___}};____=$($__<<<$_____|$__)
    _____=${____:$((${#__}-${#___})):${#?}};___=$___$_____$_____;____=$($__<<<$____|$__|$__)
    ___=$___${____:$((${#?}+${#__})):${#?}};___=$___' '${____:$((${#___}+${#___})):${#?}}
    ___=$___${__:$((${#____}/${#___}-${#?})):${#?}};___=$___${____:$((${#____}#$_____-${#___})):${#?}}
    ___=$___\ ${____:$((${#__}+${#?})):${#?}}${__:$((${#__}>>${#?})):${#?}}${__:${#_____}:${#?}}
    ___=$___${____:$((${#___}-${#?}-${#?})):${#?}};___=${___,,}
    ____=${____:$((${#___}+${#__}-${#?})):$((${#?}+${#?}))}
    ____=${____::${#?}}${__:${#_____}:${#?}}${____:${#?}};${____,,}<<<${___^}

    Для запуска потребуется «Баш» четвёртой версии. Ничего вредоносного скрипт не делает смело запускайте из-под «рута», просто выведет надпись «Happy new year». Исходник надо скопировать в файл и запустить.

    Теперь немного о принципе работы.

    «Баш», к счастью, богат на разнообразные закорюки, но имена переменных, в условиях наших ограничений, могут состоять только из разного количество символов подчёркивания, их хорошо видно в коде — в них я собираю нужные последовательности букв. Откуда же берутся сами буквы?

    О, тут мне пришлось поломать голову!

    Чтобы начать получать буквы в промышленных количествах, мне сначала нужно получить в какой-то переменной имя команды base64 — передавая ей на вход всякий бред, можно получить на выходе весь алфавит.

    Первые три буквы я взял из имени командного интерпретатора («bash», благо путь к нему передаётся на входе в переменной «$_»), а четвёртую — из имени специального файла, который используется, если некая программа не умеет принимать данные на стандартный вход. Имя файла всегда начинается с «/dev/fd», отсюда и берётся недостающая «e».

    Цифры получить проще.

    Во-первых, «баш» (как и многие шеллы) позволяет измерить длину переменной через конструкцию «${#имя}» (например, получить единицу проще простого — это просто длина значения переменной кода возврата предыдущей команды, так как у меня это значение всегда ноль, её длина всегда один).

    Во-вторых, конструкция $((…)) позволяет делать вычисления, комбинируя длины разных переменных с операциями, я получаю недостающие цифры. Операций много, что даёт довольно большую свободу, из экзотики мне пришлось один раз применить операцию смены системы исчисления — решётку.

    После того как я получил команду «base64», подставляя ей на вход (иногда через цепочку вызовов) имеющиеся у меня данные, можно выудить из возвращаемого мусора оставшиеся буквы. Их я выкусываю при помощи операции удаления символов или выделения подстроки — эти операции в «шеллах» так же делаются «закорюками».

    Ближе к концу пригождаются новые операции с переменными в четвёртом «баше» — там теперь можно менять регистр буквы, без этого пришлось бы куда тяжелее.

    Так в конце получается команда «cat<<<'Happy new year'», которую я и запускаю. Почему не «echo» или «printf»? Они просто длиннее — каждая лишняя буква это морока с переменными и операциями.

    Happy new year!
    Share post

    Similar posts

    AdBlock has stolen the banner, but banners are not teeth — they will be back

    More
    Ads

    Comments 22

      +4
      Шедеврально! Сколько времени ушло на изобретение?) И да, с Наступающим!
        +3
        Базовый принцип-то я быстро придумал (10—20 минут), а практический результат рождался дольше — потренировался на двух «hello world» ([1], [2]) и сделал этот скрипт :)
        –7
        «Баш»
          +4
          Да, «Баш», уважаемый Eugene Pankov.
            –7
            Почему тогда не пиэйчпифак?
              +3
              Тема отдельной статьи.
                0
                Можно ждать статью? Серьезно, интересно узнать в чем разница
                  0
                  Это вероятно. Эти мысли размазаны по комментариям моего блога, если будет время, соберу в статью.
                    –2
                    Если так много исключений, может ваша теория неверна?
                +5
                Потому что вы лингвистические зануды
            0
            Для тех у кого нету Баша www.tutorialspoint.com/execute_bash_online.php
              +1
              Так в конце получается команда «cat<<<'Happy new year'», которую я и запускаю. Почему не «echo» или «printf»? Они просто длиннее — каждая лишняя буква это морока с переменными и операциями.


              echo 'Happy new year' короче же на 1 символ? Да и можно без кавычек:

              cat<<<'Happy new year'
              echo Happy new year
              
                +3
                Не буквенные и не цифровые символы-то нас не волнуют — их можно использовать непосредственно.
                +2
                -bash-4.1# bash test.sh
                test.sh: line 2: -${#___}: substring expression < 0
                test.sh: line 3: bash64: command not found
                test.sh: line 3: bash64: command not found
                test.sh: line 4: bash64: command not found
                test.sh: line 4: bash64: command not found
                test.sh: line 4: bash64: command not found
                test.sh: line 6: 0#: invalid number (error token is "0#")
                test.sh: line 10: b: command not found
                
                  0
                  У меня 4.3.30. Я, к сожалению, не очень-то знаю какие возможности «баша» в какой версии появились.
                    0
                    4.2.53 скрипт запускает (http://www.tutorialspoint.com/execute_bash_online.php).
                    0
                    Теперь еще бы tool в который кормишь текст, а на выходе получаешь код башфака.
                      0
                      Возможно займусь после праздников :)
                      0
                      А не проще был для получения цифр считать аргументы:
                      % bash -c $'__(){\n__=$#\n}\n__ ! + - \\\\;  echo $__'
                      4

                      ? Я в первую очередь об этом подумал.

                      Кстати говоря, $(( )) и $[ ] — одно и то же. Но почему‐то все используют двойные скобки.
                        0
                        Возможно в каких-то случаях и проще, но цифры очень разные нужны. Вот тут, например, я получал число 17:

                        ${#____}#$_____-${#___}

                        От случая зависит. Я задумывался о том, чтобы использовать функции, тем более, что им можно давать всякие прикольные имена:

                        $ bash -c $'@(){ __=$#;};@ ! + - \\\\;  echo $__'
                        4

                        Но на практике обошёлся без них. Возможно, если создавать транслятор «любая строка → Bashfuck», эта идея очень пригодится.
                        Кстати говоря, $(( )) и $[ ] — одно и то же. Но почему‐то все используют двойные скобки.
                        Кому уж что нравится. :) Я, например, больше люблю использовать $(…), а не `…` и let вместо ((…)).
                          0
                          let я что‐то нигде не видел, а относительно $() есть объективные соображения: попробуйте вставить `` внутрь ``. Это возможно с экранированием, но очень неудобно.
                        0
                        Написал ответ на статью на zsh: habrahabr.ru/post/247249/.

                        Only users with full accounts can post comments. Log in, please.