Часть 50
Last updated
Was this helpful?
Last updated
Was this helpful?
Смысл этого туториала состоит в том, чтобы создать небольшой гайд по реверсингу и отладке ядра. Я не думаю, что очень важно делать очень подробное введение про то, что такое ядро. Для этого есть тысяча туториалов. Но несмотря на это я скопирую эти определения.
KERNEL или ЯДРО это фундаментальный компонент любой операционной системы. Оно отвечает за то, что программное обеспечение и аппаратное обеспечение любого компьютера может работать вместе в той же системе, для чего оно управляет памятью программ и исполняемых процессов, управляет временем процессора, который используют программы, или заботится о предоставлении доступа и правильной работе периферических устройств и других физических элементов оборудования.
Мы видим, что в режиме пользователя находятся приложения, функции API WINDOWS, драйвера, которые обрабатываются в режиме пользователя, в то время как в режиме ядра находится сама операционная система, аппаратное обеспечение и драйвера, которые работают в режиме ядра.
Когда ты запускаешь приложение, оно входит в режим пользователя, где WINDOWS создает конкретный процесс для приложения. Каждое приложение имеет свой защищенный виртуальный адрес. Ничто не может изменить данные, которые принадлежат другому процессу и не имеет доступа к виртуальному пространству самой операционной системы. Следовательно, это режим, который предоставляет меньше привилегий. Даже доступ к аппаратному обеспечению ограничен, и для вызова сервисов системы приложения должны прибегать к API WINDOWS.
Режим ядра или KERNEL по другому — это то место, где код который выполняется, имеет прямой доступ ко всему аппаратному обеспечению и всей памяти оборудования. Здесь весь код делит то же адресное пространство, и может даже получать доступ в адресные пространства всех процессов режима пользователя. Это опасно, так как если драйвер в режиме ядра изменит то, что не должен, то это может повлиять на работу всей операционной системы.
Этот режим ядра состоит из исполнительных сервисов, таких как контроллер кэша, диспетчера связи, диспетчера В/В, локальных вызовов процедур, или диспетчеров электропитания и памяти. Они, в свою очередь, формируются из нескольких модулей, которые выполняют конкретные задачи, контроллеры ядра, ядро и Слой Абстрагирования Оборудования или HAL.
Мы продолжаем копировать определения. Сейчас идет определение виртуальной памяти.
Виртуальная память - это техника используемая операционными системами для доступа к большему количеству памяти чем физически доступно. ОС прибегает к альтернативным решениям хранения данных, когда иссякает установленная память RAM.
Компьютеры используют память RAM для хранения файлов и данных, которые необходимы как операционной системе так и программному обеспечению, которое мы запускаем; её высокая производительность гарантирует оптимальную производительность но, рано или поздно, она всегда заполняется. Именно в этот момент WINDOWS прибегает к виртуальной памяти.
Для создания виртуальной памяти WINDOWS создаёт файл в хранилище, которые мы назначаем, будь то на традиционном жестком диске или SSD; операционная система генерирует файл под названием PAGEFILE.SYS (вы можете найти его скрытым в корневой директории вашей системы) где она хранит данные, которые не помещаются в память RAM, но которые необходимы для работы ПК.
Поскольку, когда мы работаем с очень требовательными приложениями (такими как видеоигры) или у нас есть несколько одновременно работающих приложений, Вы можете заметить как система начинает замедляться, особенно если у ПК недостаточно памяти RAM. Это тот самый момент, когда WINDOWS начинает задействовать файл подкачки и память RAM будет переполнена; поэтому предотвращаются сбои и нестабильность, но вместо этого снижается производительность.
На этом месте, легко сделать вывод, что чем больше RAM мы имеем в оборудовании, тем лучше мы заметим разницу в более требовательном программном обеспечении, которое мы используем. Хотя цена памяти в последнее время резко упала, она остается по-прежнему высокой. Поэтому в большинстве случаев необходимо прибегать к решениям оперативной памяти.
Здесь мы видим виртуальное адресное пространство каждого процесса, который начинается от адреса 0x0 до 0xFFFFFFFF и которое операционная система использует для управления RAM и SWAPкак мы говорили ранее.
И также видим 32-х битное виртуальное адресное пространство каждого процесса, которое разделяется. Как мы видим на картинке от адреса 0x0 до 0x7FFFFFFF это часть пользовательского пространства где располагаются программы и от адреса 0x7FFFFFFF до 0xFFFFFFFF это пространство ядра.
Хорошо. Давайте перестанем воровать с Интернета инфу и подготовим гайд. Очевидно мы не можем отлаживать ядро с помощью отладчика типа OLLYDBG или IDA в режиме пользователя, потому что они не могут получить доступ как любая программа в режиме пользователя, в часть ядра.
Мы должны подготовить целевую машину где будем отлаживать ядро. В моём случае, я использую VMWARE WORKSTATION и у меня есть моя целевая машина WINDOWS 7 SP1 32, без каких либо обновлений.
Те, кто использует более обновленные целевые машины могут обнаружить, что некоторые вещи не будут работать соответствующим образом, потому что машины пропатчены. Но поскольку мы начинаем с самого начала, лучше видеть всё проще и продвигаться постепенно.
Как только мы подготовим окружающую среду, возможно, что мы продолжим позже с ВИДЕО ТУТОРИАЛАМИ, поэтому важно все хорошо подготовить, чтобы идти дальше нормально.
Моя основная машина, в этом случае, это WINSOWS 7 SP1 64, со всеми патчами до сегодняшнего дня. Хотя мы могли бы использовать другую систему, может случиться, что кое-какая вещь не будет работать точно также как у меня, но такое может случиться и так.
В моей основой машине, я буду использовать IDA версии 6.8. И прежде чем, вы закричите, что уже в сеть утекла IDA 7, я скажу, что она имеет баг, который закрывает программу при попытке присоединения отладчика для отладки 32-х битного ядра. Поскольку в моей работе мне покупают IDA официально, разработчики прислали мне патч, который устраняет этот баг. Но очевидно я не могу распространять его. Возможно кто-то найдет место из-за чего падает программа и поймет как избежать это и пофиксит его и получить валидный патч для IDA 7. Но пока мы будем использовать версию 6.8.
Конечно, также основная машина должна иметь установленный WINDBG и настроенные символы. И обратите внимание, что в этой папке символов, в том время, когда используем их, они скачиваются сами. В моём случае папка называется SYMBOLS.
Поскольку в моих переменных среды есть переменная _NT_SYMBOL_PATH
Её значение равно
SRV*c:\symbols*http://msdl.microsoft.com/download/symbols
И эта строка позволяет загружать символы с сервера microsoft. Очевидно Вам нужно что-то сделать, чтобы отладчик смог подключаться через фаерволлы, прокси или чего нибудь ещё, чтобы получить доступ к репозиторию символов.
Следующая вещь - необязательна. На моей главной машине у меня есть, т.е. на машине с WINDOWS 7, установлен старый WDK 7.1.0 https://www.microsoft.com/en-us/download/details.aspx?id=11800
Но на другой машине, на которой у меня установлен WINDOWS 10, чтобы стараться делать те же самые вещи, у меня есть установленная VISUAL STUDIO 2015 с WDK 10 поскольку на данный момент VISUAL STUDIO 2017 не позволяет использовать WDK.
У меня есть две возможности сделать это. С помощью обоих методов нужно компилировать драйвер по старинке вручную в текстовом редакторе (красивый) или по-современному. И увидем, работает ли этот способ и посмотрим различая.
Чтобы протестировать драйверы нужно перейти по ссылке http://www.osronline.com/article.cfm?article=157
Зарегистрируйтесь и загрузите OSR DRIVER LOADER, который поможет нам легко загрузить и протестировать наш драйвер.
Загрузите также DEBUG VIEW с сайта MICROSOFT
https://docs.microsoft.com/en-us/sysinternals/downloads/debugview.
И как только у нас будут всё эти инструменты, мы загружаем VIRTUAL KD
http://virtualkd.sysprogs.org/download/
В этот момент последняя версия это 3. Если выйдет более новая, не забудьте её скачать.
После само-распаковки видно
Видно, что существует папка TARGET, которая является той, которую нужно скопировать в целевую машину. Остальная часть файлов предназначена для основной машины.
После этого я копирую папку TARGET в целевую машину.
И запускаю VMINSTALL с правами администратора.
Эту галочку я тестировал несколько раз и если я не снимал её в WINDOWS 7, то ничего не работало. В любом случае, всё равно можно сделать снимок, чтобы сделать тест и если ничего не заработает, вернуться назад к снимку и повторить попытку.
Перед тем как нажать INSTALL, скопируйте имя и вставьте его в блокнот на основной машине. Теперь я снимаю галочку и нажимаю INSTALL.
Заметьте, что если всё правильно, машина будет оставаться замороженной при запуске. Это то, что должно случиться, иначе что-то установленно неправильно. Перед тем как нажимать YES, давайте запустим в основной машине другую часть VIRTUALKD. Я выполняю с правами администратора VMMON64.EXE. После того как файл запуститься, давайте вернемся назад и нажмем YES.
Здесь мне будет представлена возможность запустить машину в нормальном режиме или запустить в режиме отладки ядра, что является выделенным на картинке. Если я соглашаюсь и машина запускается нормально не работает, но иногда не обязательно устанавливать все заново. Когда она загружается, я приказываю ей перегрузиться и выбираю тот же самый пункт, чтобы увидеть зависнет ли она снова.
Поскольку моя машина запускается нормально, я не восстанавливаю ничего.
Я пытаюсь запустить этот REG файл и затем вернуться обратно в VMINSTALL, чтобы увидеть заработал ли он сейчас.
При перезагрузке он запускается. На главной машине, если в программе VMMON64 не находится слово YES под колонкой OS, это значит что что-то не так.
После нескольких попыток и нескольких перезапусков, я думаю, что трюк состоит в том, чтобы перегружать целевую машину из самой системы, а не из меню VMWARE. Если всё работает, должно случиться это.
Целевая машина должна быть заморожена в самом начале.
Здесь под словом OS должно находиться слово YES и если Вы установите галочку на START DEBUGGER AUTOMATICALLY должен запускаться WINDBG. Но в DEBUGGER PATH вы должны указать корректный путь до WINDBG.EXE, тогда он запуститься,
Мы вводим G, и ENTER в WINDBG и отладчик продолжит загружать систему. Как только я войду в целевую машину, то я возвращаюсь в WINDBG и нажимаю BREAK из меню DEBUG или CTRL + BREAK.
Там я исполняю команду !PROCESS -1 0
Я нахожусь в командной строке. Посмотрим список процессов с помощью команды !PROCESS 0 0
Это список процессов. Если я хочу переключиться на контекст другого процесса, чтобы поставить там BP, я бы сделал так.(Например переключиться на EXPLORER, который в моем случае имеет адрес 85E626F0 рядом со словом PROCESS)
Я нажимаю G и контекст переключается
Я вижу в каком процессе я нахожусь сейчас
Если Вы не хотите тратить время, Вы можете пропустить загрузку символов в этот момент. Поскольку это только для практики, то потребуется много времени. Если вы хотите продолжить, перейдите на следующую страницу, где заканчивается пунктирная область.
Я перегружаю символы с помощью команды .RELOAD /F
Это будет занимать какое-то время. Некоторые символы будут скачаны сами, потому что они находятся в репозитории. Некоторые модули не будут иметь символов. Но папка символом должна быть заполнена.
Здесь мы видим, что WINDBG находится в состоянии BUSY и загружает символы (скачивает). Первый раз, когда мы это сделаем, это будет очень долго, потому что у программы нет символов. Следующие разы не будут являться для нас такой проблемой.
Если программа не загрузила символы, вы можете использовать команду !SYM NOISY
перед RELOAD
.
Run !sym noisy before .reload to track down problems loading symbols.
Многие спросят, если это курс IDA, почему мы не присоединяемся сразу в начале загрузки IDA с помощью плагина WINDBG.
Смысл в том, что WINDBG я использую для того, чтобы добраться до нужной точки, где я хочу отлаживать и как только я её достигаю я присоединяюсь с помощью IDA, потому что IDA иногда падает и всё подвисает, поэтому лучше использовать и доходить до интересующей точки c помощью WINDBG, отлаживать и покидать WINDBG в неинтересующей части, что является более надежным способ для удаленной отладки ядра. В любом случае, я могу прерваться, закрыть WINDBG и целевая система останется заморожена и потом присоединить IDA с плагином WINDBG и продолжить отладку без проблем. Это мы и сделаем дальше.
Если Вы перезагрузили с помощью команды LM, Вы увидите модули и их символы
Те модули, у которых есть символы, они сохраняются в мою папку SYMBOLS. Это означает, что все хорошо настроено, а если нет, то пусть Билл Гейтс поплачет.
Я буду делать простой тестовый драйвер типа HELLO WORLD на основной машине. Тот, кто не хочет его компилировать, он будет находиться в папки туториала.
В папке, которая не имеет пробелов ни в имени, ни в пути, я создаю текстовый файл и размещаю внутри него следующий код.
Я переименовываю его как HELLOWORLDDRIVER.C. Затем сделаю другой файл, который называется SOURCES с таким содержанием.
И ещё один, который называется MAKEFILE.DEF
Чтобы скомипилировать его, если я установил DWK 7.1, я иду в панель установленных программа WINDOWS на главной машине.
И я запускаю X86 FREE BUILD ENVIRONMENT из WINDOWS 7.
Здесь я меняю путь, чтобы он был без пробелов, где находятся 3 файла.
Я выполняю команду BUILD.
Файлы компилируется.
Чтобы увидеть работает ли драйвер, я копирую файл SYS в целевую машину (если она остановлена в WINDBG, я нажимаю G и ENTER для того, чтобы она запустилась) и там уже я запускаю OSRLOADER с правами администратор. Версия XP хорошо работает в WINDOWS 7.
Я ищу драйвер и открываю его.
Нажимаю кнопку REGISTER SERVICE.
Затем нажимаю START SERVICE и если не появляется BSOD и выходит то же самое сообщение, значит все хорошо. Чтобы увидеть, то что печатает драйвер, мы должны использовать DEBUG VIEW от имени администратор.
И когда я запускаю программу и останавливаю драйвер
Драйвер не может показать вывод на консоль.
В WINDBG также видно
Если я нажму START SERVICE, то заставляю его работать и прервусь в WINDBG.
Я вижу все процессы с помощью команды !PROCESS 0 0 и внутри этого списка есть такой
Я переключаю контекст на него с помощью команды
Я нажимаю G и ENTER
Я переключаю контекст
Если мы выполним команду LM, увидим, что у нас нет символов для нашего драйвера
91109000 9110f000 HelloWorldDriver (deferred)
Поскольку у нас есть файл PDB, мы можем заставить отладчик загрузить символы
В папке SYMBOLS есть папка с именем PDB
Мы добавляем туда папку под названием HELLOWORLDDRIVER.PDB
Внутри других папок есть подпапка с различными длинными номерами. Как мы её получаем?
Как только мы создали папку HELLOWORLDDRIVER.PDB, мы возвращаемся в WINDBG и вводим команду
Отладчик говорит нам имя папки, которую не находит. Мы создаем её, копируя туда PDB и затем выполняем команду
.reload /f HelloWorldDriver.sys
Затем, с помощью команды LM можно увидеть символы. В моём случае файл находится в папке TEST.
С помощью команды X можно увидеть содержимое символов.
Там есть адреса и названия . Если мы хотим поставить BP в WINDBG, стоит это делать находясь контексте процесса.
bp /p @$proc HelloWorldDriver!DbgPrint
Вместо BP HELLOWORLDDRIVER!DRIVERUNLOAD. Возможно в этом случае это не так важно. Но если этот BP установить в системной функции, отладчик будет останавливаться тысячи раз, когда каждый процесс использует эту функцию. В то время как при использовании одиночного-контексного BP, только тогда, когда отладчик используется текущий процесс
Давайте посмотрим, работает ли это
Сейчас мы запускаем отладчик с помощью G и ENTER
Здесь я останавливаюсь и вижу, что это функция, которая вызвыает печать. В этом случае, когда я не знаю какой процесс который вызывает функцию, можно поместить BA E1 или BP если конечно отладчик не останавливается много раз как в этом случае.
Хорошо. Сейчас продолжим уже с IDA. Для этого мы откроем в IDA 6.8 HELLOWORLDDRIVER.SYS и если PDB находится в той же папке, она его загрузит. Иначе его будет нужно найти и попросить загрузить.
В IDA мы идем в пункт DEBUGGER → SWITCH DEBUGGER и выбираем WINDBG.
Затем в через DEBUGGER → DEBUGGER OPTIONS → SET SPECIFIC OPTIONS мы выбираем пункт KERNEL MODE DEBUGGING.
И затем идем в PROCESS OPTIONS.
В CONNECTION STRING мы помещаем строку соединения с таким содержанием.
Возьмем имя из VIRTUALKD.
Готово. Мы соглашаемся.
Мы замечаем, что WINDBG прервался.
И идём в пункт IDA DEBUGGER → ATTACH TO PROCESS
Должно показаться слово KERNEL и мы соглашаемся. Если этого не будет, значит мы сделали не правильно что-то из предыдущих шагов или машина не может соединиться из-за какой-то ошибки.
Если IDB в IDA имеет то же самое имя, т.е. мы его не меняем и он по-прежнему продолжает называется HELLOWORLDDRIVER.IDB, отладчик должен обнаружить, что он загружает похожий модуль. Мы подтверждаем, что это тот же самый и нажимаем SAME
Как только я загрузил драйвер, мы можем начать отлаживать. Где то здесь будет панель WINDBG где мы могли бы вводить команды WINDBG.
Я могу также ставить BP в IDA
И здесь у нас сейчас ничего не работает. Запускаем систему командой G в WINDBG. Я должен нажать RUN в IDA или F9.
Мы видим, что по изображению в целевой машине все заработало и разморозилось. Мы можем запустить и останавливать драйвер как раньше, для того, чтобы он остановился на BP.
Здесь мы видим, что всё работает отлично.
На другом компьютере у меня есть VISUAL STUDIO 2015 с WDK 10
Если я скомпилирую его так, чтобы не было ошибок, мне нужно понизить уровень требования или изменить его.
Также в настройках драйвера меняем, что он для WINDOWS 7
И при компиляции, он не даёт нам ошибку.
Если я удаляю BP и выхожу из IDA то целевая машина размораживается.
Я копирую драйвер в целевую машину.
Я ищу сервис, запускаю его и останавливаю, В DEBUGVIEW мы видим сообщения. Хотя, очевидно, драйвер не остановится в IDA, потому что это другой драйвер, но я могу пойти в IDA, чтобы приостановить процесс и пойти в DEBUGGER DETACH FROM PROCESS и мы могли бы снова заново присоединить WINDBG через RUN DEBUGGER в VMMON или если нет, открыть новый SYS в IDA с помощью его PDB.
Драйвер немного сложнее чем предыдущий.
Мы заново настраиваем IDA, изменяя отладчик на WINDBG, оставляя его в режиме ядра и используем ту же строку соединения.
Когда я нажимаю START, мне появляется сообщение.
Я говорю отладчику, что это то же самое. Я нажимаю SAME.
Я ищу между функциями. Я вижу функцию _DRIVERENTRY и нахожу вызов здесь.
Поэтому я устанавливаю там BP и нажимаю RUN. Затем я загружаю и выгружаю драйвер и мне появляется сообщение. Если этот то же самое, я говорю ему, что да.
И идет остановка на BP как и раньше, но с этой другой версией драйвера.
Это было всего лишь началом, чтобы увидеть как конифигурировать систему для отладки ядра. Возможно следующие туториалы будут в виде видео для посвящения этой теме.
Автор оригинального текста — Рикардо Нарваха.
Перевод и адаптация на русский язык — Яша Яшечкин.
Перевод специально для форума системного и низкоуровневого программирования - WASM.IN
21.10.2018