Развлечения джентельменов: Binary Golf

Перепробовав все возможные излишества, девиации и грани декаданса, истинный джентельмен всегда возвращается к компилятору.

Нет это не баг, это спецэффект!
Нет это не баг, это спецэффект!

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

Я ошибался.

То что описано в этой статье — за гранью понимания нормального разработчика и тем более нормального человека, далекого от ИТ.

Я честно и при всем желании не смогу объяснить даже современным «молодым специалистам» от разработки, протирающим штаны в опенспейсе за шлепаньем форм для очередного корпоративного маркетплейса насколько круто то что описано в этой статье.

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

Добро пожаловать, снова: https://binary.golf/
Добро пожаловать, снова: https://binary.golf/

Любовь и байты

Однажды в одном хорошем пабе собрались несколько настоящих джентельменов от мира разработки:

демосценеры, реверс-инженеры, ИБ-аналитики малвари и разумеется яркие представители «другой стороны».

Когда в одном месте собираются столь крутые профи, обязательно начинается потеха под названием «кто круче»:

─── Binary Golf Grand Prix 1 ───────────────────────────────────────────────//──

Welcome to the Binary Golf Grand Prix! This is a challenge for people who like
to craft tiny binaries.

Так и появился на свет этот замечательный конкурс:

The goal of the Binary Golf Grand Prix is to challenge programmers to make the smallest possible binary that fits within certain constraints.

Cуть развлечения — создать минимально возможный запускаемый бинарник, который делает хоть что‑то интересное.

Но этого показалось мало, поэтому помимо основной задачи, джентельмены каждый год придумывают себе дополнительные:

The binary you will craft will be the same executable when flipped backwards.

Да, вы все правильно поняли, а некоторые наверное даже сильно удивились с такой постановки вопроса — задача заключается в создании запускаемого приложения, которое бы продолжило запускаться его бинарное содержимое перевернуть:

$ xxd some.random.exe | head -n 1
00000000: 4d5a 9000 0345 0000 0400 0000 ffff 0000  MZ...E..........

The entire binary will be reversed, and the first byte, will be the last byte:

4d5a 9000 0345 .... <-- reversed --> .... 4503 0090 5a4d 


Критериев оценки в столь замечательном конкурсе два длина и толщина:

размер запускаемого бинарника и «процент реиспользования» байт при запуске в обратном порядке.

В оригинале:

Scores will be calculated based on both the size of the executable, as well asthe percentage of bytes executed when it is run.

Так что у джентельменов все серьезно.

Исходный код всех работ с описанием выложен на Github, также можно посмотреть разбор победителей этого замечательного конкурса за 2020й год и дальше не читать:

Но если вы все же решили продолжить, то ниже будет описан реальный запуск каждой работы этого удивительного конкурса.

BootNoodle: A Palindromic Bootloader for BGGP

Автор: xcellerator

Статья с детальным описанием процесса находится тут, а так выглядит оригинальный бинарник со стильным оформлением:

4d12b76bb0bed253f2ab25867404dab5.png

Запускается в эмуляторе QEMU:

qemu-system-x86_64 bin/bootnoodle.bin

В работе:

947f2a5a0b4373fbcddd0d471f581ca6.png

Вот так выглядит сборка и создание «зеркальной» копии:

mkdir bin 2>/dev/null
nasm -f bin -o bin/bootnoodle.bin src/bootnoodle.asm
dd if=bin/bootnoodle.bin of=bin/tmp.bin bs=1 count=256
rm bin/bootnoodle.bin
perl -0777pe '$_=reverse $_'  bin/tmp.bin > bin/tmp2.bin
cat bin/tmp.bin bin/tmp2.bin > bin/bootnoodle.bin
rm bin/tmp*

512 байт на все, если вы вдруг не заметили.

И это у джентельменов считается «слишком много».

ns.bggp: Palindromic 64 bit ELF binary

Автор: netspooky

Статья с описанием: https://n0.lol/elf-palindrome-original/

Работа с оформлением, которую можно распечатать и повесить в рамку на стену:

bc54db3d98e33ad8e839040affa0de33.png

Он же в упакованном виде:

base64 -d <<< \
f0VMRgUP/zFIPLCQkJDrNAIAPgABAAAABAAAAAEAAAAcAAAAAAAAAAAAAAAAAAAAAQAAAEAAOAAB\
AAIA6wsAAAAAAADrCwAAAAAAADzrwDFIUFVQUFlTUFlQU1lQUFVQ6xiQkJCQkAUPlbZAIObBSMaJ\
D7LHiQAAAAG4AQAAAInHsg+JxkjB5iBAtpUPBZCQkJCQGOtQVVBQWVNQWVBTWVBQVVBIMcDrPAAA\
AAAAAAvrAAAAAAAAC+sAAgABADgAQAAAAAEAAAAAAAAAAAAAAAAAAAAcAAAAAQAAAAQAAAABAD4A\
AjTrkJCQsDxIMf8PBUZMRX8= > ns.bggp

Теперь о печальном:

This was tested and built on Ubuntu 20.04 with kernel 5.4.0–42-generic.

Из-за последних изменений в ядре, бинарник более не работает на 6.х ядрах, по крайней мере мне не удалось запустить ни на одной из подконтрольных систем, увы.

Вот так это должно было выглядеть:

$ ./build.sh
Executing initial binary...
PUPPYSPYPSYPPUP
00000000: 7f45 4c46 050f ff31 483c b090 9090 eb34  .ELF...1H<.....4
00000010: 0200 3e00 0100 0000 0400 0000 0100 0000  ..>.............
00000020: 1c00 0000 0000 0000 0000 0000 0000 0000  ................
00000030: 0100 0000 4000 3800 0100 0200 eb0b 0000  ....@.8.........
00000040: 0000 0000 eb0b 0000 0000 0000 3ceb c031  ............<..1
00000050: 4850 5550 5059 5350 5950 5359 5050 5550  HPUPPYSPYPSYPPUP
00000060: eb18 9090 9090 9005 0f95 b640 20e6 c148  ...........@ ..H
00000070: c689 0fb2 c789 0000 0001 b801 0000 0089  ................
00000080: c7b2 0f89 c648 c1e6 2040 b695 0f05 9090  .....H.. @......
00000090: 9090 9018 eb50 5550 5059 5350 5950 5359  .....PUPPYSPYPSY
000000a0: 5050 5550 4831 c0eb 3c00 0000 0000 000b  PPUPH1..<.......
000000b0: eb00 0000 0000 000b eb00 0200 0100 3800  ..............8.
000000c0: 4000 0000 0100 0000 0000 0000 0000 0000  @...............
000000d0: 0000 0000 1c00 0000 0100 0000 0400 0000  ................
000000e0: 0100 3e00 0234 eb90 9090 b03c 4831 ff0f  ..>..4.....<H1..
000000f0: 0546 4c45 7f                             .FLE.

Reversing...
Executing binary in reverse...
PUPPYSPYPSYPPUP
00000000: 7f45 4c46 050f ff31 483c b090 9090 eb34  .ELF...1H<.....4
00000010: 0200 3e00 0100 0000 0400 0000 0100 0000  ..>.............
00000020: 1c00 0000 0000 0000 0000 0000 0000 0000  ................
00000030: 0100 0000 4000 3800 0100 0200 eb0b 0000  ....@.8.........
00000040: 0000 0000 eb0b 0000 0000 0000 3ceb c031  ............<..1
00000050: 4850 5550 5059 5350 5950 5359 5050 5550  HPUPPYSPYPSYPPUP
00000060: eb18 9090 9090 9005 0f95 b640 20e6 c148  ...........@ ..H
00000070: c689 0fb2 c789 0000 0001 b801 0000 0089  ................
00000080: c7b2 0f89 c648 c1e6 2040 b695 0f05 9090  .....H.. @......
00000090: 9090 9018 eb50 5550 5059 5350 5950 5359  .....PUPPYSPYPSY
000000a0: 5050 5550 4831 c0eb 3c00 0000 0000 000b  PPUPH1..<.......
000000b0: eb00 0000 0000 000b eb00 0200 0100 3800  ..............8.
000000c0: 4000 0000 0100 0000 0000 0000 0000 0000  @...............
000000d0: 0000 0000 1c00 0000 0100 0000 0400 0000  ................
000000e0: 0100 3e00 0234 eb90 9090 b03c 4831 ff0f  ..>..4.....<H1..
000000f0: 0546 4c45 7f                             .FLE.

Comparing hashes...
c082d226c96b7251649c48526dd9766071fa5e59  ns.bggp
c082d226c96b7251649c48526dd9766071fa5e59  ns.bggp.R

Текст «PUPPYSPYPSYPPUP» это вывод приложения при запуске.

Viznut/PWP

Автор: viznut

Статья с описанием: http://viznut.fi/demos/vic20/vizpalapziv.html

Работа:

1e652b605d388fa719d0a1b5373c7b66.png

Также сие произведение компьютерного исскуства показано в работе на заглавной картинке к статье, краткая аннотация от автора:

Entry name: VIZPALAPZIV
Executable format: Commodore 8-bit PRG format on Commodore VIC-20
Number of bytes: 20 (including the 2-byte start address)
Executed bytes: 18 (every byte except the start address, i.e. 90%)

Bytes: 7c 00 8f 0f 90 25 48 48 73 a9 a9 73 48 48 25 90 0f 8f 00 7c

Да, это программа для Commodore, вот такой игрушечной машинки из 80х:

041d9e7f696ec93276c7742c47f83a79.jpeg

Которую мало кто из читателей имел возможность видеть в живую.

BGGP.COM

Автор: Boo Khan Ming

Работа:

af3b17a15e13bca08cc8ec135967a0c8.png

Как гласит известная поговорка:

неважно чем вы занимаетесь, всегда найдется азиат который сделает это лучше вас.

И код выше — лучшая тому иллюстрация.

Простой малазийский паренек сорвал куш — его код стал победителем этой специальной олимпиады в 2020 м году:

Hi!
Nice to meet you everyone there!
I am Wu (Boo Khan-Ming) from Malaysia.
I am not a scene/demo coder. 
Just join this ASMCOMPO3 for fun.

Исходник на ассемблере под DOS:

JMP 103             EB01
RET                 C3
MOV AX, B800        B800B8
MOV ES, AX          8EC0
MOV DI, 07D0        BFD007  
MOV AX, 9090        B89090
MOV ES:[DI], AX     268905
ADD AX, 2689        058926
NOP                 90
NOP                 90
MOV AX, D007        B807D0
MOV DI, 8EC0        BFC08E
MOV AX, B800        B800B8
RET                 C3

Вот так это выглядит в работе:

При работе синий блок еще и мигает.
При работе синий блок еще и мигает.

Эпилог

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

Так что точно будет продолжение, следите за аннонсами на канале.

P.S.

Отдельно доставляет блог создателя BGGP, некоторые материалы оттуда точно будут переведены в ближайшем будущем.

P.P. S.

Хабр не поддерживает анимацию, поэтому не получилось вставить оригинальный GIF с эффектами на заглавной картинке, насладиться им без заморочек со сборкой и запуском можно в оригинальной статье в нашем блоге.

0×08 Software

Мы небольшая команда ветеранов ИТ‑индустрии, создаем и дорабатываем самое разнообразное программное обеспечение, наш софт автоматизирует бизнес‑процессы на трех континентах, в самых разных отраслях и условиях.

Оживляем давно умершее,  чиним никогда не работавшее и создаем невозможное — затем рассказываем об этом в своих статьях.

© Habrahabr.ru