Этот сайт — моя персональная записная книжка. Интересны мне, по большей части, программирование, история и события из моей жизни.

Обратная разработка GIFLITE.EXE

Вчера мучился бессонницей, нужно было чем-то себя занять. Обычно я в таких случаях занимаюсь «Виолой», а тут, видимо, на меня повлияло близкое знакомство с JOPA — компилятором Джавы, решил направить свои силы куда-нибудь ещё.

Когда-то давно, когда я активно верстал, формат GIF был одним из самых ходовых, для анимации так вообще альтернатив не было. И мы в то время в обязательном порядке занимались оптимизацией графики.

В случае GIF очень хорошо помогала известная утилита GIFLITE.EXE — коммерческая разработка компании «Вайт Ривер Софтвейр» (White River Software), которая, по всей видимости, давно исчезла, так как я про неё ни в какой другой связи никогда ничего не слышал.

Утилита была под DOS, но я тогда работал под «Виндой» и проблем это не создавало, но позже, когда я пересел на «Мак», пользоваться ей стало неудобно. Тем не менее я всё равно ей ещё долго пользовался через всякие эмуляторы.

Она всегда меня интриговала — было интересно что она вообще такое делает, как ей удаётся уменьшить размер гифа и чем отличаются её методы сжатия, которые задаются ключом -m.

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

Забегая вперёд, хочу сказать, что эксперимент удался — программа создаёт в точности такие же GIF-файлы во всех режимах и я, кстати, получил ответ на свой вопрос — бо́льшая часть методов в ней объединяет близкие цвета, уменьшая файл за счёт этого.

А теперь, немного подробностей.

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

Opus 4.5 показался смелым исследователем, который идёт к цели, не пасует перед проблемами. Если где-то что-то непонятно, выскажет несколько гипотез, сам их проверит, докопается до истины. Выше всяких похвал.

GPT-5.1 Codex Max показался немного медлительным и чуть туповатым парнем, таким неповоротливым увальнем сибирских размеров, старательным, но звёзд с неба не хватающим.

Grok Code — торопыга, который как будто считает себя чересчур способным, много фантазирует, принимая свои фантазии за реальность и вообще слишком некритично, без рассуждений всё воспринимающий.

Во-вторых, я хоть и написал на «Гитхабе», что делал обратную разработку методом «чёрного ящика», на деле пришлось активно смотреть в исходники.

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

Потом я установил radare2 с плагином r2ghidra и нарезал бинарный файл на сишные функции. Код восстановился плохо, с лакунами, поэтому я запустил отдельную сетку, которой буквально по шагам объяснял что делать. Основная идея — довести сишный код до читаемого состояния, разбираясь с функциями от самых коротких к более длинным.

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

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

В полным соответствии с принципом Парето, 20% кода отняло у меня 80% времени. Тут очень хорошо показал себя Opus 4.5, — поскольку в коде разобраться было сложно, там 40 тысяч строк на ассемблере, он ставил очень много эксприментов, сравнивая два набора файлов между собой — тот, который получался при запуске оригинального GIFLITE.EXE с нашим.

Мы долго не могли добиться бинарной точности результирующих файлов — очень много нюансов, которые влияли на то, что получалось. Вплоть до реализации алгоритма сортировки цветов, функции хеширования и прочих мелких деталей. Восстанавливать детали помог ассемблерный код — в Си некоторые подробности не перенеслись, отчасти из-за таблицы виртуальных функций, которую «Гидра» (r2ghidra) расщёлкать не смогла.

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

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