Мониторинг реестра в кернеле

Тема в разделе "WASM.NT.KERNEL", создана пользователем sasha_s, 22 июн 2009.

Статус темы:
Закрыта.
  1. sasha_s

    sasha_s New Member

    Публикаций:
    0
    Регистрация:
    21 дек 2005
    Сообщения:
    165
    Адрес:
    Belarus
    Мониторю ф-ции доступа к реестру:
    NtCreateKey
    NtOpenKey

    NtDeleteKey
    NtDeleteValueKey

    и прочие NtEnumerate(Value)Key и т.д.

    В МСДНе (http://msdn.microsoft.com/en-us/library/aa489583.aspx) написано:
    HKEY_LOCAL_MACHINE => \Registry\Machine
    HKEY_USERS => \Registry\User
    HKEY_CLASSES_ROOT => No kernel-mode equivalent
    HKEY_CURRENT_USER => No simple kernel-mode equivalent

    Т.е. мне надо задавать рулы доступа на разные ключи, а как узнать что прога полезла именно в HKEY_CURRENT_USER\ХХХ ?

    И еще проблема с NtCreateKey, NtOpenKey.

    В NtCreateKey есть параметр POBJECT_ATTRIBUTES ObjectAttributes, но в нем всегда относительное имя ключа вроде 'Software\ХХХ\YYY' и понять куда именно сие пишеться (\Registry\Machine или \Registry\User) я не знаю как.
    В NtOpenKey в POBJECT_ATTRIBUTES ObjectAttributes или пустая строка, или строка с умопомрачительной длинной в тысячи символов забитая 0х00 в перемежку с 0xFF.

    Как контролировать доступ к реестру в этих ф-циях?
    Единственная идея создавать ключ, по хендлу получать имя и потом уже смотреть по рулам и если надо то удалять. Но как-то топорно...
     
  2. wasm_test

    wasm_test wasm test user

    Публикаций:
    0
    Регистрация:
    24 ноя 2006
    Сообщения:
    5.582
    Как это нет?
    HKCU это \Registry\User\ид-юзера\
    HKCR это \Registry\User\ид-юзера\CLSID
    ZwQueryObject (ObjectNameInformation)
     
  3. x64

    x64 New Member

    Публикаций:
    0
    Регистрация:
    29 июл 2008
    Сообщения:
    1.370
    Адрес:
    Россия
    Ну давайте по порядку.

    По поводу преобразования имён

    Физические ключи:

    HKEY_LOCAL_MACHINE = \Registry\Machine
    HKEY_USERS = \Registry\User

    Виртуальные ключи:

    HKEY_CURRENT_USER = \Registry\User\{<SID>}
    HKEY_CLASSES_ROOT = А вот этот ключ представляет собой склейку двух подключей:

    \Registry\User\{<SID>}\Software\Classes
    \Registry\Machine\Software\Classes

    Здесь {<SID>} - это SID пользователя, от имени которого вызвана реестровая API-функция, таким образом, например, в службе HKCU будет указывать на один ключ, а в обычном интерактивном приложении на другой (если, конечно, служба не запущена от имени того же пользователя).

    По поводу определения HKCU

    После всего вышесказанного, думаю, это просто. Достаточно запросить SID у текущего потока, перевести его в строку и сравнить с SID'ом, который в имени ключа, если совпали значит это HKCU. Здесь удобно использовать следующие функции: ZwCurrentThread(), ZwCurrentProcess(), ZwOpenThreadTokenEx(), ZwOpenProcessTokenEx() - это если у потока нет токена, ZwQueryInformationToken() с классом TokenUser, затем RtlConvertSidToUnicodeString() и сравнить с тем, что в имени ключа.

    По поводу извлечения полного имени ключа

    В pObjectAttributes -> ObjectName может лежать относительное имя. В любом случае, сначала необходимо проверить поле pObjectAttributes->RootDirectory, если оно не NULL, тогда следует запросить имя корневого ключа через ZwQueryObject() с классом ObjectNameInformation. Если делать через колбек, тогда ничего этого не нужно, достаточно будет вызвать ObQueryNameString() на поле Object в структуре колбека и получишь сразу полное имя ключа.

    По поводу долбанных хуков

    Для тех, кто живёт в танке: уже давно колбек есть - CmRegisterCallback(). Его более чем достаточно для организации блокировки запросов к реестру.
     
  4. sasha_s

    sasha_s New Member

    Публикаций:
    0
    Регистрация:
    21 дек 2005
    Сообщения:
    165
    Адрес:
    Belarus
    Все сработало для NtCreateKey и там RootDirectory имеет имя вроде '\REGISTRY\MACHINE' и т.д.

    Но в NtOpenKey при вызове ZwQueryObject вываливается STATUS_INVALID_HANDLE(0xC0000008).
    Ладно, стал я получать имя ключа по хендлу после открытия и вот что открывает NtOpenKey:
    '\BaseNamedObjects\shell.{210A4BA0-3AEA-1069-A2D9-08002B30309D}'
    '\BaseNamedObjects\shell.{A48F1A32-A340-11D1-BC6B-00A0C90312E1}'

    Что это за объекты?
     
  5. x64

    x64 New Member

    Публикаций:
    0
    Регистрация:
    29 июл 2008
    Сообщения:
    1.370
    Адрес:
    Россия
    Ты по ошибке похукал NtOpenSemaphore вместо NtOpenKey, и эти объекты - семафоры.
     
  6. sasha_s

    sasha_s New Member

    Публикаций:
    0
    Регистрация:
    21 дек 2005
    Сообщения:
    165
    Адрес:
    Belarus
    Да. В самом деле ошибся пока забивал таблицы для нужных ОС и SP.

    Кстати в эту тему вопросс: https://wasm.ru/forum/viewtopic.php?pid=325135#p325135
    Может есть опыт и в этом?
     
  7. x64

    x64 New Member

    Публикаций:
    0
    Регистрация:
    29 июл 2008
    Сообщения:
    1.370
    Адрес:
    Россия
    А не слишком ли вы, маладой чилавег, хотите от меня? В поиск, - всё это было уже много раз.
     
  8. sasha_s

    sasha_s New Member

    Публикаций:
    0
    Регистрация:
    21 дек 2005
    Сообщения:
    165
    Адрес:
    Belarus
    Ок. Буду рыть форум раз уже было.

    :)
    Я же исходников не требую...
    Да и старый я уже...
     
  9. wasm_test

    wasm_test wasm test user

    Публикаций:
    0
    Регистрация:
    24 ноя 2006
    Сообщения:
    5.582
    Зачем забивать таблицы хардкодом, если можно выдрать номера в реалтайме из нтдлл?

    Делаешь ZwQuerySystemInformation (SystemModulesInformation) - находишь базу ntdll.dll. Она промаплена во все процессы, включая System, поэтому не важно из контекста какого процесса искать.

    Для каждого сервиса, номер которого хочешь найти:
    1. Ручным перебором экспортов ntdll.dll находишь точку входа в функцию с именем сервиса. Все нтоскрнл сервисы экспортируются в ntdll на соответствующие стабы.
    2. Каждый стаб имеет вид:
    Код (Text):
    1. mov eax, NUMBER
    2. ...
    3. Опкод первой инструкции: B8 XX XX XX XX, где XXXXXXXX - номер сискола в таблице.
     
  10. wasm_test

    wasm_test wasm test user

    Публикаций:
    0
    Регистрация:
    24 ноя 2006
    Сообщения:
    5.582
    Ой уже посмотрел, что по ссылке спрашивают тоже самое))
     
  11. Forever

    Forever Виталий

    Публикаций:
    0
    Регистрация:
    12 апр 2008
    Сообщения:
    244
    Great
    Зачем выдирать номера в реалтайме из нтдлл, если можно забивать таблицы хардкодом? :)
    У каждого метода свои преимущества и недостатки, по мне лучше носить с собой, и не нужно будет писать кучу сомнительного кода.
    Кстати, если нужно выдрать имена функций по номерам то можно выполнить команду в WinDbg.
    Код (Text):
    1. dds nt!KiServiceTable L poi( nt!KiServiceLimit )
    Получишь табличку с адресами.
     
  12. wasm_test

    wasm_test wasm test user

    Публикаций:
    0
    Регистрация:
    24 ноя 2006
    Сообщения:
    5.582
    Хардкод - это по-любому сомнительный метод. Носить с собой неуниверсально и у тебя будет падать.

    Ну ты прям как клерк - "зачем делать нормально, если можно через жопу?"
     
  13. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    Great
    Ты уж извени меня, но через задницу ты делаешь всё. Для вызова сервиса достаточно знать его номер, незачем искать какието модуля в памяти, грузить их с диска и извлекать номера.
     
  14. Forever

    Forever Виталий

    Публикаций:
    0
    Регистрация:
    12 апр 2008
    Сообщения:
    244
    Great
    А Clerk абсолютно прав. Выдрать нормально номер произвольной функции не всегда красиво получится. К тому же это того не стоит.
     
  15. SashaTalakin

    SashaTalakin New Member

    Публикаций:
    0
    Регистрация:
    15 дек 2008
    Сообщения:
    261
    Clerk
    поэтому great программист а ты ясли подумай над этим
     
  16. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    Forever
    Я отлично понимаю Грита - он все решения принимает как наиболее простые, максимально совместимые и минимально стабильные и не надёжные.
     
  17. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    SashaTalakin
    Вы у меня в игноре.
     
  18. wasm_test

    wasm_test wasm test user

    Публикаций:
    0
    Регистрация:
    24 ноя 2006
    Сообщения:
    5.582
    Clerk
    Надо видеть разницу между компактностью и красотой и универсальностью. Выбирать из массива сразу готовый номер - красиво и компактно.
    Просто далеко не всем и не всегда требуется писать вири, требуется писать и легальный софт тоже, поэтому гораздо лучше, если он будет без перекомпилирования работать на новой ос, чем если придется зашивать туда новые номера системных сервисов.
    Разные цели - разные методы. У меня весь софт вполне мирный и дружелюбный, отсюда соответствующий стиль и соответствующие решения.

    Ну вообще диалог на эту тему бесполезен, так что предлагаю всем остаться при своих мнениях.
    Мыслите шире.
     
  19. wasm_test

    wasm_test wasm test user

    Публикаций:
    0
    Регистрация:
    24 ноя 2006
    Сообщения:
    5.582
    Неправда. Прочитай пред пост.
     
  20. Clerk

    Clerk Забанен

    Публикаций:
    0
    Регистрация:
    4 янв 2008
    Сообщения:
    6.689
    Адрес:
    РБ, Могилёв
    Great
    Может быть.. Но я есчо не видел обратного.)
     
Статус темы:
Закрыта.