Странно выглядят все Zw и проч функи с переходами на KiFast.. KiInt.. Они, часом не автогенерируются при загрузке оси? Если да, то чем?
Откуда такие мысли? Открой ntdll.dll в IDA и посмотри. Меняется только содержимое 7FFE0300. Полагаю в MS этот код макросами генерили.
че-то я не особо понял.. Zw в ядре - это ядерные переходники к Nt-сервисам, каждая Zw-оболочка небольшая..
ну и?) в р3 никакой разницы между Zw и Nt нет. в экспортах ntdll они указывают на одну и туже функцию > Они, часом не автогенерируются при загрузке оси? Если да, то чем? автогенерируются?... ну вообще-то они в файле присутствуют физически как-бы. вообще странный топик какой-то
функи, не только zw, интерфейсные к ядру все имеют один формат mov eax, <номер сервиса> mov edx, 7FFE0300 call dword [edx] возник вопрос, почему так с edx? Это не компилерная оптимизация. Во всяком случае не мсвс. если писано на асме, то почему так с edx, ведь он дальше не используется? Вот и возник вопрос, а что если это автогенератор и гдето есть компактно список номеров сервисов и соответствие их интерфейсам.
R0 режим: Zw функции ядра, и соответвенно все поинтеры передаваемые им могут быть как r3 так и r0 Nt функции юзермоде, и передаваемые им поинтеры зависят от PreviousMode треда. Обычно r3 поинтеры.
макрос для стабов в юзермоде Код (Text): USRSTUBS_ENTRY1 macro ServiceNumber, Name, NumArgs cPublicProc _Zw&Name, NumArgs PUBLICP _Nt&Name, NumArgs LABELP _Nt&Name, NumArgs .FPO ( 0, NumArgs, 0, 0, 0, 0 ) mov eax, ServiceNumber ; (eax) = service number mov edx, MM_SHARED_USER_DATA_VA+UsSystemCall call [edx] stdRET _Zw&Name stdENDP _Zw&Name endm макрос для стабов в р0 Код (Text): SYSSTUBS_ENTRY1 macro ServiceNumber, Name, NumArgs cPublicProc _Zw&Name,NumArgs .FPO ( 0, NumArgs, 0, 0, 0, 0 ) extrn _KiSystemService:PROC mov eax, ServiceNumber ; (eax) = service number lea edx, [esp]+4 ; (edx) -> arguments pushfd ; EFLAGS to trap frame push KGDT_R0_CODE ; CS to trap frame call _KiSystemService ; EIP to trap frame and enter handler stdRET _Zw&Name stdENDP _Zw&Name endm
Автогенерируется вектор UsSystemCall и UsSystemCallReturn на фазе инициализации ядра #1. Первое поле указывает на заглушку KiFastSystemCall/KiIntSystemCall, второе поле - указывает на адрес возврата по Sysexit. PspInitPhase1() -> PspInitializeSystemDll() -> PspLookupKernelUserEntryPoints(). Определяется поддерживается ли инструкция Sysenter, если поддерживается, то определяется адрес в ntdll точки KiFastSystemCall, иначе определяется адрес KiIntSystemCall и этот указатель(RVA + OH.ImageBase) загружается в UserSharedData. Поле UsSystemCallReturn заполняется аналогично(экспорт ntdll как KiFastSystemCallRet). Код загружающий указатели: Код (Text): PspLookupKernelUserEntryPoints( [...] if (KeFeatureBits & KF_FAST_SYSCALL) { // // Get the addresses of the fast system call code. // EntryName = "KiFastSystemCall"; Status = PspLookupSystemDllEntryPoint(EntryName, (PVOID *)&SharedUserData->SystemCall); if (!NT_SUCCESS(Status)) { KdPrint(("Ps: Cannot find fast system call address\n")); return Status; } // // Get the addresses of the fast system call return code. // EntryName = "KiFastSystemCallRet"; Status = PspLookupSystemDllEntryPoint(EntryName, (PVOID *)&SharedUserData->SystemCallReturn); if (!NT_SUCCESS(Status)) { KdPrint(("Ps: Cannot find fast system call return address\n")); return Status; } } else { // // Get the addresses of the fast system call code. // EntryName = "KiIntSystemCall"; Status = PspLookupSystemDllEntryPoint(EntryName, (PVOID *)&SharedUserData->SystemCall); if (!NT_SUCCESS(Status)) { KdPrint(("Ps: Cannot find int2e system call address\n")); return Status; } } // // Ret instruction to test no execute state of shared user data. // SharedUserData->TestRetInstruction = 0xc3; Для возврата в юзермод по Int/Sysexit проверка не выполняется, а используется самомодификация кода ядра. Код (Text): KiSystemCallExitBranch: jnz short KiSystemCallExit pop edx pop ecx popfd jmp edx KiSystemCallExit: iretd KiSystemCallExit2: test dword ptr [esp+8], EFLAGS_TF jne short KiSystemCallExit pop edx add esp, 4 and dword ptr [esp], NOT EFLAGS_INTERRUPT_MASK popfd pop ecx sti sysexit По умолчанию инструкция перехода в KiSystemCallExitBranch направлена на KiSystemCallExit, при разрешении использования sysexit смещение в инструкции увеличивается, направляя тем самым обработку на KiSystemCallExit2.