Как я могу рассчитать смещение файла виртуального адреса памяти таблицы экспорта? - PullRequest
1 голос
/ 07 марта 2020

Итак, я пытался прочитать DLL-файл, все было хорошо, пока я не дошел до дополнительных каталогов данных заголовка, в частности его первого члена, таблицы экспорта.

Моя проблема в том, что я не могу двигаться смещение моего считывателя, потому что виртуальный адресный элемент основан на памяти VA, а мой читатель основан на смещении файла. Может помочь визуальный пример:

Как видите, загруженный виртуальный адрес, который этот просмотрщик PE читает по адресу таблицы экспорта из каталога данных (необязательный заголовок), является значение 0x00002630 (теперь будем называть его hex1).

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

Адрес, который он перенаправляет мне, является 0x00001a30 (давайте теперь будем называть его hex2).

Я провел несколько тестов самостоятельно, например, разделив hex1 на 8, потому что я думал, что это может быть переход от выравнивания памяти, равного 4096, и выравнивания файла, равного 512, но он не дал мне тот же результат, что и hex2. Я также сделал несколько странных вещей, чтобы попытаться получить эту формулу, но это дало мне еще более странные результаты.

Итак, мой вопрос был бы, как я могу получить / рассчитать смещение этого файла (hex2), если я только знать смещение памяти в каталоге данных (hex1)?

1 Ответ

1 голос
/ 08 апреля 2020

Предполагая, что вы используете MSV C C / C ++, вам сначала нужно найти массив структур IMAGE_SECTION_HEADER после опционального заголовка. В SDK есть макрос IMAGE_FIRST_SECTION (pNtHeaders), в котором вы просто передаете указатель вашего PE-заголовка, чтобы облегчить этот процесс. Он просто пропускает необязательный заголовок в памяти, где начинаются заголовки разделов. Этот макрос также будет работать как с 32-битными, так и с 64-битными Windows PE файлами.

Получив адрес массива IMAGE_SECTION_HEADER, вы проведете oop через структуры вплоть до FileHeader.NumberOfSections, используя указатель математика. Каждая из структур описывает относительный запуск адреса памяти (VirtualAddress) для каждого из названных разделов PE вместе со смещением файла (PointerToRawData) к этому разделу в файле, который вы загрузили.

Размер раздел В этом файле находится SizeOfRawData. Теперь у вас есть все, что вам нужно для преобразования любого заданного значения RVA в смещение файла. Сначала проверьте каждый виртуальный адрес IMAGE_SECTION_HEADER с помощью RVA, который вы ищете. Т.е.:

if (uRva >= pSect->VirtualAddress && (uRva < (pSect->VirtualAddress + pSect->SizeOfRawData))
{
    //found
}

Если вы найдете соответствующий раздел, вычтите VirtualAddress из поискового RVA, затем добавьте смещение PointerToRawData:

uFileOffset = uRva - pSect->VirtualAddress + pSect->PointerToRawData

Это приведет к смещению из начало файла, соответствующего этому RVA. На этом этапе вы перевели RVA в смещение файла.

ПРИМЕЧАНИЕ. Из-за заполнения, неправильных файлов PE и т. Д. c. Вы можете обнаружить, что не все RVA будут сопоставлены с местоположением в файле по адресу в какой момент вы можете отобразить сообщение об ошибке.

...