Техника защиты компакт-дисков от копирования

         

Подключение дампа памяти


Для подключения дампа памяти к отладчику Windows Debugger (windbg.exe) в меню File

выберете пункт Crash Dump или воспользуйтесь "горячей" комбинацией клавиш <Ctrl>+<D>. В отладчике i386kd.exe для той же цели служит ключ "–z" командной строки, за которым следует полный путь к файлу дампа, отделенный от ключа одним или несколькими пробелами, при этом переменная окружения _NT_SYMBOL_PATH должна быть определена и должна содержать полный путь к файлам символьных идентификаторов, в противном случае отладчик аварийно завершит свою работу. Как один из вариантов, можно указать в командной строке ключ "–y" и тогда экран консоли будет выглядеть так:

i386kd –z C:\WINNT\memory.dmp -y C:\WINNT\Symbols, причем отладчик следует вызывать из Checked Build Environment/Free Build Environment консоли, находящейся в папке Windows 2000 DDK, иначе у вас ничего не получится.

Хорошая идея –— ассоциировать DMP-файлы с отладчиком i386kd.exe, запуская их одним нажатием клавиши <Enter> из менеджера FAR. Впрочем, выбор средства анализа –— дело вкуса. Кому-то нравиться KAnalyze, а кому-то достаточно и простенького DumpChk. Выбор аналитических инструментов чрезвычайно велик (один лишь DDK содержит четыре из них!) и, чтобы хоть как-то определиться с выбором, мы остановимся на i386kd.exe, также называемом Kernel Debugger.

Как только консоль отладчика появится на экране (а Kernel Debugger –— это консольное приложение, горячо любимое всеми, кто провел свою молодость за текстовыми терминалами), курсор наскоро дизассемблирует текущую машинную инструкцию и своим тревожным мерцанием затягивает нас в пучину машинного кода. Ну что, будем глазки строить или все-таки дизассемблировать? –— незлобно ворчим мы, выбивая на клавиатуре команду "u", заставляющую отладчик продолжить дизассемблирование.

Судя по символьным идентификаторам PspUnhandledExceptionInSystemThread и KeBugCheckEx мы находимся глубоко в ядре, а точнее –— в окрестностях того кода, что выводит BSOD на экран (листинг 3.22).


Откроем его: Панель управления à Администрирование à Просмотр событий (листинг 3.24).

Листинг 3.24. Копия "голубого экрана смерти", сохраненная в системном журнале

Компьютер был перезагружен после критической ошибки:

0x0000001e (0xc0000005, 0xbe80b000, 0x00000000, 0x00000000).

Microsoft Windows 2000 [v15.2195]

Копия памяти сохранена: C:\WINNT\MEMORY.DMP.

Листинг 24 копия голубого экрана смерти, сохраненная в системном журнале

Отталкиваясь от категории критической ошибки (0x1E), мы без труда сможем определить адрес инструкции-убийцы –— 0xBE80B000 (в приведенном листинге 3.24 он выделен полужирным шрифтом). Применяем команду u BE80B000 для просмотра его содержимого и видим следующий результат (листинг 3.25).

Листинг 3.25. Результат дизассемблирования дампа памяти по адресу, сообщенному "голубым экраном смерти"





kd>u 0xBE80B000

be80b000 a100000000          mov             eax,[00000000]

be80b005 c20800      ret             0x8

be80b008 90                  nop

be80b009 90                  nop

be80b00a 90                  nop

be80b00b 90                  nop

be80b00c 90                  nop

be80b00d 90                  nop

Листинг 25 результат дизассемблирования дампа памяти по адресу, сообщенному голубым экраном смерти

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

Хорошо, а как быть, если копии экрана смерти в нашем распоряжении нет? На самом деле, синий экран всегда с нами, надо только знать где искать! Попробуйте открыть файл дампа в любом HEX-редакторе и вы обнаружите следующие строки (листинг 3.26).

Листинг 3.26. Копия голубого экрана в заголовке дампа программы

00000000:  50 41 47 45 44 55 4D 50 ¦ 0F 00 00 00 93 08 00 00   PAGEDUMP0   У•



00000010:  00 00 03 00 00 80 8B 81 ¦ C0 A4 46 80 80 A1 46 80     ¦  АЛБLдFААбFА

00000020:  4C 01 00 00 01 00 00 00 ¦ 1E 00 00 00 05 00 00 C0   LO  O   ^   ¦  L

00000030:  00 B0 80 BE 00 00 00 00 ¦ 00 00 00 00 00 41 47 45    -А-         AGE

Листинг 26 копия голубого экрана в заголовке дампа программы

С первого же взгляда удается опознать все основные Bug Check-параметры: 1E 00 00 00 –— это код категории сбоя 0x1E (на процессорах x86 наименее значимый байт располагается по меньшему адресу, то есть все числа записываются в обратном порядке); 05 00 00 C0 –— код исключения ACCESS VIOLATION; а 00 B0 80 BE –— и есть адрес машинной команды, породившей это исключение. В комбинации же 0F 00 00 00 93 08 легко узнается номер билда системы, стоит только записать его в десятичной нотации.

Для просмотра Bug Check-параметров в более удобочитаемом виде можно воспользоваться следующей командой отладчика: dd KiBugCheckData (листинг 3.27).

Листинг 3.27. Bug Check-параметры, отображаемые в удобочитаемом виде

kd> dd KiBugCheckData

dd KiBugCheckData

8047e6c0  0000001e c0000005 be80b000 00000000

8047e6d0  00000000 00000000 00000001 00000000

8047e6e0  00000000 00000000 00000000 00000000

8047e6f0  00000000 00000000 00000000 00000000

8047e700  00000000 00000000 00000000 00000000

8047e710  00000000 00000000 00000000 00000000

8047e720  00000000 00000000 00000000 00000000

8047e730  00000000 e0ffffff edffffff 00020000

Листинг 27 Bug Check параметры, отображаемые в удобочитаемом виде

Другие полезные команды: !drivers –— выводящая список драйверов, загруженных на момент сбоя, !arbiter –— показывающая всех арбитров вместе с диапазонами арбитража, !filecache –— отображающая информацию о кэше файловой системы и PT, !vm –— отчитывающаяся об использовании виртуальной памяти и т. д. и т. п. –— всех не перечислишь! (полный перечень команд вы найдете в руководстве по своему любимому отладчику).



Конечно, в реальной жизни определить истинного виновника краха системы намного сложнее, поскольку всякий нормальный драйвер состоит из множества сложно взаимодействующих функций, образующих запутанные иерархические комплексы, местами пересеченные туннелями глобальных переменных, превращающих драйвер в самый настоящий лабиринт. Приведем только один пример. Конструкция вида mov eax, [ebx], где ebx == 0, работает вполне нормально, послушно возбуждая исключение, и пытаться "поговорить с ней по-мужски" –— бессмысленно! Нужно найти тот код, который записывает в регистр EBX нулевое значение, и сделать это непросто. Можно, конечно, просто прокрутить экран вверх, надеясь, что на данном участке программный код выполнялся линейно, но никаких гарантий, что это действительно так у нас нет, равно как нет и возможности обратной трассировки (back trace). Грубо говоря, адрес предшествующей машинной инструкции нам неизвестен и "закладываться" на прокрутку экрана нельзя!

Загрузив подопытный драйвер в любой интеллектуальный дизассемблер, автоматически восстанавливающий перекрестные ссылки (например, дизассемблер IDA Pro), мы получим более или менее полное представление о топологии управляющих ветвей программы. Конечно, дизассемблирование в силу своей статической природы, не гарантирует, что управление не перекинулось откуда-то еще, но, по крайней мере, сужает круг поиска. Вообще же, о дизассемблировании написано множество хороших книг (и "Фундаментальные основы хакерства" Криса Касперски в том числе[Y96] [n2k97] ), поэтому не будем останавливаться на этом вопросе, а просто пожелаем всем читателям удачи[Y98] [n2k99] .



Рис.унок 3.5. Отладчик i386kd за работой (пиво, бутерброды прилагаются); несмотря на свою отталкивающую внешность это чрезвычайно мощный и удобный в работе инструмент, позволяющий проворачивать умопомрачительные пассажи нажатием всего пары-тройки клавиш (одна из которых вызывает ваш собственный скрипт).





Рис.унок 3.6. Windows Dedbugger c загруженным дампом памяти. Обратите внимание: отладчик самостоятельно высвечивает Bug Check-коды, не ожидая пока мы об этом его попросим, а при попытке дизассемблирования инструкции, возбудившей исключение, на экране выскакивает "Module Load: W2K_KILL.SYS", сообщающая нам имя драйвера-убийцы. Вроде бы мелочь, а как приятно!

методы низкоуровневого управления приводами      1

интерфейсы взаимодействия с оборудованием      32

доступ через CD-ROM-драйвер      44

доступ через cooked-моде (режим блочного чтения)      12611

доступ через SPTI      15614

доступ через ASPI      32631

доступ через SCSI-порт      43641

доступ через SCSI-мини порт      46646

взаимодействие через порты ввода/вывода      56656

доступ через MSCDEX драйвер      68667

взаимодействие через собственный драйвер      71670

сводная таблица характеристик различных интерфейсов      71671

способы разоблачения защитных механизмов      72672

>>>>> отжиг дисков. за, против и немного вокруг      75674

>>>>> блокирование/разблокирование кнопки EJECT      79678

>>>>> хакерские секреты Рецепты тормозной жидкости для CD      81680

примеры исследования реальных программ      82681

Alcohol 120%      82681

Easy CD Creator      83682

Clone CD      83682


Содержание раздела