mono cecil что это

Mono.Cecil: делаем свой «компилятор»

Одной из самых роскошных тем для программистов, балующихся изобретением велосипедов, является написание собственных языков, интерпретаторов и компиляторов. Действительно, программа, способная создавать или исполнять другие программы, инстинктивно вселяет благоговейный трепет в сердца кодеров — потому что сложно, объемно, но безумно увлекательно.

Большинство начинают с собственных интерпретаторов, которые представляют собой в общем виде огромный свитч команд в цикле. Интересно, вольготно, но муторно и весьма медленно. Хочется чего-то более шустрого, чтобы JIT’ить умело и, желательно, само следило за памятью.

mono cecil что это

Программа будет требовать имя, и выводить в консоли Hello, %username%.

Mono.Cecil — это библиотека, позволяющая работать со сборкой как с массивом байтов. C ее помощью можно как создавать свои собственные сборки, так и ковыряться и модифицировать уже существующие. Она предоставляет широкий спектр классов, которыми (обычно) удобно пользоваться.

Предмет беседы

Вот, собственно, готовый код (без описания класса, формы и всего прочего, кроме собственно метода-генератора):

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

Что же там творится?

Написанная на С#, та же самая программа выглядела бы вот так (описание класса я опущу):

Для этого мы берем две строки, первая — константа, вторая определяется на этапе компиляции и тоже становится константой, кладем их в стек. String.Concat складывает эти строки и оставляет на вершине стека результат, который берется Console.WriteLine и выводится на экран.

После этого, чтобы программа не закрылась прежде, чем мы успеем что-то прочитать, требуем Console.ReadLine() — а поскольку оно возвращает считанную строку, которая нам не нужна, выкидываем ее из стека, после чего с чувством выполненного долга покидаем уже ставшую почти родной функцию Main.

О байткоде

LDSTR загружает в стек строку. Очевидно, в качестве параметра ему требуется строка. По сути, «загружает строку в стек» означает, что не сама строка в стек кладется, а только указатель на то место в памяти, где она располагается — но для нас, как для программистом IL, это не важно. Важно только то, что следующие команды смогут ее оттуда взять и использовать.

CALL, как можно догадаться из названия, вызывает метод. Для этого ему необходимо передать ссылку на объект с описанием этого самого метода, который предварительно нужно импортировать. Для импорта следует «найти» метод в типе, передав имя и список типов его параметров в виде массива — вот почему запись такая ужасная. По-хорошему, тут нужно было бы написать какой-нибудь обработчик, который преобразует строку вида «String.Concat(string, string)» вот в этот ужас — можете попробовать этим заняться.

POP выкидывает из стека верхний элемент. Ничего особенного. Нужен нам потому, что Console.ReadLine() возвращает значение, а наша функция — void, следовательно мы не можем там его оставить и должны очистить.

RET — от слова return, производит выход из текущей функции. Обязательно должна быть в конце каждой функции, а может быть и не одна — в зависимости от того, сколько у вас точек выхода из нее.

Результаты работы

В конце концов, скомпилировав и запустив программу, введя туда свое имя и нажав увесистый кнопарь Compile, мы получаем в той же папке миниатюрный бинарничек greeter.exe, который весит ровно 2048 байт.

Запускаем его, и вуаля!
mono cecil что это

Источник

Mono.Cecil FAQ

Now that I have the library, how do I use it?

Here is an example of an application browsing all the types contained in a managed assembly:

We can see the result on the output console:

This code creates the Mono.Cecil.AssemblyDefinition which corresponds to the MyLibrary assembly. You can also get one of the ModuleDefinitions (AssemblyDefinition.Modules property) which are contained into an assembly. In general, you have to work with that one named MainModule (AssemblyDefinition.MainModule property)

What are the entities contained in an assembly which Cecil provides an object model for?

Here is a simplified class diagram of the main entities Cecil is dealing with and their relationships all together:

mono cecil что это

An AssemblyDefinition is created by the static method ReadAssembly which works with an assembly file. Each of them contains a ModuleDefinitions collection. In general, you have to work with a main ModuleDefinition (you can get it by using the MainModule property).

A ModuleDefinition contains TypeDefinitions. Each of them contains collections of:

You can also get the constructors of a type by using the Constructors property. A constructor is a MethodDefinition. A PropertyDefinition owns two MethodDefinitions which corresponds to the Get and the Set.

A MethodDefinition contains a MethodBody. You can get all the CIL instructions of a MethodDefinition by using the CilWorker property. In addition, the MethodDefinition contains an Instructions property.

mono cecil что это

I would like to add some tracing functionality to an assembly I can’t debug, is it possible using Cecil?

Yes it is. This technique is named AOP. Here is a simple example on how to do it with Cecil. You’ll have to learn CIL if you want to make some more advanced stuff.

We take for this example the same assembly MyLibrary as previously. Instead of writing the name of each type, we will insert the following code into each methods of each type of the assembly:

The first thing to do is getting the System.Reflection.MethodInfo which correspond to the Console.WriteLine (string value) method.

Next, you have to get all methods of each type of the MyLibrary assembly in order to insert the MSIL instructions.

The last thing to do is saving the assembly which contains the modifying types:

After executing this code, you can use the modifying assembly in a new Console project. You have to add a reference to this assembly.

This code produces also this result:

You can download the examples used in this FAQ here

Источник

Русские Блоги

Используйте Mono.Cecil для динамического изменения сборки для взлома коммерческих компонентов (только для исследований и изучения)

Прежде всего, позвольте предположить, что есть такая коммерческая составляющая, которая удовлетворяет следующим условиям:

1. Обфусцирован код сборки

2. Сборка имеет строгое название и подписано.

3. Интерфейс пользовательского интерфейса сборки дополнен информацией об авторских правах, например водяными знаками и т. Д.

Здесь я имею в виду компонент входа в систему в статье, написанной ранее (http://www.cnblogs.com/liping13599168/archive/2010/05/07/1729357.html) и преобразовать его в компонент Silverlight, структура проекта показана на рисунке:

mono cecil что это

Среди них библиотека классов BusinessComponent используется в качестве выбранного «коммерческого компонента». Здесь класс CopyRight записывается как информация для печати водяного знака:

mono cecil что это

Вы можете увидеть эффект информации об авторских правах, прикрепленной к компоненту

Затем, чтобы строго указать и подписать BusinessComponent, щелкните проект правой кнопкой мыши и установите следующие параметры:

mono cecil что это

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

Для чего именно используется этот snk? Через некоторое время это увидят все.

Наконец, я воспользуюсь инструментом обфускации Dotfuscator, чтобы скрыть код BusinessComponent.dll.

mono cecil что это

Поскольку здесь я использую старую версию Dotfuscator 4.2, она не поддерживает путаницу сборки Sliverlight. Заинтересованные друзья могут скачать и попробовать ее самостоятельно. Официальный адрес:http://www.preemptive.com

Итак, здесь был разработан прототип коммерческого компонента BusinessComponent. Теперь возьмите в руки инструмент Mono.Cecil, чтобы изменить его.

Во-первых, официальная загрузка проекта mono.cecil, откройте проект для его активной компиляции, вы можете получить Mono.Cecil.dll в каталоге Silverlight_Release

Затем представьте его проекту, добавьте кнопку на страницу и щелкните, чтобы запустить программу события:

Среди них module получает модуль Module в сборке, а module.Types может получать все типы в сборке:

mono cecil что это

Выберите имя типа Type как Copyright, и все методы, полученные этим типом, могут быть получены через type.

mono cecil что это

Выберите имя метода как SetRightInfo, method.Body.Instructions может получить информацию о вызове стека IL в методе:

mono cecil что это

Таким способом можно удалить информацию о водяных знаках, это очень просто 🙂

Последняя строка module.Write («C: \\ BusinessComponent.dll»); предназначена для перезаписи измененной сборки в новую сборку;

Запустите программу, и вы получите новую сборку BusinessComponent на диске C.

Теперь я повторно представляю новую сборку, чтобы посмотреть, будет ли удалена информация о водяных знаках, перекомпилировать и найти ошибку компиляции:

mono cecil что это

Потом переподписываюсь через sn.exe:

mono cecil что это

Показывает, что открытый ключ не спарен. Это очевидно, потому что business.snk раньше задавался вручную с помощью метки Sign в VS. Он использовал открытый ключ этого файла, а mykey.snk использовал бы свой собственный открытый ключ.

Поскольку он не может быть взломан, я изменю его подпись и буду использовать свои собственные открытый и закрытый ключи для подписи, и так уж получилось, что Mono.Cecil может удовлетворить ваши потребности.

Откройте окно командной строки VS2010 и введите на диске C:

Таким образом, случайным образом генерируется файл RSA, содержащий открытый ключ и закрытый ключ, а затем, чтобы извлечь его открытый ключ, введите:

Вы можете получить данные открытого ключа, такие как publicKey и publicKeyToken

mono cecil что это

Получите две строки строк, скопируйте их все и продолжайте добавлять код кнопки прямо сейчас:

Перекомпилируйте и выполните, информация об открытом ключе скомпилирована, а на диске C также создается новая сборка BusinessComponent.dll.

В это время не спешите вводить сборку, сначала повторно подпишите новую сборку в частном порядке и введите команду:

mono cecil что это

Хорошо, сейчас его можно повторно ввести, а затем перекомпилировать код в это время:

mono cecil что это

Теперь запустите программу (обратите внимание, что вы должны переключить программу SilverlightApp в режим OOB, прежде чем вы сможете изменить сборку):

Источник

Инъекции MSIL кода в стороннюю сборку при помощи Mono.Cecil. Реализация принципов АОП в NET

Введение

Mono.Cecil

Качественно иной подход предлагает бесплатная библиотека с открытым исходным кодом Mono.Cecil. Главное отличие подхода Mono.Cecil от подхода Reflection в том, что данная библиотка работает с NET сборкой как с потоком байт. При загрузке сборки, Mono.Cecil разбирает PE заголовок, CLR заголовок, MSIL код классов и методов и т.д. работая напрямую с потоком байтов, представляющим сборку. Таким образом, с помощью данной библиотеки можно как угодно (в пределах предусмотренного) изменять имеющуюся сборку.

Скачать Mono.Cecil можно тут.

Сразу замечу, что модификация сторонней сборки, подписанной строгим именем, приведет к сбросу подписи со всеми вытекающими последствиями. После модификации сборку можно переподписать (тем же ключом, если у вас он есть, либо другим — если, например, необходимо положить сборку в GAC).

Небольшой пример

Сразу рассмотрим на примере использование возможностей Mono.Cecil. Предположим, у нас есть сторонняя сборка некоторого консольного приложения без исходного кода, в котором есть тип Program. У нас нет доступа к исходному коду, но мы хотим, чтобы данное приложение при вызове каждого метода выводило, на консоль некоторое сообщение. Для этого напишем собственное консольное приложение. В качестве аргумента при запуске будем передавать путь к целевому приложению:

При передаче пути к сторонней сборке нашему консольному приложению, оно добавит в начало каждого метода IL код, выводящий на консоль сообщение «Inject!», после чего сохранит измененную сборку. При запуске измененной сборки, каждый метод будет писать в консоль «Inject!».

Остановимся подробнее на вышеприведенном коде. Как известно, NET поддерживает множество языков программирования. Достигается это за счет того, что любой код на любом языке программирования компилируется в CIL — Common Intermediate Language — промежуточный язык. Почему промежуточный? Потому что после, код на CIL преобразуется в инструкции соответствующего процессора. Таким образом, код на любых языках компилируется в примерно одинаковый код CIL, засчет чего вы можете использовать, например, сборку на VB в вашем проекте на C#.

Таким образом, каждая сборка условно говоря представляет собой набор метаданных (которые, например, использует Reflection), и набор инструкций на CIL.

Я не буду останавливаться подробно на описании CIL, поскольку это не является темой данной статьи. Я ограничусь лишь тем, что будет важно для дальнейшего, а именно — некоторыми особенностями CIL-инструкций. Информацию о представлении метаданных и других инструкциях вы всегда можете найти в интернете.

Для начала рассмотрим часть кода из примера выше:

Поскольку Mono.Cecil воспринимает сборку как набор инструкций (байтов), то мы можем менять ее содержимое без каких либо ограничений. После добавления CIL кода мы сохраняем ее (как набор байтов) и получаем модифицированную сборку.

Реальное примение кодогенерации для реализации аспектно-ориентированного подхода

Рассмотрим применение указанного выше подхода к собственным сборкам. Очень часто нам хочется выполнять некоторый код при входе или выходе из какого-либо метода, причем иметь доступ к некоторым данным, описывающим метод, либо его контекст. Простейший пример — логгер. Если мы хотим записывать в лог вход и выход из каждого метода, то писать однообразный код в начале и конце каждого метода может быть весьма утомительно. Также, на мой взгляд, это несколько загрязняет код. Кроме того, мы не можем получить доступ к параметрам метода на стеке автоматически, и если мы хотим также записывать состояние параметров на входе — придется делать это вручную. Вторая известная проблема — это реализация INotifyPropertyChanged, который приходится прописывать каждому свойству вручную.

Рассмотрим другой подход. Для его тестирования создадим новое консольное приложение. Добавим класс:

Для экспериментов создадим два консольных приложения. Первое будет содержать определение атрибута и все методы, необходимые для инъекции кода в сторонние приложения. Второе приложение будет тестовым. Рассмотрим сначала короткий код тестового приложения:

Это простое консольное приложение, которое вызывает метод MethodToChange с параметром text равным Test. Данный метод помечен атрибутом TestMethodInterceptionAttribute, унаследованным от MethodInterceptionAttribute. OnEnter переопределен для вывода на консоль информации о любых помеченных данным атрибутом методах. Без предварительно обработки, данное приложение при запуске вызовет Console.ReadLine и завершит работу.

Продолжим рассмотрение главного приложения (тоже консольного). Для демонстрации примера MSIL кода и для помощи в дальнейшей разработке напишем следующий вспомогательный метод:

Данный метод считывает имеющийся MSIL код у какого-либо метода сборки (или у всех) и записывает его в файл dump.txt. Чем это может быть полезно? Предположим, мы знаем, какой конкретно код мы хотим добавить в стороннюю сборку, но не хотим писать весь MSIL код с нуля. Тогда мы запишем этот код на C# в какой-либо свой метод и сделаем его дамп. После чего будет гораздо проще писать MSIL с помощью Mono.Cecil, уже имея готовый пример того, как он будет выглядеть (конечно, для просмотра MSIL кода сборок можно применять и другие, более удобные методы).

Рассмотрим, что же мы хотим получить в начале каждого метода (в виде С#):

Часть дампа этого кода на MSIL:

IL_0000: nop
IL_0001: call System.Reflection.MethodBase System.Reflection.MethodBase::GetCurrentMethod()
IL_0006: ldtoken EmitExperiments.MethodInterceptionAttribute
IL_000b: call System.Type System.Type::GetTypeFromHandle(System.RuntimeTypeHandle)
IL_0010: call System.Attribute System.Attribute::GetCustomAttribute(System.Reflection.MemberInfo,System.Type)
IL_0015: castclass EmitExperiments.MethodInterceptionAttribute
IL_001a: stloc V_1
IL_001e: ldloc V_1
IL_0022: callvirt System.Void EmitExperiments.MethodInterceptionAttribute::OnEnter()
.

Далее я просто приведу полный код метода InjectToAssembly (с подробными комментариями), который добавит ко всем методам с MethodInterceptionAttribute указанной сборки необходимый код:

Не забудем также про метод Main нашего консольного приложения:

Что и требовалось. Теперь, каждый метод, помеченный TestMethodInterception, будет перехвачен и каждый его вызов будет обработан без написания большого количества повторяющегося кода. Для автоматизации процесса, можно использовать Post-Build события в VS, таким образом, чтобы после успешного построения какого-либо проекта автоматически обрабатывать готовую сборку и внедрять код на основе атрибутов. Также можно создать атрибуты уровня класса или сборки, чтобы внедрить код сразу во все методы класса или сборки.

Использование АОП позволяет писать чистый и легко поддерживаемый код, в основном засчет того, что большая часть кода генерируется автоматически на основе аспектов.

Источник

Как работать с Mono.Cecil?

Mono.Cecil: нужна документация
Собственно сабж. Нужна норм. документация, в инете ничего нормального не нашел 🙁

Merging(Объединение) сборок при помщи Mono.Cecil
Вот сделал: using System; using System.Collections.Generic; using System.Linq; using.

Как заставить Mono работать с GIT
Я не могу разобраться, как заставить его работать с гитом! При создании репозитория я нигде не могу.

Сорри что так долго, инет еле ползёт 🙁

А можно пример кода.

Добавлено через 54 секунды
Вот делаю так:

Добавлено через 5 минут
А есть какой-нибудь алгоритм, чтобы ещё и C# код получать??

Добавлено через 2 часа 32 минуты
Видимо я поторопился в выводами.

Добавлено через 4 минуты

Добавлено через 43 минуты
SSTREGG, Немного модифицировал код:

Добавлено через 8 минут
SSTREGG, огромнейшее спасибо, но сорри у меня пропала возможность говорить спасибки.

Добавлено через 14 минут
Delog, Ох, легко сказать, тяжело сделать

Вложения

mono cecil что этоImages.ZIP (11.7 Кб, 23 просмотров)

Вложения

mono cecil что этоMonoUse.rar (332.9 Кб, 42 просмотров)

Создал отдельную тему, посвящённую транслятору MSIL-C#. Только вот интересно, как сделать это транслятор

Вложения

mono cecil что этоMonoUse.rar (724.4 Кб, 52 просмотров)

Спасибо, но как получить форматированный текст(с пробелами там и выделением цветами).

Добавлено через 4 часа 3 минуты
А как получить исходный код метода, который нажали в TreeView. С реплейсом не получилось. Я получаю полный путь, но не получается получить код не всей сборки, а отдельного кусочка, например метода.

Добавлено через 14 часов 40 минут
Не получается получить ресурсы. Делаю так:

Что интересно я не так делаю?

Добавлено через 3 часа 22 минуты
А нельзя ли написать программу, которая удаляет неиспользующиеся поля, классы, константы т.е. проще говоря программу, которая занималась бы сборкой мусора из других программ.

Добавлено через 47 минут
SSTREGG, а можно пример кода, где читается сборка и в неё что-то записывается(неважно что).

Будет ли работать приложение, скомпилированное под Mono в Linux, в Windows
К примеру, я скомпировал простую форму GTK# в monodevelop (.net framework выбрал 2). Она будет.

Как запустить код в mono?
подскажыте мне как работать с mono 2.0. Например есть у меня код using System; class.

Как поставить Mono на Windows
Опишите пожалуйста кто делал,как?И какие инструменты нужны?

Источник

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *