Аналог GetProcAddress в ядре

Тема в разделе "WASM.NT.KERNEL", создана пользователем hiddy, 29 мар 2019.

  1. hiddy

    hiddy Member

    Публикаций:
    0
    Регистрация:
    10 мар 2019
    Сообщения:
    82
    Добрый день, пытаюсь ради спортивного интереса написать драйвер без таблицы импорта. Знаю что с помощью MmGetSystemRoutineAddress можно динамически получать адрес процедуры модуля ntoskrnl.exe, но этого не достаточно для выполнения поставленной задачи. RtlFindExportedRoutineByName уже ближе, собственно эту функцию и нужно реализовать. Вот ее прототип:
    Код (Text):
    1.  
    2. NTKERNELAPI
    3. PVOID
    4. NTAPI
    5. RtlFindExportedRoutineByName(
    6. _In_ PVOID ImageBase,
    7. _In_ PCCH RoutineName
    8. );
    9.  
    И сразу первый вопрос. Как получить imagebase ntoskrnl.exe без использования импорта? На данный момент использую PsLoadedModuleList.
    Второй вопрос. Как правильно парсить таблицу экспорта ntoskrnl.exe? Пробовал стандартным методом, но без использования ядерной функции RtlImageDirectoryEntryToData, не выходит правильно получить адреса.
    Буду рад любой помощи.
     
    Последнее редактирование: 29 мар 2019
  2. njeen

    njeen Active Member

    Публикаций:
    0
    Регистрация:
    26 мар 2017
    Сообщения:
    138
    Адрес:
    Ташлинск
    Искать адрес функции экспортируемой в ядре с помощью MmGetSystemRoutineAddress и им подобных функций ненадежно. Лучше парсите самостоятельно таблицу экспорта. Мне приходилось сталкиваться с тем, что в ядре может быть forwarding export, а MmGetSystemRoutineAddress() его не могла обработать и возвращался адрес не на функцию, а на соотв. заглушку-forwarding в экспорте.
    Парсить экспорт так же, как обычный pe.
    Базу ntoskrnl - кажется, можно было узнать, получив адрес gdt и взяв оттуда адрес обработчика, принадлежащего адресному пространству модуля ядра, далее - уже перейти к адресу базы.
     
    Коцит нравится это.
  3. Indy_

    Indy_ Well-Known Member

    Публикаций:
    4
    Регистрация:
    29 апр 2011
    Сообщения:
    4.775
    Обработчик исключения установить, далее вызвать исключение и получить адрес возврата. Затем используя тот же обработчик для безопасного поиска в памяти найти заголовок PE.
     
  4. hiddy

    hiddy Member

    Публикаций:
    0
    Регистрация:
    10 мар 2019
    Сообщения:
    82
    Вы имеете ввиду KeGetPcr? Либо бсод во время вызова функции, либо неверные данные..

    Есть примеры? Или почитать чего можно?

    С экспортом вроде разобрался, спасибо.
     
  5. vx1d

    vx1d Member

    Публикаций:
    0
    Регистрация:
    13 дек 2016
    Сообщения:
    118
    имелось ввиду инструкция SGDT

    это только для 32 битного шелкода
    для 64битного шелкода вроде нет способа динамической установки обработчика исключения
     
  6. hiddy

    hiddy Member

    Публикаций:
    0
    Регистрация:
    10 мар 2019
    Сообщения:
    82
    Не хватило у меня знаний разобраться с получением базового адреса ядра без вызовов апи. Итог: импорт с указателем на PsLoadedModuleList.

    Тред прошу не закрывать, может кто-нибудь захочет поделится мыслями по поводу данного вопроса.

    Благодарю всех участников за помощь. :thank_you:
     
  7. Indy_

    Indy_ Well-Known Member

    Публикаций:
    4
    Регистрация:
    29 апр 2011
    Сообщения:
    4.775
  8. vx1d

    vx1d Member

    Публикаций:
    0
    Регистрация:
    13 дек 2016
    Сообщения:
    118
    Обсуждаются исключения в драйвере
    по ссылке выше обсуждается обработка исключений в юзермоде, для юзермоды в динамике проще использовать: AddVectoredExceptionHandler
    но все равно вопрос актуальный как в ядре в динамике установить обработчик исключений для x64

    что если искать драйвер с секцией .pdata, секцию c атрибутом discarded, писать туда код и патчить .pdata для установки нашего обработчика
     
  9. hiddy

    hiddy Member

    Публикаций:
    0
    Регистрация:
    10 мар 2019
    Сообщения:
    82
    Тогда уж сразу в ntoskrnl.exe это все пихать. На сколько я знаю это безопасно на данный момент.
     
  10. Indy_

    Indy_ Well-Known Member

    Публикаций:
    4
    Регистрация:
    29 апр 2011
    Сообщения:
    4.775
    vx1d,

    А есть разница ?
    Там описан механизм установки доверенных обработчиков, не зависящий от апи.
     
  11. vx1d

    vx1d Member

    Публикаций:
    0
    Регистрация:
    13 дек 2016
    Сообщения:
    118
    "For dynamically generated functions [JIT compilers], the runtime to support these functions must either use RtlInstallFunctionTableCallback or RtlAddFunctionTable to provide this information to the operating system"
    а в ядре есть аналог?
     
  12. Indy_

    Indy_ Well-Known Member

    Публикаций:
    4
    Регистрация:
    29 апр 2011
    Сообщения:
    4.775
    vx1d,

    Есть некая RtlInsertInverted.., но дело не в этом. Что бы получить импорт нужно знать базу ядра. Я посмотрел, наверно можно попробовать использовать следующее.

    При сервисной обработке есть безопасное место KiSystemServiceCopyStart - KiSystemServiceCopyEnd. Чтобы найти можно взять указатель KiSystemCall64 из мср(LSTAR).
     
  13. Rel

    Rel Well-Known Member

    Публикаций:
    2
    Регистрация:
    11 дек 2008
    Сообщения:
    5.241
    в ядре есть JIT-компилятор? o_O
     
  14. Indy_

    Indy_ Well-Known Member

    Публикаций:
    4
    Регистрация:
    29 апр 2011
    Сообщения:
    4.775
    Rel,

    Имеется ввиду динамический код. Обычная защита функций это фишка пе формата, но для этого образ должен содержать нужную инфу. Поэтому я и говорил что не нужно ничего вызывать. Так как у тс пе образ. В 64 из за защиты убрали динамику типо сех. Но всё равно методы найдутся, как выше например. Строим граф для значения из мср, формируем окружение и можем безопасно читать память. Обработчик не выполняет никаких проверок типо KPP, тупо безопасный диапазон выбирающих инструкций.

    Можно конечно установить ловушку в IDT. Но это не метод, так как что бы включить прерывания - нужно скопировать себе код, формирующий TF. Иначе нельзя обращаться в подкачиваемую память. Будет рекурсивный крэш.
     
    Последнее редактирование: 9 апр 2019