Лекция: Как сломать TRIAL.COM

"— Я говорю людям: смотрите! У меня есть руки! Но мне говорят: «А что такое руки?»

Ф. Херберт. «Дюна».

Однажды вздумалось мне создать свою группу. Мысль, естественно, бредовая, но с другой стороны заманчивая. Многие проекты просто невозможно реализовать в одиночку. Группа же из пяти-десяти профессионалов уже способна написать хотя бы свою операционную систему или полный эмулятор 386+, включая и защищенный режим.

Одним из способов определить профессионализм человека — подсунуть ему crack_me и посмотреть, как он его взломает. В последнее время, кстати, хороших. crack_me стало очень мало. Обычно закладывают какой-нибудь математический алгоритм, решение которого требуется найти. Или, что еще хуже, просто зашиф­ровывают достаточно криптостойким алгоритмом — так, чтобы полный анализ был не возможен. Утомительные часы перебора (а то и дни) — кому они интересны?

Я попытался (и не без успеха) предложить нетривиальную задачу, рассчитан­ную на нестандартное мышление, при этом предоставив неограниченную свободу творчества. Увы, я был разочарован. Никто так и не приблизился к решению. Самое парадоксальное, что задачка была очень простой и… А, впрочем, зачем «и» — все равно никто не решил.

Ø Crack Me by [KPNC] ',ODh,Oah

Ø Если вы сломаете данный crack me, то получите членство в группе [KPNC]

Ø Под «сломать» понимается узнать, на кого зарегистрирован demo_def: точнее,

Ø расшифровать его. Там содержится имя экс-президента группы. Скажу сразу:

Ø оно не мое, поэтому забудьте про атаку по открытому тексту. Скажу больше

Ø для расшифровки нужно найти ключ длиной в шесть байт. Два из них –

Ø OxFO 0х83. Остается четыре. Ну что — найдете? Аль нет? Взломать будет

Ø непросто — эти шесть байт просто отсутствуют в ключе, (см. сам ключ)

Ø Есть два независимых метода взлома, так что дерзайте...

Ø [KPNC@ID.ru]

Ниже будет дано подробное решение. Быть может, оно кого-то рассмешит. Но… действительно, задачка проста (см. trial.corn). Условие, конечно, сформули­ровано нечетко, и прежде всего надо было определить: что собственно делать? Достоверно было известно только то, что в файле demo_def содержится имя вице-президента группы (и успел же он появиться!). И его надобно найти. Рассмотрим внимательнее этот файл:

00000000: ВА 01 14 00-5В 4В 50 4Е-43 5D 77 77-B4 01 10 00 Цхх [KPNC]ww-lxx

00000010: 42 02 C3 01-4C 01 04 00-9F 01 ЕЕ 00-55 01 10 00 ВхххЬхххЯхюхЦхх

00000020: 24 04 CD 01-EA 00 82 02-48 02 03 77-11 83 17 33 $х=хъхВхНххыхГхЗ

00000030: 84 02 82 02-6C 03 — - ДхВх1х

Ясно, что [KPNC] — это никак не искомое имя. Тогда… посмотрим как работает расшифровщик:

00000061: BF9701 mov di, 00097; Приемник

………………………………..

0000002E: AD lodsw; Читаем слово шифротекста<—1 0000002F: 33DB xor bx,bx; BX == NULL

00000031: 86E3 xchg ah,bl; BL == HiByte(AX)

00000033: F6F3 div Ы; AL === AH/ ~AL

00000035: AA stosb; Пишем расшифрованный байт 00000036: E2F6 loop 00000002E; —(1)—1

00000038: E85COO call 000000097; Вызываем расшифрованный ключ 0000003В: СЗ retn; Возврат.

Э, да шифровка-то тривиальна. И все бы коту масленица, да разработчик упоминал о каких-то шести «слизанных» байтах, в которых и «зарыта собака». Действительно, в demo_def шесть нулевых байт! И все старшие, т.е. делители. Ясно, что х/О смысла не имеет, и программа просто аварийно завершается. Разумеется, пропавшие байты по заверениям автора не относятся собственно к имени, да и не могли относиться, так как иначе было бы попросту нечестно. Хотя, в любом случае это не важно — уж слишком беспорядочно они разбросаны по тексту...

Давайте подумаем: что можно выжать из этого файла и какую тактику нам применить? Конечно же по открытому тексту! А почему нет? Мы же знаем очень много об этом коде, который выводит сообщение. Места хватит только на то, чтобы вывести его через функцию f.9\int 21, или, во всяком случае, через f.6 Хотя f.6 откинем — рассмотрим последнее слово шифротекста — ОхЗбС. Расшиф­руем его — ОхбС \ 0х3 == 0х36 == '$'. Опля! Кой-что интересное! Не так ли, господа? Пойдем дальше, точнее, вернемся назад и расшифруем еще два симво­ла — 0х82 \ 2 == 0х41 == 'А' и 0х84 \ 2 == 0х42 == 'В'. Итак, экс-президента зовут *ВА. А дальше нам путь преграждает любопытнейшая комбинация 0х17 \ 0х33 == 0? Запахло нечистым… 03\77;11\83; 17\ 33 целых три символа шифротекста, равные нулю, а в сумме шесть байт! Если их сложить с теми загадочными нулями, то… в общем многовато получится!

82\ 02 == 0х41 'А' и 48\ 02= 0х24 = '$' как-то непонятно выглядит. Однако так или иначе коду, выводящему это безобразие, отводится все меньше и меньше места, как раз ровно столько, сколько хватит на f.9, — но в таком случае мы имеем открытый текст, т.е. здоровую дыру, в которую можно пролезть. Заметим, что вызов int 0х21 трудно замаскировать. И точно, мы видим...

00000000: ВА 01 14 00-5В 4В 50 4Е-43 5D 77 77-B4 01 10 00 uxxx[kpnc]ww-)xx

00000010: 42 02 СЗ 01-4C 01 04 00-9F 01 ЕЕ 00-55 01 10 00 Bxl-xLxxxAxioxUxx

00000020: 24 04 CD 01-EA 00 82 02-48 02 03 77-11 83 17 33 $х=хъхВхНххчхГхЗ

00000030: 84 02 82 02-6C 03 — - ДхВх1х

Хотя, конечно, автор мог использовать call на тело своей программы, где стоит int 21 (ОхЕ8), но ОхЕ8 в коде не наблюдается, a OxCD ('=') есть. А что есть еще? Есть 0х21 (offset 0х10), но почему-то стоящий далеко от OxCD и ОхВ4 есть (mov ah,9), ну и 0х9 можно найти (offset 0х20, 0х24\0х4). Есть также MOV DX,? (ОхВА) и его старший байт — операнды (0х1 — 0х77 \0х77).

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

Пусть нам с некоторой достоверностью известен фрагмент оригинального текста, тогда можно проследить логику перемешивания байт. Допустим, OxCD и 0х21. Их отделяют всего 0х16 байт, или, точнее, ОхЕА в знаковом представлении.

cd oi-ea оо

Поразительно! Такое совпадение! Выходит, ключ содержится в файле! Ну а как пара mov ah,9 (ОхВ4 0х9)? Их отделяют 0х10 байт. И снова

в4 0110 оо

Итак, кажется, что-то прояснилось. Логика шифрования понятна. Можно хоть сейчас садиться и писать собственный дешифровщик. Ноль обозначает, что следующий расшифровываемый символ находится на п (где п — значение младшего байта) расстоянии от текущего. Любопытный прием. Криптор может «блохой» прыгать по файлу, собирая разбросанные байты.

ОК. Это мы выяснили. Теперь можно расшифровать demo_def, «выцарапать» из него имя и зашифровать снова. Но не будем торопиться. Это была только первая самая легкая стадия проверки на знание основ криптоанализа. (Примитив­нейшая атака по открытому тексту, что может быть еще проще?) Поразительно, но никто этого так и не решил! Печально, очень печально.

Ну да ладно, вторая стадия — на сообразительность. Чтобы trial.corn вывел это имя на экран, необходимо всего лишь изменить его расшифровщик. Это нетрудно сделать, если обратить внимание на следующие строки:

00000156: Е81600 call 00000016F 00000159: 49 dec ex 0000015A: B43F mov ah,03F ;"?" 0000015C: CD21 int 021

(см. сам файл). T.e. можно записать ключ по любому адресу в файле! И кое-что это подтверждает!

00000166: 803С90 cmp b, [si],090 ;«P» 00000169: 7403 je 00000016E — (з) 0000016В: E8COFF call 00000012Е — (4) 0000016Е: СЗ retn

Смысл этих строк такой — если первый байт ключа '90' == NOP, то он затирает trial.corn и тот, даже не делая попытки его расшифровать, переходит к другому ключу!

Так, про недостающие шесть байт —

00000002: 98 cbw 00000003: 83C406 add sp,006 00000006: 03FO add si,ax

их нужно вписать в обработчик int 0х0. При этом он будет корректно работать.

еще рефераты
Еще работы по истории