Подключение дампа памяти
Для подключения дампа памяти к отладчику 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