|
|
| Посл.отвђт | Сообщенiе |
|
|
Дата: Дек 2, 2003 19:05:55 Драйвер при вызовах функций ядра определяет PID процесса, который вызывает их (это ведь можно наверное сделать?) Вот это и меня интересует. |
|
|
Дата: Дек 2, 2003 19:56:18 Ну таки ядро имеет доступ к контексту процесса, чтоб определить его привелегии на выполнение операций. Следовательно и PID там есть. Иначе было бы нелогично весьма -) |
|
|
Дата: Дек 2, 2003 20:17:19 rst Разумеется. В линухе это элементарно. В винде планировщик тоже должен знать. Подождем Four-F. :) |
|
|
Дата: Дек 3, 2003 11:04:03 · Поправил: Four-F [ rst: А такая, слегка бредовая идея... ] Гы. Этот способ уже приходил мне как-то в голову. Идея, кстати, только кажется бредовой с первого взгляда, но именно применительно к win32k и если её немного развить получается очень даже красиво. [ rst: Делаем миррор ServiceTable (для себя).. ] Это не так просто, т.к. функция KiSystemService, которая занимается диспетчеризацией системных сервисов, берет адрес таблицы из KTHREAD.ServiceTable. Это указатель либо на KeServiceDescriptorTable для не-GUI потоков, либо KeServiceDescriptorTableShadow для GUI потоков. Так вот, сделав копию ServiceTable нужно поместить указатель на неё в KTHREAD.ServiceTable. А это поле тоже, к сожалению, перезжает с места на место, в зависимости от версии системы. Есть KeAddSystemServiceTable, которая добавляет новую таблицу. Набрав в гугле KeAddSystemServiceTable можно даже пару-тройку статей об этом найти. Только не понятно как потом эту таблицу удалить. Но в данном случае можно и без копии обойтись, а работать прямо с KeServiceDescriptorTableShadow. Схема примерно такая: Узнаем индексы NtUserSetWindowsHookEx в NT4, 2000, XP, 2003 сервис пак не принципиально. Берем разницу maxIndex-minIndex. Прибавляем её к maxIndex и вычитаем из minIndex. Получаем некий диапазон индексов (с запасом) в пределах которого имеет смысл искать. Допустим это будет ~100-150 индексов. Вряд ли больше. Всего в таблицке для win32k ~600 функций. Запускаем драйвер. Создаем в юзере поток и усыпляем его на событии. ID потока передаем драйверу. Этот поток будет не-GUI, т.е. он пока не трогает win32k. Сканим W32pArgumentTable (она содержит кол-во параметров сервисов) в пределах нашего диапазона индексов, и ищем все сервисы с 6 параметрами - именно столько принимает NtUserSetWindowsHookEx. Т.к. таких функций мало, число кандидатов уменьшается в ~10-20 раз. Т.о. имеем всего ~5-10 таргетов, которые и хучим и начинаем следить в хуковой функции за ID потоков, которые вызывают похученные сервисы - это просто - PsGetCurrentThreadId. Устанавливаем событие, на котором спит юзерный поток (на osr.com есть статья как разделять событие между ядром и юзером). Проснувшийся юзерный поток вызывает SetWindowsHookEx с заведомо ошибочным набором параметров (зачем нам лишний хук), но так чтобы вызов до ядра дошёл. Это будет первый его GUI-вызов - система конвертнет его в GUI-поток в PsConvertToGuiThread и его KTHREAD.ServiceTable = KeServiceDescriptorTableShadow. Хуковая функция в драйвере увидит этот вызов и ID потока будет ровен искомому. Можно еще для пущей осторожности переданные параметры проверить - драйвер должен заранее знать с какими параметрами юзер вызвал SetWindowsHookEx. Всё. Вертаем все назад. Искомый индекс и соответственно адрес у нас в кармане. Вот примерно такая схема. Практически руки не доходят проверить, но я на 99,99% уверен, что должно работать. [ rst: в WinXP там не in2e а jmp на sysenter то-ли в ntdll толи в kernel32. ] Под XP и 2003 sysenter вызывает KiSystemService, точно также как в NT4 и 2000 это делает int2e. В любом случае индекс вызываемого сервиса через регистр передается. Так что для нас это ничего не меняет. |
|
|
Дата: Дек 3, 2003 14:49:22 Так вот, сделав копию ServiceTable нужно поместить указатель на неё в KTHREAD.ServiceTable. А это поле тоже, к сожалению, перезжает с места на место, в зависимости от версии системы. А нельзя ли "по-живому" ServiceTable резать?. Т.е. как я понял - она представляет из себя приблизительно тоже самое что и таблица векторов прерываний в старом добром ДОСе. Следовательно там храняться указатели на функции. Так вот драйвер делает у себя стабины указателей. Что-то типа: API_1: jmp orig_API_1 И адреса этих стабов прописывает в ServiceTable. А оригинальные адреса прописывает в стабы. И тогда не нужно искать указатель на ServiceTable... |
|
|
Дата: Дек 3, 2003 15:39:17 [ rst: А нельзя ли "по-живому" ServiceTable резать?. ] Я именно это и предлагаю - патчить существующую KeServiceDescriptorTableShadow. [ rst: И адреса этих стабов прописывает в ServiceTable. ... И тогда не нужно искать указатель на ServiceTable... ] Как же пропишешь адреса стабов в ServiceTable не найдя указатель на неё? :-) Найти указатель на KeServiceDescriptorTableShadow не проблема, а указатель на KeServiceDescriptorTable вообще открыто экспортируется. |
|
Powered by miniBB 1.6 © 2001-2002
Время загрузки страницы (сек.): 0.056 |