Издательский дом ООО "Гейм Лэнд"ЖУРНАЛ ХАКЕР #72, ДЕКАБРЬ 2004 г.

Абсолютный ноль

Николай «GorluM» Андреев

Хакер, номер #072, стр. 072-068-2


Спускаемся на нулевой уровень

Любое приложение, запущенное в user mode, само по себе значение cpl (current privilege level) с трех на ноль не сменит, тут хитрое программистское решение нужно. И оно есть, и даже не одно. Существуют, как минимум, два способа выполнения необходимого кода на нулевом уровне привилегий. Первый – официальный, которым пользуются все производители аппаратных наворотов для ПК и хитрых системных инструментов типа SoftIce, заключается он в написании собственного драйвера уровня ядра. Просто пишешь драйвер, запихиваешь куда-нибудь в него свой код, а далее все, как в MSDN написано, – с помощью Service Manager API подгружаешь получившуюся фигню к системе, и твой код выполняется. Способ, как я уже говорил, официальный, неприкольный. В вирусах и червяках его использовать нереально, т.к. таскать с собой бинарник драйвера – большой геморрой. В троян, в принципе, можно впихнуть, но отдельно писать драйвер, а отдельно - пользовательскую часть приложения - тоже некрасиво, не говоря уже об удобстве. Есть, конечно, и плюсы в использовании этого способа. К примеру, устройства-фильтры для перехвата сообщений ввода/вывода (о них позже) реализовать будет попроще, чем во втором способе. Да и не надо будет искать адреса ядерного API – все само найдется при загрузке.

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

Ring0 без дров

Если открыть третий том IA-32 Intel® Architecture Software Developer’s Manual, единственного достойного учебника по низкоуровневому программированию на интеловских процессорах, на 120-ой странице можно прочесть, что в cpu есть специальные механизмы, позволяющие перелезать с одного уровня привилегий на другой с помощью шлюзов. Шлюзы бывают четырех типов: interrupt gate – шлюз прерывания, task gate – шлюз задачи, trap gate – шлюз ловушки и call gate – шлюз вызова. Достаточно грамотно оформить любой из них, и пользовательское приложение сможет переползать в нулевое кольцо. Другое дело – как их оформить?

Каждый шлюз – это специфическая запись в одной из системных таблиц. К примеру, шлюз ловушки, шлюз прерывания и задачи – это специальные записи в IDT, дескрипторной таблице прерываний. А шлюз вызова (калгейт) – это элемент глобальной или локальной дескрипторной таблицы, GDT или LDT. Обычно во всех этих таблицах со страшными названиями хранятся жизненно важные для работы процессора в защищенном режиме данные, такие как векторы прерываний, описания сегментов памяти и прочая фигня, которая нам совершенно не нужна, – нам важно только одно - заставить приложение перелезть в ring0.

Назад на стр. 072-068-1  Содержание  Вперед на стр. 072-068-3