Взлом SEA 1.3.
Тяжелый случай.

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

Предыстория

В начале 99 года на моем счету было 9 успешно взломаных программ (хороший повод начать делать зарубки на клавиатуре), к тому же я тогда был очень самоувереным и потому взялся за интересную с моей точки зрения тему: взлом программы, работающей в защищенном режиме с использованием DOS 4GW. Под горячую руку попался SEA 1.3 - популярный вьювер графических файлов для DOS. Проблема заключалась в том, что при каждом запуске и выходе из программы надо было нажимать клавишу F6, что было довольно неудобно. Из всех хакерских инструментов у меня тогда имелись только HIEW версии, как помнится, 5.60, SoftIce 3.23 и W32Dasm, заведомо непригодный для решения этой проблемы. Через несколько часов я понял, что был слишком самоуверенным.

Статья

Во-первых, программа была написана на Watcom C/C++, с которым я никогда раньше не имел дела.
Во-вторых, оказалось, что программа непонятно зачем использует как 16-, так и 32-битную run-time system (это можно увидеть при помощи любого текстового просмотрщика, достаточно только поискать строку "Watcom").
Ну и ко всему прочему, из всего моего набора инструментов поставленной задаче хоть как-то соответствовал только HIEW. Но отступать было уже поздно, да и вьювером попользоваться очень хотелось.

Первое, что я сделал, это поставил breakpoint на обращение к видеопамяти. Для этого было нужно всего лишь нажимать Ctrl-D до тех пор, пока SoftIce не оказался в реальном режиме (это нетрудно определить по виду окна исполняемого кода - в качестве адресов там стоят значения вида XXXX:XXXX, а название текущего программного модуля - I/O System (можно и другое)). Теперь пишем BPR B800:0000 B800:0100 W (остановка при попытке записи в первые 257 байт видеопамяти, используемой для вывода текста в стандартном текстовом режиме). Разумеется, для успешного выполнения всех этих операций лучше находиться в режиме командной строки, т.к. все файловые менеджеры очень активно работают с экраном и вызывают множество ложных срабатываний.

Все это я делал для того, чтобы:

Немного повозившись с SoftIse, я более-менее освоился в коде нужного мне участка программы. Вообще, единожды увтдев код, генерируемый Watcom C, его нетрудно узнать (но не понять - это отдельный больной вопрос) и во всех других случаях. Если MS Visual C оптимизирует код за счет упрощения арифметических расчетов и мелких хитростей при вызове функций, но при этом ассемблерный листинг довольно легко читается, то в Watcom оптимизация построена на ускорении доступа к промежуточным результатам и часто используемым переменным, из-за чего программы не имеют очевидной структуры и неудобны для понимания. В общем, я нашел функцию вывода строки и после этого добрался до следующего куска (вместо реальных адресов - смещение в файле):

 ..............

 0004D007: E870590700                call 000C297C
 0004D00C: B860BD0100                mov eax,0001BD60
 0004D011: E8D6570000                call 000527EC ; Этот call проверяет,не
                                                   ; нажата ли клавиша F6
                                                   ; и возвращает результат
                                                   ; в AX
 0004D016: 85C0                      test eax,eax
 0004D018: 74F2                      jz 0004D00C
 0004D01A: B860BD0100                mov eax,0001BD60
 0004D01F: E8E4570000                call 00052808 ; Ожидает нажатия какой-
                                                   ; -либо клавиши.Возвращает
                                                   ; что-то вроде сканкода.
                                                   ; Непонятно,
                                                   ; зачем это здесь надо.
 0004D024: E8D8720700                call 000C4301
 0004D029: 3D40010000                cmp eax,00000140 ; Проверка: а не F6 ли
                                                      ; нажата?
 0004D02E: 75DC                      jnz 0004D00C
 0004D030: 5A                        pop edx
 0004D031: C3                        ret
 ................

Нетрудно догадаться, что для нормальной работы программы нужно всего лишь исправить jz 4D00C на jmp 4D030 (74 F2 на EB 16 по смещению в файле 4В018/19) - тогда программа будет считать, что клавиша F6 была нажата. Поскольку этот кусок кода работает только два раза (считывание клавиш во время работы собственно вьювера производится совсем другой функцией), никаких побочных эффектов это, казалось бы, вызывать не должно. Попробуем теперь сделать эти исправления в файле и запустить программу...

И что мы видим: на экране сообщение об ошибке CRC, а компьютер повис, и повис хорошо (если сделать это под NT, то просто повис). А все потому, что одна очень известная операционная система намертво виснет от банальной последовательности

        cli
myself: jmp myself

Чтобы не приходилось слишком часто давить Reset, нужно как-то обезвредить эту ловушку (а таких ловушек там оказалось больше чем достаточно). Например, поставить вместо cli (запретить прерывания) противоположную по действию команду sti или просто nop. После этого зависшую задачу по крайней мере можно успешно снять. Скажу честно - полностью изничтожить проверку CRC мне (да и не только мне - см. примечание) не удалось. Зато удалось ее обмануть. Дело в том, что программа проверяет не свою контрольную сумму, а контрольную сумму файла SEA.EXE! Из этого следует очевидный вывод: перед исправлением снять с SEA.EXE копию с другим именем, но в той же директории, исправить эту копию и потом запускать не SEA.EXE, а именно ее. И пускай себе она проверяет на целостность оригинальный файл - мы его не меняли!

Вот теперь все отлично работает и можно пользоваться вьювером, не отвлекаясь на нажимание всяких посторонних кнопок.

Примечание

В SEA 1.3 предусмотрен и другой способ - при помощи ключевого файла. Однако мне так и не удалось обнаружить ни одного такого файла, а единственный известный мне взлом SEA 1.3 провернул недавно ушедший на покой Marquis (кроме всего прочего, основатель United Cracking Forces, то есть далеко не последний человек в Warez Cracking), причем он тоже беспощадно правил машинный код и не отключил полностью проверку CRC. Самым очевидным отличием в его варианте взлома было то, что он переименовал оригинальный SEA.EXE в SEA.OLD а соответствующие исправления вносил в SEA.EXE.

(C) CyberManiac