The Kernel-Bridge Framework

Тема в разделе "WASM.PROJECTS", создана пользователем HoShiMin, 18 ноя 2018.

  1. Indy_

    Indy_ Well-Known Member

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

    > Ты делаешь данные нечитабельными

    Если заблокировать область памяти то во первых ловушки это всегда просто решали, а во вторых возникает проблема - когда второй поток начнёт выборку. Ты ведь тупо не разблокируешь память, это асинхрон. Поэтому область нужно переместить в памяти, технически это называется пересборка", морф либо в виде блока релокация - базовая техника виксов. Как ты это сделаешь через таблицы трансляции, на каждой выборке пошлёшь межпроцессорное прерывание что бы тормознуть cpu, да это какой то бред.
     
  2. HoShiMin

    HoShiMin Well-Known Member

    Публикаций:
    5
    Регистрация:
    17 дек 2016
    Сообщения:
    1.422
    Адрес:
    Россия, Нижний Новгород
    В гипервизоре у каждого процессора свой собственный набор таблиц EPT, описывающих всю доступную процессору физ. память.
    Процессор меняет атрибуты страниц только у себя, поэтому ни с кем синхрониться не надо.
    --- Сообщение объединено, 3 авг 2020 ---
    Кстати, ещё момент, чисто эстетический.
    Чтобы подменить память, мне нужно в поле записать новый указатель.
    Код (C):
    1.  
    2. struct EPT_PTE
    3. {
    4.     ... Какие-то поля ...
    5.     uint64_t hostPhysAddr;
    6. };
    7.  
    8. EPT_PTE* pte = getEptPte(guestPhysAddr);
    9. pte->hostPhysAddr = newPagePhysAddr;
    10.  
    Красиво и просто.

    Ты же предлагаешь что-то пересобирать и релоцировать, когда то же самое я делаю буквально в одну инструкцию - в один mov.
     
    Последнее редактирование: 3 авг 2020
    TrashGen и q2e74 нравится это.
  3. Indy_

    Indy_ Well-Known Member

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

    Давай на примере. Есть область памяти. Что бы её скрыть нужно подменить все выборки к ней, те вначале обнаружить, затем подменить. Обычно делается так - находится первая выборка, область релоцируется, либо если это секция с релоками(pe-формат), то её можно пересобрать. Область блокирована, к ней происходит выборка, срабатывает триггер(если визор), либо ловушка(#GP), пересчитывается адресная дельта - управление получает релоцированная область либо морф буфер, в любом случае текущий адрес отображён на буфер модом кода. Далее управление отпускается и отрабатывает изменённый код.

    Но а как отработает этот механизм EPT и прочая харда ?
     
  4. HoShiMin

    HoShiMin Well-Known Member

    Публикаций:
    5
    Регистрация:
    17 дек 2016
    Сообщения:
    1.422
    Адрес:
    Россия, Нижний Новгород
    Он работает на лету. Ты делаешь страницу недоступной для выборки, которую хочешь поймать.
    Нужно поймать чтение - делаешь страницу нечитабельной. Надо поймать исполнение - делаешь неисполняемой.
    Когда процессор пытается получить доступ, которого у страницы нет - вылетает EPT Violation. Ты его ловишь и обрабатываешь, как тебе угодно.
     
  5. Indy_

    Indy_ Well-Known Member

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

    Хорошо и как как это практически реализовать ?

    Допустим нужно промониторить системный загрузчик. Ты весь нэйтив заблочишь. И что делать когда сработает ловушка ?

    Отобразишь на другой адрес и туда кинешь управление.. это рекурсивная проблема. Не говоря уже про тайминг.
     
  6. HoShiMin

    HoShiMin Well-Known Member

    Публикаций:
    5
    Регистрация:
    17 дек 2016
    Сообщения:
    1.422
    Адрес:
    Россия, Нижний Новгород
    Если нужно промониторить системный загрузчик, я возьму WinDbg.
    Чем и как? В обработчике гипервизора я по-прежнему могу обращаться к функциям NT (которые доступны на высоких IRQL), т.к. нахожусь в адресном пространстве системы.
    Соответственно, в обработчике ловушки я могу вызвать PsGetCurrentProcess(), узнать, откуда вызывают, из какого режима (юзермод\ядро), сделать всё необходимое для обработки.
    Но зачастую и этого не надо, т.к. чаще всего задача стоит "просто скрыть" или "просто подменить" для всех без разбора.

    Да, здесь ты меня подловил: если код, который исполняется в странице, читает сам себя, а на чтение у тебя стоит страница с нулями, ты уйдёшь в вечный цикл подмен.
    Однако, я решил это просто и элегантно: я дал пользователю возможность самому задавать страницы, которые будут видны, когда код читает сам себя и когда код пишет сам в себя.
    И всё, даже эта проблема решена.

    И по-прежнему, одним единственным mov'ом. И разумеется, это ультрабыстро: например, у меня за амортизированную константу, считай за O(1).
     
    q2e74 нравится это.
  7. Indy_

    Indy_ Well-Known Member

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

    > Да, здесь ты меня подловил:

    Ничего я не ловил это классика - перемещение и передача управления, при этом возникает рекурсивная проблема, буфер выполняется и к нему применяется то же решение что к исходному и так по цепочке.
     
  8. HoShiMin

    HoShiMin Well-Known Member

    Публикаций:
    5
    Регистрация:
    17 дек 2016
    Сообщения:
    1.422
    Адрес:
    Россия, Нижний Новгород
    ...это знать надо
    [​IMG]

    Но, в любом случае, я и это решил простым и прямолинейным способом.
    А детали реализации можешь глянуть вот здесь.
     
  9. Indy_

    Indy_ Well-Known Member

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

    По ссылке смотреть нечего там какие то архитектурные манипуляции на самом дне.

    > ...это знать надо

    Конечно. Для какой то модификации блока он перемещается, затем возникает та же задача с уже перемещённым блоком и каждый раз усложняется. Доходит даже до корреляции патчей. Нельзя тупо подменить данные, ты это сделать не смог какие бы сказки не рассказывал давно наработана по этой теме глубокая теория. И обкатана на практике а не в сферическом вакууме ради написать ;)
     
  10. HoShiMin

    HoShiMin Well-Known Member

    Публикаций:
    5
    Регистрация:
    17 дек 2016
    Сообщения:
    1.422
    Адрес:
    Россия, Нижний Новгород
    Но ведь... Ты можешь скачать готовые бинарники у меня с гитхаба и проверить всё сам. Все эти апишки проброшены в юзермодную библиотечку.
    Подключи User-Bridge.h и из неймспейса Hypervisor дёрни функцию KbVmmInterceptPage.

    Или посмотри в папке Kernel-Tests: там у меня юзермодная утилитка для тестов, вот готовый пример, который подменяет страничку с кодом.
    Всё, что я тебе рассказываю, уже готовое ready-to-use решение. Бери и пользуйся!
    --- Сообщение объединено, 3 авг 2020 ---
    Вспомнилась цитата из трека ГРОТа:
     
    Последнее редактирование: 3 авг 2020
  11. Indy_

    Indy_ Well-Known Member

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

    > Подключи User-Bridge.h и из неймспейса Hypervisor дёрни функцию KbVmmInterceptPage.

    Всё дело в том, что это можно сделать более простым путём. Тем более в юзер. Теоретически может и интересно во всём этом копаться, но практически смысла не видно :)

    Бесчисленное количество задач/семплов решено через юзер визор и небыло никогда необходимости в км вирте и даже не нужен был виндебаг. Может если задача по ядру это всё как то поможет, но очень сомневаюсь. Там старые годные инструменты, никакая вирта там не нужна.
    --- Сообщение объединено, 4 авг 2020 ---
    > дёрни функцию KbVmmInterceptPage.

    И на асинхронной выборке будет синь. Ты сам выше писал что никакой синхрон не нужен, это значит что как только ты начал использовать ос апи твой код кривой и анстаб и вылетит на первом синхрон событии, даже атака не нужна ;)
     
  12. Rel

    Rel Well-Known Member

    Публикаций:
    2
    Регистрация:
    11 дек 2008
    Сообщения:
    5.241
    Раньше их были тыщи, сейчас видимо уже миллионы семплов прошли через легендарный визор вирус блокады. Своего рода успех, раз этот инструмент так активно используется в антивирусной индустрии.
    --- Сообщение объединено, 4 авг 2020 ---
    Если кодец инжектится в существующий процесс и выполняется в контексте другого процесса, то ядерный визор будет эффективнее.
     
  13. HoShiMin

    HoShiMin Well-Known Member

    Публикаций:
    5
    Регистрация:
    17 дек 2016
    Сообщения:
    1.422
    Адрес:
    Россия, Нижний Новгород
    Откуда берётся всё, что берётся? Я выше написал, почему синхронизация не нужна.

    Давай ещё раз: потому что подмена памяти происходит для каждого процессора отдельно, и подмена на одном процессоре никак не влияет на остальные.
    По одному и тому же виртуальному адресу каждый логический процессор видит разную память с разными правами.

    Ты ведь даже не проверял, верно? А я устраивал нагрузочное тестирование, к одной и той же странице параллельно обращаясь из трёх десятков потоков на чтение, запись и исполнение с 16 логических процессоров одновременно.
    И на основе чего тогда ты делаешь выводы?

    В твоём визоре синхронизация необходима, т.к. у всех процессоров общая PTE на всех. В гипервизоре я для каждого процессора создаю его собственное адресное пространство - у каждого процессора своя EPT, её не с кем синхронизировать, т.к. доступ к ней имеет только процессор-владелец.
     
    q2e74 нравится это.
  14. Indy_

    Indy_ Well-Known Member

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

    > Ты ведь даже не проверял, верно?

    А что проверять ?

    Говорил же, покажи пример - возьми простейшее приложение и крутни своим визором. Что бы был результат. Кому твои PTE нужны :lol:
     
  15. M0rg0t

    M0rg0t Well-Known Member

    Публикаций:
    0
    Регистрация:
    18 окт 2010
    Сообщения:
    1.574
    разве визор и гипервизор это одно и тоже? Это же разные технологии как бы.
     
  16. q2e74

    q2e74 Active Member

    Публикаций:
    0
    Регистрация:
    18 окт 2018
    Сообщения:
    988
    HoShiMin, запилите четвертую часть статьи в виде пошаговой инструкции, что вы делали. Повторим где-то на недельке, запишем, зальем на ютуб, разместите на гитхабе.
     
  17. Rel

    Rel Well-Known Member

    Публикаций:
    2
    Регистрация:
    11 дек 2008
    Сообщения:
    5.241
    Ну нет, но да. То что Инде называет визором - это по сути наколеночный дби, то что Хошимин называет гипервизором - это по сути гипервизор. Проблема в том, что в голове Инде есть только одна задача - поиск оеп, и от этого он пытается любой софт натянуть на эту задачу.
     
    TrashGen нравится это.
  18. HoShiMin

    HoShiMin Well-Known Member

    Публикаций:
    5
    Регистрация:
    17 дек 2016
    Сообщения:
    1.422
    Адрес:
    Россия, Нижний Новгород
    Здесь одной статьёй не обойдётся.
    В третьей закончили на настроенном EPT, всё готово к запуску визора.
    Одна статья уйдёт на сам запуск (на настройку VMCS), другая - на написание обработчиков #VMEXIT'ов.
    Третья - уже скрытие памяти.

    А я взялся с нуля переписывать кб.
    Уже глаза мозолит заглавный CamelCase - переписываю уже на человеческом camelCase. Вычищаю легаси, добавляю больше плюсов, новые апишки, рефакторинг всего и вся...
    В общем, всё будет (и статьи тоже), но не сразу...
     
    q2e74 нравится это.
  19. Indy_

    Indy_ Well-Known Member

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

    > разве визор и гипервизор это одно и тоже?

    Одно и тоже, разница лишь в моде. Гипером называется тк понятие ввели вендоры. Сделай тоже в р0 это гипером не будет обычный визор, хоть и будет работать в точности как и хард вирта. Вообще визор это механизм трассировки по сути потока инструкций или выборки. Как не странно хв такое не умеет, это аналог механизма исключений в ином моде. Тоже самое элементарно реализуется на старых добрых ловушках.

    Внимание замылили сложностью хв, это предназначено исключительно для запуска ос в ос. Но многие пытаются натянуть сову на глобус без практических целей, нравится видимо ядро дебажить и прочие сложности.
     
    Последнее редактирование: 5 авг 2020
  20. HoShiMin

    HoShiMin Well-Known Member

    Публикаций:
    5
    Регистрация:
    17 дек 2016
    Сообщения:
    1.422
    Адрес:
    Россия, Нижний Новгород
    Откуда ты всё это берёшь? Что, гипервизор не умеет трассировать код? Тогда почитай главу "Monitor Trap Flag", что само по себе нужно для пошаговой трассировки гостя, а также, главу про перехват прерываний, что позволит ловить тебе гостевые int3 и Single Step.
    У кого это элементарно реализуется?
    Пропатчишь IDT - тебя съест PatchGuard. Пропатчишь PTE - начнётся нерешаемая гонка процессоров.
    Что ты собрался пересобирать? Ты даже не знаешь, кто, откуда и из какого контекста будет вызывать скрываемую страницу.
    Она может быть и в юзермоде, и в ядре, к ней могут обращаться из любого процесса, на любом IRQL, на чтение, запись и исполнение одновременно, сразу из разных процессоров.
    На эту страницу могут создавать отображения, в том числе, отображения на нижележащую физическую память напрямую (MmMapIoSpace).
    Во всех этих случаях подмена должна работать корректно.

    Где эти "старые годные" инструменты? Приведи хоть один пример. Не в виде бумажных концептов, которые невозможно осуществить на практике, а реальные готовые проекты.
    У меня - вот, на гитхабе. Не просто концепт, а готовое решение с юзермодным интерфейсом. Полторы тысячи строк логики, которые покрывают все описанные выше случаи. Причём, в общем виде: я не покрывал ни один из этих случаев специальным кейсом.
    И PatchGuard остаётся включённым - в системе не патчится ни одного байта.
    Есть что противопоставить?
     
    TrashGen и Rel нравится это.