XML-документация для FieldAttributes.HasFieldRVA
состояний (выделено мной):
Указывает, что поле имеет относительный виртуальный адрес (RVA). RVA - это местоположение тела метода в текущем изображении в качестве адреса относительно начала файла изображения, в котором оно находится.
Похоже, что это техника для быстрой инициализации массивов примитивных типов в поля статического массива путем помещения массива в его макет в памяти с определенным смещением в исполняемый образ.
RVA = 00003E98 говорит вам, что это за смещение. RuntimeHelpers::InitializeArray
- это метод internalcall
, который просто копирует биты. Строгий дизассемблер, такой как IDA или ILDASM, не сообщит вам значения.
Чтобы получить значения, у вас есть как минимум два три варианта.
1. Используйте лучший инструмент для работы
Кажется, IDA больше подходит для отладки и разборки собственного исполняемого файла. Его выходной сигнал IL аналогичен выходному сигналу ILDASM, который примерно настолько низок, насколько он получает.
ILSpy и аналогичные инструменты будут показывать значения инициализации. Вы должны просто скопировать объявление и инициализацию поля прямо из окна декомпиляции.
Посмотрите, как в .NET 4.7.2 инициализатор типа System.Char
инициализирует поле categoryForLatin1
. Представление IL почти идентично вашему примеру. Представление C # близко к тому, что вы увидите в исходном коде, за исключением того, что исходный код для System.Char
использует константы. Декомпиляторы не могут знать, какая константа использовалась в источнике для каждого значения, но с небольшим исследованием и интуицией, вы можете получить это самостоятельно.
На самом деле, если это полностью управляемая сборка, такой инструмент будет намного лучше для всей работы по обратному проектированию, потому что он даст вам вывод C #. Переводить IL в C # вручную может быть весело ... пока это не так.
2. Получить поле во время выполнения
Не запуская саму программу, вы можете спросить ее, каковы значения.
Создайте новое консольное приложение и добавьте ссылку на исполняемый файл. Получите объект FieldInfo
для рассматриваемого поля и затем вызовите GetValue(null)
для него. Затем выполните итерацию по возвращенному массиву и выведите значения, предпочтительно отформатированные, чтобы вы могли просто скопировать / вставить в ваш новый проект.
FieldInfo field = typeof(WindowsService.Program.DecryptFileToFile).GetField("<field name>", BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic);
byte[] array = (byte[])field.GetValue(null);
foreach (byte value in array)
{
Console.Writeline("0x{0:X2}", value);
}
Это предполагает, что я правильно понял структуру класса и что вложенный тип DecryptFileToFile
является открытым. Если это не так, вам нужно выполнить дополнительную работу по отражению, чтобы добраться до него.
3. Прочитайте исполняемый файл напрямую (опция бонуса)
Возможно, вы сможете посмотреть на это смещение в самом файле и посмотреть, что это за 16 байтов. IDA должна позволить вам перейти к этому смещению и просмотреть там данные. Я не знаю IDA, но это кажется достаточно простым средством для любого отладчика.
Честно говоря, я не совсем уверен в этом варианте, но я чувствовал, что был бы упущен, если бы не упомянул об этом. Если другие два варианта недоступны для вас и это дает значимые данные, моя шляпа уходит вам.
РЕДАКТИРОВАТЬ : Я попытался просмотреть смещение в файле на диске, а данных там не было. Это должно относиться к смещению, загруженному в память.
NEW 3. ILDASM дает дает вам байты
Может быть, МАР тоже. Вы просто должны знать, где искать. Директива .field
будет иметь метку в конце at I_xxxxxxxx
. Вот это System.Char::categoryForLatin1
:
.field static assembly initonly valuetype
'<PrivateImplementationDetails>'/'__StaticArrayInitTypeSize=256' B53A2C6DF21FC88B17AEFC40EB895B8D63210CDF
at I_004E49CC
Позже в файле вы увидите директиву .data
с той же меткой, определяющей необработанные байты:
.data cil I_004E49CC = bytearray (
0E 0E 0E 0E 0E 0E 0E 0E
// and so on for another 248 bytes
)