Таблица импорта (IT) vs таблица импорта адресов (IAT)

Я пытался проанализировать / отобразить информацию в таблице адресов импорта (IAT) процесса после его загрузки и запуска. Я понимаю, что вызовы API в программах переходят к соответствующей точке в IAT, которая затем переходит к фактической функции в загруженных DLL.

правильно ли, что IAT можно найти, прочитав заголовок PE и следуя OptionalHeader.DataDirectory [1] указатель на массив IMAGE_IMPORT_DESCRIPTORs. Затем после FirstThunk указатели. Тогда как OriginalFirstThunk указатели здесь, дадут вам исходную таблицу импорта (IT)?

Я также попытался следовать за OptionalHeader.Указатель DataDirectory[12] в заголовке PE, но это было еще менее успешным.

Я тестировал это, пытаясь разобрать эту структуру для блокнота.exe (32bit), используя ReadProcessMemory из другого процесса.

вот грубый C-psuedocode для того, что я делать:

char buf[128];

// get first import descriptor
readMemory(&import, procImgBase + DataDirectory[1].VirtualAddress, sizeof(IMAGE_IMPORT_DESCRIPTOR));

// get dll name 
readMemory(buf, import.Name + procImgBase, 127);
printf("libname: %sn", buf);

// get first function name
DWORD iltAddress = 0;
readMemory(&iltAddress, import.FirstThunk + procImgBase, 4);
readMemory(buf, iltAddress + procImgBase, 127);
printf("fname: %sn", libName + 2); // <-- the +2 for the 2byte 'hint' of import lookup table entries

Если, с 3-й по последнюю строку, я заменяю его на import.OriginalFirstThunk вместо FirstThunk, он будет печатать все, как ожидалось. Я должен что-то упустить концептуально, и поэтому мне было интересно, может ли кто-нибудь прояснить, что это для меня?

большое спасибо!

2 ответов


похоже, что вы направляетесь в правильном направлении. Некоторые примечания:

  • DataDirectory дает вам смещение к массиву IMAGE_IMPORT_DESCRIPTOR, который завершается записью всех нулей. Будет один IMAGE_IMPORT_DESCRIPTOR для каждой библиотеки DLL то есть импортные
  • в IMAGE_IMPORT_DESCRIPTOR имеет смещения до 2 массивов IMAGE_THUNK_DATA, один который поддерживает смещения имен импортированных функций (OriginalFirstThunk) и другое, что теперь фактические адреса функции (FirstThunk)

поскольку исполняемый файл запущен, IAT должен содержать фактический адрес функции, а не RVA для записи имени.

вы могли бы сделать что-то вроде этого:

DWORD rva_to_name_of_function = 0;
DWORD address_of_function = 0;

// get the RVA of the IMAGE_IMPORT_BY_NAME entry
readMemory(&rva_to_name, import.OriginalFirstThunk + procImgBase, 4);

// copy the name of the import
readMemory(buf, rva_to_name + procImgBase + 2, 127);

// get the actual address that was filled in by the loader
readMemory(&address_of_function, import.FirstThunk + procImgBase, 4);

printf("fname: %s address: %X", buf, address_of_function); 

взгляните на эту статью для некоторых полезных деталей: http://msdn.microsoft.com/en-us/magazine/cc301808.aspx


Эрик дал хороший ответ, вот некоторые дополнительные пояснения:

Я понимаю, что вызовы API в программах переходят к соответствующей точке в IAT, которая затем переходит к фактической функции в загруженных DLL.

программа использует вызов PTR DS: [IAT-ADDRESS], который считывает с адреса в IAT, чтобы определить, где программа находится во время выполнения.

в то время как указатели OriginalFirstThunk здесь, даст вам оригинал Импортировать таблицу (IT)?

указатели OriginalFirstThunk указывают на таблицу поиска импорта (ILT). Если вы откроете двоичный файл на диске, ILT и IAT идентичны; оба содержат строки имен функций RVA. После загрузки программы записи IAT (в памяти) перезаписываются адресами импортированных функций.

по моему опыту, лучшим источником информации в таблице импорта и всех сопутствующих структурах данных является сама спецификация PE. Если вы будете терпеливо читать раздел об импорте, все станет ясно.

http://msdn.microsoft.com/en-us/windows/hardware/gg463125