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

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

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

Сертификат подписи кода (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, и именно по этой вот несуразной причине алгоритмы конвертации несколько усложнились.

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

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

Метки:  , ,

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

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

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

Простой 32-битный драйвер на ассемблере

Метки:  ,

В предыдущей статье, описывающей алгоритм установки драйвера в систему Windows, мы немного разбирались в том, из каких шагов состоят алгоритмы обнаружения оборудования и установки соответствующих драйверов. Вскоре после этого родилась идея перейти к практической части и осуществить попытку написания собственного, самого простого драйвера на ассемблере. Нет, не каких-то монументальных циклов статей, а исключительно для себя, так сказать, что бы как-то уже начать изучение области разработки драйверов на Ассемблере под операционную систему Windows. После продолжительного обследования предметной области выяснилось, что более-менее серьезная разработка драйверов для Windows ведется на языках программирования C/C++, это объясняется тем, что данные языки являются фактически "языками системы", то есть на них и написаны многие части операционной системы. Однако это вовсе не исключает утверждения, что и на ассемблере вполне себе можно разработать драйвер. Да, соглашусь что делать это не так уж и сподручно, по сравнению с тем же C, поскольку для последнего в качестве серьезного подспорья выпущен специализированный пакет разработки (DDK), но тем не менее все же возможно.

подробнее о простом драйвере на ассемблере

Генератор случайных чисел на ассемблере

Метки:  , ,

Задач, в которых возникает необходимость генерировать случайные числа в заданном диапазоне значений, существует великое множество: это и игры, где создание разнообразных игровых полей, движение объектов да и довольно большое количество логики может быть подчинено так называемой случайности, это и более серьезные направления, такие как шифрование (криптография) и некоторые другие области. Иными словами, любой уважающий себя разработчик всегда должен иметь под рукой генератор случайных чисел. Тем не менее термин генератор случайных чисел не совсем корректен, поскольку считается, что источники истинных случайных чисел найти довольно сложно. Поэтому, применительно к компьютерным системам архитектуры x86 используется несколько иное название - генератор псевдослучайных чисел (сокращенно ГПСЧ).

Генератор псевдослучайных чисел (ГПСЧ, англ. pseudorandom number generator, PRNG) — алгоритм, создающий последовательность чисел, элементы которой "независимы" друг от друга и подчиняются заданному распределению.

Практически у всех реализаций ГПСЧ имеется некая внутренняя переменная (или несколько переменных), которая называется инициализатором (стартовым значением) ГПСЧ. При первом выполнении функции ГПСЧ значение этой переменной присваивается из псевдослучайного источника, определяемого той или иной архитектурой (например на x86 можно задействовать для этой цели инструкцию rdtsc). В процессе дальнейшего выполнения функции ГПСЧ, та же переменная становится уже "текущим" значением ГПСЧ и содержит очередное псевдослучайное число. То есть, каждый раз при вызове функции ГПСЧ со значением этой переменной производятся некоторые операции (могут быть любыми, зависит от конкретной реализации алгоритма), целью которых является получение значения, (в идеале) максимально независимого от предыдущего.

еще о генераторе случайных чисел на ассемблере

Размер окна приложения на ассемблере

Метки:  ,

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

Получить размер окна приложения