Перехват системных вызовов в режиме ядра Получение номеров системных вызовов Для получения номеров системных вызовов можно использовать такой метод: Посмотреть экспорт ntdll.dll и для каждой экспортируемой функции с именем Nt... посмотреть, с каких байт она начинается. Функции, которые производят системные вызовы начинаются с команды mov eax, system_call_number Это байты 0xB8 [4 байта - номер вызова]. Таким образом, просмотрев все функции можно получить, номера системных вызовов. Этот метод у меня работал на Windows XP, Windows Server 2003, Windows 2000. Перехват системных вызовов в ядре. Чтобы перехватить сразу все системные вызовы в windows 2000 и windows XP/server 2003 нужно использовать разные способы, т.к. они используют разные методы для реализации системных вызовов. Перехват системных вызовов в Windows XP. Windows XP и Server 2003 для системных вызовов используют команду процессора sysenter. Команда использует 3 MSR (Model Specific Register): SYSENTER_CS_MSR - 0x174 SYSENTER_ESP_MSR - 0x175 SYSENTER_EIP_MSR - 0x176 Чтобы установить свой обработчик можно поменять EIP_MSR на адрес обработчика. CS_MSR и ESP_MSR можно оставить, как их установила операционная система. Наш обработчик выполнит свой код и прыгнет на настоящий обработчик операционной системы. Перед переходом на обработчик операционной системы нужно вернуть все регистры и флаги в состояние в котором они были при входе в наш обработчик. При установке/снятии обработчика нужно отключить прерывания, чтобы другой поток не прервал наш и не произвел системный вызов в то время, пока не установлен правильный адрес обработчика. Перехват системных вызовов в Windows 2000. В Windows 2000 для системных вызовов используется прерывание 0x2E. Чтобы перехватить вызов нужно изменить таблицу прерываний IDT. Interrupt descriptor в IDT: typedef struct _KIDTENTRY { /*000*/ WORD Offset; /*002*/ WORD Selector; /*004*/ WORD Access; /*006*/ WORD ExtendedOffset; /*008*/ } KIDTENTRY, * PKIDTENTRY, **PPKIDTENTRY; Код замены обработчика: __asm{ cli sidt idt_address } idt_table=(KIDTENTRY *)((idt_address >> 16) & 0xffffffff); old_addr=(idt_table[int_number].ExtendedOffset << 16) | (idt_table[int_number].Offset); idt_table[int_number].Offset=(addr & 0xffff); idt_table[int_number].ExtendedOffset=(addr >> 16); __asm{ sti } Замена обработчика прерывания у меня не работала в MS Virtual PC. При замене обработчика прерывания машина выдавала MessageBox с сообщением об ошибке и перегружалась. В VMWare перехват работает нормально. SoftIce и прерывания Похоже, что softice при запуске меняет некоторые дескрипторы прерывания в IDT. Я заметил это, когда смотрел дескриптор для 0x2E, прерывания системного вызова в windows 2000. Например, у меня в XP после запуска softice меняется адрес обработчика 0x2E. При этом сам softice по команде "idt 2E" показывает старый, не измененный адрес. Наиболее вызываемые системные вызовы Списки системных вызовов, которые вызывались наибольшее количество раз у меня на компьютере. Просто во время работы замерил и привел здесь. Выше - больше количество вызовов. Тест 1: NtDelayExecution NtWaitForSingleObject NtRequestWaitReplyPort NtReleaseMutant NtReplayWaitReceivePort NtClose NtSetInformationFile NtYieldExecution NtWriteFile NtOpenKey Тест 2: NtWaitForMultipleObjects NtSetEvent NtClearEvent NtSetTimer NtFindAtom NtDuplicateObject NtWaitForSingleObject NtClose NtReleaseMutant NtRequestWaitReplyPort Ссылки Про команду sysenter и про обработку прерываний - Intel manual. В книге Sven Schreiber "Undocumented Windows 2000 secrets" подробно описан перехват системных вызовов с помощью KeServiceDescriptorTable.