Пред­ставь: откры­ваешь файл с кодом в тек­сто­вом редак­торе — и видишь абсо­лют­но пус­тое мес­то, хотя скрипт прек­расно выпол­няет­ся. Такая обфуска­ция дей­стви­тель­но сущес­тву­ет. В этой статье мы изу­чим магичес­кие при­емы, зас­тавля­ющие код исче­зать пря­мо у нас перед гла­зами. Ты уви­дишь, как сов­ремен­ные обфуска­торы исполь­зуют эту идею, что­бы прев­ратить обыч­ный скрипт в пус­тоту, сох­раняя его работос­пособ­ность.

Ты, веро­ятно, читал мои статьи про раз­личные спо­собы обфуска­ции. Сре­ди опи­сан­ных мною методов встре­чают­ся даже весь­ма курь­езные. Понят­ное дело, самый луч­ший спо­соб скрыть код — ког­да в ито­ге его не вид­но вооб­ще или он замас­кирован внут­ри лож­ной отвле­кающей информа­ции.

Вто­рой слу­чай называ­ется сте­ганог­рафи­ей. Сегод­ня же я хочу рас­ска­зать о пер­вом слу­чае: ког­да, открыв код в тек­сто­вом редак­торе, непос­вящен­ный юзер видит на его мес­те... пус­тое ничего. Да, такое дей­стви­тель­но быва­ет: сущес­тву­ют методы обфуска­ции, пос­ле которых вмес­то при­выч­ной мешани­ны слу­чай­ных сим­волов получа­ется визу­аль­но пус­тое мес­то, как буд­то код отсутс­тву­ет вов­се.

Нем­ного пораз­мыслив, лег­ко догадать­ся, как дос­тичь подоб­ного эффекта: сущес­тву­ет мно­жес­тво слу­жеб­ных сим­волов, визу­аль­но не отоб­ража­емых тек­сто­выми редак­торами, — про­белы, табуля­ции, все­воз­можные перево­ды строк и так далее. Конеч­но, хакеры, воору­жен­ные шес­тнад­цатерич­ными редак­торами, сме­ются над подоб­ными огра­ниче­ниями, но прос­тому поль­зовате­лю, у которо­го Hex-редак­тор вызыва­ет бла­гого­вей­ный ужас и для прос­мотра по умол­чанию нас­тро­ен какой‑нибудь Wordpad, Notepad или, в самом прод­винутом слу­чае, cat, такое кажет­ся сво­еоб­разной маги­ей. Осо­бен­но если этот самый поль­зователь при­вык к мод­ным ныне скрип­товым язы­кам с тек­сто­вым кодом типа Python или JavaScript, для которых обфуска­ция как раз наибо­лее акту­аль­на.

Счи­тает­ся, что впер­вые подоб­ная идея была выс­казана в качес­тве шут­ки еще в 1997 году соз­дателем С++ Бьёр­ном Стра­устру­пом, как абсур­дный путь эво­люции язы­ка С++. Одна­ко в наш безум­ный век любая стран­ная идея воп­лоща­ется в реаль­ность, и спус­тя пять лет Эдвин Брэ­ди и Крис Мор­рис соз­дали эзо­тери­чес­кий язык прог­рамми­рова­ния Whitespace. Собс­твен­но, в этом язы­ке впер­вые и была воп­лощена кон­цепция невиди­мос­ти кода в тек­сто­вом редак­торе.

Для ее реали­зации в язы­ке оста­вили все­го три зна­чимых сим­вола: про­бел (код сим­вола 0x20, обоз­нача­емый соз­дателя­ми как L), табуля­ция (0x9, T) и перевод стро­ки, Line feed (0xA, S). Осталь­ные сим­волы исполь­зуют­ся в качес­тве ком­мента­риев, что дела­ет воз­можным при­мене­ние кода Whitespace в сте­ганог­рафии. Как видишь, зна­чимые сим­волы дей­стви­тель­но не отоб­ража­ются в тек­сто­вом редак­торе, хотя выделя­ются и редак­тиру­ются, я уж не говорю про шес­тнад­цатерич­ные редак­торы. Поэто­му для наг­ляднос­ти прог­раммы на Whitespace записы­вают пос­ледова­тель­ностью сим­волов S, T, L или гра­фичес­ки, выделяя про­белы от табуля­ций раз­ными цве­тами.

Как и все нор­маль­ные язы­ки прог­рамми­рова­ния, Whitespace име­ет свой син­таксис и свою сис­тему команд: шесть команд манипу­ляции со сте­ком (push, dup, copy, swap, discard и slide), пять ариф­метичес­ких команд (add, sub, mul, div и mod), две коман­ды дос­тупа к пулу перемен­ных heap (store и retrieve), семь управля­ющих команд — куда ж без них (label, call, jmp, jz, jn, ret, exit). Еще есть четыре коман­ды вво­да‑вывода (outchar, outnum, readchar и readnum). У команд име­ются аргу­мен­ты — чис­ла и стро­ки в дво­ичном пред­став­лении, где про­бел интер­пре­тиру­ется как ноль, а табуля­ция — еди­ница.

Не буду силь­но углублять­ся в под­робнос­ти осо­бен­ностей язы­ка, про него и так написа­но дос­таточ­но ста­тей, с которы­ми ты можешь озна­комить­ся самос­тоятель­но, нап­ример на Хаб­ре, я же хочу рас­ска­зать нес­коль­ко о дру­гом.

Ес­ли называть вещи сво­ими име­нами, Whitespace — это даже не язык прог­рамми­рова­ния, а байт‑код неко­его упро­щен­ного сте­ково­го ассем­бле­ра. Понят­ное дело, при всем количес­тве спе­циали­зиро­ван­ных IDE, соз­данных для лю­бите­лей стран­ного, на пол­ном серь­езе писать прог­рамму в про­белах, табуля­циях и перево­дах стро­ки ни один пси­хичес­ки здо­ровый человек не смо­жет (хотя это, похоже, соз­дателя­ми и не задумы­валось изна­чаль­но).

Да­же для пре­обра­зова­ния с птичь­его кода LSSSTSTTS тре­бует­ся прос­тей­ший тран­сля­тор, а по‑хороше­му для «прог­рамми­рова­ния» на таком язы­ке нужен ассем­блер. Да и в качес­тве обфуска­тора эта кон­цепция не осо­бо под­ходит, в пер­вую оче­редь тем, что тран­сля­ция с любого сов­ремен­ного высоко­уров­невого объ­ектно ори­енти­рован­ного скрип­тового язы­ка на подоб­ный сте­ковый ассем­блер дос­таточ­но тру­доем­ка и тре­бует боль­шого объ­ема кода (который, к нес­частью, прек­расно видим в тек­сто­вом редак­торе и неил­люзор­но тор­мозит при работе).

Тем не менее прог­раммист­ская общес­твен­ность в свое вре­мя была так впе­чат­лена этим язы­ком, что соз­дала реали­зации интер­пре­тато­ра Whitespace на мно­гих популяр­ных язы­ках: нап­ример, на JavaScript, Python и даже на Ruby.

Продолжение доступно только участникам

Материалы из последних выпусков становятся доступны по отдельности только через два месяца после публикации. Чтобы продолжить чтение, необходимо стать участником сообщества «Xakep.ru».

Присоединяйся к сообществу «Xakep.ru»!

Членство в сообществе в течение указанного срока откроет тебе доступ ко ВСЕМ материалам «Хакера», позволит скачивать выпуски в PDF, отключит рекламу на сайте и увеличит личную накопительную скидку! Подробнее

  • Подпишись на наc в Telegram!

    Только важные новости и лучшие статьи

    Подписаться

  • Подписаться
    Уведомить о
    0 комментариев
    Старые
    Новые Популярные
    Межтекстовые Отзывы
    Посмотреть все комментарии