Получить адрес памяти загруженных сборок - PullRequest
0 голосов
/ 02 марта 2019

Мне нужно получить адрес памяти загруженных сборок в моем домене приложения.Когда сборки загружаются в приложение .Net, они полностью загружаются в основную память приложения.

Если мы ищем в памяти этот шаблон байтов:

byte[] pe_pattern = {
    0x4D, 0x5A, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
    0xFF, 0xFF
};

Мы находим, где и какой адрес они положили в память.Но мне нужно сделать это без сканирования памяти из-за производительности.

Я пытался получить загруженные сборки с помощью AppDomain.CurrentDomain.GetAssemblies() и получить их адрес как объекты с помощью сборщика мусора, а некоторые другие методы могутможно найти здесь: Адрес памяти объекта в C #

Но адрес, который я получаю , не является правильным адресом, У меня нет ошибок.

В C ++ есть способ сделать это, чтобы получить загруженные библиотеки DLL с помощью loadlibrary, но в C # я ничего не смог найти.

Как я могу получить адреса памяти загруженных сборок вмое приложение C #?

1 Ответ

0 голосов
/ 24 марта 2019

Я не уверен, ищете ли вы (1) виртуальный адрес сопоставленного файла сборки или (2) виртуальный адрес, на котором код JITed помещается после загрузки сборки.

Далее я рассмотрю простой случай, когда хост-процесс загружает несколько сборок.Код можно найти здесь .Давайте сосредоточимся на том, что происходит, когда загружается x64_Assembly.dll .

Если то, что мы ищем, определено выше (1) (виртуальный адрес сопоставленного файла в процессе ')адресное пространство), то это означает выделенную строку ниже, показанную в выходных данных VMMap.Это где ОС загружает файл, содержащий сборку.Я не знаю, как вы могли бы получить это программно из своего собственного приложения.

enter image description here

For (2), это виртуальный адрес, гдеJIT-код сборки найден, вы можете увидеть соответствующий адрес, если войдете в код с помощью отладчика:

enter image description here

As этот поток указывает, что сборка JITed помещается в кучу, которую вы можете легко проверить, снова используя VMMap.В моем случае адрес, показанный в отладчике, можно увидеть в блоке кучи с VMMap:

enter image description here

Так на какой адрес вы нацеливаетесь?

Позднее обновление : Вы можете использовать CLR MD для получения очень интересных данных.Взгляните на простой код ниже (взят из «Написание высокопроизводительного кода .NET» Бена Уотсона), который получает (1) и , возможно (2).Вы можете видеть, что адрес образа загруженной сборки в VMMap соответствует значению module.ImageBase, поэтому вы обязательно получите (1).Однако для (2) значение module.Address НЕ совпадает с переменной m_assembly, замеченной в отладчике в моем исходном ответе, поэтому один из них показывает что-то еще.Однако, если вы подумаете об этом, не весь код JITed одновременно - вместо этого CLR будет JIT компилировать методы так, как (и если) они вызываются.Поэтому я считаю, что виртуальные адреса, содержащиеся в 2 переменных, указывают на некоторую общую структуру, представляющую сборку.

enter image description here

Поскольку вы упомянули, у вас есть доступ к проверкесодержимое памяти, вы можете довольно быстро выяснить, какая из двух переменных представляет интерес для (2).

Как вы могли бы сделать это на практике?Я имею в виду создание проекта CLR MD, который просто выводит информацию, которую вы ищете ((1) и (2), в простой файл)), а затем запускает этот EXE-файл вашим основным кодом, чтобы он анализировал ваш процесс исборка он загружает и записывает данные.Когда процесс CLR MD завершается, ваш реальный код может получить информацию, записанную в файле, и работать с теми виртуальными адресами, которые он получил.В моем примере выше PID был просто жестко задан (я использовал Process Explorer, чтобы увидеть назначенный PID), но вы, вероятно, могли бы передать его в качестве аргумента в свой проект CLR MD.

Вы можете использовать ManageОпция NuGet Packages for Solution в Visual Studio для установки CLR MD и ее настройки для вашего конкретного проекта, а затем просто добавьте using Microsoft.Diagnostics.Runtime.

2 вещей, которые необходимо учитывать:

  • "битность" используемого вами кода CLR MD должна соответствовать анализируемому процессу (например, не создавать один для x86, а другой для x64; полные сведения о сборкахзагрузка по кросс-битности в статье, на которую я ранее ссылался )
  • , вам придется использовать AttachFlag.Passive в методе AttachToProcess, иначе ваш исходный код будет приостановлен на неопределенный срок,Я также проверил эту опцию после того, как сделал снимок экрана выше и успешно получил значения module.ImageBase и module.Address, плюс исходный код продолжал работать просто отлично.
...