Стек вызовов Windows API
Запись от _lunar_ размещена 11.04.2022 в 14:59
Показов 2553
Комментарии 0
|
В этой записи я постараюсь простым понятным языком объяснить что такое API в целом, а также его разновидности в зависимости от того, где это API исполняется. Сперва, предлагаю внимательно посмотреть на скриншот и запомнить последовательность вызовов (не стал рисовать свои скриншоты, т.к. этот в полной мере описывает весь процесс) Итак, после того, как исходный код был скомпилирован, появляется пользовательское приложение (файл с расширением *.exe). EXE файл это исполняемый файл со строго типизированной структурой заголовка Portable Executable (PE). Формат PE достаточно объемный, и поэтому кажется сложным. Но Microsoft любезно предоставляет спецификацию этого формата PE Format, так что с освоением проблем не должно возникнуть. Такая структурированность требуется для того, чтобы загрузчик Windows смог проецировать таблицы с кодом, заложенные в EXE файле, в виртуальное адресное пространство, для дальнейшего его исполнения на процессоре (инструкция за инструкцией). Я сейчас не буду подробно останавливаться на каждой таблице, но нужно запомнить вот что: у EXE файлов всегда есть таблица импорта адресов - Import Address Table (IAT) (за исключением случаев, когда код написан без среды выполнения C Runtime (CRT)). Вернёмся на шаг назад - к исходному коду. Когда программист пишет код будущего пользовательского приложения, он использует заготовленные файлы хидеров (Header), в которых определены различные константы, прототипы функций и многое другое. Хидер это просто текст и не более. Ещё программист использует библиотеки (*.lib), чтобы связать (слинковать) прототип функции из хидера с реальной функций в одной из системных библиотек DLL. Именно эта связь формирует таблицу импорта адресов (IAT) в заголовке PE будущего EXE файла. Снова вернёмся к скриншоту, на котором для примера выбрана функция WriteFile и весь её стек вызовов. И вот тут уже можно начинать задать вопрос - что же такое Application Programming Interface (API)? Начнем с пользовательского окружения - то, что доступно непосредственно пользователю: Windows API (WinAPI). WinAPI это документированное API, т.е. к прототипам его функций есть описание и спецификации. WinAPI представляет собой массивный набор функций, распределенный по нескольким системным библиотекам DLL. Основные системные библиотеки пользовательского окружения: kernelbase.dll (до Windows 8 это была kernel32.dll и теперь она служит лишь стабом для совместимости), user32.dll, gdi32.dll, advapi32.dll, ntmarta.dll, shell32.dll и др. В них собрано огромное количество функций, которые и формируют WinAPI. Когда программист в коде использует функцию WriteFile, он вызывает её API из соответствующей системной библиотеки (в данном случае kernel32.dll).По сути API это ничто иное как исполняемый код в самой библиотеки DLL. Там выполняются различные internal функции (не экспортируемые функции), вычисления, заполнение переменных, переданных программистом через аргументы функции WriteFile.Формируется так называемый пользовательский контекст - массив данных, который передаётся ядру ОС через ссылку на стек (шлюз)
WriteFile в библиотеке kernel32.dll будет вызов функции NtWriteFile с тем самым пользовательским контекстом.Есть ещё несколько библиотек пользовательского окружения, таких как ntdll.dll и win32u.dll, функции которых доступны из UserMode. Набор их функций формирует так называемое NativeAPI. NativeAPI это недокументированное API, и разбор прототипов его функций осуществляется энтузиастами в ручном режиме с помощью отладчиков и дизассемблеров. Главная задача этих функций - передать пользовательский контекст в ядро ОС. Делается это переключением (или точнее системным прерыванием) процессора в защищенный режим (ProtectedMode). В современных ОС и процессорах для этого используются инструкции SYSCALL или SYSENTER (внутри KiFastSystemCall) (в старых ОС это системное прерывание называлось int 2e (внутри KiIntSystemCall))Возврат контекста из ядра ОС в пользовательский режим осуществляется инструкциями SYSRET или SYSEXIT (внутри KiFastSystemCallRet).После того, как процессор перешёл в защищенный режим (ProtectedMode), переданный пользовательский контекст начинает обрабатываться в ядре ОС - ntoskrnl.exe Для этого используется процедура ZwWriteFile (не путайте с функций NtWriteFile из библиотеки ntdll.dll). Код API, который исполняется в ядре ОС называется KernelAPI. KernelAPI это недокументированное API (небольшая часть функций всё же описана в WDK, но не все). В кругах низкоуровневых программистов функции KernelAPI ещё называют сервисами (или подпрограммами системных служб). Дальше опускаться уже не будем - там только слой аппаратных абстракций (HAL) и само железо. В двух словах: HAL транслирует код в оперативной памяти таким образом, чтобы другие микроконтроллеры смогли обработать запросы от центрального процессора и предоставить ответы. Вот одна из Hal-функций, которые начиная с поздних версий Windows 10, переехали из hal.dll в ядро ОС ntoskrnl.exe
1. операционная система Windows предоставляет API интерфейсы, расположенные в библиотеках DLL. 2. пользовательское приложение вызывает API, реализованное в библиотеках DLL. 3. большинство функций API в конечном итоге вызывают подпрограммы системных служб (сервисы) в ntoskrnl.exe Все менеджеры, утилиты, программы и т.д. используют API. API не может использовать менеджеры и утилиты в качестве запуска службы и прочего. API это программный интерфейс, выполняющий определенные команды, которыми пользуются программисты при разработке приложений. | ||||||||||
Размещено в Без категории
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Всего комментариев 0
Комментарии


