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

Discussion in 'WASM.NT.KERNEL' started by hiddy, Mar 29, 2019.

  1. hiddy

    hiddy Member

    Blog Posts:
    0
    Joined:
    Mar 10, 2019
    Messages:
    82
    Добрый день, пытаюсь ради спортивного интереса написать драйвер без таблицы импорта. Знаю что с помощью MmGetSystemRoutineAddress можно динамически получать адрес процедуры модуля ntoskrnl.exe, но этого не достаточно для выполнения поставленной задачи. RtlFindExportedRoutineByName уже ближе, собственно эту функцию и нужно реализовать. Вот ее прототип:
    Code (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, не выходит правильно получить адреса.
    Буду рад любой помощи.
     
    Last edited: Mar 29, 2019
  2. njeen

    njeen Active Member

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

    Indy_ Well-Known Member

    Blog Posts:
    4
    Joined:
    Apr 29, 2011
    Messages:
    4,788
    Обработчик исключения установить, далее вызвать исключение и получить адрес возврата. Затем используя тот же обработчик для безопасного поиска в памяти найти заголовок PE.
     
  4. hiddy

    hiddy Member

    Blog Posts:
    0
    Joined:
    Mar 10, 2019
    Messages:
    82
    Вы имеете ввиду KeGetPcr? Либо бсод во время вызова функции, либо неверные данные..

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

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

    vx1d Member

    Blog Posts:
    0
    Joined:
    Dec 13, 2016
    Messages:
    118
    имелось ввиду инструкция SGDT

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

    hiddy Member

    Blog Posts:
    0
    Joined:
    Mar 10, 2019
    Messages:
    82
    Не хватило у меня знаний разобраться с получением базового адреса ядра без вызовов апи. Итог: импорт с указателем на PsLoadedModuleList.

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

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

    Indy_ Well-Known Member

    Blog Posts:
    4
    Joined:
    Apr 29, 2011
    Messages:
    4,788
  8. vx1d

    vx1d Member

    Blog Posts:
    0
    Joined:
    Dec 13, 2016
    Messages:
    118
    Обсуждаются исключения в драйвере
    по ссылке выше обсуждается обработка исключений в юзермоде, для юзермоды в динамике проще использовать: AddVectoredExceptionHandler
    но все равно вопрос актуальный как в ядре в динамике установить обработчик исключений для x64

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

    hiddy Member

    Blog Posts:
    0
    Joined:
    Mar 10, 2019
    Messages:
    82
    Тогда уж сразу в ntoskrnl.exe это все пихать. На сколько я знаю это безопасно на данный момент.
     
  10. Indy_

    Indy_ Well-Known Member

    Blog Posts:
    4
    Joined:
    Apr 29, 2011
    Messages:
    4,788
    vx1d,

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

    vx1d Member

    Blog Posts:
    0
    Joined:
    Dec 13, 2016
    Messages:
    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

    Blog Posts:
    4
    Joined:
    Apr 29, 2011
    Messages:
    4,788
    vx1d,

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

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

    Rel Well-Known Member

    Blog Posts:
    2
    Joined:
    Dec 11, 2008
    Messages:
    5,317
    в ядре есть JIT-компилятор? o_O
     
  14. Indy_

    Indy_ Well-Known Member

    Blog Posts:
    4
    Joined:
    Apr 29, 2011
    Messages:
    4,788
    Rel,

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

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