Ремонт, сервис, услуги » Информация » Диспетчеризация системных служб




Диспетчеризация системных служб

Автор: addministr от 16-07-2014, 20:46

Категория: Информация



На процессорах x86, предшествующих процессорам Pentium II, Windows использует инструкцию 0x2e (46 в десятичном выражении), которая приводит к системному прерыванию. Windows заполняет запись 46 в IDT указателем на диспетчер системных служб. Системное прерывание заставляет выполняемый поток перейти в режим ядра и войти в диспетчер системных служб. В регистр процессора EAX передается числовой аргумент, показывающий номер запрашиваемой системной службы. Регистр EDX указывает на список параметров, который вызывающая программа передает системной службе. Для возвращения в пользовательский режим диспетчер системной службы использует инструкцию iret (interrupt return — возврат из прерывания). На процессоре x86 Pentium II и выше Windows использует инструкцию sysenter, которую компания Intel определила специально для быстродействующих диспетчеров системных служб.

Для поддержки инструкции Windows сохраняет во время загрузки адрес процедуры диспетчера системных служб, находящейся в ядре, в машинно-зависимый регистр (machine-specific register, MSR), связанный с инструкцией. Выполнение инструкции приводит к переходу в режим ядра и к выполнению кода диспетчера системных служб. Номер системной службы передается в регистр процессора EAX, а регистр EDX указывает на список аргументов вызывающей программы. Для возврата в пользовательский режим диспетчер системных служб обычно выполняет инструкцию sysexit. В некоторых случаях, например, при установленном на процессоре флаге пошагового выполнения, диспетчер системных служб использует вместо нее инструкцию iret, потому что sysexit не позволяет возвращаться в пользовательский режим с измененным регистром EFLAGS, что необходимо в том случае, если инструкция sysenter была выполнена, когда флаг trap был установлен в результате трассировки, проводимой отладчиком в пользовательском режиме или при пропуске системного вызова.

Поскольку некоторые старые приложения могли быть жестко запрограммированы на использование инструкции int 0x2e для самостоятельного использования системного вызова (не поддерживаемой операции), 32-разрядная версия Windows сохраняет этот механизм готовым к использованию на системах, поддерживающих инструкцию sysenter, по-прежнему регистрируя обработчик. В архитектуре x64 Windows использует инструкцию syscall, передавая номер системного вызова в регистре EAX, и любые параметры, вне тех четырех, в стеке. В архитектуре IA64 Windows использует инструкцию epc (привилегированный режим ввода — EnterPrivilegedMode). Первые 8 аргументов системного вызова передаются в регистрах, а остальные 8 передаются в стеке.

Определение местоположения диспетчера системных служб.

Как уже ранее говорилось, вызовы 32-разрядной системы осуществляются через прерывание, из чего следует, что обработчик должен быть зарегистрирован в IDT или через специальную инструкцию sysenter, которая во время загрузки использует для сохранения адреса обработчика регистр MSR. На некоторых 32-разрядных системах AMD Windows использует вместо нее инструкцию syscall, которая похожа на 64-разрядную инструкцию syscall. Определить местоположение соответствующей процедуры для любого метода можно следующим образом:

Для просмотра обработчика на 32-разрядных системах с версией системного вызова диспетчера с помощью прерывания 2E нужно набрать в отладчике ядра команду !idt 2e.

lkd> !idt 2e Dumping IDT: 2e: 8208c8ee nt!KiSystemService

Для просмотра обработчика на системах с версией sysenter нужно воспользоваться командой отладчика rdmsr для чтения данных из MSR-регистра 0×176, в котором хранится адрес обработчика:

lkd> rdmsr 176 msr[176] = 00000000’8208c9c0 lkd> ln 00000000’8208c9c0 (8208c9c0) nt!KiFastCallEntry При использовании 64-разрядной машины можно посмотреть на 64-разрядный диспетчер вызова служб, повторяя этот шаг, но используя вместо прежнего MSR-регистр 0xC0000082, который используется для вызова версии syscall для 64-разрядного кода. Вы увидите, что он соответствует nt!KiSystemCall64: lkd> rdmsr c0000082 msr[c0000082] = fffff800’01a71ec0 lkd> ln fffff800’01a71ec0 (fffff800’01a71ec0) nt!KiSystemCall64

Можно дизассемблировать процедуру KiSystemService или процедуру KiSystemCall64 с помощью команды u. В итоге на 32-разрядной системе вы заметите следующие инструкции:

nt!KiSystemService+0x7b: 8208c969 897d04 mov dword ptr [ebp+4],edi 8208c96c fb sti 8208c96d e9dd000000 jmp nt!KiFastCallEntry+0x8f (8208ca4f) Поскольку реальные операции диспетчеризации системных вызовов являются общими, независимо от механизма, используемого для выхода на обработчик, старый обработчик, основанный на применении прерывания, для выполнения тех же общих задач просто вызывается в середине более нового обработчика, основанного на применении инструкции sysenter. Единственные отличающиеся части обработчиков связаны с генерацией фрейма системного прерывания и установкой значений конкретных регистров. Во время загрузки 32-разрядная Windows определяет тип процессора, на котором она выполняется, и устанавливает соответствующий используемый код системного вызова путем сохранения указателя на правильный код в структуре SharedUserData.

Код системной службы для NtReadFile в пользовательском режиме имеет следующий вид: 0:000> u ntdll!NtReadFile ntdll!ZwReadFile: 77020074 b802010000 mov eax,102h 77020079 ba0003fe7f mov edx,offset SharedUserData!SystemCallStub (7ffe0300) 7702007e ff12 call dword ptr [edx] 77020080 c22400 ret 24h 77020083 90 nop Номер системной службы — 0×102 (258 в десятичном формате), а инструкция call выполняет установленный ядром код диспетчера системной службы, чей указатель находится по адресу 0x7ffe0300. (Это соответствует элементу SystemCallStub структуры KUSER_SHARED_DATA, который начинается с адреса 0x7FFE0000.) Поскольку следующий вывод взят из Intel Core 2 Duo, он содержит указатель на sysenter: 0:000> dd SharedUserData!SystemCallStub l 1 7ffe0300 77020f30 0:000> u 77020f30 ntdll!KiFastSystemCall: 77020f30 8bd4 mov edx,esp 77020f32 0f34 sysenter.

Так как у 64-разрядных систем есть только один механизм для осуществления системных вызовов, точки входа системной службы в Ntdll.dll, как показано здесь, напрямую используют инструкцию syscall: ntdll!NtReadFile: 00000000’77f9fc60 4c8bd1 mov r10,rcx 00000000’77f9fc63 b810200000 mov eax,0×102 00000000’77f9fc68 0f05 syscall 00000000’77f9fc6a c3 ret Kernel-Mode System Service Dispatching Для обнаружения информации о системной службе в таблице диспетчера системной службы ядро использует номер системного вызова.

На 32-разрядных системах эта таблица похожа на таблицу диспетчера прерываний, за исключением того, что каждая запись содержит указатель на системную службу, а не на процедуру обработки прерывания. На 64-разрядных системах таблица реализована несколько иначе, она содержит не указатели на системные службы, а смещения относительно самой таблицы. Этот механизм адресации лучше подходит имеющемуся в системе x64 двоичному интерфейсу прикладных программ — application binary interface (ABI) и формату кодирования инструкций. ПРИМЕЧАНИЕ. В зависимости от используемого пакета обновлений номера системных служб могут меняться — компания Microsoft время от времени добавляет или удаляет системные службы, и номера системных служб генерируются автоматически, как часть компиляции ядра.
Диспетчеризация системных служб
Исключения системных служб.



Уважаемый посетитель, Вы зашли на сайт как незарегистрированный пользователь.
Мы рекомендуем Вам зарегистрироваться либо войти на сайт под своим именем.

Архив | Связь с админом | Конфиденциальность

RSS канал новостей     Яндекс.Метрика