eXeL@B —› Крэки, обсуждения —› KeServiceDescriptorTableShadow |
Посл.ответ | Сообщение |
|
Создано: 10 сентября 2005 18:16 · Личное сообщение · #1 |
|
Создано: 11 сентября 2005 14:27 · Личное сообщение · #2 |
|
Создано: 12 сентября 2005 10:43 · Личное сообщение · #3 |
|
Создано: 12 сентября 2005 11:22 · Личное сообщение · #4 |
|
Создано: 12 сентября 2005 16:00 · Личное сообщение · #5 Barakuda пишет: А чем тебе не подходит импорт с Win32k.sys ? Тем, что функции не экспортируются. Barakuda пишет: А что мешает вызывать Int 2eh с EAX кодом системного сервиса ? Сколько не пробовал, только синий экран получил. Да и к тому же мне надо эти функции перехватывать, так что KeServiceDescriptorTableShadow искать все равно придется. |
|
Создано: 13 сентября 2005 10:32 · Личное сообщение · #6 1) О самих стуктурах: typedef struct SystemServiceDescriptorTable { SSD SystemServiceDescriptors[4]; } SSDT, *LPSSDT; Ниже приводятся описания остальных структур: typedef VOID *SSTAT[]; typedef unsigned char SSTPT[]; typedef SSTAT *LPSSTAT; typedef SSTPT *LPSSTPT; typedef struct SystemServiceDescriptor { LPSSTAT lpSystemServiceTableAddressTable; ULONG dwFirstServiceIndex; ULONG dwSystemServiceTableNumEntries; LPSSTPT lpSystemServiceTableParameterTable; } SSD, *LPSSD; Я думаю это ты знаешь. 2) В ядре существует функция, для добавления новых сервисов - KeAddSystemServiceTable. Она умеет добавлять сервисы в обе таблицы. Учитывая тот факт что 0-й дескриптор у них идентичен можно, путем сканирования кода функции KeAddSystemServiceTable, найти адрес Shadow таблицы. Как это делается: /* * Find the address of the KeServiceDescriptorTableShadow. * Uses technique from Undocumented Windows NT. */ static struct srv_table * find_shadow_table () { unsigned char *check = (unsigned char *)KeAddSystemServiceTable; int i; struct srv_table *rc=0; for (i=0; i<100; i++) { __try { rc = *(struct srv_table**)check; if (!MmIsAddressValid (rc) || (rc == KeServiceDescriptorTable) || (memcmp (rc, KeServiceDescriptorTable, sizeof (*rc)) != 0)) { check++; rc = 0; } } __except (EXCEPTION_EXECUTE_HANDLER) { rc = 0; } if (rc) break; } return rc; } 3) Если же по каким-то причинам этот метод не дал положительного результата, то делается попытка использовать жесткий адрес (KeServiceDescriptorTable-0x230) - т.к. положение Shadow таблицы в памяти не изменилось с WinNt4 SP3. Возможен вариант, но это на твой страх и риск, получения KeServiceDescriptorTable с ntoskrnl.exe и добавления 0х50 байт, для получения w32k!W32pServiceTable. 4) Почитай Свена Шрайбера, а также Марка Руссиновича. У них очень хорошо изложен теоретический материал. А для практики - существуют исходники руткитов и трейсеров. |
|
Создано: 13 сентября 2005 13:08 · Личное сообщение · #7 |
|
Создано: 13 сентября 2005 13:25 · Личное сообщение · #8 Вот исходник, который РАБОТАЕТ именно по такому принципу (Правда функция поиска Shadow имеет несколько другое имя: "LPSSDT FindShadowTable(void)" ) he4dev.e1.bmstu.ru/HookSysCall/He4Hook.zip Если уж не хватит терпения разобратся, то тебе стоит задать этот вопрос на форуме www.wasm.ru/forum/action=vtopic&forum=4 И скажи всётаки какая у тебя Windows. Неужели трудно в Айсе написать "d KeServiceDescriptorTable" и приплюсовать 0х50 байт для получения указателя на адреса процедур W32k ? |
|
Создано: 13 сентября 2005 14:12 · Личное сообщение · #9 |
|
Создано: 13 сентября 2005 14:37 · Личное сообщение · #10 |
|
Создано: 14 сентября 2005 21:00 · Личное сообщение · #11 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. в следующий раз подобные вопросы задавай на васме, я обычно сижу там, и такой вопрос без внимания не оставлю. ----- Скажем дружно - нафиг нужно. |
eXeL@B —› Крэки, обсуждения —› KeServiceDescriptorTableShadow |