Полное название SSDT — Таблица дескрипторов системных служб, таблица дескрипторов системных служб. Эта таблица представляет собой связь между Win32 API Ring3 и API ядра Ring0. SSDT не только содержит огромную таблицу индексов адресов, но также содержит некоторую другую полезную информацию, такую как базовый адрес индекса адреса, количество сервисных функций и т. Д. Изменяя адреса функций в этой таблице, можно подключать общие функции и API-интерфейсы Windows для достижения цели фильтрации и мониторинга некоторых представляющих интерес системных действий. Некоторые HIPS, антивирусное программное обеспечение, программное обеспечение для мониторинга системы и мониторинга реестра часто используют этот интерфейс для реализации собственных модулей мониторинга.
Windows выше NT 4.0Операционная системаВ, по умолчанию существует две таблицы описания системных служб. Эти две таблицы расписания соответствуют двум различным типам системных служб. Две таблицы расписания: KeServiceDescriptorTable и KeServiceDescriptorTableShadow. Среди них KeServiceDescriptorTable в основном работает с Kernel32.dll из уровня Ring3. KeServiceDescriptorTableShadow в основном обрабатывает системные вызовы из User32.dll и GDI32.dll, а KeServiceDescriptorTable экспортируется в ntoskrnl.exe (файлы ядра операционной системы Windows, включая уровень ядра и исполнительного органа), а KeServiceDescriptorTableShadow — это Он не экспортируется операционной системой Windows, и все содержимое SSDT завершается через KeServiceDescriptorTable.
ПОЛНАЯ ИНСТРУКЦИЯ DSDT/SSDT DSL AML! HACKINTOSH!
2. Структура SSDT
На следующем рисунке представлена структура KeServiceDescriptorTable, экспортированная из ntoskrnl.exe, проанализированная IDA.
Ниже приводится конкретное значение KeServiceDescriptorTable.
~~~c++
typedef struct _KSYSTEM_SERVICE_TABLE <
PULONG ServiceTableBase; // Базовый адрес SSDT (таблица диспетчеризации системных служб)
PULONG ServiceCounterTableBase; // Используется для проверенных сборок, включая количество вызовов каждой службы в SSDT
ULONG NumberOfService; // Количество сервисных функций, NumberOfService * 4 — это размер всей таблицы адресов
ULONG ParamTableBase; // Базовый адрес SSPT (таблица параметров системной службы)
> KSYSTEM_SERVICE_TABLE, *PKSYSTEM_SERVICE_TABLE;
С введением выше мы можем просто рассматривать KeServiceDescriptor как массив (его суть — массив) ** в API ntdll.dll прикладного уровня в этой таблице описания системных сервисов (SSDT). Ему соответствует служба. Когда наше приложение вызывает API в ntdll.dll, оно в конечном итоге вызывает соответствующую системную службу в ядре. С SSDT нам нужно только указать ядру, чтобы он вызвал Индекс в SSDT, где расположена служба, в порядке, а затем ядро может найти соответствующую службу в SSDT на основе этого значения индекса, а затем ядро может вызвать службу для выполнения запроса вызова API приложения. Базовая структура может относиться к следующему рисунку:
Установка SQL Server Data Tools (SSDT)
3. Полный процесс выполнения прикладного уровня, вызывающего Win32 API.
Используя вышеупомянутую основу SSDT, давайте рассмотрим полный процесс вызова Win32 API (здесь в основном относится к API в ntdll.dll) на уровне приложения. Здесь мы в основном анализируем NtQuerySystemInformation API в ntdll.dll Назовите процесс.
(PS: Диспетчер задач Windows использует этот API для получения информации о процессах системы и т. Д.).
Затем дайте базовый процесс вызова этих API
По сути, в операционной системе Windows ZwQuerySystemInformation и NtQuerySystemInformation в Ntdll.dll являются одной и той же функцией. Как вы можете видеть на снимке экрана ниже, адреса входа этих двух функций указывают на одну и ту же область, а адреса входа их функций совпадают. ,
Хорошо известный API в Ntdll.dll — это просто функция-оболочка. Когда API в Kernel32.dll передает Ntdll.dll, проверка параметров будет завершена, а затем будет вызвано прерывание (int 2Eh или инструкция SysEnter) для достижения Войдите в уровень Ring0 из Ring3 и сохраните номер службы (то есть значение индекса в массиве SSDT), который будет вызываться в регистре EAX, и поместите адрес параметра в назначенный регистр (EDX), а затем скопируйте параметр в ядро. В адресном пространстве указанная служба вызывается в массиве SSDT в соответствии со значением индекса, хранящимся в EAX.
Давайте посмотрим на ZwQuerySystemInformation в ntoskrnl.exe:
На скриншоте выше вы можете видеть, что ZwQuerySystemInformation под Ring0 помещает 0ADh в регистр eax, а затем вызывает функцию распределения системных служб KiSystemService, и эта функция KiSystemService основана на значении индекса в регистре eax, а затем Затем найдите элемент SSDT, значение индекса которого хранится в регистре eax в массиве SSDT, и, наконец, вызовите системную службу в соответствии с адресом системной службы, хранящимся в этом элементе SSDT. Например, здесь можно вызвать системную службу, соответствующую адресу, сохраненному в KeServiceDescriptorTable [0ADh]. То есть вызывается NtQuerySystemInformation под Ring0. На этом весь процесс вызова NtQuerySystemInformation на уровне приложения завершен.
Во-вторых, принцип SSDT Hook
1. Введение в принцип SSDT Hook
Используя приведенную выше часть основы, вы можете взглянуть на принцип SSDT HOOK. На самом деле, принцип SSDT Hook очень прост. Из приведенного выше анализа мы можем узнать, что массив SSDT хранит системные службы Адрес, например адрес системной службы NtQuerySystemInformation в Ring0, сохраняется в KeServiceDescriptorTable [0ADh]. Поскольку это Hook, мы можем заменить адрес службы, сохраненный в KeServiceDescriptorTable [0ADh], и заменить наш собственный Hook Замените исходный адрес на адрес функции обработки, чтобы наша собственная функция обработки Hook вызывалась каждый раз при вызове KeServiceDescriptorTable [0ADh].
Снимок экрана ниже перед SSDT Hook:
Снимок экрана ниже после SSDT Hook, вы можете видеть, что адрес службы в SSDT был изменен на MyHookNtQuerySystemInformation. В этом случае каждый раз, когда система вызывает системную службу NtQuerySystemInformation, она по существу вызывает MyHookNtQuerySystemInformation, и мы хотим, чтобы система Стабильность системы (по крайней мере, чтобы не дать ей сбой), исходная служба в системе обычно вызывается в MyHookNtQuerySystemInformation, то есть NtQuerySystemInformation.
Давайте посмотрим на конкретный код для резервного копирования, изменения и восстановления SSDT:
Источник: russianblogs.com
Microsoft SQL Server Data Tools
Всё необходимое для установки можно найти на странице загрузки в Data Developer Center. Выбрав необходимую версию вы сможете без труда установить инструменты на свой компьютер и описывать это не вижу смысла. После установки в окне создания нового проекта у вас появится новый тип проекта:
Создав новый проект вы увидите следующее:
На панели SQL Server Object Explorer (меню View -> SQL Server Object Explorer) мы видим нечто очень похожее на Object Explorer в SQL Server Management Studio, из которого убрано всё, что не имеет большого смысла на этапе разработки базы данных.
Подключившись к существующей базе, можно производить разработку базы данных в так называемом Connected режиме. Это мало чем отличается от классического подхода используемого в SQL Server Management Studio и в данной статье рассматриваться не будет.
Disconnected режим
Этот режим разработки нам наиболее интересен, т.к. именно он позволяет получить основные преимущества использования SSDT.
В основе работы лежит очень простая идея – позволить разработчикам хранить все скрипты создания объектов БД (tables, views, store procedures и т. д.) в проекте специального типа в составе имеющегося или нового решения (solution). На основе скриптов, Visual Studio может сгенерировать DACPAC файл, который по сути является zip архив со всеми t-sql скриптами. Имея DACPAC файл можно будет произвести публикацию (publish) на требуемом экземпляре базы данных, путём сравнения схемы описанной в DACPAC и схемы в целевой базе данных. В ходе публикации, специальные механизмы производят сравнения, в результате чего автоматически создаются миграционные скрипты для применения изменений без потери данных.
Для того что увидеть это в действии, предлагаю посмотреть следующие примеры.
Начнём с возможности импорта. Вызываем контекстное меню проекта и видим 3 возможных варианта:
- Script (*.sql) – добавляет один или несколько *.sql файлов из заданного расположения в структуру проекта;
- Data-tier Application (*.dacpac) – добавляет *.sql файлы, а так же различные настройки базы данных из специального DACPAC файла, описанного выше; может содержать не только схему базы, но так же данные и различные настройки базы;
- Database… — аналогичен предыдущему варианту, но источником данных служит существующая база
После завершения импорта мы увидим крайне похожую картину, с тем единственным различием, что структура базы будет представлена в Solution Explorer в качестве *.sql файлов.
Так же мы всегда можем добавить новые элементы воспользовавшись диалоговым окном Add New Item, в котором перечислены все возможные объекты базы данных:
Добавим таблицу TestTable. Новый файл-скрипт TestTable.sql будет добавлен в корень проекта и для удобства мы его перенесём в папку Tables.
Для создания схемы таблицы мы можем использовать как панель дизайнера, так и панель T-SQL. Все изменения сделанные на одной панели будут сразу же отображены в другой.
Так же мы можем изменять существующие скрипты. Visual Studio для этого предоставляет удобный и любимый всеми IntelliSense. Так как мы не подключены к физической базе данных, Visual Studio для корректной работы IntelliSence парсит все скрипты в проекте, что позволяет ей мгновенно отражать последние изменения сделанные в схеме базы данных.
Хочу обратить внимание на то, что мы не должны заботиться об инкрементных изменениях нашей базы. Вместо этого мы всегда создаём скрипты так, как если бы объекты создавались заново. При публикации DACPAC пакета миграционные скрипты будут сгенерированы автоматически, путём сравнения DACPAC файла и схемы в целевой базе (target Database).
Как уже упоминалось, DACPAC содержит не только схему и данные, но ещё и ряд полезных настроек, для просмотра/редактирования которых мы можем воспользоваться окном свойств нашего проекта.
Свойство Target platform позволяет выставить версию базы данных, для которой будут валидироваться скрипты в проекте. Минимальная поддерживаемая версия MS SQL Server 2005. Если например задать версию базы 2005 и попробовать создать колонку типа Geography, то при компиляции мы получим следующее сообщение:
На закладке Project Settings, мы можем задать настройки базы данных, нажав на кнопку Database Settings. Нажав на неё мы увидим диалог с настройками, аналогичные тем, что мы привыкли видеть в SQL Server Management Studio:
Так же хочется упомянуть закладку SQLCMD Variables, на которой мы можем задавать различные переменные для дальнейшего их использования в наших скриптах.
Публикация DACPAC файла (publishing)
После того, как все настройки заданы и *.sql скрипты добавлены/обновлены мы можем применить изменения к целевой базе (target database). Для этого идём в меню Build->Publish или же выбираем аналогичный пункт в контекстном меню проекта.
В появившемся диалоговом окне задаём строку подключения к базе назначения (target database) и если необходимо — дополнительные настройки, нажав на кнопку Advanced:
Большинство настроек понятны без дополнительного описания, поэтому не будем на них останавливаться подробно, но рекомендую с ними ознакомиться, что бы в случае невозможности успешно «запаблишить» проект, вы знали в чём может быть проблема.
Если требуется производить публикацию в целевую базу данных более одного раза, то настройки можно сохранить в publish профиль, нажав на кнопку Create Profile. Это добавит в наш проект файл с расширением *.publish.xml и в дальнейшем мы сможем произвести публикацию без необходимости вводить настройки ещё раз. Если же какой-то из профилей публикации должен быть использован по умолчанию, то можно в контекстном меню файла публикации выбрать пункт Set As Default Publish Profile. Этот профиль будет автоматически загружаться в диалог Publish.
- Бесплатная редакция Visual Studio с установленными SSDT (в частности для publish используются клиентские инструменты, входящие в состав DAC Framework, устанавливаемые вместе с SSDT)
- MS SQL Server Management Studio + DAC Framework
- Консольная утилита SqlPackage.exe
- Windows PowerShell (пример)
- Data-tier Application Framework (DACFx) позволяющий поставить DACPAC файл, путём вызова методов из C# программы (документация и пример)
Data Seeding
В нашем проекте создадим папку DataSeeding (имя не имеет значения) и в неё добавим новый скрипт.
По сути все типы в разделе User Script являются обычными *.sql скриптами и отличаются лишь значением свойства “Build Action” у вновь созданного файла.
Логика из файла PostDeployment.sql будет выполнена после применения всех изменений схемы базы данных. В случае создания PreDeployment.sql — логика выполнится перед применением изменений схемы.
Значение свойства Build Action для файлов созданных через шаблон Script (Not in Build) будет установлено в «None». Они полезные для удобного структурирования команд в отдельных файлах, которые вызываются из Pre или Post Deployment скриптов.
Файлы созданные через шаблон Script имеют значение Build Action равное «Build», и их содержимое добавляется к результирующему скрипту, который выполняется при publish’e DACPAC файла в момент изменения схемы базы.
В виду того, что в проекте может быть только один Post Deployment script и его размер может быстро вырасти, рекомендуется логику вставки данных выносить в отдельные скрипты. Именно поэтому мы добавим файл типа Script (Not in Build), а в Post Deployment script добавим ссылку на него. Вот как это будет выглядеть:
Теперь при публикации нашего проекта, в базе всегда будут вставлены 2 записи в таблицу Employees.
Tools -> SQL Server
На ряду с возможностью создания Database проекта, установка SSDT добавляет ряд полезных инструментов, доступных из меню Tools.
Думаю, что из названия и так понятно, что каждый из пунктов делает. Как пример, покажу удобный графический инструмент сравнения схем. В качестве источника и целевого объекта можно выбрать один из трех вариантов:
Мы сравним наш проект с локальной базой данных. Результат сравнения будет выглядеть следующим образом:
В результирующем окне мы можем применить различные способы группировки (по схеме, по типу объектов и по требуемому действию) для более удобного просмотра предлагаемых изменений и выбрать те объекты, которые требуется обновить. Для того, что бы применить миграционный скрипт необходимо нажать кнопку Update – это приведёт Target DB к состоянию нашего проекта.
Refactoring
Это моя любимая фича. Для примера, покажем как переименовать колонку LastName в таблице Employees. Для этого открываем скрипт создания таблицы, в редакторе таблицы выделяем колонку LastName и в меню SQL -> Refactor выбираем пункт Rename:
Задаём новое имя:
Просматриваем последствия переименования и применяем предложенные изменения:
В результате все скрипты будут изменены и после первого рефакторинга в проект будет добавлен специальный файл *.refactoring. В нём будут сохраняться все изменения схемы в историческом порядке в формате XML документа. Эти данные будут полезны при генерации миграционного скрипта и позволят более правильно мигрировать схему и данные.
Unit testing
Создадим наш первый юнит тест. Для этого вызовем контекстное меню для хранимой процедуры, которую мы хотим протестировать:
В появившемся диалоговом окне у нас будет возможность выбрать дополнительные объекты (если они есть) и задать тип и имя тестового проекта и имя класса, содержащего код юнит теста:
Создав проект нам будет предложено выбрать базу данных на которой будут запускаться тесты, а также некоторые настройки проекта:
После успешного создания у нас откроется графический редактор юнит теста, в нижней части которого будут представлены различные проверки для тестируемого объекта. В нашем случае это хранимая процедура EmployeeGetList.
Наша задача сводится к тому, что бы написать необходимый Sql скрипт и задать требуемые условия проверки, которые будут произведены после выполнения кода скрипта. Проверки могут быть разные: время исполнения, количество возращённых строк, Checksum возвращённых данных и т.п. Полный список проверок можно найти в выпадающем меню под текстом скрипта и над таблицей проверок. Для каждой проверки можно задать ряд настроек через стандартную панель Properties. Для её вызова необходимо в контекстном меню конкретной проверки выбрать пункт Properties.
Например, вот так будет выглядеть проверка возвращаемого количества строк:
А вот так можно проверить Checksum:
По сути эта проверка выполняет наш скрипт (получает 2 строки из таблицы Employees) и на полученных данных находит Checksum. Наша задача на этапе создания теста, найти эталонные данные, на них посчитать Checksum и в дальнейшем с этим значением будет производиться сверка полученного результата. Иными словами, это удобный способ убедиться, что результат хранимой процедуры не меняется. Для получения контрольного значения Checksum, необходимо воспользоваться кнопкой в окне Properties, которая позволит выбрать эталонную базу и получить эталонное значение Cheсksum:
Заключение
Надеюсь этот краткий обзор позволил получить общее представление, что такое SSDT и как они могут быть полезны в вашем проекте. Безусловно тут не были рассмотрены все детали. Но вам, как разработчику это и не нужно. Вы должны просто иметь общее представление списка возможностей, а дальнейшее их использование надеюсь будет интуитивно понятным, т.к. разработчики SSDT хорошо потрудились и снабдили инструменты огромным количеством помощников (wizards) и контекстных подсказок.
- Блог компании Инфопульс Украина
- Программирование
- .NET
- SQL
- Microsoft SQL Server
Источник: habr.com