IDP, перенаправление выборки DF на нужное место

Тема в разделе "WASM.WIN32", создана пользователем zerodawn, 18 авг 2018.

Метки:
  1. zerodawn

    zerodawn Member

    Публикаций:
    0
    Регистрация:
    16 янв 2018
    Сообщения:
    94
    Привет, решил изучить материалы инде, понравилось место где идет речь про DFG, вот цитата:

    Идея довольно интересной показалась. Регаем VEH обработчик, ставим на .rdata мониторинг и ловим каждый доступ к ней. В VEH обработчике ловим адрес исключение и смотрим по какому адресу была попытка чтения, после чего заменяем некоторый адрес по формуле f(addr) = real_address, где addr - адрес чтения, real_address - настоящий.

    И вот тут возникает вопрос. Допустим есть код:

    Код (Text):
    1.  
    2. mov eax, byte ptr DS:[ptr]
    3.  
    И вот следующая цитата:

    То есть, Каким образом на этапе компиляции пересобрать все поинтеры, чтобы после применения f(ptr) результат был настоящим поинтером? То есть, другими словами, каким образом реализовать то что в цитате написано как:

    Каким образом на этапе компиляции переместить данные с такое место, чтобы после применения f(ptr) результат указывал на выбираемые данные?

    P.S.

    Проверить аттрибуты секции? Сравнить поинтер, чтобы он не был в пределах кодовой секции? :nea:
     
  2. Indy_

    Indy_ Well-Known Member

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

    Если выборка данных произошла, то инструкция имеет ModR/M. Эффективный адрес кодируется в ModR/M через регистровые компоненты. Некоторый из них изменяется, тогда адресация произойдёт в другую область памяти. Например mov eax,[R + DISP]: MRM имеет базу R(Ea = R + DISP). Тогда изменяется R на дельту адресов Ea + Delta = @Buffer. Delta = @Buffer - Ea. Тогда R' = R + Delta и новый Ea = R + DISP + @Buffer - Ea(= R + DISP) = @Buffer. При срабатывании ловушки Ea = Cr2.

    Использование ловушек лишь частный случай. Так можно при трассировке для каждой инструкции раскодировать MRM и подменить выбираемые данные, разместив их в буфер или же эмулируя инструкцию. Первый способ проще, так как не нужна дополнительная эмуляция. При такой выборке область памяти куда происходит обращение не существует. Так как Ea пересчитывается при факте выборки, то прочий код, для которого не пересчитывается Ea прочитать данные из этой области не может(анклав).

    > Каким образом на этапе компиляции переместить данные с такое место, чтобы после применения f(ptr) результат указывал на выбираемые данные?

    Адреса в динамике пересчитываются. Это не компиляторный способ.

    Тут пример есть https://wasm.in/threads/skrytie-modulja.31872/
     
  3. superakira

    superakira Guest

    Публикаций:
    0
    zerodawn, ты заюзал это? норм? робит или сыро?
     
  4. Indy_

    Indy_ Well-Known Member

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

    Не отвечает пока. Анклавом можно сделать и полностью модуль. Тогда авер память читать не сможет, но тс пока молчит.
     
  5. zerodawn

    zerodawn Member

    Публикаций:
    0
    Регистрация:
    16 янв 2018
    Сообщения:
    94
    Сорри, был в отъезде, читал все ридонли т.к пасс на основном ПК.

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

    Впрочем, понятно. Я поигрался с самим механизмом отлова - в дебаггере реально такое будет реверсить геморройно, в статике тоже нихера не понятно. Спасибо за идею.

    Как дойдут руки до реализации x86 эмулятора снова отпишу ( если дойдут ). А с работающим эмулятором грех сами адреса кодировать, а не инструкции =)

    Может у кого есть решение без реализации эмулятора? Я ничего не смог придумать.

    Честно, я понял только саму идею IDP, а как сделать модуль анклавом я так и не понял особо. Хотел как раз про это спросить. Я вкурсе про Intel-SGX, а софтверная реализация мне не понятна.

    Насколько мне понятно пока, там предлагается запретить ав чтение памяти при помощи того, что все поинтеры encoded и при эмуляции он не сможет в хандлер визора приложения попасть, или как?

    Вот тут на пальцах желательно мне объяснить, думаю не мне одному этот момент не ясен)
     
    Последнее редактирование: 22 авг 2018
  6. Indy_

    Indy_ Well-Known Member

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

    Нормально потоки данных не выбираются на ловушках. Тоесть варианта есть два - блокировка страницы и отлов #GP, либо раскодировать адрес. Первый случай использовался когда число выборок не значительное. Во втором случае вам нужен визор.

    Мне не охота одно и тоже втирать каждому, есть публикации по сабжу.

    Как это работает: реализуется анклав на все типы выборок. R/W/X. Если с первыми понятно, то на исполнение - передача управления в образ будет отслежена, как вы изначально планировали через ловушки или визор-декодером EA.

    Это планировалось реализовать как мотор, была попытка, посмотрите на rohitab.com

    Всё множество задач свелось к оптимизации визора(на кряклабе темы). Пока это не решиться, то не решится и остальное.
     
    zerodawn нравится это.
  7. Indy_

    Indy_ Well-Known Member

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

    > Может у кого есть решение без реализации эмулятора? Я ничего не смог придумать.

    Я это пропустил наверно. Именно это решение и использовалось последние годы. Это я и называю визором. Это не эмуляция, а прямое исполнение линейных блоков. Их связывают ветвления, лишь их нужно эмулировать, но это элементарная обработка. Блок загружается в буфер и там исполняется напрямую(DYE). В последнем случае попытка реализовать это без копирования, что садит профайл - блоки собираются в большой буфер; на это нужно довольно много памяти, но делает обработку очень быстрой. Из проблем - такое исполнение не пригодно для реализации анклава или защиты, либо придётся дробить блоки на каждую инструкцию, тогда оптимизация такая теряет смысл. Второй проблемой стали авл деревья - для быстрой трансляции адреса на буфер. Системная реализация однопоточная и если это обернуть в RW-блокировку, то из за огромного количества записей всё приложение тупо повиснет. Но это всё технические детали.

    https://exelab.ru/f/index.php?action=vthread&forum=6&topic=25248

    Эмуляция IA это весьма сложная задача, конечны код получится огромным. Обьём кода напрямую определяет его стабильность. В случае DYE код минимален, возможность произвольного глюка исключается при качественной реализации. Так же важный момент блочного исполнения - не деление блока, те он исполняется как одна инструкция, в случае эмуляции это невозможно, каждая должна эмулироваться. Но опять же блочное исполнение не годится для реализации анклавов, воможно как то описать по типу символического исполнения блок, но это пока не проработано, так что хз.

    Если конкретно по данной задаче говорить - то профайл абсолютно никакого значения не имеет, главное недетект. Просто наши цели немного разные, вам нужен недетект, у меня задача на профайл, что бы запустить защиту от OP в реалтайме https://wasm.in/threads/antiinzhekt-otlovit-smenu-konteksta.32315/#post-392808

    > предлагается запретить ав чтение памяти при помощи того, что все поинтеры encoded

    Память не существует, данные передаются в поток при событии выборки данных(data fetch). В любом ином режиме такой выборки нет, соотвественно для него нет и данных. Я ведь подробно показал в #2. Это что касается данных(R/W). Для исполнения - инструкции последовательно могут быть раскодированы из буфера. Фактически это тоже выборка, только на исполнение при ветвлениях.
     
    Последнее редактирование: 23 авг 2018
    zerodawn нравится это.
  8. Indy_

    Indy_ Well-Known Member

    Публикаций:
    4
    Регистрация:
    29 апр 2011
    Сообщения:
    4.775
    Вот очень старый пример, это первая версия DYE: https://yadi.sk/d/tQPb17Nr3TjTJM

    Что бы вы сравнили с аналогичным по решаемой задаче эмулятором :)

    Это была первая попытка реализовать image-enclave: https://yadi.sk/d/46fQlNDertQSi

    Там есчо какая то дока была https://yadi.sk/i/8MB_I8NlrhR6P но я особо не помню подробности.

    И тут какие то доки есть https://yadi.sk/i/8MB_I8NlrhR6P

    Вот есчо какой то POC: https://yadi.sk/d/1LdDcTzpsnCS3

    Это я с ядиска выбрал, там есчо много всякого, но к архивам примечания не делаю, только могу по названию вспомнить что в них. Если что то запаролено, то пасс обычный "vx".
     
    zerodawn нравится это.
  9. zerodawn

    zerodawn Member

    Публикаций:
    0
    Регистрация:
    16 янв 2018
    Сообщения:
    94
    Спасибо большое за ответы, теперь стало окончательно все понятно. Понял отличие визора от эмулятора. Действительно, визор проще.

    Следуюя линку в экзелабе, тупой вопрос может

    Каким образом после перехода в стабе-эмуляторе ветвления получаем адрес откуда был совершен переход? Что эмулировать? Не проще записывать int3 и ловить в VEH'е смещение, и читать с темп-буфера сохраненное оригинальное значение. Таким образом, кстати, можно протрейсить весь поток исполнения и записать туда наномиты.
     
  10. Indy_

    Indy_ Well-Known Member

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

    Если вы мои посты смотрели на кл, то там всё основано на тестах профайла. Либо дизасм проходит тест на стабильность и профайл.

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

    Это может использоваться либо в км, либо для целей отладки в юм.

    > Каким образом после перехода в стабе-эмуляторе ветвления получаем адрес откуда был совершен переход?

    Элементарно раскодируем, любой дизасм возвращает эту инфу. Это либо релатив, либо выборка MODRM.
     
  11. Indy_

    Indy_ Well-Known Member

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

    > Таким образом, кстати, можно протрейсить весь поток исполнения и записать туда наномиты.

    Что угодно можно сделать. В качестве тестов когда то давно был взят VMP. Он был запущен под визором и все инструкции собирались в память. Их было ~1.5Gb, визор выделил(использовался есчо и кэш инструкций, софтверная бд) лишь несколько Kb кода, огромный цикл VM VMP. Далее код собирался конструктором в единое целое и таким образом решалась задача, хоть она и была нацелена тупо на тесты сборки визора, а не на тесты протекторов. Другие тесты выполнялись на тяжёлых апп, типо браузеров. При обычном копировании и декодере кседа профайл садился десятикратно. Это очень мало, при эмуляции больше на порядки. Основной профайл уходит на операцию копирования и на декодер. Но это в первых реализациях, сейчас уже пошло дальше.

    Софтверные анклавы - это угроза для AV, это поломает сам принцип эмуляции и сделает невозможным детект в памяти. За разработку этих вещей могут точно подвесить".

    Странно только что кроме тс этим никто не интересовался, эти статьи были написаны впустую.
     
  12. zerodawn

    zerodawn Member

    Публикаций:
    0
    Регистрация:
    16 янв 2018
    Сообщения:
    94
    Ошибаетесь, у меня очень много в жабах знакомых, которые пытались воспроизвести, но потерпели фиаско.

    По большей части из-за непривычной терминологии. Многие просто не поняли. А я не побоялся уточнить. Спасибо за ответы, если будут еще - я буду мучать, ок? :)
     
  13. zerodawn

    zerodawn Member

    Публикаций:
    0
    Регистрация:
    16 янв 2018
    Сообщения:
    94
    Каким образом происходит "изоляция памяти"? Допустим в линейном коде есть инструкция lea eax, [memory], или mov eax, dword ptr DS:[global]? Или еще хуже: запись по поинтеру.

    + как быть с зависимым от базы кода, т.к вот я смотрю:

    > При записи в этот буфер линейный блок копируется и в конце дописывается jmp near rel на стаб, который выполняет эмуляцию оригинального ветвления.

    Я так понимаю линейный блок берется, копируется в буфер, после него ставится jmp на стаб эмулятора и запускается тред в этот буфер? Как отлавливать попытки чтения/записи с произвольной памяти? Не ставить же везде PAGE_NOACCESS, а если указатель "невзначай" попадет в уже выделенную страницу памяти, принадлежающую, например, ntdll/kernel32/самому визору?

    Ладно, эти проблемы решаются прогрузкой в память модуля по той базе, на которую он расчитан (если релоков нет), то тогда можно нарваться на другую проблему ( меньшую, но не очень приятную ). Придется весь визор писать в базонезависимом стиле, чтобы в случае чего перетащить код визора под другой адрес и не мешать эмулируемому модулю. Как?

    Я вот это не понимаю, ведь визор работает в одном адресном пространстве, что и загруженное приложение.
     
  14. Indy_

    Indy_ Well-Known Member

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

    По первой ссылке рабочий был пример. Ваши проблемы надуманны, так как у вас всё почему то крутится вокруг эмуляции. Да и вообще вы не понятно что спрашиваете.

    Посмотрите как раскодируется эффективный адрес и вычисляется линейный. Так же посмотрите в документации что это такое. IA, v3, Logical Address to Linear Address Translation.
     
  15. Indy_

    Indy_ Well-Known Member

    Публикаций:
    4
    Регистрация:
    29 апр 2011
    Сообщения:
    4.775
    > Как отлавливать попытки чтения/записи с произвольной памяти?

    Раскодировать эффективный адрес(MODRM). Устал уже повторять ^
     
  16. unc1e

    unc1e Active Member

    Публикаций:
    2
    Регистрация:
    28 июл 2017
    Сообщения:
    287
    Ее не существует. В прямом смысле. Вот так выглядит функа, которая проверяет поддержку софтверных анклавов
    [​IMG]
     
  17. Indy_

    Indy_ Well-Known Member

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

    Может материал изучить следует, а не утверждать только по термину одинаковому. Это никакого отношения к SGX не имеет, абсолютно никакого.
     
    zerodawn нравится это.
  18. zerodawn

    zerodawn Member

    Публикаций:
    0
    Регистрация:
    16 янв 2018
    Сообщения:
    94
    В моем понятии раскодировать - это прочитать инструкцию и сделать ее дизасм, после чего достать оттуда эффективный адрес.

    А что в вашем?

    Если я буду линейный блок запускать на реальном процессоре каким образом я смогу раскодировать эффективный адрес нужной мне инструкции?
    Чем это вообще будет отличаться от эмуляции, если мне придется раскодировать эффективный адрес каждой инструкции?

    Ок, как без эмуляции понять какую инструкцию мне надо раскодировать? Или все подряд раскодировать?

    Ваш ассемблерный код абсолютно нечитаемый, по ссылке выше об этом тоже написали.
     
  19. Indy_

    Indy_ Well-Known Member

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

    Вы перешли на обсуждение технических деталей, вы суть поняли и теперь тех плана вопросы идут. Я ведь говорил, вы хотя бы полистали приведённые примеры, там всё это есть. Зачем спрашивать фундаментальную инфу.

    Что такое ModR/M ?
     
  20. zerodawn

    zerodawn Member

    Публикаций:
    0
    Регистрация:
    16 янв 2018
    Сообщения:
    94
    Ну если кратко, то просто кодирование в инструкциях косвенной адресации/регистров/адресов etc

    листал, чужой асм код ( да еще на такую тему ) крайне трудно воспринимать.