Подскажите, если я вызову напрямую KiSystemService (тупо call из драйвера, получив ее адрес из MSR), куда вернется управление после того, как KiSystemService отработает? Непосредственно в функцию драйвера, из которой она была вызвана? Или нет?
В мср KiFastCallEntry, это шлюзе прерывания указатель на KiSystemService. KiSystemService вызывается из стубов в ядре, никаких проблем с вызовом нет, так как прерывание сохраняет Cs, Ss, Esp, Eip которые нужны для возврата, тоесть это параметры функции. Загружаем ядреные селекторы и можем свободно вызывать, возврат на адре который мы укажем(разумеется если сервис не изменяет его). PreviousMode вычисляется самой функцией на основе кодового селектора, сохраняется Fs. KiFastCallEntry из ядра не заюзать. В сегментные регистры по возврату будут перезагружены юзермодные селекторы, возврат на фиксированный в разделяемой памяти адрес и пр., попытка вызвать скорее всего приведёт к бсоду, во первых что PCR будет недоступной(в Fs мусор на PCR ссылающемся).
В шлюзе 2E? Кстати, имея базу IDT, для позиционирования на определенный дескриптор нужно умножать на его номер или на (его номер+1)? есть ли нулевой дескриптор?
Вызвал. Отработало, вроде. Управление назад не вернулось, в юзермоде выбивает активный процесс. БСОДа нет.
Ну да, управление в юзермод передаётся по возврату из KiFastCallEntry, селекторы ведь юзермодные. Но смотря откуда вызов. Если место не критическое, то упасть не должно.
Если ты имеешь в виду KiFastCallEntry, то может быть и бсод, а может и нет. А KiSystemService она напрямую каллами обычно и дергается из Zw* функций.
Спасибо за консультации, перехватил KiFastCallEntry. Код: Код (Text): void __declspec(naked) NewSyscall() { DWORD Reax; __asm { pushad pushfd push fs push eax pop Reax } DPRINT("Service No.: %#x", Reax); __asm { pop fs popfd popad jmp OldSyscall } } void SetXpSyscallHook() { __asm { pushad mov ecx, 0x176 rdmsr mov OldSyscall, eax mov eax, NewSyscall xor edx, edx wrmsr popad } } void DeleteXpSyscallHook() { __asm { pushad mov ecx, 0x176 mov eax, OldSyscall xor edx, edx wrmsr xor eax, eax mov OldSyscall, eax popad } } Итого имеем: вот именно такой код выносит систему на ребут. Но если написать вот так: Код (Text): DWORD Reax; __asm { pushad pushfd push fs } DPRINT("Here"); То все работает нормально. Как можно безопасно получить номер вызываемого системного сервиса? Спасибо.
Ума не приложу почему вывод eax не работает. Я понимаю, что KiFastCallEntry вызывается из пользовательского режима и там же регистры и заполняются. Но, что, регистры меняют значение при передаче управления этому сервису? Я где-то туплю, подскажите, пожалуйста.
В функции naked если ты не опрделелил ebp, то обращение к локальной переменной будет смотреть вникуда. Потому, что компилер посчитает, что кадр стека есть и будет адресовать переменную через ebp. Тебе нужно либо заполнить ebp нужным образом (mov ebp, esp / sub esp, 4), либо отказаться от локальной переменной и сделать что-то в роде Код (Text): .. push eax ; service number push szFormat call DbgPrint add esp, 8 ; _cdecl .. где szFormat - глобальная перемееная char *szFormat = "Service No. %lx";
Great, Clerk Уважаемые, спасибо за желание помочь. Great Сделал как ты сказал - вставил пролог (mov ebp, esp / sub esp, 4), переменную сделал глобалом. Стало лучше - теперь не просто ребут, а таки бсод. (( Clerk Мне нужно перехватить KiFastCallEntry и получить номер вызываемого системного сервиса. Все, задача на этом заканчивается. Если не трудно, подскажите, где еще можно поковырять.
Спасибо за помощь, решение найдено на каком-то китайском сервере. Если кому интересно: sysenterhook.c Код (Text): #include<ntddk.h> #include "OpCodeSize.h" ULONG uSysenter; UCHAR uOrigSysenterHead[8]; PUCHAR pMovedSysenterCode; ULONG i; __declspec(naked) void MyKiFastCallEntry(void) { __asm{ pop edi mov i, eax } __asm{ pushad push fs push 0x30 pop fs } DbgPrint("Get service ID:%X",i); __asm{ pop fs popad jmp pMovedSysenterCode } } ////////////////////////////////////////////////////// VOID OnUnload(IN PDRIVER_OBJECT DriverObject) { __asm{ cli mov eax,cr0 and eax,not 10000h mov cr0,eax } memcpy((PVOID)uSysenter,uOrigSysenterHead,8); __asm{ mov eax,cr0 or eax,10000h mov cr0,eax sti } ExFreePool(pMovedSysenterCode); DbgPrint("Unload sysenterHook"); } //////////////////////////////////////////////////////// VOID HookSysenter() { UCHAR cHookCode[8] = { 0x57, //push edi 0xBF,0,0,0,0, //mov edi,0000 0xFF,0xE7}; //jmp edi UCHAR JmpCode[]={0xE9,0,0,0,0}; //jmp 0000 int nCopyLen = 0; int nPos = 0; __asm { mov ecx,0x176 rdmsr mov uSysenter,eax } DbgPrint("sysenter:0x%08X",uSysenter); nPos = uSysenter; while(nCopyLen<8) { nCopyLen += GetOpCodeSize((PVOID)nPos); nPos = uSysenter + nCopyLen; } DbgPrint("copy code lenght:%d",nCopyLen); pMovedSysenterCode = ExAllocatePool(NonPagedPool,20); memcpy(uOrigSysenterHead,(PVOID)uSysenter,8); *((ULONG*)(JmpCode+1)) = (uSysenter + nCopyLen) - ((ULONG)pMovedSysenterCode + nCopyLen)- 5; memcpy(pMovedSysenterCode,(PVOID)uSysenter,nCopyLen); memcpy((PVOID)(pMovedSysenterCode + nCopyLen),JmpCode,5); *((ULONG*)(cHookCode+2)) = (ULONG)MyKiFastCallEntry; DbgPrint("Saved sysenter code:0x%08X",pMovedSysenterCode); DbgPrint("MyKiFastCallEntry:0x%08X",MyKiFastCallEntry); __asm{ cli mov eax,cr0 and eax,not 10000h mov cr0,eax } memcpy((PVOID)uSysenter,cHookCode,8); __asm{ mov eax,cr0 or eax,10000h mov cr0,eax sti } } NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject,PUNICODE_STRING RegistryPath) { DbgPrint("Welcome to sysenterhook.sys"); DriverObject->DriverUnload = OnUnload; HookSysenter(); return STATUS_SUCCESS; } OpCodeSize.h Код (Text): #define Naked __declspec( naked ) ULONG MaskTable[518] = { 0x00004000, 0x00004000, 0x00004000, 0x00004000, 0x00008000, 0x00008000, 0x00000000, 0x00000000, 0x00004000, 0x00004000, 0x00004000, 0x00004000, 0x00008000, 0x00008000, 0x00000000, 0x00000000, 0x00004000, 0x00004000, 0x00004000, 0x00004000, 0x00008000, 0x00008000, 0x00000000, 0x00000000, 0x00004000, 0x00004000, 0x00004000, 0x00004000, 0x00008000, 0x00008000, 0x00000000, 0x00000000, 0x00004000, 0x00004000, 0x00004000, 0x00004000, 0x00008000, 0x00008000, 0x00000008, 0x00000000, 0x00004000, 0x00004000, 0x00004000, 0x00004000, 0x00008000, 0x00008000, 0x00000008, 0x00000000, 0x00004000, 0x00004000, 0x00004000, 0x00004000, 0x00008000, 0x00008000, 0x00000008, 0x00000000, 0x00004000, 0x00004000, 0x00004000, 0x00004000, 0x00008000, 0x00008000, 0x00000008, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00004000, 0x00004000, 0x00000008, 0x00000008, 0x00001008, 0x00000018, 0x00002000, 0x00006000, 0x00000100, 0x00004100, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000100, 0x00000100, 0x00000100, 0x00000100, 0x00000100, 0x00000100, 0x00000100, 0x00000100, 0x00000100, 0x00000100, 0x00000100, 0x00000100, 0x00000100, 0x00000100, 0x00000100, 0x00000100, 0x00004100, 0x00006000, 0x00004100, 0x00004100, 0x00004000, 0x00004000, 0x00004000, 0x00004000, 0x00004000, 0x00004000, 0x00004000, 0x00004000, 0x00004000, 0x00004000, 0x00004000, 0x00004000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00002002, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000020, 0x00000020, 0x00000020, 0x00000020, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000100, 0x00002000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000100, 0x00000100, 0x00000100, 0x00000100, 0x00000100, 0x00000100, 0x00000100, 0x00000100, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00004100, 0x00004100, 0x00000200, 0x00000000, 0x00004000, 0x00004000, 0x00004100, 0x00006000, 0x00000300, 0x00000000, 0x00000200, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00004000, 0x00004000, 0x00004000, 0x00004000, 0x00000100, 0x00000100, 0x00000000, 0x00000000, 0x00004000, 0x00004000, 0x00004000, 0x00004000, 0x00004000, 0x00004000, 0x00004000, 0x00004000, 0x00000100, 0x00000100, 0x00000100, 0x00000100, 0x00000100, 0x00000100, 0x00000100, 0x00000100, 0x00002000, 0x00002000, 0x00002002, 0x00000100, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000008, 0x00000000, 0x00000008, 0x00000008, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00004000, 0x00004000, 0x00004000, 0x00004000, 0x00004000, 0x00004000, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00002000, 0x00004000, 0x00004000, 0x00004000, 0x00004000, 0x00004000, 0x00004000, 0x00004000, 0x00004000, 0x00004000, 0x00004000, 0x00004000, 0x00004000, 0x00004000, 0x00004000, 0x00004000, 0x00004000, 0x00000000, 0x00000000, 0x00000000, 0x00004000, 0x00004100, 0x00004000, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000, 0x00000000, 0x00004000, 0x00004100, 0x00004000, 0xFFFFFFFF, 0x00004000, 0x00004000, 0x00004000, 0x00004000, 0x00004000, 0x00004000, 0x00004000, 0x00004000, 0x00004000, 0xFFFFFFFF, 0xFFFFFFFF, 0x00004100, 0x00004000, 0x00004000, 0x00004000, 0x00004000, 0x00004000, 0x00004000, 0x00004000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF }; Naked ULONG GetOpCodeSize_ASM_CODE(PVOID Start, PVOID Tlb) { __asm{ pushad mov esi, [esp+24h] mov ecx, [esp+28h] xor edx, edx xor eax, eax L005: and dl, 0F7h mov al, [ecx] inc ecx or edx, [esi+eax*4h] test dl, 8h jnz L005 cmp al, 0F6h je L035 cmp al, 0F7h je L035 cmp al, 0CDh je L040 cmp al, 0Fh je L045 L019: test dh, 80h jnz L052 L021: test dh, 40h jnz L067 L023: test dl, 20h jnz L057 L025: test dh, 20h jnz L062 L027: mov eax, ecx sub eax, [esp+28h] and edx, 707h add al, dl add al, dh L032: mov [esp+1Ch], eax popad retn L035: or dh, 40h test byte ptr [ecx], 38h jnz L019 or dh, 80h jmp L019 L040: or dh, 1h cmp byte ptr [ecx], 20h jnz L019 or dh, 4h jmp L019 L045: mov al, [ecx] inc ecx or edx, [esi+eax*4h+400h] cmp edx, -1h jnz L019 mov eax, edx jmp L032 L052: xor dh, 20h test al, 1h jnz L021 xor dh, 21h jmp L021 L057: xor dl, 2h test dl, 10h jnz L025 xor dl, 6h jmp L025 L062: xor dh, 2h test dh, 10h jnz L027 xor dh, 6h jmp L027 L067: mov al, [ecx] inc ecx mov ah, al and ax, 0C007h cmp ah, 0C0h je L023 test dl, 10h jnz L090 cmp al, 4h jnz L080 mov al, [ecx] inc ecx and al, 7h L080: cmp ah, 40h je L088 cmp ah, 80h je L086 cmp ax, 5h jnz L023 L086: or dl, 4h jmp L023 L088: or dl, 1h jmp L023 L090: cmp ax, 6h je L096 cmp ah, 40h je L088 cmp ah, 80h jnz L023 L096: or dl, 2h jmp L023 retn } } ULONG GetOpCodeSize(PVOID Start) { __asm { push Start push offset MaskTable call GetOpCodeSize_ASM_CODE add esp, 8 } }
Сразу сказал бы что перехватить нужно, а то юзать из ядра.. Китайцы как обычно кроме тупо сплайснуть ничсего больше придумать не могут.)
Подскажите еще такой момент. Когда мы оказываемся в функции-перехватчике сплайснутого KiFastCallEntry, на каком стеке мы оказываемся? На DPC? И как переключиться на стек ядра? У меня возникла следующая проблема, думаю из-за этого. Из перехватчика вызываю ZwWriteFile, пытаюсь писать в уже созданный файл. Результат - NTSTATUS = 0xC0000008 (STATUS_INVALID_HANDLE). Хендл - глобал. Если напечатать его значение - оно валидно.
Код (Text): OBJECT_ATTRIBUTES oa; UNICODE_STRING fileName; HANDLE hFile=0x00; NTSTATUS ns=0x00; IO_STATUS_BLOCK StatusBlock; char buf[260]; char oD=0x0D; char oA=0x0A; void WriteServiceNumber(int num) { sprintf(buf,"%#x",num); strncat(buf,&oD,1); strncat(buf,&oA,1); DPRINT("Buf is: %s",buf); if (num==0x00db) { DPRINT("HANDLE is: %#x", hFile); ns=ZwWriteFile(hFile, <----STATUS_INVALID_HANDLE NULL, NULL, NULL, &StatusBlock, buf, strlen(buf), 0, NULL ); DPRINT("ZwWriteFile said (NTSTATUS): %#x",ns); } } NTSTATUS WriteStartLine() { IO_STATUS_BLOCK StatusBlock; NTSTATUS ns=0x00; KeQuerySystemTime(&dwCurrentTime); ExSystemTimeToLocalTime(&dwCurrentTime,&dwLocalTime); RtlTimeToTimeFields(&dwLocalTime,&fullTime); DPRINT("-------- START: %d.%d.%d %d:%d:%d --------",fullTime.Day,fullTime.Month,fullTime.Year,fullTime.Hour,fullTime.Minute,fullTime.Second); sprintf(szDate,"-------- START: %d.%d.%d %d:%d:%d --------",fullTime.Day,fullTime.Month,fullTime.Year,fullTime.Hour,fullTime.Minute,fullTime.Second); strncat(szDate,&oD,1); strncat(szDate,&oA,1); DPRINT("HANDLE HERE is: %#x", hFile); ns=ZwWriteFile(hFile, <--- STATUS_SUCCESS NULL, NULL, NULL, &StatusBlock, szDate, strlen(szDate), 0, NULL ); DPRINT("ZwWriteFile said (NTSTATUS): %#x",ns); return ns; } __declspec(naked) void MyKiFastCallEntry(void) { __asm{ pop edi mov i, eax } __asm{ pushad push fs push 0x30 pop fs } if (i<=0x0116) { WriteServiceNumber(i); //DbgPrint("Get service ID:%X",i); } __asm{ pop fs popad jmp pMovedSysenterCode } NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject,PUNICODE_STRING RegistryPath) { WCHAR wszFileName[]=L"\\DosDevices\\c:\\MyLogs\\log8.txt"; IO_STATUS_BLOCK StatusBlock; NTSTATUS ns=0x00; DbgPrint("Welcome to sysenterhook.sys"); //------------------------------------------------------------------- RtlInitUnicodeString(&fileName, wszFileName); InitializeObjectAttributes ( &oa, &fileName, OBJ_CASE_INSENSITIVE, NULL, NULL ); DPRINT("fileName: %S", fileName.Buffer); ns=ZwCreateFile(&hFile, FILE_APPEND_DATA, &oa, &StatusBlock, 0, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ | FILE_SHARE_WRITE , FILE_OPEN_IF, FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0); DPRINT("ZwCreateFile said (NTSTATUS): %#x",ns); WriteStartLine(); strncat(Buffer,&oD,1); strncat(Buffer,&oA,1); ns=ZwWriteFile(hFile, NULL, NULL, NULL, &StatusBlock, Buffer, strlen(Buffer), 0, NULL ); DPRINT("ZwWriteFile said (NTSTATUS): %#x",ns); //------------------------------------------------------------------- DriverObject->DriverUnload = OnUnload; HookSysenter(); return STATUS_SUCCESS; HookSysenter и OnUnload приведены выше. Я их не менял совсем.
Интересно что будет если выполнить такой код при установленном перехвате: Код (Text): push fs pop ds mov eax,116h ;NtYieldExecution ID Call KiFastSystemCall Ну а для полноты картины код который позволит вызвать сервис в обход вашего перехвата, либо покажет голубой огонёк: Код (Text): push EFLAGS_TF popfd sysenter