Контекст устройства отображения

Метки:  ,

В многозадачной операционной системе семейства Windows отсутствует возможность прямого бесконтрольного вывода на экран (как это было во времена MSDOS), тут все подчинено некоему регламенту. С целью обеспечения возможности вывода на устройство (экран, принтер, память) одновременно от множества источников (приложений), в Windows был создан специализированный механизм под названием контекст устройства (device context, DC) и подмножество обеспечивающих его работу функций. Указанные функции определяют размер клиентской области, шрифт, цвета и другие GDI-атрибуты и возвращают (предоставляют) приложению так называемый дескриптор контекста устройства (Device Context Descriptor). Поскольку контекст устройства является одним из основополагающих понятий в понимании механизмов вывода информации на устройство, я постараюсь дать некоторое количество определений для погружения в тему:

больше информации о контексте устройства

Консольное приложение на ассемблере

Метки:  , , , , , , , , , ,

После разработки серии оконных приложений, мы познакомились с основными принципами программирования графических примитивов. И тут дернула меня нечистая написать простую программку для решения специфической микрозадачи. Понятное дело, что использовать оконный интерфейс для подобного случая не очень то и хотелось, поэтому было решено сделать приложение консольным .. лучше бы я в этот огород вообще не лез! :) Ну уж, как говорится "взялся за гуж, не говори что не дюж".
Было бы бессмысленно отрицать, что в последние десятилетия роль графического интерфейса существенно возросла, тем не менее в новейших операционных системах текстовые режимы всё еще сохраняются в виде разнообразных графических подсистем, в частности - текстового пользовательского интерфейса (окна командной строки/терминала). Из этого следует, что если уж текстовый режим до сей поры присутствует в операционных системах, значит он не является исключительно аппаратным рудиментом, поддержка которого существует лишь на уровне видеоадаптера, а представляет собой актуальный и активно используемый механизм. Основная причина по которой текстовый режим всё еще существует, заключается в следующем:

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

еще о консольном приложении на ассемблере

STOP 0x00000033

Метки:  , ,

Критическая ошибка STOP 00000033 имеет символическое имя UNEXPECTED_INITIALIZATION_CALL (НЕПРЕДУСМОТРЕННЫЙ_СИСТЕМНЫЙ_ВЫЗОВ). По задумке разработчиков, данный системный сбой должен сообщать нам о некоем "неожиданном" системном вызове, который по идее, не должен был быть осуществлен в той ситуации (контекст работы, глобальные флаги и переменные), в которой он произошел. Как всегда у Microsoft с классификацией ошибок черт ногу сломит, и порой довольно сложно понять причину только лишь по символическому имени :) Иначе говоря, если вы видите останов STOP 00000033, то возникла ситуация, в которой в контексте (процесса/потока) ядра, был выполнен вызов внутренней функции одного из этапов инициализации и в этот самый момент ядро находилось в фазе, в которой оно в данный момент не должно было находиться. В общем то, как вы сможете увидеть далее в статье, символическое имя не лишено смысла, поскольку в некоторым алгоритмическим нюансам сложно бывает придумать внятное описание.

Подробнее о сбое STOP 0x00000033

ci.dll - библиотека проверки цифровых подписей

Метки:  , , , , , , , , ,

И последним этапом в цепочке проверки целостности кода стадии загрузки 32-битной операционной системы Windows 7 является библиотека ci.dll (именуемая разработчиками Модулем Целостности Кода, Code Integrity Module). Данный компонент впервые появился в операционной системе Windows 7 и в своем составе имеет функции, обеспечивающие проверку целостности бинарных образов на этапе отображения/загрузки в адресное пространство ядра. Таким образом, можно сделать вывод, что фактически проверке по задумке разработчиков, подлежат только ключевые образы, являющиеся для системы критичными в плане безопасности. Область действия функционала ci.dll ограничивается только локальной системой, то есть той, на которой непосредственно происходит выполнение кода функций, иначе говоря библиотека является ни чем иным как изолированным идентификатором безопасности локальной системы.
Теперь, собственно, сделаем небольшое отступление для того, что бы дать краткое описание необходимых для понимания происходящего механизмов. С определенного времени в Windows появились так называемые сертификаты подписи кода.

Сертификат подписи кода (Code Signing Certificate) - цифровой "документ" для программного обеспечения (бинарные модули/скрипты), удостоверяющий автора программы и гарантирующий целостность (неизменность) кода.

больше информации о библиотеке ci.dll

Отключение проверки целостности ядра ntoskrnl.exe

Метки:  , , , , , , ,

Никогда не интересовались каким именно образом ядро Windows проверяет собственный код на попытку внесения изменений? Ведь современные операционные системы должны иметь механизмы защиты и причин для этого достаточно, одни руткиты чего стоят. Например, в 32-разрядной системе (x86) Windows, начиная с версии Vista, вполне официально присутствуют опции включения/отключения проверки целостности компонентов, участвующих в процессе запуска операционной системы: это флаги загрузки ENABLE_INTEGRITY_CHECKS и TESTSIGNING. В этой же версии в ядре появилась новая функция, носящая название SepInitializeCodeIntegrity и фактически являющаяся контейнером (оберткой) для передачи управления функции CiInitialize (экспортируемой библиотекой ci.dll). В случае, когда проверка целостности включена в операционной системе, SepInitializeCodeIntegrity внутри себя выполняет вызов функции CiInitialize, при отключенной же проверке обращения к функциям данной библиотеки не происходит. Помимо своего собственного кода, ядро ntoskrnl.exe производит проверку некоторых других критичных для системы модулей: драйверов этапа загрузки (флаг BOOT_START), системных драйверов (флаг SYSTEM_START), и драйверов, подгружаемых уже в процессе функционирования операционной системы (флаги DEMAND_START, AUTO_START). Целостность кода загружаемых ядром исполняемых образов проверяется двумя ядерными функциями:

  • Функция SeValidateImageHeader (контейнер к функции CiValidateImageHeader из ci.dll) -- вызывается на этапе отображения исполняемого образа в адресное пространство ядра.
  • Функция SeValidateImageData (контейнер к функции CiValidateImageData из ci.dll) -- вызывается на стадии загрузки модуля ядра.

еще про отключение проверки целостности ядра ntoskrnl

Отключение проверки целостности bootmgr и winload

Метки:  , ,

Зачастую возникают потребности изучения процесса загрузки операционной системы Windows на уровне исходного кода. Ну а тут уж без внесения изменений в код просто не обойтись.. и в этом самом месте нас ждет разочарование. Дело в том, что если вносить изменения в код модулей bootmgr, winload.exe и файлы драйверов, участвующих в процессе начальной загрузки, то процесс запуска операционной системы начинает "вылетать" с ошибками, "валиться" в синий экран и режим восстановления. Логично, ведь мы столкнулись с проверкой целостности bootmgr и winload, которая препятствует модификации исполняемых образов, задействованных в цепочке запуска. Подобный механизм впервые появился в линейке операционных систем Windows начиная с версии Vista и теперь приобрел перманентно-устойчивый вид. Для самописных драйверов разработчики оставили возможность загрузки в тестовом режиме (флаг TESTSIGNING), тем не менее остаются условия, при которых внесение изменений в код компонентов оканчивается отказом в запуске ОС. Исследователям архитектуры Windows этот факт существенно портит настроение, поэтому сегодня мы разберем несколько нестандартный метод отключения проверки целостности bootmgr и winload.

Для 32/64-битных версий Windows Vista/7/8 и далее есть вполне официальный способ отключения проверки проверки целостности драйверов режима загрузки, тем не менее иногда приходится работать с тестовыми (измененными) версиями некоторых загрузочных файлов, в этом случае требуется отключение вообще всех проверяющих механизмов.

больше информации про отключение проверки целостности bootmgr и winload

IDA интерфейс не поддерживается

Метки:  , , , , ,

При использовании интерактивного дизассемблера IDA (6.х+ версий) на некоторых системах наблюдается интересная проблема: при типовой загрузке произвольного файла, для которого имеется отладочная информация, программа сперва выдает запрос на подгрузку файла символов (.pdb-файл) с сервера Microsoft или локального хранилища символов:

IDA symbol load

больше информации об ошибке IDA интерфейс не поддерживается

Секция ресурсов в FASM

Метки:  , , , , , , , ,

Откровенно говоря, когда программист впервые сталкивается с необходимостью использования ресурсов в своем коде, каких-либо особых трудностей у него не возникает, благо в Сети имеется некоторое (не сказать что большое) количество материала, на основе которого можно составить некое начальное представление. Действительно, организация секции ресурсов на уровне описания в исходном коде выполнена на доступном уровне. Тем не менее, существует ряд неудобств, первое из которых заключается в том, что для формата ассемблера FASM перед глазами нет настольного материала, к которому можно время от времени возвращаться за разного рода уточнениями. Ну а второе (и основное) состоит в совершенно не тривиальной внутренней организации ресурсов приложения на низком уровне (уровне исполняемого модуля). Поэтому, думаю будет не лишним обратить внимание на эту тему и составить своего рода памятку по основным терминам и определениям, да и понимание принципов построения ресурсов не является лишним как для разработчика, так и для реверс-инженера (реверсера), изучающего внутреннее устройство Windows.

продолжить изучение секции ресурсов в FASM

Шестнадцатеричное число в строку на ассемблере

Метки:  ,

В своё время в практике разработчика довольно часто можно было встретить задачи по преобразованию типов данных, одним из подвидов которых является конвертация шестнадцатеричного числа в строку, иными словами преобразование байта/слова/двойного слова в строку символов ASCIIZ (упрощенно: текстовое представление) для последующего использования. Проблема стара как мир ЭВМ и на низком уровне состоит в последовательной конвертации полубайтов (ниббла, 4 бит) в представление ASCIIZ. Чаще всего полученное представление числа используется для вывода на устройство отображения (экран). И все было бы достаточно тривиально, если бы между шестнадцатеричными значениями (0..F) и соответствующими кодами таблицы (набора) ASCII имелось прямое соответствие, но разработчики стандарта решили иначе, итогом чего явился досадный факт разделения ряда ASCII-кодов символов на границе '9' и 'A' (шестнадцатеричные значения 39h и 41h соответственно). Существующая реальность имеет два независимых ряда: 0-9 и A-F, и именно по этой вот несуразной причине алгоритмы конвертации несколько усложнились.

больше информации о конвертации шестнадцатеричного числа в строку

Длина строки на ассемблере

Метки:  , ,

Вычисление длины строки на ассемблере, как одна из наиболее часто возникающих задач, занимала умы разработчиков еще на заре компьютерной эпохи :) Однако впоследствии, с появлением и развитием операционных систем, и, соответственно, доступностью многочисленных встроенных сервисных функций работы со строками (в числе которых предоставляется и функция вычисления длины строки), подобные помысли практически перестали волновать умы представителей сообщества. С развитием высокоуровневых языков все меньше людей задумываются о том, "а как же там на низком уровне всё это реализовано", редко кого волнует оптимизация кода по быстродействию. Даже разработчики, что-либо пишущие на ассемблере, охотнее обращаются к встроенному функционалу, предоставляемому программным интерфейсом, нежели собственными наработкам, и их можно понять, поскольку производительности предоставляемых системой функций, да и языка в целом вполне хватает для того, что бы в большинстве задач не отвлекаться на пару сотен лишних тактов.
К вычислению/заданию длины строки в исходном коде применимы две основных стратегии:

  • Статическая - когда длины строк известны заранее и задаются в исходном коде в виде констант;
  • Динамическая - когда длины строк заранее неизвестны (данные, полученные в процессе работы) и вычисляются в ходе выполнения кода;

читать полностью про вычисление длины строки на ассемблере