Разрешение импорта Windows PE SxS

Я сейчас пишу свою собственную версию загрузчика Windows (хотя и очень простую), и пока все идет неплохо. Однако я столкнулся с небольшой загвоздкой, когда дело доходит до рекурсивного обхода таблицы импорта для загруженного модуля.

Для большинства зависимостей все работает хорошо, и я могу просто рекурсивно загрузить модуль. Однако для некоторых зависимостей это просто нарушает целевой процесс. После дальнейшего расследования я понял, что это из-за параллельных сборок Windows. По сути, зависимость в загруженном PE была другой версией SxS модуля, используемого в целевом процессе.

В одном случае загружаемая мной библиотека DLL ссылалась на msvcr90.dll, но целевой процесс использовал более раннюю версию среды выполнения: msvcr71.dll.

Теперь загрузчик Windows может справиться с этим нормально, так что, очевидно, есть правильный способ сделать это. Я немного читал о контекстах активации, но они не помогли мне разобраться в проблеме.

Вызов LoadLibrary сам по себе не переводит dll в правильную версию.

LoadLibraryW(L"msvcr90.dll");

Просто возвращает 0. Кто-нибудь знает

а) Как определить, является ли импорт сборкой SxS

б) Как разрешить импорт в правильную версию SxS для процесса.

Я действительно не понимаю, как это сделать. Я знаю большую часть формата файлов PE из исследований, но я почти уверен, что SxS выходит за рамки структуры PE.

Если вам нужна дополнительная информация, просто прокомментируйте. У исполняемого файла нет внешнего манифеста, а его встроенный манифест не указывает версию среды выполнения. Однако он содержит копию msvcr71.dll в своем рабочем каталоге, если это кому-то вообще поможет.

Ваше здоровье.


person Jason Larke    schedule 24.06.2012    source источник
comment
Вы только что видите вершину айсберга, затопившего Титаник. Вам также придется иметь дело с манифестами, встроенными в качестве ресурса или предоставленными на диске, политиками издателя, перенаправлениями привязки, COM без реестра, динамической активацией через CreateActCtx, настраиваемыми путями поиска DLL, установленными с помощью SetDllDirectory. Документация паршивая.   -  person Hans Passant    schedule 24.06.2012
comment
@HansPassant Мне удалось заставить это работать. Вы были правы в том, что это была лишь верхушка айсберга, ха-ха. В конце концов, мне пришлось написать Resource Walker, чтобы найти внутренний манифест .dll (RT_MANIFEST). Затем мне пришлось написать заглушку сборки, которая обрабатывала все Activation Context вещи. Конечно, я мог бы просто написать его на C ++ и обернуть в .dll со статической связью (то есть без SxS), а затем использовать его для загрузки всех следующих библиотек, но это казалось излишним, поэтому я сделал это в сборке. По сути, я скармливаю функции сборки строку с необходимыми зависимостями, разделенную нулем ...   -  person Jason Larke    schedule 20.07.2012
comment
а также путь к манифесту (я извлек внутренний манифест во временный файл, CreateActCtx нужен путь к манифесту). Затем он создает контекст активации, просматривает список модулей, разделенных нулями, и вызывает GetModuleHandle для каждого из них. Если GetModuleHandle возвращает 0, он переходит к вызову LoadLibrary. Если по-прежнему 0, функция выходит из функции. Я знаю, что пропустил самую сложную часть, просто используя LoadLibrary в Activation Context, но я действительно хотел использовать свой собственный загрузчик только для основной dll, а не для ее зависимостей.   -  person Jason Larke    schedule 20.07.2012


Ответы (1)


Фактически, зависимости SxS выходят за рамки PE-структуры! Как вы знаете, таблицы импорта PE перечисляют имена зависимостей, но не их версии. При обработке этих таблиц зависимостей загрузчик также просматривает манифест зависимых от PE изображений. Если манифест документирует одну или несколько библиотек (например, msvcr90, advapi32, ....), загрузчик просматривает папку winsxs, чтобы найти зависимость. Вот статья, в которой обзор этой сборки и как собрать эту информацию на C ++.

person mox    schedule 24.06.2012
comment
На самом деле, вам не нужно создавать имя зависимости WinSxs самостоятельно. Все, что вам нужно сделать, это проверить с помощью CreateActCtx. Если загрузчик обнаружит эту зависимость, он построит для вас правильный путь (например, x86_microsoft-windows-msvcrt_31bf3856ad364e35_6.1.7601.17744_none_d33c3413fd4084d9)! - person mox; 24.06.2012
comment
С параллельными сборками (WinSxs) сложно работать. У меня возникла эта проблема во время реализации PeStudio (winitor.com) - person mox; 24.06.2012
comment
Спасибо за ссылку, она проясняет ситуацию. Единственное, как проверить, является ли данное имя импорта WinSxS? Я имею в виду, что в манифесте Microsoft.VC90.CRT связан с msvcr90.dll, но как эта ссылка установлена? Если я сначала прочитаю манифест для определения импорта, совместимого с WinSxS, как мне сопоставить их с конкретным именем импорта? - person Jason Larke; 24.06.2012
comment
Хорошо, я решил, что первым делом нужно составить список всех возможных импортов WinSxS, сначала просмотрев ресурс RT_MANIFEST изображения и разрешив все возможные зависимости WinSxS от него. Однако я изо всех сил пытаюсь понять, как преобразовать информацию манифеста в каталог SxS. Я не знаю, каков окончательный идентификатор по отношению к манифесту, то есть: C:\Windows\winsxs\x86_microsoft.vc90.crt_1fc8b3b9a1e18e3b_9.0.21022.8_none_bcb86ed6ac711f91 бит bcb86ed6ac711f91 не найден в манифесте, поэтому я не уверен, как это решить: / - person Jason Larke; 24.06.2012
comment
Задача загрузчика (с помощью WinSxS Manager) - определить реальный путь к библиотеке. Как упоминалось в статье, путь зависит от языка, токена открытого ключа и т. Д. Пусть загрузчик решит эту проблему за вас. Используйте Api контекста активации (msdn. microsoft.com/en-us/library/windows/desktop/) - person mox; 24.06.2012
comment
Суть этого вопроса в том, что я пишу свой собственный загрузчик, поэтому я не могу просто поручить загрузчику Windows сделать это за меня. - person Jason Larke; 24.06.2012
comment
в порядке. но вы можете использовать api контекста активации! ты пробовал это? - person mox; 24.06.2012
comment
Предположительно контекст активации должен быть получен из процесса, выполняющего загрузку. Учитывая, что я пишу это на C # и загружаюсь в удаленные процессы, я не думаю, что будет простой задачей получить контексты активации локального потока из удаленного процесса: / Я мог бы сделать это с некоторыми менее чем - желательная приостановка и перенаправление потока, но я бы предпочел просто отменить ресурсы для RT_MANIFEST и разрешить пути sxs оттуда. - person Jason Larke; 24.06.2012
comment
Вы сказали это. Я просто собираюсь проанализировать текущий ресурс RT_MANIFEST изображений (если он есть) и разрешить оттуда ссылки SxS. Если не сработает - очень плохо :) - person Jason Larke; 24.06.2012
comment
Отрицательный, сам процесс уже загрузил другую версию msvcr SxS. Есть ли способ проверить, загружена ли уже зависимость SxS? - person Jason Larke; 24.06.2012
comment
да, конечно, просто вызовите GetModuleHandle с именем зависимости SxS, если она уже загружена, вы получите ее дескриптор. - person mox; 24.06.2012
comment
Да, я неправильно понял управление версиями. В итоге мне просто пришлось делать несколько действительно хакерских и беспорядочных вещей, но теперь это работает: 3 - person Jason Larke; 24.06.2012