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

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

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

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

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

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

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

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

Метки:  , ,

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

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

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

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

Метки:  ,

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

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