Сервисы Сервисы и драйверы — наиболее практическая часть всего материала. Сервисы Windows — примерно как демоны в UNIX. Отличаются от обычных программ некоторыми свойствами: в первую очередь, сервисы взаимодействуют не с пользователем, а с другими программами. Главный смысл сервиса в том, что они выступают как расширение функциональности ОС. Например, существуют сервисы для веб-сервера, файлового сервера и т. д. Сервисы могут запускаться без явного волеизъявления пользователя. Например, при старте системы. Сервисы работают не от имени пользователя, а от имени системы или специального псевдопользователя. Сервисы рассматриваются как доверенная часть ОС, их полномочия почти ничем не ограничены. Иногда службы сами ограничивают свои полномочия, например веб-сервер запускается от имени бесправного пользователя. Далее только о Windows. В реестре есть ветка, которая называется база сервисов. Там хранится информация обо всех сервисах, установленных в системе. HKLM\system\CurrentControlSet\Services CurrentControlSet указывает на ControlSet###. ControlSet002 — бекап, создается при выключении. (В regedit папочки = ключи, файлы справа = значения, имя+данные) Обязательные значения в описании сервисов: Type. o o o o o Kernel driver. Драйвер какого-то устройства, работает в режиме ядра. Является модулем расширения ядра. Может управлять только простым устройством, на котором не поддерживается ФС. File system driver. Имеет несколько дополнительных функций. Позволяют в общем дереве ФС (см. ниже) делать новые точки монтирования Own process. Это почти обычная программа, работает от имени пользователя (или SYSTEM). Нет оконного интерфейса. Пример: веб-серверы, СУБД и другие тяжеловесные сервисы. Share process. Маленькие сервисы, которые неудобно делать отдельными процессами. Dhcp-клиент, netsend и прочее. Каждый процесс создает нагрузку, без share process процессов было бы несколько сотен. Для такие сервисов создаются специальные процессы-контейнеры: services.exe (первый, внутри него работает SCM, диспетчер сервисов) и svchost.exe. В XP их много, т. к. появилась возможность запускать их с разными конфигурациями, например, от имени разных пользователей. Interactive. Флаг, может сочетаться с own и share process. До win2003 сервис не может взаимодействовать с графическим интерфейсом. Но, объявив сервис interactive, можно предоставить ему эту возможность. Обычно используется для отладки или хакерами. Начиная с Vista — поддерживается весьма ограничено. Сервис не видит ни один desktop, видит только другие интерактивные сервисы. Start — описывает режимы загрузки данного сервиса. o Disabled. Данный сервис не может запускаться ни при каких обстоятельствах. o Manual. o Automatic. o System (загружаются до automatic) o Boot (загружаются до system). (нижние три — только для драйверов) ErrorContol — что делать при ошибке. Group — сервисы группируются, а для групп назначается порядок загрузки. Tag — уточняет режим загрузки внутри группы. ImagePath — путь к исполняемому файлу данного сервиса. DependOnService — зависимости. Любая другая запись допустима. Устройство ФС (справедливо для win2000): \ o o o Device Cdrom0 HardDiskVolume1 ?? C: (ссылка) D: (ссылка) Registry Управление сервисами. Изначально в Windows была утилита net: net start net stop Начиная с XP (а может и раньше) появилась утилита sc. Она сложна, поэтому при написании софта часто используются специальные загрузчики. Кратко перечислим основные функции, которые используются для управления сервисами программно. OpenSСManager() Возвращается SC_HANDLE или NULL. Закрывается функцией CloseServiceHandle() Необходимо указать доступ. Обычно указывают доступ SC_MANAGER_ALL_ACCESS Создается новый сервис функцией CreateService() Открыть существующий сервис с помощь этой функции нельзя, открывается он функцией OpenService() Удаляются сервисы функцией DeleteService() Функция примечательна тем, что нужен handle для удаления, т. е. нужно открыть сервис. Но открытый сервис удалить нельзя. Поэтому сервис всего лишь помечается для удаления, а удалится только тогда, когда на него закроется последний handle. ControlService() позволяет остановить, обновить конфигурацию и т. д. srvany — программа позволяет запускать в качестве сервиса любую программу. Сервис должен сообщать системе о том, что функционирует он нормально, обычная программа будет закрыта секунд через 20. Как писать свой сервис. В сервисе должен быть обработчик запросов. Эта функция в ходе инициализации сервиса должна быть зарегистрирована в системе. Сервис должен иметь функцию ServiceMain() (Функция main() или winMain() все равно должна быть) Эта функция делает 2 вещи. Во-первых, она регистрирует обработчик управляющих сигналов, вовторых, она вызывается функцию SetServiceStatus() в которой сообщает ОС, что сервис стартован (а также говорит, какие сигналы готов обрабатывать сервис — например, никакие). И третье, самое важное, вызывается функция StartServiceCtrlDispatcher(), которая никогда не возвращает управления. В вечном цикле внутри она вызывает ServiceMain(), а затем ждет сигнала, чтобы вызывать обработчик. Отладка Запустить отладчик из-под Администратора, сделать attach to process. Системный вызов DbgBreakPoint(). Драйверы Драйвер — особый вид сервиса. Драйвер работает в нулевом кольце защиты. Начиная с 256-го процессора, существуют функции защиты памяти. Главная идея в том, что не каждая программа имеет доступ ко всей памяти, ко всем портам, т. е. ко всем аппаратным ресурсам. Имеется 2 кольца защиты. Кольцо защиты привилегированных программ и непривилегированных программ. Непривилегированные программы (user mode) не могут обращаться к портам аппаратуры, не могут узнавать и модифицировать таблицы прерываний, они не могут управлять распределением памяти и могут обращаться только к той памяти, которая им явно позволена. Kernel mode — обычно в нем работает только ядро ОС. Программы в kernel mode делают все, что хотят. В процессорах Intel — 4 кольца защиты. Два кольца между kernel и user mode — сейчас не используются (используется в OS/2). «Драйвер принтера» не является драйвером, он является библиотекой. Драйвер принтера не работает в kernel mode, а драйвером называется по чисто исторической причине. Зачем нужны драйверы? Во-первых, чтобы управлять нестандартным железом. Чтобы управлять «железкой», необходимо соответствующим образом реагировать на сигналы, посылать сигналы, понимать формат данных и т. д. Есть где-то около пятидесяти стандартных операций. Для некоторых видов железок существуют соглашения, для таких устройств не нужны драйвера (приводы, мыши и т. д.). Иногда рассматривать некую виртуальную сущность, будто бы это была железка (разделы жесткого диска, большинство сетевых протоколов). Отсюда возникла концепция драйвер логического устройства. Также, в Windows есть понятия физической и логической клавиатуры. Смысл физически различных клавиатур инкапсулируется в понятия логической клавиатуры. В современных ОС логических устройств обычно больше чем физических. Драйверы могут образовывать цепочки. В цепочке более низкие драйверы обслуживают запросы более высоких. Ниже самого низкого драйвера лежит железо. Пример: Прикладные программы Ядро Логический диск Физический диск Железка Существует множество видов драйверов. Есть два интерфейса для работы с драйверами. Первый — интерфейс сервисов. Поддерживает команды «инсталлировать», «стартовать», «остановить» и т. д. Каждый драйвер обязан поддерживать хотя бы одно устройство. CreateFile() Можно вместо файла указать устройство и оно откроется (создавать устройства таким образом нельзя). FILE_SHARE_READ | FILE_SHARE_WRITE Позволить другим программа использовать устройство. SetFilePointer() Эта функция перемещает указатель текущей позиции в файле. (Не все устройства это поддерживают, только накопительные.) DeviceIoControl() Всё, что не чтение и не запись — управление (извлечь диск, отформатировать хард, прочитать геометрию жесткого диска). Как писать драйвер. Физически драйвер представляет собой извращенный вид библиотеки. Он загружается в адресное пространство ядра. Структура адресного пространства процесса Win32: User memory Kernel memory Всего 4 ГБ. 64 КБ после и до NULL — запрещены. У всех процессов вторая половина (kernel memory) — одинакова. Ядру не нужно думать, в адресном пространстве какого процесса оно сейчас находится. Драйвер грузится во вторую половину. Драйверы имеет некоторые отличия от стандартных библиотек: Драйверы не могут использоваться WinAPI, только NTAPI. Весь код WinAPI грузятся в user memory. o NTAPI — в ntdll.dll. Поверх, по сути, эмулятор Windows. WDK (DDK) —продукт для создания драйверов (маны, примеры и т .д.). Есть build, утилита для компиляции драйверов. Главный заголовочный файл — ntddk.h. Отлаживать драйвер следует на виртуальной машине. Фатальная ошибка — смерть всей системы целиком (синий экран). Windbg (из пакета Debugging tools) — для отладки. В виртуальной машине создается COM-порт. В boot.ini дописывается /debugport=com1 и /baudrate=115200 к записи соответствующей операционной системы. Для драйверов есть функция для вывод информации на консоль отладчика: DbgPrint(); Начиная с Vista — только DbgPrintEx(). (Старая функция не работает.) Все драйверы начинаются с: NTSTATUS DriverEntry(PDRIVER_OBJEACT pDriverObject, PUNICODE_STRING RegistryPath); ntstatus.h — коды ошибок. PUNICODE_STRING: 2: длина буфера 2Б: длина строки 4Б: указатель строка Не обязана заканчивать нулевым символом, более того, может содержать нулевой символ в середине. \Registry\Machine\System\ — конфигурации драйверов. Каждый драйвер должен иметь хотя бы одно устройство. Усройство создается с помощью IoCreateDevice() Параметры: Имя: \Device\имя Device extension, нужен, когда драйвер может обслуживать несколько разных устройств (например, драйвер ФС). выдается DEVICE_OBJECT. Следует делать IoDeleteDevice(). Чтобы обращаться к устройство через WinAPI нужно создать линк \??\link. IoCreateSymbolicLink() Delete() Запросы, которые все драйверы обязаны обрабатывать: Create o Например, обеспечивает монопольный доступ. Close Часто, эти обработчики пустые. Еще: Read Write DeviceControl Прототип: NTSTATUS XDispatchY (PDEVICE_OBJECT pDeviceObject, PIRP pirp) IRP — пакет. IoStatus.Status.Information следует возвращать ноль. IoCompleteRequest завершает обработку запроса. Есть такое понятие — IRP stack. Необходим, когда в обработке запроса участвуют несколько драйверов. Перехват информационных потоков. Программа CreateFile Windows API (Kernel32.dll) NtCreateFile NT API (ntdll.dll) Ядро Драйвер mov eax, номер mov edx, p call edc ret число1 ... p: sysenter/syscall/int 2E ret число2 Для sysenter и syscall используется регистр STAR MSR. Указывает на KiSystemService. Фрагмент: mov rax, a sub rax, длина кадра стека jmp rax ... mov mov mov mov rax, [rsi+4] [rdi+4], rax rax, [esi] [rdi], rax Код для копирования N байт сам занимает N байт. KeServiceDescriptorTable — экспортируемая переменная ядрая. Содержит указатель на SST (System Service Table). SST Service Table LowCall = 0 HiCall ServiceTable ... ... (HiCall+1 штука) Для всех функций в NT API существует два имени: NT... и Zw... В пользовательском режиме NT=Zw. Однако в режиме ядра NT — функция-сервер, Zw — функция клиент. Когда приходит управление из прикладной программы, вызывается функция-сервер, но для своих нужд вызывается функция-клиент. Zw включает в себя NT. Вызывать надо Zw, перехватывать — NT. Если драйвер запишет в нужный индекс SST свою функцию, то система вызовет ее. Способы поиска функции в SST: Обратиться по имени, выяснить адрес (функция должна быть экспортируема и быть в либах). Руками найти адрес функции в памяти (функция должна быть экспортируема). Функция может быть не экспортируема. Можно извлечь номер прямо из машинного кода (обычно из клиентской программы) Программная закладка Это программа или фрагмент программы, скрытно внедряемый в атакуемую систему, для осуществления НСД к ее ресурсам. Две четко выраженные стадии: внедрение и функционирование. Этим закладка отличается от других вредоносных программ. Слово «программа» не означает, что это экзешник, это может и библиотека, и драйвер, и вебстраница, и макросы в Ворде. НСД мы понимаем расширенно, не только как чтение, но и изменение, удаление и нарушение доступности. Начиная с 2002 года, НСД без программной раскладки считается извращением (раньше, например, пытались создать пользователя). Закладки хороши тем, что позволяют не только эксплуатировать существующие уязвимости, но и создавать новые. Закладки позволяют эксплуатировать кратковременные уязвимости. Закладка может активно противодействовать методам ее обнаружения. Классификация (модели): Наблюдатель. o По сути, обычная программа. o Оказывает воздействия только по команде нарушения. o Имеется сервер на зараженной системе и клиент на машине нарушителя. o Умеет: Работа с ФС. Работа с реестром. Управление списком процессов. o Есть хорошая идея — ядро + плагины. Ядро умеет скачивать, устанавливать, удалять и управлять плагинами. o TCP. Открытие слушающего сокета служит сигналом для фаервола, поэтому нужно обходить фаерволы или отключать их. o UDP. Можно эмулировать TCP на более высоком уровне. Впервые UDP использован в Cult of the dead cow. Дырку закрыли, но UDP продолжают использовать. o NPFS. Надстройка над SMB, используется в файловых и принт-серверах от Микрософта. o HTTP. Веб-сервер на зараженной машине — подозрительно. Клиент — надо ждать соединений, к тому же палится адрес злоумышленника (эту проблему можно решить созданием ретранслятора, что тоже очень неудобно). o Недостаток: неудобно работать, особенно с множеством зараженных. Перехват. o Более глубоко интегрирована в систему, перехватывает информационные потоки. o Является наиболее популярной. o Перехватывает Аутентификационные данные. Документы Сетевой трафик. o Перехватчики паролей — древнейший тип. Бывают трех родов: 1 рода — спуффер. Ложное приглашение на ввод пароля. XSS — идея в том, что юзеры подсовывают ссылку на один сайт, а он попадает на другой. Или на тот же, но с другой формой. 2 рода — кейлогер. В основном под Винду. Меняет механизм локализации клавиатуры. В Винде механизм основывается на hook’ах. Есть ограничения, связанные с мандатным разграничением прав. Продвинутая идея — брать не весь клавиатурный ввод, а только ввод в определенные окна определенных программ. Плюс собирать дополнительные сообщения, типа изменения размера окна и т. д. Можно сформировать критерии о том, что сообщение пришло в программу, которая интересует кейлогер. Достоинства: легко делается, работает надежно. Недостатки: хуки работают только на том же десктопе, пользователи делают опечатки (это больше касается текста, а не паролей), сложно замаскировать. 3 рода. Непосредственный перехват на стадии аутентификации. Подмена программы login в Юниксе. o Перехват документов Перехват информационных потоков — крайне сложен на практике. File mapping — перехват при свопинге, тоже не реализуется нормально. В целом — ничего нормально работающего не существует. Реально работающий способ — просмотр журнала недавно открытых документов (лог пишется функцией shOpenDocument), а также просто просматривать популярные папки, типа Мои документы или Рабочий стол. Обнаружить такую закладку очень сложно, только по сторонним признакам o Перехват сетевого трафика Снифферы. Практически невозможно скрыть. Несанкционированный перехват трафика. Нормально работает только Микрософтовский фаервол :) Короче, нет механизмов, которые одновременно скрытно и надежны. Частные решения: Электронная почта. Можно просто найти хранилище почтовой программы. (В Аутлуке, правда, в файле лежит что-то типа FATоподобной ФС.) Есть MAPI (Messaging Application Programming Interface). Клиент ведет лог (аська, твиттер и т. д.) Веб-интерфейс. Решается тоже просмотром файлов на диске. Искажение o (Закладки подменяет информацию, выходит не то, что входит. Пример — драйвер, которым мы писали в начале семестра.) o o o o o Основное назначение — стелс-технологии. Закладка скрывает от пользователя свое присутствие в системе. Простейший пример — скрытие файла путем перехвата получения списка файлов директории. Аналогично можно скрывать процессы, ключи реестра и т. д. Причем перехват SST — не лучший вариант. Есть некоторые типичные проблемы, которые палят закладку. Причем не всегда понятно, что скрывается, но понятно, что что-то скрывается. Проблема общей статистики. Например, скрыли процесс, в списке его нет. Однако не сойдется сумма по процессорному времени (небольшое отклонение, правда, можно списать на ошибку округления). Еще ярче эта ситуация проявляется с сетевым трафиком. Для борьбы с этой проблемой используют «оракулов», которые не дают закладке занимать много ресурсов. Проблема индусских мониторов. Закладка тестируется на стандартных мониторах, однако существует и всякие другие, например, идущие в комплекте с китайским железом. Они используют нестандартные способы снятия статистики. Rootkit revealer — программа для выявления стелсов. Сканирует реестр и ФС дважды — с помощью штатных средств и на более низком уровне. Потом ищет разницу. Противодействие есть — не скрывать закладку от таких программ. Режим гипервизора — помещение ядра ОС в песочницу. В некоторым смысле, текущая система становится виртуальной. Таких закладок пока нет, ибо написание таковых по сложности сравнимо с написанием ядра ОС. Про сеть. Работает идея проксирования. Закладки встраивается в сетевую подсистему ОС. Весь трафик перенаправляется на специальную машину. Несколько историй про перехват экзотических информационных потоков: Девяностые годы, банки. Через ФИДО распространилась «ускорялка» (Турбокриптон) для криптографических преобразований. Система проверки ЭЦП. Закладка сканировала видеопамять и стирала буковки «НЕ». Слово «НЕКОРРЕКТНО» превращалось в «КОРРЕКТНО». Внедрение в браузер. Находим ссылки Google ads и меняем на ссылки другой рекламный ресурс. Повышение привилегий. Юзер заходит на машину с закладкой, дает закладке специальную команду — и ему повышаются права. Мощная идея: подправить монитор безопасности объекта в ядре, чтобы права доступа контролировались по другим правилам (как зарегистрировался в закладке, тот и имеет права). Но со временем стало понятно, что лучше сделать так, чтобы закладка исполнялось из под прав суперпользователя, а пользователю вообще не надо заходить в систему стандартными средствами. Внедрение программных закладок Если система не имеет уязвимости, то внедрить закладку невозможно. На практике уязвимости обычно есть. Классы: Уязвимость ПО. o Переполнение буфера. Код затереть сложно, обычно затирают указатели на код. Борьба: Рэндомизация размещения в памяти. Запрет исполнения кода из области данных. o Забытые проверки. Уязвимости политики безопасности. o Человеческий фактор. o Не человеческий фактор.