Здравствуйте, пытаюсь сделать перехват функций из win32k.sys методом правки Service Descriptor Table Shadow. Саму ssdt нашёл, сравнил адрес найденной ssdt с тем адресом, что находит strace – они одинаковые. Проблема в том, что после замены адреса нужной функции моя функция не вызывается. В моей функции делается минимум действий: вызов DbgPrint и вызов реальной функции. Просмотрел исходник strace – никаких принципиальных отличий от своего кода не заметил, также ищется ssdt, также делается замена. В чём может быть проблема?
Зачем Shodow? ИМХО просто SDT править надо(KeServiceDescriptorTable которая). А может ещё сорс выложишь, а то по твоему объяснению всё должно работать как часы.
Добраться до ф-ий win32k.sys можно только через Shadow таблицу. На мой взгляд тоже работать должно как часы, но не работает и не могу понять почему. Вот ключевые моменты Код (Text): PSERVICE_DESCRIPTOR_TABLE find_shadow_table () //тут проблем нет, ищет правильно { unsigned char *check = (unsigned char *)KeAddSystemServiceTable; int i; PSERVICE_DESCRIPTOR_TABLE rc = NULL; for (i=0; i<100; i++) { __try { rc = *(PVOID *)check; if (!MmIsAddressValid (rc) || (rc == KeServiceDescriptorTable) || (memcmp (rc, KeServiceDescriptorTable, 4) != 0)) { check++; rc = NULL; } } __except (EXCEPTION_EXECUTE_HANDLER) { rc = NULL; } if (rc) break; } return rc; } ... //замена KeServiceDescriptorTableShadow = find_shadow_table(); True_EngTextOut = (EngTextOut_t)KeServiceDescriptorTableShadow->win32k.ServiceTable[sdt_number]; (EngTextOut_t)KeServiceDescriptorTableShadow->win32k.ServiceTable[sdt_number] = New_EngTextOut; ... //ну, и код New_EngTextOut, если это имеет значение BOOL APIENTRY New_EngTextOut( IN SURFOBJ *pso, IN STROBJ *pstro, IN FONTOBJ *pfo, IN CLIPOBJ *pco, IN RECTL *prclExtra, IN RECTL *prclOpaque, IN BRUSHOBJ *pboFore, IN BRUSHOBJ *pboOpaque, IN POINTL pptlOrg, IN MIX mix ) { DbgPrint("Inside EngTextOut"); return True_EngTextOut(pso,pstro,pfo,pco,prclExtra,prclOpaque,pboFore,pboOpaque,pptlOrg,mix); } Как уже говорил, мой код почти ничем не отличается от кода strace, strace работает, мой - нет. зы тестировалось на WinXP SP1, на других системах не проверял.
И ещё что интересно: если поставить перехват из моего драйвера, а потом запустить strace, то он пакажет адрес в ssdt для этой ф-ии = addr New_EngTextOut. Потом установит свой перехват и успешно отработает.
В обычной SDT доступа к win32k вообще нет. Вот собственно была такая проблема на cracklab.ru: Код (Text): Ms-Rem Ранг: 56.7 (постоянный) Статус: Участник Создано: Сен 15, 2005 08:00:55 Цитата Личное сообщение Цитата Личное сообщение MaxSS Помню геморроился я сам как-то с этим делом. Трабл номер раз: при перемещении SDT антивирусом КарлаСпермского меняется содержимое первой SST и смещение Shadow SDT, а следовательно вышеприведенный код не работает. Проблема решается сканированием KiAddSystemServiceTable на инструкцию lea ecx, KeServiceDescriptorTableShadow[eax]. Вот работающий код находящий Shadow SDT на виндах от NT4 до лонгхорна и не боящийся приколов Дяди Карла: void GetKeServiceDescriptorTableShadow() { PUCHAR cPtr, pOpcode; ULONG Length; for (cPtr = (PUCHAR)KeAddSystemServiceTable; cPtr < (PUCHAR)KeAddSystemServiceTable + PAGE_SIZE; cPtr += Length) { if (!MmIsAddressValid(cPtr)) break; Length = SizeOfCode(cPtr, &pOpcode); if (!Length || (Length == 1 && *pOpcode == 0xC3)) break; if (*(PUSHORT)pOpcode == 0x888D) { KeServiceDescriptorTableShadow = *(PVOID *)(pOpcode + 2); break; } } } Функция SizeOfCode - получает размер инструкции по указателю. Я использовал свой дизассемблер длин LDasm. Трабл номер два: содержимое SST win32k как и сам драйвер win32k.sys отображаються на ЮЗЕРМОДНЫЕ АДРЕСА, как и все драйвера имеющие отношение к графической подсистеме. Это не баг, так как на их страницах стоит атрибут супервизора. Соответствующая память отмаплена ТОЛЬКО в GUI процессы. Тоесть нужно подключаться к GUI процессу и там читать/модифицировать SST win32k. Я рекомендую подключаться к csrss.exe. Код ищущий этот процесс (не по имени): HANDLE GetCsrPid() { HANDLE Process, hObject; HANDLE CsrId = (HANDLE)0; OBJECT_ATTRIBUTES obj; CLIENT_ID cid; UCHAR Buff[0x100]; POBJECT_NAME_INFORMATION ObjName = (PVOID)&Buff; PSYSTEM_HANDLE_INFORMATION_EX Handles; ULONG r; Handles = GetInfoTable(SystemHandleInformation); if (!Handles) return CsrId; for (r = 0; r < Handles->NumberOfHandles; r++) { if (Handles->Information[r].ObjectTypeNumber == 21) //Port object { InitializeObjectAttributes(&obj, NULL, OBJ_KERNEL_HANDLE, NULL, NULL); cid.UniqueProcess = (HANDLE)Handles->Information[r].ProcessId; cid.UniqueThread = 0; if (NT_SUCCESS(NtOpenProcess(&Process, PROCESS_DUP_HANDLE, &obj, &cid))) { if (NT_SUCCESS(ZwDuplicateObject(Process, (HANDLE)Handles->Information[r].Handle, NtCurrentProcess(), &hObject, 0, 0, DUPLICATE_SAME_ACCESS))) { if (NT_SUCCESS(ZwQueryObject(hObject, ObjectNameInformation, ObjName, 0x100, NULL))) { if (ObjName->Name.Buffer && !wcsncmp(L"\\Windows\\ApiPort", ObjName->Name.Buffer, 20)) { CsrId = (HANDLE)Handles->Information[r].ProcessId; } } ZwClose(hObject); } ZwClose(Process); } } } ExFreePool(Handles); return CsrId; } Трабл номер три: для выхова этих функций нужно использовать GUI поток. Отличается он от обычного тем, что в его NT_TIB в ServiceTable лежит указатель не на KeServiceDescriptorTable, а на KeServiceDescriptorTableShadow. Для создания GUI потока можно воспользоваться неэкспортируемой функцией PsConvertToGuiThread, но несуществует надежного способа ее поиска, поэтому я рекомендую менять указатель в NT_TIB вручную. Трабл номер четыре: необходимо чтобы на процесс в котором создан поток отображались видео драйвера. Можно создать MDL, захватить память в другом процессе и отобразить себе с помощью MmMapLockedPagesSpecifyCache, но это геморно, поэтому создавай поток в том же csrss.exe. Надеюсь мой ответ тебе чем нибудь поможет. P.S. в следующий раз подобные вопросы задавай на васме, я обычно сижу там, и такой вопрос без внимания не оставлю. Может чем поможет.
im1111 Код MS-Remа видел, вообщем то от него и отталкивался. Атачится к ГУИ поцессу не обязательно, если ставить перехват из dispatch routine драйвера, которая и так вызывается в контексте вызывающего процесса. Про проделки антивируса тоже знаю, но сейчас надо заставить работать хотябы то что есть.
im1111 Скинуть только в субботу смогу. Да и нет там ничего особенного, почти всё основное уже привёл. За кадром осталась только ф-ия поиска номера системного вызова по имени, но она точно работает нормально.