C windows assembly что это
По способу взаимодействия с другими сборками и приложениями сборки можно разделить на две категории: закрытые и разделяемые.
Закрытые сборки это обычные сборки приложения, которые мы создаем в Visual Studio. Например, при создании библиотеки классов dll создается закрытая сборка. Впоследствии эту закрытую сборку мы можем использовать, подключив ее к другому проекту. А чтобы подключить к другому проекту, эту сборку можно просто положить рядом с исполняемым файлом и добавить в проект ссылку на нее через Add Reference. И на одной машине может быть десяток приложений, которые используют разные копии одной и той же сборки.
Если мы захотим удалить приложение, мы можем также удалить и используемую им закрытую сборку, и это не скажется на работе других приложений на локальной машине.
Иначе обстоит дело с разделяемыми сборками. По умолчанию при создании проекта visual Studio уже добавляет в проект ссылки на ряд разделяемых сборок. Открыв узел References (Ссылки). Например, Microsoft.CSharp.dll, System.dll, System.Core.dll — это все разделяемые сборки.
Разделяемые сборки находятся в глобальном кэше сборок (Global Assembly Cache). Местоположение кэша сборок отличается в зависимости от версии .NET, установленной на локальной машине. До .NET 4.0 глобальный кэш находился в каталоге C:\Windows\assembly. Начиная же с версии .NET 4.0 кэш сборок размещается по пути C:\Windows\Microsoft.NET\assembly\GAC_MSIL
Строгое имя сборки
Чтобы поместить сборку в GAC (глобальный кэш), эта сборка должна обладать строгим именем. В состав строгого имени входят следующие компоненты:
- Имя сборки без расширения
- Номер версии. Благодаря разграничению по версии можно использовать разные версии одной и ой же сборки
- Открытый ключ
- Необязательное значение для культуры (при локализации сборки)
- Цифровая подпись, которая создается с помощью хэш-значения содержимого сборки и значения секретного ключа. Секретный ключ представляет собой файл с расширением *.snk.
Благодаря строгому имени гарантируется уникальность сборки в глобальном кэше.
Чтобы создать строгое имя, можно воспользоваться инструментарием, который имеется в Visual Studio. Допустим, мы создали проект по типу Class Library (Библиотека классов). И теперь мы хотим подписать сборку, которая будет компилироваться, строгим именем. Для этого нажмем в окне Solution Explorer (Обозреватель решений) на имя проекта правой кнопкой мыши и в появившемся меню выберем пункт Properties (Свойства). На вкладке свойств выберем пункт Signing:

Отметим флажок Sign the assembly (Подписать сборку), как показано на рисунке. И чтобы создать новый секретный ключ, выберем в выпадающем списке пункт New . После этого откроется окно настроек секретного ключа:

Дадим новому ключу какое-нибудь имя и нажмем ОК. После этого в структуре проекта можно будет увидеть файл ключа:

После задания сборке строгого имени ее можно добавлять в GAC. Для этого воспользуемся утилитой, которая идет в комплекте с .NET Framework, под названием gacutil.exe.
Откроем командную строку под администратором. Во-первых, найдем расположение утилиты gacutil.exe на локальной машине. У меня, например, она расположена в каталоге C:\Program Files\Microsoft SDKs\Windows\v8.0A\bin\NETFX 4.0 Tools. И вначале перейдем в этот каталог:
C:\Windows\system32>cd C:\Program Files\Microsoft SDKs\Windows\v8.0A\bin\NETFX 4.0 Tools
Теперь воспользуемся одной из команд данной утилиты. Наиболее используемые команды:
- -i имя_сборки — установка сборки в GAC
- -l — вывод всего списка сборок в GAC
- -u имя_сборки — удаление сборки из GAC
Теперь вводим в командной строке команду на добавление:
C:\Program Files\Microsoft SDKs\Windows\v8.0A\bin\NETFX 4.0 Tools>gacutil -i Полное_имя_сборки

Как видно, на рисунке, в моем случае полное имя сборки C:\Users\Eugene\Documents\Visual Studio 2012\Projects\Sharp\PersonLibrary\PersonLibrary\bin\Debug\PersonLibrary.dll. И если добавление прошло успешно, то командная строка отобразит:
Assembly successfully added to the cache
И после добавления в папке C:\Windows\Microsoft.NET\assembly\GAC_MSIL мы сможем найти добавленную сборку — для нее будет создан отдельный каталог, как и для остальных сборок, который будет носить краткое имя сборки.
Теперь мы можем использовать нашу сборку из GAC. Для этого создадим какой-нибудь проект и в окне Solution Exlplorer (Обозреватель решений) нажмем на узел Referenses (Ссылки). В появившемся меню выберем Add Reference. (Добавить ссылку):

В окне добавления ссылки на сборку нажмем внизу на кнопку Browse (Обзор) и найдем в GAC нашу сборку. После этого она будет добавлена в проект, и мы сможем использовать весь заложенный в ней функционал.
Добавление сборки в GAC
Несколько вопросов по теме. При добавлении сборки в GAC, происходит ли копирование сборки в Windows\assembly? Если происходит, то как ее потом найти? Через командную строку сборка добавляется, но в папке assembly она не появляется. Правильно ли я понимаю, что в Visual Studio при добавлении ссылки показывается список сборок в GAC? Если это так, то почему я не вижу там своей сборки? Добавлял так: gacutil /i mydll.dll Пишет: сборка успешно добавлена в кэш
Отслеживать
20.1k 6 6 золотых знаков 37 37 серебряных знаков 81 81 бронзовый знак
Подписанные сборки .Net
Задумался я тут над смыслом подписания компоновочных блоков .Net. Наверняка Вы тоже подписывали свои библиотеки, что бы установить их в GAC.
В ходе расследования мы научимся изменять подписанные сборки, не обладая исходниками и секретными ключами.
Приватные сборки
При подписании библиотеки (назначении строгого имени) открытый ключ записывается в манифест. Таким образом, что бы внести изменения в чужую подписанную библиотеку, нужно просто заменить публичный ключ на свой. Или, еще проще, сделать новую сборку с таким же именем и подписать на своем ключе.
При использовании библиотеки любой публичный ключ будет принят как доверенный.
Проведем следующий эксперимент. Создадим небольшую библиотечку.
namespace signedLib < public class sLib < public static int GetNumber() < return 1; >> >
Листинг 1. Библиотека signedLib.dll
Подпишем её и добавим к проекту консольного приложения:
namespace changeKey < class Program < static void Main(string[] args) < Console.WriteLine(signedLib.sLib.GetNumber()); Console.ReadLine(); >> >
Листинг 2. Консольное приложение changeKey.exe
Затем скомпилируем релиз проекта.
С помощью .NET Reflector и плагина Reflexil отредактируем IL код подписанной библиотеки (signedLib.dll), так что GetNumber() будет возвращать не «1», а «2». Консольное приложение не заметило подмены и вывело «2».
Вывод такой: подменить/изменить приватную сборку со строгим именем очень просто. Другие сборки ссылающиеся на измененную никак на это не реагируют, не смотря на то, что были скомпилированы с оригинальной.
Обращаю внимание что речь идет именно о приватных сборках, со сборками в GAC дело обстоит иначе.
Приватные это те которые не в GAC.
Сборки в GAC
Как мы только что убедились подписанные приватные компоновочные блоки можно легко модифицировать. При этом не обязательно обладать ни исходниками, ни секретным ключом, ни правами администратора.
Вносить изменения в сборки установленные в GAC не многим сложнее.
В случаи с приватными сборками не играет ни какой роли подписаны они или нет. Подпись не проверяется, а «полный идентификатор приватного компоновочного блока состоит из имени компоновочного блока и числового номера его версии» (из книги Э. Троелсена).
Сборки устанавливаемые в GAC должны иметь так называемое строгое имя. Сборка получает строгое имя как только вы её подписываете. Идентификаторы сборок в GAC дополняются параметрами публичного ключа, подписи проверяются.
- незаметно внести изменения не получится — подпись проверку не пройдет
- свой публичный ключ не подсунешь — идентификатор сборки изменится
Но не нужно быть криптографом что бы все же изменить библиотеку в GAC, а нужно обладать правами администратора и знать параметры утилиты sn.exe.
Страдальцы не имеющие студии вручную используют стандартную утилиту sn.exe для подписания компоновочных блоков.
Итак, возьмем проект уже знакомой библиотеки signedLib.dll (см. листинг 1). подпишем её и установим в GAC.
gacutil.exe /i D:\projects\changeKey\signedLib\bin\Release\signedLib.dll
Добавим референс к консольному приложению changeKey.exe (см. листинг 2). Компилируем релиз, убеждаемся что в папке с программой нет файла signedLib.dll (значит сборка будет загружена из GAC). Запускаем changeKey.exe — приложение показывает «1».
С этого момента воображаем себя атакующими — у нас нет исходников, нет секретного ключа. Но нам надо что бы метод GetNumber() возвращал не 1 а 2.
Структуру файлов ниже C:\Windows\assembly проводник windows не показывает. Создадим псевдодиск на который будет проецироваться нужный каталог:
subst b: C:\Windows\assembly
В проводнике появился диск B.
рис. 1. Папки ниже C:\Windows\assembly
.Net сборки попадают в папку GAC_MSIL, находим нужную папку (её название совпадает с названием .dll файла). Внутри будет еще одна папка, а в ней наконец signedLib.dll. Копируем signedLib.dll на рабочий стол.
С помощью замечательной программы .NET Reflector и не менее замечательного плагина Reflexil будем редактировать библиотеку. Предварительно перепишем токен публичного ключа и его значение в блокнот (они нам пригодятся позже). Как мы уже знаем публичный ключ записан в самой сборке, теперь в этом можно окончательно убедиться.
рис. 2. Параметры публичного ключа
После правки IL кода и сохранения изменений, программа сообщит о том что цифровая подпись нарушена и предложит варианты дальнейших действий:
Нажимаем «Remove Strong Name» — удалить цифровую подпись. Закрываем сборку.
Теоретически закрывать сборку нет необходимости и нам должен подойти вариант «Register it for verification skipping». Однако у меня эта операция заканчивается ошибкой. К тому же в обучающих целях лучше проделать все операции вручную.
- измененная, не подписанная dll библиотека;
- публичный ключ оригинальной библиотеки.
Осталось установить её в GAC. Для этого воспользуемся механизмом отложенной подписи. Если сборка содержит информацию о публичном ключе, но не имеет цифровой подписи — говорят что она имеет отложенную подпись. Придумал это какой-то извращенный мозг из микрософт «для тестирования».
Сделать такую сборку с помощью .NET Reflector не составляет никакой сложности — нужно заполнить соответствующие поля, они выделены желтым на рис.2. (Помните мы копировали их значения в блокнот?). И не забудьте поставить галочку «HasPublicKey».
В теории публичный ключ нужно извлекать из секретного с помощью утилиты sn.exe, и потом с помощью неё же создавать отложенную подпись.
Мы получили сборку которая называется так же как оригинальная, имеет такую же версию и такой же публичный ключ. Т.е. если, её установить в GAC она получит точно такой же идентификатор как и оригинальная (см. начало начало статьи). Как я писал выше, по умолчанию у сборок в GAC проверяется подпись, однако проверку подписи можно отключить — опять же «для тестирования».
Что бы отключить проверку подписи dll на данном компьютере нужно воспользоваться sn.exe
sn -Vr C:\Users\Alex\Desktop\signedLib.dll
Удаляем оригинальную сборку из GAC:
gacutil /u signedLib,Version=1.0.0.0,Culture=neutral,PublicKeyToken=2b1b71846e76146e
gacutil /i C:\Users\Alex\Desktop\signedLib.dll
Радуемся, глядя на выведенную gacutil.exe надпись:
Assembly successfully added to the cache
Вот мы и добились желаемого — изменили библиотеку установленную в GAC. Что бы еще раз порадоваться (и проверить результат) запускаем наше приложение changeKey.exe, которое в начале статьи выводило 1, теперь он покажет 2.
Подведем итог
Публичный ключ записан в самой сборке (точнее в манифесте);
В случаи с приватными сборками подписи не проверяются.
- Сделать копию нужного dll файла из C:\Windows\assembly (воспользовавшись командой subst)
- Извлечь из сборки публичный ключ
- Модифицировать IL код сборки и удалить цифровую подпись
- Добавить к измененному файлу публичный ключ, полученный на шаге 2 (создадим отложенную подпись)
- Отменить проверку цифровой подписи для модифицированной сборки на данном компьютере
- Удалить оригинальную сборку из GAC
- Установить модифицированную сборку.
Для шагов 5, 6, 7 нужно обладать правами администратора.
What’s up with the C:\Windows\Assembly folder?
If you go to the C:\Windows\Assembly folder on windows 10 (and possibly earlier versions as well) file explorer looks all weird. What’s going on?
As you can see in the image, the menu at the top is different, the path is gone, and the name column says «assembly name». In addition, the context menu is different, and the files cannot be opened. Viewing the folder in powershell gives a completely different list of contents (pictured below) 
asked Nov 2, 2022 at 0:30
135 9 9 bronze badges
Nov 2, 2022 at 0:46
@Ramhound the menus at the top are missing, the context menu is different, and the files cannot be opened. (adding these details to question)
Nov 2, 2022 at 0:49
Try the simple repair (DISM / SFC) and then we will go from there. . (1) Open cmd.exe with Run as Administrator. (2) DISM.exe /Online /Cleanup-image /StartComponentCleanup (3) DISM.exe /Online /Cleanup-Image /Restorehealth (4) SFC /SCANNOW (5) Restart when all the above is complete and test.
Nov 2, 2022 at 0:58
1 Answer 1
You’re seeing specialized view of the folder contents — similar to the Fonts and Recent Items folders, which also have specialized views.
The folders all have a desktop.ini file (most commonly associated with specifying custom icons and language-specific display names) with a value named CLSID in the [.ShellClassInfo] :
Assembly:
[.ShellClassInfo] CLSID=
Fonts:
[.ShellClassInfo] CLSID=
Recent Items:
[.ShellClassInfo] LocalizedResourceName=@%SystemRoot%\system32\shell32.dll,-21797 InfoTip=@shell32,dll,-12692 IconResource=%SystemRoot%\system32\imageres.dll,-117 CLSID=
The folders must have their ReadOnly attribute set for the desktop.ini file to be displayed, so if you want to see the actual files in Explorer, clear the folder’s ReadOnly attribute in PowerShell using:
$dir = Get-Item c:\Windows\Assembly $dir.Attributes = $dir.Attributes -band -bnot [System.IO.FileAttributes]::ReadOnly
and re-set it using:
$dir = Get-Item c:\Windows\Assembly $dir.Attributes = $dir.Attributes -bor [System.IO.FileAttributes]::ReadOnly