PE Loader и TLS

Тема в разделе "WASM.WIN32", создана пользователем jeer0, 8 дек 2017.

  1. jeer0

    jeer0 Member

    Публикаций:
    0
    Регистрация:
    31 июл 2017
    Сообщения:
    35
    Всем привет.
    Вопрос о работе PE-загрузчика, который загружает DLL, имеющую IMAGE_DIRECTORY_TLS.
    Реально ли написать такой загрузчик без использования сомнительных
    хаков (использование оффсетов в недокументированных структурах, вызов недокументированных API не до конца понятного назначения и т.д.) ?
    Насколько я сейчас понимаю, там нужно работать с TEB.ThreadLocalStoragePointer, да ещё и вызывать что-то при создании и завершении потока.
    Экспортируемых функций для работы с TLS на уровне ntdll!LdrXxx не нашел.
    Есть разбирающиеся в этом вопросе?
    Спасибо!
     
    Последнее редактирование: 8 дек 2017
  2. Indy_

    Indy_ Well-Known Member

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

    > Реально ли написать такой загрузчик без использования сомнительных хаков

    Нет. Вы можите только эмулировать или вмешаться в логику работы системного загрузчика, например захватить его и симулировать некоторые данные. Иначе никак решить нельзя. Суть в том, что тлс отрабатывает на этапе загрузки апп, но так как ваше апп это загрузчик для другого апп, то получается что механизм не запускается, те корреляция. Обычно лучше симулировать данный механизм, так как врядле у вас загручик является надстройкой(такой за всё время был один и мой: LWE). Если вы вручную формируете образ в памяти, то данная задача смысла не имеет, конечно вы должны иммитировать тлс.
     
  3. Indy_

    Indy_ Well-Known Member

    Публикаций:
    4
    Регистрация:
    29 апр 2011
    Сообщения:
    4.775
    Ну и следует добавить что ручное" формирование образа это просто дикость, нубость, так как это абсолютная не совместимость с системой - загрузчик поддерживает огромное число механизмов. В таком случае использование системных механизмов бессмысленно и абсурдно. Полноценный лоадер должен являться надстройкой над системным загрузчиком - нтлдр захватывается и симулируются низкоуровневые данные. Таким образом он отрабатывает штатно, но данные подменяются. Лишь в этом случае имеет смысл спросить про тлс.
     
  4. jeer0

    jeer0 Member

    Публикаций:
    0
    Регистрация:
    31 июл 2017
    Сообщения:
    35
    Пока я сталкивался только с проблемой с TLS, которая решается компиляцией C++ -кода с флагом /Zc:threadSafeInit- (речь идет о Visual Studio 2015). Просто хотелось раз и навсегда избавиться от необходимости указывать этот флаг всему коду, который может быть загружен моим собственным загрузчиком (тоесть, например, составляющий DLL, которая куда-то инжектится).
    Другие механизмы на практике проблем не вызывали. О каких именно идет речь?

    Это как? Что именно и где нужно перехватить и симулировать? Не могу найти в гугле LWE :dntknw:

    Кстати, да, покопавшись в проблеме я понял, что это называется implicit TLS и что
    загрузчик выделяет специальный слот в TEB.ThreadLocalStoragePointer и поддерживает актуальность этого слота при создании новых потоков. Короче, универсальное решение тут невозможно. Так что да, никак.
     
  5. rmn

    rmn Well-Known Member

    Публикаций:
    0
    Регистрация:
    23 ноя 2004
    Сообщения:
    2.348
    jeer0,
    Не слушай его. Его сейчас на аппаратной виртуализации переклинило и он думает, что без визоров вообще ничто действительно рабочее написать невозможно :)
     
    Indy_ нравится это.
  6. Indy_

    Indy_ Well-Known Member

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

    Ну а причём тут визоры и вм ?

    jeer0,

    > Это как? Что именно и где нужно перехватить и симулировать? Не могу найти в гугле LWE :dntknw:

    Это работает следующим образом.

    На ключевые сервисы ставится фильтр, они иммитируются. Тоесть NtMapView отображает в память не файловую секцию, а декриптует в память образ.
    Что бы не портить патчем нэйтив(нтдлл) он линейно копируется в буфер(релоцируется) и там фиксятся сервисы, устанавливается на них фильтр.
    Затем происходит штатный вызов загрузчика, который перенесён в буфер. Он работает как обычно, за исключением симуляции образа. Я использовал knowndll секции.

    https://yadi.sk/d/vRgDzkySrRowe

    - дату посмотрите реализации :preved:

    Есчо можите посмотреть как скрыть образ https://yadi.sk/d/aK1r0ajK36X58R(pass: vx).
     
  7. jeer0

    jeer0 Member

    Публикаций:
    0
    Регистрация:
    31 июл 2017
    Сообщения:
    35
    Indy_, угу, понятно. Вызвать обычную LoadLibrary, но перехватив NtMapView* и подсунув проекцию своей DLL "из памяти" вместо проекции DLL с диска. Я вот только боюсь следующего. Не получится ли так, что какой-нибудь функции виндового лоадера
    не понравится факт наличия загруженной DLL, у которой информация о View или Section не соответствует действительности (т.е. той информации, которую сохраняет лоадер в PEB) ?
    Вообще это выглядит как хороший способ, может быть, кто-то его использовал на практике и может высказаться о его стабильности и подводных камнях?

    > дату посмотрите реализации

    А когда последний раз это успешно использовалось?
     
  8. Indy_

    Indy_ Well-Known Member

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

    > Не получится ли так, что какой-нибудь функции виндового лоадера не понравится факт наличия загруженной DLL, у которой информация о View или Section не соответствует действительности

    Получится. Это касается защиты, например NX. Но это не проблема.

    > А когда последний раз это успешно использовалось?

    Не помню точно, но когда то запускали на 10-ке, оно работало. Не работало вроде как с .net, но я тогда отказался разбираться. А есчо наверно те файлы у ав в базах, так как на этом активно тестились ав, впрочем не важно.
     
  9. jeer0

    jeer0 Member

    Публикаций:
    0
    Регистрация:
    31 июл 2017
    Сообщения:
    35
    > Получится. Это касается защиты, например NX. Но это не проблема.

    Что такое NX защита и почему это не проблема? Речь ведь не о noeXecute bit ("nx bit") ?
     
  10. Indy_

    Indy_ Well-Known Member

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

    Блокировка исполнения исключений(safeseh или nxseh не помню как называтеся, но это не важно) в не image памяти. Это очень старый механизм. Более того последние версии системы поддерживают кучу новых механизмов. Можно предсказать теоретически как что с ними связано на основе описаний. Но главная проблема в андок механизмах, их весьма много, всякие валидации стека и прочее, так что не имея самой новой ос предсказать ничего нельзя, увы. Я как то поднимал вопрос про модуля от новых версий ос, это помогло бы всем, но это никому не нужно и не интересно.)
     
  11. Indy_

    Indy_ Well-Known Member

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

    Решает. Именно потому что изначально подход общий оно работает в новых версиях ос. Это нэйтив, он не меняется.

    Лишь глупый ньюби решится на симуляцию нтлдр.

    Принцип релокации элементарен - не зависимо от режима(86/64) кодовая секция нт может быть перемещена как линейный массив. В первом случае нет релатив(относительных адресов) адресации за пределы секции, это противоречит пе формату, это не возможно. Во втором случае фиксапов нет, они не нужны, так используется rip-адресация, так что это отлично сработает на 64.
     
    Последнее редактирование: 29 дек 2017
    PaperMoon нравится это.
  12. Indy_

    Indy_ Well-Known Member

    Публикаций:
    4
    Регистрация:
    29 апр 2011
    Сообщения:
    4.775
    > в андоках утопать желания и времени нету.

    Очень годная мысль и сам подход к задаче, за неё лайкнул :)
     
  13. Indy_

    Indy_ Well-Known Member

    Публикаций:
    4
    Регистрация:
    29 апр 2011
    Сообщения:
    4.775
    В #12 я допустил ошибку и не правильно сказал. Из за предновогоднего состояния" ушёл от исходной задачи на свою :)

    Это не существенная деталь, но всё же следует поправить.

    Принцип следующий. Есть серия сервисных вызовов из нэйтив на которые нужно поставить фильтр и симулировать. Уставновка фильтра может быть выполнена многими способами, я использовал линейное копирование кодовой секции(86), для сокрытия(не изменять код и лишний раз не использовать ловушки). 86 модуля не имеют межсекционной релатив адресации.
    В 64 моде межсекционная релатив адресация присутствует, причём это нельзя в статике определить. Адресация в иную секцию происходит через фиксированное смещение при релатив адресации, а ссылки на данное смещение в пе не имеется. Таким образом 64 секция не может быть никак перенесена в другую область памяти.
    Поэтому фильтр на 64 следует ставить иным образом.
     
  14. Indy_

    Indy_ Well-Known Member

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

    Показать можите ваше решение ?
     
  15. Indy_

    Indy_ Well-Known Member

    Публикаций:
    4
    Регистрация:
    29 апр 2011
    Сообщения:
    4.775
    Отличный прямо ответ, как впрочем и описание вашей проблемы. Всё понятно.)
     
  16. Indy_

    Indy_ Well-Known Member

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

    Повторяем диалог, ну что бы вам стало понятно:

    > Покажите ваше решение.
    >> Всё норм, есть траблы. status_bad. Буду копать. Есть мысли - дай знать, нет идей - нет сурков.
    > Фейк понятен.
    >> Вываливается, забей. Я отписал, может куму будет интересно.

    :sarcastic_hand:
     
  17. Indy_

    Indy_ Well-Known Member

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

    В ядре 8-ки данного статуса нет, как и на msdn. Последний там следующий:

    Но данный статус находит гугл как STATUS_DYNAMIC_CODE_BLOCKED. Это значит что система отклоняет запрос на аллокацию исполняемой памяти. Не вижу проблемы в этом случае.
     
  18. Indy_

    Indy_ Well-Known Member

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

    А что именно не так с нэйтивом ?
    Он не релоцируется, хоть имеет релоки на 86, но загружается первым и содержит глобальные указатели. На 64 rip адресация и релоки не нужны. Это значит что можно его копировать как строку.
    Сброс загрузчика необходим лишь в одном случае - это запуск образа с тлс. Но это очень плохой способ, отвалится многое. На 86 первый фейл будет при соеденении с csrss, повторное подключение невозможно.
     

    Вложения:

    • RPE.rar
      Размер файла:
      8,5 КБ
      Просмотров:
      574
  19. PaperMoon

    PaperMoon New Member

    Публикаций:
    0
    Регистрация:
    13 авг 2017
    Сообщения:
    16
    Я попробовал, отлично получилось с дллкой. А вот с PE не очень понятно можно ли грузануть экзешник, вроде LoadLibrary отрабатывает, бинарь обрабатывается Ldr* ф-циями, релоки отрабатывают, но при попытке на точку входа прыгнуть, падает на ЦРТ ф-циях. Это вообще возможно, бинарь загрузить данной техникой?
     
  20. PaperMoon

    PaperMoon New Member

    Публикаций:
    0
    Регистрация:
    13 авг 2017
    Сообщения:
    16
    Вру. Сейчас чекнул на минимальном фасмовском сепле Hello World x86, не обрабатываются импорты, секции не мапятся в вирт память, релоков тож нет, нифига короче не делается по сути. Попробую найти на чём зытыкается загрузчик, я так думаю что кроме отсутствия IMAGE_FILE_DLL 0x2000 в Characteristics ещё на чём-то