Средства отладки режима ядра операционной системы Windows. Хардкорная отладка с Linice: учимся работать в консольном отладчике ядра Режим отладки ядра windows 7 время выполнения

Для проведения отладки ядра необходимо подключиться к компьютеру с помощью нуль-модемного кабеля или модемного соединения. Компьютер, выполняющий отладку, будет называться “Host”, а название “Target” получит проблемный компьютер.

Оба компьютера должны работать под управлением одной и той же версии Windows, а символьные файлы для компьютера Target должны быть установлены на компьютере Host. Символьные файлы предоставляются на установочном компакт-диске Windows в каталоге Support\Debug.

Для включения отладки необходимо внести изменения в файл BOOT.INI на компьютере Target.

1. Поменяйте атрибуты файла BOOT.INI:

attrib c:\boot.ini – r – s

2. Отредактируйте этот файл и в строку запуска Windows добавьте параметр /debug (для того, чтобы сообщить системе о необходимости загрузки в оперативную память отладчика ядра при загрузке Windows). Дополнительными параметрами являются /Debugport, сообщающий системе, какой порт COM необходимо использовать (по умолчанию COM2) и /Baudrate - для указания скорости передачи данных (по умолчанию указана скорость 19200 бод, но лучше использовать 9600). Например:


multi(0)disk(0)rdisk(0)partition(0)\WINDOWS="Windows NT" /debug /debugport=com2 /baudrate=9600

3. Сохраните файл.

4. Установите предыдущие атрибуты файла BOOT.INI:

attrib c:\boot.ini +r +s

В данном примере компьютер Target разрешил соединение через порт COM2 со скоростью 9600 бит/с.

Компьютер Host должен быть настроен с использованием параметров, необходимых для проведения отладки. Кроме того, должны быть установлены символьные файлы. Для их установки перейдите в каталог \support\debug на установочном компакт-диске и введите следующую команду:

expndsym : <целевой диск и каталог>

Например:

expndsym f: d:\symbols

Установка может занять некоторое время. Помните, что если на компьютер Target были установлены пакеты обновлений, символьные файлы этих пакетов также следует установить на компьютер Host. Символьные файлы для пакетов обновлений можно загрузить с сайтега компании Microsoft.

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

Описание системных переменных

Определение этих переменных можно разместить в командном файле для того, чтобы избежать ввода соответствующих команд при каждой загрузке:

echo off
set _nt_debug_port=com2
set _nt_debug_baud_rate=9600
set _nt_symbol_path=d:\symbols\i386
set _nt_log_file_open=d:\debug\logs\debug.log

Теперь необходимо скопировать программное обеспечение отладки ядра, которое расположено в каталоге support\debug\<процессор> на установочном компакт-диске (support\debug\I386). Проще всего скопировать весь каталог полностью, поскольку он имеет небольшой размер (около 2,5 Мбайт). Для платформы I386 используется отладчик, который поставляется в виде файла I386KD.EXE. Отладчик запускается с помощью команды I386KD. Для ввода команды нажмите комбинацию клавиш и подождите, пока появится приглашение командной строки kd>.

Отладчики режима ядра находятся между CPU и операционной системой. Это означает, что, когда вы останавливаете отладчик режима ядра, операционная система также полностью останавливается. Нетрудно сообразить, что переход операционной системы к резкому останову полезен, когда вы работаете с таймером и над проблемами синхронизации. Все-таки, за исключением одного отладчика, о котором будет рассказано ниже (в разделе "Отладчик SoftlCE" данной главы), нельзя отлаживать код пользовательского режима с помощью отладчиков режима ядра.

Отладчиков режима ядра не так много. Вот некоторые из них: Windows 80386 Debugger (WDEB386), Kernel Debugger (1386KD), WinDBG и SoftlCE. Каждый из этих отладчиков кратко описан в следующих разделах.

Отладчик WDEB386

WDEB386 - это отладчик режима ядра Windows 98, распространяемый в составе Platform SDK. Этот отладчик полезен только для разработчиков, пишущих драйверы виртуальных устройств Windows 98 (VxD). Подобно большинству отладчиков режима ядра для операционных систем Windows, отладчик WDEB386 требует для работы две машины и нуль-модемный кабель. Две машины необходимы потому, что часть отладчика, которая выполняется на целевой машине, имеет ограниченный доступ к ее аппаратным средствам, так что он посылает свой вывод и получает команды от другой машины.

Отладчик WDEB386 имеет интересную историю. Он начинался как внутренний фоновый инструмент Microsoft в эпоху Windows 3.0. Его было трудно использовать, и он не имел достаточной поддержки для отладки исходного кода и других приятных свойств, которыми нас испортили отладчики Visual C++ и Visual Basic.

"Точечные" (DOT) команды - наиболее важная особенность WDEB386. Через прерывание INT 41 можно расширять WDEB386 с целью добавления команд. Эта расширяемость позволяет авторам VxD-драйверов создавать заказные отладочные команды, которые дают им свободный доступ к информации в их виртуальных устройствах. Отладочная версия Windows 98 поддерживает множество DOT-команд, которые позволяют наблюдать точное состояние операционной системы в любой точке процесса отладки.

Отладчик I386KD

Windows 2000 отличается от Windows 98 тем, что реально действующая часть отладчика режима ядра является частьюNTOSKRNL. EXE - файла главного ядра операционной системы Windows 2000. Этот отладчик доступен как в свободных (выпускных), так и в проверенных (отладочных) конфигурациях операционной системы. Чтобы включить отладку в режиме ядра, установите параметр загрузчика /DEBUG в BOOT. INI и, дополнительно, опцию загрузчика /DEBUGPORT, если необходимо установить значение коммуникационного порта отладчика режима ядра, отличающееся от умалчиваемого (СОМ1). I386KD выполняется на своей собственной машине и сообщается с машиной Windows 2000 через кабель нуль-модема.

Отладчик режима ядра NTOSKRNL. EXE делает только то, что достаточно для управления CPU, так чтобы операционная система могла быть отлажена. Большая часть отладочной работы - обработка символов, расширенные точки прерывания и дизассемблирование - выполняется на стороне 1386KD. Одно время Windows NT 4 Device Driver Kit (DDK) документировал протокол, используемый в кабеле нуль-модема. Однако Microsoft больше его не документирует.

Мощь 1386KD очевидна, если посмотреть на все команды, которые он предлагает для доступа к внутреннему состоянию Windows 2000. Знание механизма работы драйверов устройств в Windows 2000 поможет программисту следить за выводом многих команд. Не смотря на всю свою мощь, i386KD почти никогда не применяется, потому что это консольное приложение, которое очень утомительно использовать для отладок исходного уровня.

Иногда у меня возникает ситуация, когда Windows ожидает время загрузки для отладчика ядра. Вы видите текст «Windows start», но не логотип.

Если я присоединяю отладчик сейчас, воспроизводится анимация логотипа Windows 7. После этого логотип начинает пульсировать. На этом этапе процесс загрузки больше не продвигается. Загрузка процессора снижается до минимума. Я жду обычно несколько минут, но ничего не происходит.

Это происходит не всегда. Однако, если это произойдет, сброс VM не поможет. Для устранения этой проблемы мне нужно использовать ремонт при запуске. К сожалению, это длится вечно.

Любые идеи, что я могу сделать, кроме запуска ремонта при запуске?

Заранее спасибо!

3

2 ответы

Чтобы устранить проблему, с которой вы столкнулись, достаточно просто нажать F10 во время загрузки. И удалить/отладить и связанные параметры. Затем нажмите enter.

Предложение: Не используйте параметр/debug для параметра меню загрузки по умолчанию. Скопируйте конфигурацию загрузки в новую запись. Затем установите его в режим отладки. Windows не знает, когда вы будете использовать отладчик. Поэтому он должен ждать.

чПФ ОЕЛПФПТЩЕ ХЛБЪБОЙС РП ТБВПФЕ У ПФМБДЛПК СДТБ У БЧБТЙКОЩНЙ ДБНРБНЙ РБНСФЙ. лБЛ РТБЧЙМП, ЧБН ОХЦОП ВХДЕФ ЪБДБФШ ПДОП ЙЪ ХУФТПКУФЧ РПДЛБЮЛЙ, РЕТЕЮЙУМЕООЩИ Ч ЖБКМЕ /etc/fstab . уВТПУ ПВТБЪПЧ РБНСФЙ ОБ ХУФТПКУФЧБ, ОЕ СЧМСАЭЙЕУС ХУФТПКУФЧБНЙ РПДЛБЮЛЙ, ОБРТЙНЕТ, МЕОФЩ, Ч ДБООЩК НПНЕОФ ОЕ РПДДЕТЦЙЧБАФУС.

Note: йУРПМШЪХКФЕ ЛПНБОДХ dumpon (8) ДМС ХЛБЪБОЙС СДТХ НЕУФБ, ЗДЕ ОХЦОП УПИТБОСФШ БЧБТЙКОЩЕ ДБНРЩ. рПУМЕ ОБУФТПКЛЙ РП ЛПНБОДЕ swapon (8) ТБЪДЕМБ РПДЛБЮЛЙ ДПМЦОБ ВЩФШ ЧЩЪЧБОБ РТПЗТБННБ dumpon . пВЩЮОП ЬФП ЧЩРПМОСЕФУС ЪБДБОЙЕН РЕТЕНЕООПК dumpdev Ч ЖБКМЕ rc.conf (5) . еУМЙ ЪБДБОБ ЬФБ РЕТЕНЕООБС, ФП РПУМЕ УВПС РТЙ РЕТЧПК НОПЗПРПМШЪПЧБФЕМШУЛПК РЕТЕЪБЗТХЪЛЕ ВХДЕФ БЧФПНБФЙЮЕУЛЙ ЪБРХЭЕОБ РТПЗТБННБ savecore (8) . пОБ УПИТБОЙФ БЧБТЙКОЩК ДБНР СДТБ Ч ЛБФБМПЗ, ЪБДБООЩК Ч РЕТЕНЕООПК dumpdir ЖБКМБ rc.conf . рП ХНПМЮБОЙА ЛБФБМПЗПН ДМС БЧБТЙКОЩИ ДБНРПЧ СЧМСЕФУС /var/crash .

мЙВП ЧЩ НПЦЕФЕ ЪБДБФШ ХУФТПКУФЧП ДМС УВТПУБ ПВТБЪБ РБНСФЙ СЧОП ЮЕТЕЪ РБТБНЕФТ dump Ч УФТПЛЕ config ЛПОЖЙЗХТБГЙПООПЗП ЖБКМБ ЧБЫЕЗП СДТБ. фБЛПК УРПУПВ ЙУРПМШЪПЧБФШ ОЕ ТЕЛПНЕОДХЕФУС Й ПО ДПМЦЕО ЙУРПМШЪПЧБФШУС, ФПМШЛП ЕУМЙ ЧЩ ИПФЙФЕ РПМХЮБФШ БЧБТЙКОЩЕ ПВТБЪЩ РБНСФЙ СДТБ, ЛПФПТПЕ БЧБТЙКОП ЪБЧЕТЫБЕФ УЧПА ТБВПФХ РТЙ ЪБЗТХЪЛЕ.

Note: дБМЕЕ ФЕТНЙО gdb ПЪОБЮБЕФ ПФМБДЮЙЛ gdb , ЪБРХЭЕООЩК Ч ``ТЕЦЙНЕ ПФМБДЛЙ СДТБ"". рЕТЕИПД Ч ЬФПФ ТЕЦЙН ДПУФЙЗБЕФУС ЪБРХУЛПН gdb У РБТБНЕФТПН -k . ч ТЕЦЙНЕ ПФМБДЛЙ СДТБ gdb ЙЪНЕОСЕФ УЧПЈ РТЙЗМБЫЕОЙЕ ОБ (kgdb) .

Tip: еУМЙ ЧЩ ЙУРПМШЪХЕФЕ FreeBSD ЧЕТУЙЙ 3 ЙМЙ ВПМЕЕ ТБООАА, ЧЩ ДПМЦОЩ ЧЩРПМОЙФШ ХУЕЮЕОЙЕ ПФМБДПЮОПЗП СДТБ ЛПНБОДПК strip, Б ОЕ ХУФБОБЧМЙЧБФШ ВПМШЫПЕ ПФМБДПЮОПЕ СДТП:

# cp kernel kernel.debug # strip -g kernel

ьФПФ ЫБЗ ОЕ ФБЛ ХЦ Й ОЕПВИПДЙН, ОП ТЕЛПНЕОДХЕН. (чП FreeBSD 4 Й ВПМЕЕ РПЪДОЙИ ТЕМЙЪБИ ЬФПФ ЫБЗ ЧЩРПМОСЕФУС БЧФПНБФЙЮЕУЛЙ Ч ЛПОГЕ РТПГЕУУБ РПУФТПЕОЙС СДТБ make .) лПЗДБ СДТП ХУЕЮЕОП, БЧФПНБФЙЮЕУЛЙ ЙМЙ РТЙ РПНПЭЙ ЛПНБОД ЧЩЫЕ, ЧЩ НПЦЕФЕ ХУФБОПЧЙФШ ЕЗП ПВЩЮОЩН ПВТБЪПН, ОБВТБЧ make install .

ъБНЕФШФЕ, ЮФП Ч УФБТЩИ ЧЕТУЙСИ FreeBSD (ДП 3.1, ОЕ ЧЛМАЮБС ЬФПФ ТЕМЙЪ), ЙУРПМШЪХЕФУС СДТБ Ч ЖПТНБФЕ a.out, РПЬФПНХ ЙИ ФБВМЙГЩ УЙНЧПМПЧ ДПМЦОЩ ТБУРПМБЗБФШУС РПУФПСООП Ч РБНСФЙ. у ВПМШЫПК ФБВМЙГЕК УЙНЧПМПЧ Ч ОЕ ХУЕЮЕООПН ПФМБДПЮОПН СДТЕ ЬФП ЙЪМЙЫОСС ФТБФБ. рПУМЕДОЙЕ ТЕМЙЪЩ FreeBSD ЙУРПМШЪХАФ СДТБ Ч ЖПТНБФЕ ELF, ЗДЕ ЬФП ОЕ СЧМСЕФУС РТПВМЕНПК.

еУМЙ ЧЩ ФЕУФЙТХЕФЕ ОПЧПЕ СДТП, УЛБЦЕН, ОБВЙТБС ЙНС ОПЧПЗП СДТБ Ч РТЙЗМБЫЕОЙЙ ЪБЗТХЪЮЙЛБ, ОП ЧБН ОХЦОП ЪБЗТХЦБФШ Й ТБВПФБФШ У ДТХЗЙН СДТПН, ЮФПВЩ УОПЧБ ЧЕТОХФШУС Л ОПТНБМШОПНХ ЖХОЛГЙПОЙТПЧБОЙА, ЪБЗТХЦБКФЕ ЕЗП ФПМШЛП Ч ПДОПРПМШЪПЧБФЕМШУЛПН ТЕЦЙНЕ РТЙ РПНПЭЙ ЖМБЗБ -s , ХЛБЪЩЧБЕНПЗП РТЙ ЪБЗТХЪЛЕ, Б ЪБФЕН ЧЩРПМОЙФЕ ФБЛЙЕ ЫБЗЙ:

# fsck -p # mount -a -t ufs # so your filesystem for /var/crash is writable # savecore -N /kernel.panicked /var/crash # exit # ...to multi-user

ьФБ РПУМЕДПЧБФЕМШОПУФШ ХЛБЪЩЧБЕФ РТПЗТБННЕ savecore (8) ОБ ЙУРПМШЪПЧБОЙЕ ДТХЗПЗП СДТБ ДМС ЙЪЧМЕЮЕОЙС УЙНЧПМЙЮЕУЛЙИ ЙНЕО. йОБЮЕ ПОБ ВХДЕФ ЙУРПМШЪПЧБФШ СДТП, ТБВПФБАЭЕЕ Ч ДБООЩК НПНЕОФ Й, УЛПТЕЕ ЧУЕЗП, ОЙЮЕЗП ОЕ УДЕМБЕФ, РПФПНХ ЮФП БЧБТЙКОЩК ПВТБЪ РБНСФЙ Й УЙНЧПМЩ СДТБ ВХДХФ ПФМЙЮБФШУС.

б ФЕРЕТШ, РПУМЕ УВТПУБ БЧБТЙКОПЗП ДБНРБ, РЕТЕКДЙФЕ Ч ЛБФБМПЗ /sys/compile/WHATEVER Й ЪБРХУФЙФЕ ЛПНБОДХ gdb -k . йЪ РТПЗТБННЩ gdb УДЕМБКФЕ ЧПФ ЮФП:

Symbol-file kernel.debug exec-file /var/crash/kernel.0 core-file /var/crash/vmcore.0 Й ЧХБМС - ЧЩ НПЦЕФЕ ПФМБЦЙЧБФШ БЧБТЙКОЩК ДБНР, ЙУРПМШЪХС ЙУИПДОЩЕ ФЕЛУФЩ СДТБ ФПЮОП ФБЛЦЕ, ЛБЛ ЧЩ ЬФП ДЕМБЕФЕ У МАВПК ДТХЗПК РТПЗТБННПК.

чПФ ЦХТОБМ ЛПНБОД УЕБОУБ ТБВПФЩ gdb , ЙММАУФТЙТХАЭЙК ЬФХ РТПГЕДХТХ. дМЙООЩЕ УФТПЛЙ ВЩМЙ ТБЪПТЧБОЩ ДМС ХМХЮЫЕОЙС ЮЙФБВЕМШОПУФЙ Й ДМС ХДПВУФЧБ УФТПЛЙ ВЩМЙ РТПОХНЕТПЧБОЩ. чУЕ ПУФБМШОПЕ СЧМСЕФУС ФТБУУЙТПЧЛПК ПЫЙВЛЙ, ТЕБМШОП ЧПЪОЙЛОХЧЫЕК ЧП ЧТЕНС ТБВПФЩ ОБД ДТБКЧЕТПН ЛПОУПМЙ pcvt.

1:Script started on Fri Dec 30 23:15:22 1994 2: # cd /sys/compile/URIAH 3: # gdb -k kernel /var/crash/vmcore.1 4:Reading symbol data from /usr/src/sys/compile/URIAH/kernel ...done. 5:IdlePTD 1f3000 6:panic: because you said to! 7:current pcb at 1e3f70 8:Reading in symbols for ../../i386/i386/machdep.c...done. 9: (kgdb) where 10:#0 boot (arghowto=256) (../../i386/i386/machdep.c line 767) 11:#1 0xf0115159 in panic () 12:#2 0xf01955bd in diediedie () (../../i386/i386/machdep.c line 698) 13:#3 0xf010185e in db_fncall () 14:#4 0xf0101586 in db_command (-266509132, -266509516, -267381073) 15:#5 0xf0101711 in db_command_loop () 16:#6 0xf01040a0 in db_trap () 17:#7 0xf0192976 in kdb_trap (12, 0, -272630436, -266743723) 18:#8 0xf019d2eb in trap_fatal (...) 19:#9 0xf019ce60 in trap_pfault (...) 20:#10 0xf019cb2f in trap (...) 21:#11 0xf01932a1 in exception:calltrap () 22:#12 0xf0191503 in cnopen (...) 23:#13 0xf0132c34 in spec_open () 24:#14 0xf012d014 in vn_open () 25:#15 0xf012a183 in open () 26:#16 0xf019d4eb in syscall (...) 27: (kgdb) up 10 28:Reading in symbols for ../../i386/i386/trap.c...done. 29:#10 0xf019cb2f in trap (frame={tf_es = -260440048, tf_ds = 16, tf_\ 30:edi = 3072, tf_esi = -266445372, tf_ebp = -272630356, tf_isp = -27\ 31:2630396, tf_ebx = -266427884, tf_edx = 12, tf_ecx = -266427884, tf\ 32:_eax = 64772224, tf_trapno = 12, tf_err = -272695296, tf_eip = -26\ 33:6672343, tf_cs = -266469368, tf_eflags = 66066, tf_esp = 3072, tf_\ 34:ss = -266427884}) (../../i386/i386/trap.c line 283) 35:283 (void) trap_pfault(&frame, FALSE); 36: (kgdb) frame frame->tf_ebp frame->tf_eip 37:Reading in symbols for ../../i386/isa/pcvt/pcvt_drv.c...done. 38:#0 0xf01ae729 in pcopen (dev=3072, flag=3, mode=8192, p=(struct p\ 39:roc *) 0xf07c0c00) (../../i386/isa/pcvt/pcvt_drv.c line 403) 40:403 return ((*linesw.l_open)(dev, tp)); 41: (kgdb) list 42:398 43:399 tp->t_state |= TS_CARR_ON; 44:400 tp->t_cflag |= CLOCAL; /* cannot be a modem (:-) */ 45:401 46:402 #if PCVT_NETBSD || (PCVT_FREEBSD >= 200) 47:403 return ((*linesw.l_open)(dev, tp)); 48:404 #else 49:405 return ((*linesw.l_open)(dev, tp, flag)); 50:406 #endif /* PCVT_NETBSD || (PCVT_FREEBSD >= 200) */ 51:407 } 52: (kgdb) print tp 53:Reading in symbols for ../../i386/i386/cons.c...done. 54:$1 = (struct tty *) 0x1bae 55: (kgdb) print tp->t_line 56:$2 = 1767990816 57: (kgdb) up 58:#1 0xf0191503 in cnopen (dev=0x00000000, flag=3, mode=8192, p=(st\ 59:ruct proc *) 0xf07c0c00) (../../i386/i386/cons.c line 126) 60: return ((*cdevsw.d_open)(dev, flag, mode, p)); 61: (kgdb) up 62:#2 0xf0132c34 in spec_open () 63: (kgdb) up 64:#3 0xf012d014 in vn_open () 65: (kgdb) up 66:#4 0xf012a183 in open () 67: (kgdb) up 68:#5 0xf019d4eb in syscall (frame={tf_es = 39, tf_ds = 39, tf_edi =\ 69: 2158592, tf_esi = 0, tf_ebp = -272638436, tf_isp = -272629788, tf\ 70:_ebx = 7086, tf_edx = 1, tf_ecx = 0, tf_eax = 5, tf_trapno = 582, \ 71:tf_err = 582, tf_eip = 75749, tf_cs = 31, tf_eflags = 582, tf_esp \ 72:= -272638456, tf_ss = 39}) (../../i386/i386/trap.c line 673) 73:673 error = (*callp->sy_call)(p, args, rval); 74: (kgdb) up 75:Initial frame selected; you cannot go up. 76: (kgdb) quit 77: # exit 78:exit 79: 80:Script done on Fri Dec 30 23:18:04 1994

лПННЕОФБТЙЙ Л ЧЩЫЕРТЙЧЕДЕООПНХ ЦХТОБМХ:

УФТПЛБ 6:

ьФП ДБНР, ЧЪСФЩК РТЙ РПНПЭЙ DDB (УНПФТЙ ОЙЦЕ), РПЬФПНХ ЛПННЕОФБТЙК Л БЧБТЙКОПНХ ПУФБОПЧХ ЙНЕЕФ ЙНЕООП ЧЙД ``because you said to!"" Й ФТБУУЙТПЧЛБ УФЕЛБ ЗМХВПЛБ; ПДОБЛП ЙЪОБЮБМШОПК РТЙЮЙОПК РЕТЕИПДБ Ч DDB ВЩМБ БЧБТЙКОБС ПУФБОПЧЛБ РТЙ ЧПЪОЙЛОПЧЕОЙА ПЫЙВЛЙ УФТБОЙГЩ РБНСФЙ.

УФТПЛБ 20:

ьФП НЕУФПОБИПЦДЕОЙЕ ЖХОЛГЙЙ trap() Ч ФТБУУЙТПЧЛЕ УФЕЛБ.

УФТПЛБ 36:

рТЙОХДЙФЕМШОПЕ ЙУРПМШЪПЧБОЙЕ ОПЧПК ЗТБОЙГЩ УФЕЛБ; ФЕРЕТШ ЬФП ОЕ ОХЦОП. рТЕДРПМБЗБЕФУС, ЮФП ЗТБОЙГЩ УФЕЛБ ХЛБЪЩЧБАФ ОБ РТБЧЙМШОПЕ ТБУРПМПЦЕОЙЕ, ДБЦЕ Ч УМХЮБЕ БЧБТЙКОПЗП ПУФБОПЧБ. зМСДС ОБ УФТПЛХ ЙУИПДОПЗП ЛПДБ 403, НПЦОП УЛБЪБФШ, ЮФП ЧЕУШНБ ЧЕТПСФОП, ЮФП МЙВП ЧЙОПЧБФ ДПУФХР РП ХЛБЪБФЕМА ``tp"", МЙВП ВЩМ ЧЩИПД ЪБ ЗТБОЙГЩ НБУУЙЧБ.

УФТПЛБ 52:

рПИПЦЕ, ЮФП ЧЙОПЧБФ ХЛБЪБФЕМШ, ОП ПО СЧМСЕФУС ДПРХУФЙНЩН БДТЕУПН.

УФТПЛБ 56:

пДОБЛП, ПЮЕЧЙДОП, ЮФП ПО ХЛБЪЩЧБЕФ ОБ НХУПТ, ФБЛ ЮФП НЩ ОБЫМЙ ОБЫХ ПЫЙВЛХ! (дМС ФЕИ, ЛФП ОЕ ЪОБЛПН У ЬФПК ЮБУФША ЛПДБ: tp->t_line УМХЦЙФ ДМС ИТБОЕОЙС ТЕЦЙНБ ЛБОБМБ ЛПОУПМШОПЗП ХУФТПКУФЧБ, Й ЬФП ДПМЦОП ВЩФШ ДПУФБФПЮОП НБМЕОШЛПЕ ГЕМПЕ ЮЙУМП.)

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

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

В данном цикле статей мы рассмотрим написание эксплоитов уровня ядра в ОС Windows. Важно отметить, что мы будем иметь дело с известными уязвимостями, и в реверс-инжиниринге нет необходимости (по крайней мере, для драйвера).

Предполагается, что после ознакомления со всеми статьями вы будете знать все наиболее распространенные классы брешей и методы эксплуатации, а также сможете портировать эксплоиты с архитектуры x86 на архитектуру x64 (если возможно) и ознакомитесь с новыми методами защиты в Windows 10.

Схема отладки ядра

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

Дополнительный материал для изучения:

Эксплуатация уязвимостей ядра

Этот процесс проходит намного веселее, чем эксплуатация на уровне пользователя J.

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

Темы статей этого цикла

  • Часть 1: Настройка рабочей среды
    • Конфигурирование трех виртуальных машин и системы, которая будет выступать в роли отладчика.
    • Конфигурирование отладчика WinDBG.
  • Часть 2: Полезные нагрузки
    • Изучение наиболее распространенных полезных нагрузок. В последующих частях будут рассматриваться конкретные уязвимости и, при необходимости, указываться ссылки на эту статью.
  • Остальные части.
    • Рассмотрение уязвимостей.

Жизненный цикл разработки эксплоита уровня ядра

  • Нахождение уязвимости . Эта тема не будет рассматриваться в данном цикле, поскольку мы уже точно знаем, где находятся бреши.
  • Перехват потока выполнения . Некоторые уязвимости предусматривают выполнение кода, для некоторых есть дополнительные требования.
  • Расширение привилегий . Главная цель – получить шелл с системными привилегиями.
  • Восстановление потока выполнения . Неучтенные исключения на уровне ядра приводят к краху системы. Если вы не собираетесь писать эксплоит для DoS-атаки, следует учитывать этот факт.

Типы целевых систем

Мы будем работать с уязвимостями в следующих системах (конкретная версия не принципиальна):

  • Win7 x86 VM
  • Win7 x64 VM
  • Win10 x64 VM

Начнем с архитектуры x86, и далее будем портировать эксплоит для системы Win7 x64. Некоторые эксплоиты не будут запускать на машинах с Win10 из-за присутствия новых защит. В этом случае мы либо будем изменять логику работы эксплоита, либо будем использовать полностью другой подход.

Используемое программное обеспечение:

  • Гипервизор (масса вариантов).
  • Windows 7 x86 VM
  • Windows 7 x64 VM
  • Windows 10 x64 VM

Настройка систем для отладки

Отладочные системы, с которыми мы будем взаимодействовать, предназначены для загрузки уязвимого драйвера. На этих машинах часто будут возникать крахи, поскольку большинство исключений в ядре способствуют явлениям подобного рода. Необходимо выделить достаточно оперативной памяти для этих систем.

На каждой машине, которая будет отлаживаться, нужно сделать следующее:

  • Внутри директории VirtualKD запустите файл target\vminstall.exe. Добавится новая загрузочная запись и будут доступны функции отладки и автоматическое подключение к серверу VirtualKD, установленному в системе, которая выступает в роли отладчика.

В случае с Windows 10 VM необходимо включить режим test signing, который позволяет загружать неподписанные драйвера в ядро.

После выполнения команды bcdedit /set testsinging on и перезагрузки на рабочем столе появится надпись «Test Mode».

Краткое описание модуля HEVD

Процедура DriverEntry является стартовой для каждого драйвера:

NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath) {
UINT32 i = 0;
PDEVICE_OBJECT DeviceObject = NULL;
NTSTATUS Status = STATUS_UNSUCCESSFUL;
UNICODE_STRING DeviceName, DosDeviceName = {0};

UNREFERENCED_PARAMETER(RegistryPath);
PAGED_CODE();

RtlInitUnicodeString(&DeviceName, L"\\Device\\HackSysExtremeVulnerableDriver");
RtlInitUnicodeString(&DosDeviceName, L"\\DosDevices\\HackSysExtremeVulnerableDriver");

// Create the device
Status = IoCreateDevice(DriverObject,
0,
&DeviceName,
FILE_DEVICE_UNKNOWN,
FILE_DEVICE_SECURE_OPEN,
FALSE,
&DeviceObject);

  • Эта процедура содержит вызов функции IoCreateDevice, содержащей имя драйвера, которое мы будем использовать во время коммуникации.
  • В объект DriverObject будут добавлены нужные структуры и указатели на функции.
  • Для нас важен указатель функции, связанный с процедурой DriverObject->MajorFunction , отвечающей за обработку IOCTL (I/O Control; управление вводом/выводом);
  • В HEVD эта функция называется IrpDeviceIoCtlHandler , которая представляет собой большое условное выражение со множеством ответвлений для каждого IOCTL. Каждая уязвимость имеет уникальный IOCTL.

Пример: HACKSYS_EVD_IOCTL_STACK_OVERFLOW представляет собой IOCTL, используемый для активации бреши, связанной с переполнением стека.

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

P.S. Я понимаю, что существует масса тонкостей и проблем, с которыми вы можете столкнуться. Поскольку в этом цикле основное внимание уделяется разработке эксплоитов, вам придется решать все попутные проблемы самостоятельно. Однако все возникающие вопросы вы можете задавать в комментариях.



Загрузка...
Top