Обфусцированный bash-скрипт CDN Akamai продаётся потребителям в розничных магазинах

от автора

Когда жена сказала мне: «Давай покажу футболку, которую я нашла…», у меня не было совершенно никаких предположений, но я определённо не ждал увидеть напечатанный на спине обфусцированный bash-скрипт, который выводит сообщение-пасхалку.

Я не любитель кликбейтных заголовков, но понимаю, почему редакторам они так нравятся. Заголовок статьи, строго говоря, совершенно правдив, но, наверно, не в том смысле, в котором вы бы ожидали. Обфусцированный код на самом деле оказался пасхалкой, он распространяется в магазинах Uniqlo в рамках кампании Peace for All на замечательных футболках, дизайн которых разработала Akamai.

Он очень крутой! Спереди изображено сердце в фигурных скобках:

Front

А на спине находится большой текстовый блок:

Back

Это … шебанг?!

Моя жена была права: мне действительно было интересно. Это что… шебанг?

Давайте приглядимся к текстовому блоку:

The Script

Скрипт

Да, шебанг! На футболке, продаваемой в дорогом магазине. И он определённо закодирован в base64.

Любопытно. Я сказал жене, что так, по сути, распространяются вирусы, и купил футболку.

С распознаванием возникли трудности

У меня есть хорошие и плохие новости:

  • Плохие новости в том, что base64 не имеет коррекции ошибок, поэтому транскрипция должна быть идеальной. Жаль.

  • Хорошая новость заключалась в том, что строка, похоже, осталась в сохранности. По крайней мере, она завершается нужным заполнителем и содержит соответствующие кавычки и скобки. И это хорошо, потому что Uniqlo x Akamai продают футболку другого дизайна с незавершённой надписью. Текст взят из текстового блока, который не скомпилируется. Например, импорты вырезаны, а сам код завершается на retu вместо return. И очень жаль, потому что сама футболка очень красивая и на ней есть очень идиоматическая команда go doStuff(msg, work....

Я выполнял OCR несколькими способами: сначала при помощи встроенной функции OCR circle-to-search в Android, которая часто справляется очень хорошо. Потом при помощи Tesseract с дополнительными опциями и настройками. В третий раз я пропустил текст через Claude. Затем я создал diff трёх результатов и попросил Claude вывести таблицу мест для быстрой проверки; благодаря этому стало очень просто, хотя и долго разобраться с оставшимся. В результате получилась такая строка:

IyEvYmluL2Jhc2gKCiMgQ29uZ3JhdHVsYXRpb25zISBZb3UgZm91bmQgdGhlIGVhc3RlciBlZ2chIOKdpO+4jwojIOOBiuOCgeOBp+OBqOOBhuOBlOOBluOBhOOBvuOBme+8gemaoOOBleOCjOOBn+OCteODl+ODqeOCpOOCuuOCkuimi+OBpOOBkeOBvuOBl+OBn++8geKdpO+4jwoKIyBEZWZpbmUgdGhlIHRleHQgdG8gYW5pbWF0ZQp0ZXh0PSLimaVQRUFDReKZpUZPUuKZpUFMTOKZpVBFQUNF4pmlRk9S4pmlQUxM4pmlUEVBQ0XimaVGT1LimaVBTEzimaVQRUFDReKZpUZPUuKZpUFMTOKZpVBFQUNF4pmlRk9S4pmlQUxM4pmlIgoKIyBHZXQgdGVybWluYWwgZGltZW5zaW9ucwpjb2xzPSQodHB1dCBjb2xzKQpsaW5lcz0kKHRwdXQgbGluZXMpCgojIENhbGN1bGF0ZSB0aGUgbGVuZ3RoIG9mIHRoZSB0ZXh0CnRleHRfbGVuZ3RoPSR7I3RleHR9CgojIEhpZGUgdGhlIGN1cnNvcgp0cHV0IGNpdmlzCgojIFRyYXAgQ1RSTCtDIHRvIHNob3cgdGhlIGN1cnNvciBiZWZvcmUgZXhpdGluZwp0cmFwICJ0cHV0IGNub3JtOyBleGl0IiBTSUdJTlQKCiMgU2V0IGZyZXF1ZW5jeSBzY2FsaW5nIGZhY3RvcgpmcmVxPTAuMgoKIyBJbmZpbml0ZSBsb29wIGZvciBjb250aW51b3VzIGFuaW1hdGlvbgpmb3IgKCggdD0wOyA7IHQrPTEgKSk7IGRvCiAgICAjIEV4dHJhY3Qgb25lIGNoYXJhY3RlciBhdCBhIHRpbWUKICAgIGNoYXI9IiR7dGV4dDp0ICUgdGV4dF9sZW5ndGg6MX0iCiAgICAKICAgICMgQ2FsY3VsYXRlIHRoZSBhbmdsZSBpbiByYWRpYW5zCiAgICBhbmdsZT0kKGVjaG8gIigkdCkgKiAkZnJlcSIgfCBiYyAtbCkKCiAgICAjIENhbGN1bGF0ZSB0aGUgc2luZSBvZiB0aGUgYW5nbGUKICAgIHNpbmVfdmFsdWU9JChlY2hvICJzKCRhbmdsZSkiIHwgYmMgLWwpCgogICAgIyBDYWxjdWxhdGUgeCBwb3NpdGlvbiB1c2luZyB0aGUgc2luZSB2YWx1ZQogICAgeD0kKGVjaG8gIigkY29scyAvIDIpICsgKCRjb2xzIC8gNCkgKiAkc2luZV92YWx1ZSIgfCBiYyAtbCkKICAgIHg9JChwcmludGYgIiUuMGYiICIkeCIpCgogICAgIyBFbnN1cmUgeCBpcyB3aXRoaW4gdGVybWluYWwgYm91bmRzCiAgICBpZiAoKCB4IDwgMCApKTsgdGhlbiB4PTA7IGZpCiAgICBpZiAoKCB4ID49IGNvbHMgKSk7IHRoZW4geD0kKChjb2xzIC0gMSkpOyBmaQoKICAgICMgQ2FsY3VsYXRlIGNvbG9yIGdyYWRpZW50IGJldHdlZW4gMTIgKGN5YW4pIGFuZCAyMDggKG9yYW5nZSkKICAgIGNvbG9yX3N0YXJ0PTEyCiAgICBjb2xvcl9lbmQ9MjA4CiAgICBjb2xvcl9yYW5nZT0kKChjb2xvcl9lbmQgLSBjb2xvcl9zdGFydCkpCiAgICBjb2xvcj0kKChjb2xvcl9zdGFydCArIChjb2xvcl9yYW5nZSAqIHQgLyBsaW5lcykgJSBjb2xvcl9yYW5nZSkpCgogICAgIyBQcmludCB0aGUgY2hhcmFjdGVyIHdpdGggMjU2LWNvbG9yIHN1cHBvcnQKICAgIGVjaG8gLW5lICJcMDMzWzM4OzU7JHtjb2xvcn1tIiQodHB1dCBjdXAgJHQgJHgpIiRjaGFyXDAzM1swbSIKCiAgICAjIExpbmUgZmVlZCB0byBtb3ZlIGRvd253YXJkCiAgICBlY2hvICIiCgpkb25lCgo=

Декодированный скрипт

После декодирования Base64 скрипт оказался приятной и удобно откомментированной пасхалкой:

#!/bin/bash# Congratulations! You found the easter egg! ❤️# おめでとうございます!隠されたサプライズを見つけました!❤️# Define the text to animatetext="♥PEACE♥FOR♥ALL♥PEACE♥FOR♥ALL♥PEACE♥FOR♥ALL♥PEACE♥FOR♥ALL♥PEACE♥FOR♥ALL♥"# Get terminal dimensionscols=$(tput cols)lines=$(tput lines)# Calculate the length of the texttext_length=${#text}# Hide the cursortput civis# Trap CTRL+C to show the cursor before exitingtrap "tput cnorm; exit" SIGINT# Set frequency scaling factorfreq=0.2# Infinite loop for continuous animationfor (( t=0; ; t+=1 )); do    # Extract one character at a time    char="${text:t % text_length:1}"        # Calculate the angle in radians    angle=$(echo "($t) * $freq" | bc -l)    # Calculate the sine of the angle    sine_value=$(echo "s($angle)" | bc -l)    # Calculate x position using the sine value    x=$(echo "($cols / 2) + ($cols / 4) * $sine_value" | bc -l)    x=$(printf "%.0f" "$x")    # Ensure x is within terminal bounds    if (( x < 0 )); then x=0; fi    if (( x >= cols )); then x=$((cols - 1)); fi    # Calculate color gradient between 12 (cyan) and 208 (orange)    color_start=12    color_end=208    color_range=$((color_end - color_start))    color=$((color_start + (color_range * t / lines) % color_range))    # Print the character with 256-color support    echo -ne "\033[38;5;${color}m"$(tput cup $t $x)"$char\033[0m"    # Line feed to move downward    echo ""done

Он непрерывно выводит синусоидой сообщение кампании — Peace for All:

Peace for All

Подробности: выбор шрифта

Дополнение: приведённое ниже название шрифта ошибочно! Пользователь ralphinus на Hacker News сообщил, что это Roboto Mono. Не знаю, как я проглядел совершенно отличающуюся g.

Вероятно, Uniqlo работает с Windows: моё внимание привлёк шрифт; я почти уверен, что это Consolas. (Мне посчастливилось однажды переписываться с дизайнером шрифта Лукасом де Гротом по поводу судебного дела, в котором один из его шрифтов был использован для подделки документа. Он оказался очень отзывчивым и любезно подтвердил в письменном виде все необходимые факты, хотя ничем не был нам обязан.). Обратите внимание на тонкое перечёркивание 0, отсутствие засечек 1 и скруглённые кривые букв BDyg, а также цифры 2. Это удивительно, ведь Consolas — это в основном шрифт Windows; неожиданно увидеть его при запуске Bash.

Linux, язык Интернета

Когда выпустили эту футболку, Akamai опубликовала пресс-релиз, который тоже любопытен сочетанием технологий и маркетинга:

Концепция дизайна

Более 25 лет назад компания Akamai помогла сформировать основы современного Интернета. Дизайн этой футболки отсылает к тем ранним временам, когда Всемирная сеть только входила в нашу жизнь. Светло-бежевый цвет напоминает о пластиковых корпусах первых компьютеров с Интернет-подключением, известных как «бежевые коробки». Сердце на груди символизирует то, как интернет используется во благо людей по всему миру. На спине футболки напечатан настоящий программный код. Это отсылка к Linux — открытой операционной системе, ставшей одним из краеугольных камней современного интернета. Этот общий технологический язык объединяет Akamai, ведущие мировые бренды и миллионы людей, которые пользуются их сервисами, пока мы вместе движемся к общей цели — делать мир безопаснее и повышать его связанность.

Я был не первым

Я специально не искал спойлеры, но понимал, что, разумеется, меня не первого заинтересовала эта загадка. Эту загадку решил и Вэнь Чуань Ли, в его посте тоже есть ссылка на другой пост (с которым я сверил свою транскрипцию.

ссылка на оригинал статьи https://habr.com/ru/articles/1057184/