PE Loader и TLS

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

  1. jeer0

    jeer0 New Member

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

    Indy_ Well-Known Member

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

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

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

    Indy_ Well-Known Member

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

    jeer0 New Member

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

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

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

    rmn Well-Known Member

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

    Indy_ Well-Known Member

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

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

    jeer0,

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

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

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

    https://yadi.sk/d/vRgDzkySrRowe

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

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

    jeer0 New Member

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

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

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

    Indy_ Well-Known Member

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

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

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

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

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

    jeer0 New Member

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

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

    Indy_ Well-Known Member

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

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

    superakira Active Member

    Публикаций:
    0
    Регистрация:
    2 июн 2008
    Сообщения:
    326
    Indy_, почитал твой код. красивое решение. хотел еще раз уточнить - такая загрузка решает проблему safeseh (просто из твоего поста понятно что траблы есть =))? те валидация хэндлера норм работает при такой загрузке? ибо сейчас это жуткие костыли - искать по сигнатурам функи ...
    Пробовать пока не хочу - время мало, но если ты скажешь, что бобрит, то думаю переведу на что-то высокоуровневое, мне надо и 64 бита.
    и как и было сказано - хочется свести к минимому эмуляцию загрузчика - он и так есть) в андоках утопать желания и времени нету.

    Заранее спасибо.
     
    PaperMoon и Indy_ нравится это.
  12. Indy_

    Indy_ Well-Known Member

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

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

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

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

    Indy_ Well-Known Member

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

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

    Indy_ Well-Known Member

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

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

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

    superakira Active Member

    Публикаций:
    0
    Регистрация:
    2 июн 2008
    Сообщения:
    326
    Indy_, короче я запилил.
    ты чуть поленился, в том плане, что мало сервисов трогаешь, но ты работаешь там с ноундлл, так что для филтрации и твоих вариантов хватает, в моем случае я иду по цепочке для вылавливания хэндла - думаю ты понял о чем я, мне лень расписывать. в любом случае - результат более чем норм. 32/64. все саппортит (тлсы сепшени итд), те тяжелая дллка с плюсовым рантаймом взлетела на ура. без костылей и прочего.
    thnx)
     
    Indy_ нравится это.
  16. Indy_

    Indy_ Well-Known Member

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

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

    superakira Active Member

    Публикаций:
    0
    Регистрация:
    2 июн 2008
    Сообщения:
    326
    Indy_, рановато.
    На 7 все норм. На 8 тоже. На 8.1 не смотрел. На 10 есть траблы. Те работает, но есть процессы, которые возвращают Status_bad_parametr после загрузки длл. Те подмена прошла проекции, но потом проверка чекакет какая-то. Это вот буду копать.
    На других процессах норм. Причем! Меня жутко порадовало! Упало в дллке подмененной, и как обычно винда предлагает отладить. Так как длл была с дебажно инфой, то прям податачилось и наложило сорцы... Я прифигел.

    Но вот со статусом пока буду смотреть. Это 64 битный процесс.

    Если есть мысли - дай знать. С меня сорцы.
     
  18. Indy_

    Indy_ Well-Known Member

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

    superakira Active Member

    Публикаций:
    0
    Регистрация:
    2 июн 2008
    Сообщения:
    326
    Грубо говоря так. В твоем коде после вызлва LdrLoadDll вываливается со статусом по параметру. Хз что там тебе понятно) В общем забей. Я просто отписал - малоли кто будет тоже копать.
     
  20. Indy_

    Indy_ Well-Known Member

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

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

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

    :sarcastic_hand: