Старый 14.11.2013, 09:50   #1
<Gh0St>
 
Аватар для <Gh0St>
 
Регистрация: 22.03.2012
Сообщений: 75
Репутация: 19
По умолчанию Перенос таблицы импорта

Всем привет!
В этой статье я расскажу о работе с исполняемыми файлами PE-формата, а именно о работе с таблицей импорта.
Возникла необходимость перенести таблицу импорта. Перенести в другую секцию, либо в пределах одной секции.
В данном случае перенос таблицы импорта осуществляется в пределах одной секции. Столкнувшись с такой задачей, я первым делом обратился в Гуглу, но увы, информации по этому вопросу практически никакой не нашёл. Пришлось всё исследовать самому, результаты исследований представлены в данной статье.

Пусть таблица импорта находится в секции .rdata:


В последующем происходит изменение заголовка секции .rdata.
Параметры секции и в IMAGE_DATA_DIRECTORY были такими:
Код:
Virtual Size: 0x124
Virtual Address: 0x2000
Raw Size: 0x200
Raw Address: 0xA00

Import Directory RVA: 0x206C
Import Directory Size: 0x28

Import Address Table Directory RVA: 0x2000
Import Address Table Directory Size: 0x1C
А стали такими:
Код:
Virtual Size: 0x1000
Virtual Address: 0x1B000
Raw Size: 0x200
Raw Address: 0x7400

Import Directory RVA: 0x1B06C
Import Directory Size: 0x28

Import Address Table Directory RVA: 0x1B000
Import Address Table Directory Size: 0x1C
Физический размер секции остался прежним, изменилось физическое смещение секции в файле, виртуальный адрес и виртуальный размер.

После изменения заголовка секции, необходимо обновить адреса в IMAGE_DATA_DIRECTORY. Затем необходимо скопировать существующий импорт в изменённую секцию .rdata:



Но этого недостаточно, в таблице импорта следующее:


После переноса импорта, адреса в IMAGE_IMPORT_DESCRIPTOR и массиве структур IMAGE_THUNK_DATA остались прежними.
Необходимо обновить адреса в этих структурах с учётом изменений в секции .rdata. Обновление адресов выполняется по следующей формуле:
Код:
addr = newVA + (addr - oldVa)
где, addr - обновляемый адрес
newVA - Virtual Address секции .rdata после изменения (0x1B000)
oldVA - Virtual Address секции .rdata до изменения (0x2000)
Например: OriginalFirstThunk = 0x1B000 + (0x2094 - 0x2000) = 0x1B094

Выведя формулу и получив необходимые для расчёта данные, обновим адреса с учётом изменения в секции:


После обновления адресов, появился список импортируемых функций, но в полях OFTs и FTs (IAT) старые адреса. Обновим их:


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


Несмотря на изменения в таблице импорта, функции по прежнему вызываются относительно старых виртуальных адресов 0x2000, а не новых (0x1B000). При вызове этой функции программа падает по Access violation.

Проблема решается следующим образом: необходимо выполнить в бинарном файле поиск старых адресов и заменить их на новые. Псевдокод выполняющий такой поиск с заменой представлен ниже:
Код:
MIN_ADDR = oldVA + ntHeaders.OptionalHeader.ImageBase;
MAX_ADDR = MIN_ADDR + rData.Misc.VirtualSize;

for(i = 0; i < fileSize; i++) {
	if(outputFile[i]) >= MIN_ADDR) && (outputFile[i]) <= MAX_ADDR)) {
		outputFile[i] = newVA + (outputFile[i] - oldVA);
	}
}

где, rData - заголовок обновлённой секции .rdata
fileSize - размер файла
outputFile - обрабатываемый файл
Просматривая адреса функций в таблице импорта и изучая код в отладчике, можно прийти к выводу, что в коде программы, вызов функций происходит по адресам не младше, чем oldVa + ImageBase (например, 0х0040200С), но маловероятно, что вызов функций будет происходить по адресами большим, чем oldVA + ImageBase + VirtualSize (0х2000 + 0x00400000 + 0х1000 = 0х00403000).
Проведя такое наблюдение, установим минимальный адрес (MIN_ADDR) и максимальный адрес (MAX_ADDR). Затем необходимо провести в файле поиск адресов входящих в диапазон от MIN_ADDR до MAX_ADDR включительно. И обновить каждый адрес по вышеуказанной формуле.

После обновления адресов в коде, снова запустим программу в отладчике:


Как видите функции из таблицы импорта вновь стали работоспособны.

На этом всё.
Благодарю за внимание.
__________________
- Про опыт говорят: "Мы так свои ошибки называем"
<Gh0St> вне форума   Ответить с цитированием
Старый 19.11.2013, 20:29   #2
JKornev
 
Регистрация: 03.11.2013
Сообщений: 10
Репутация: 0
По умолчанию

То что вы сдвинули структуры, вроде сделано правильно, но реализация нормализации смещений внутри кода, это полнейшая чушь. Вы хоть понимаете что ваш цикл вообще по идее скорее больше закоцает PE чем нормализует. Такие операции по переносу импорта выполняются только при наличии релоков, благодоря которым можно коректно изменять смещения в коде.
JKornev вне форума   Ответить с цитированием
Старый 20.11.2013, 19:26   #3
<Gh0St>
 
Аватар для <Gh0St>
 
Регистрация: 22.03.2012
Сообщений: 75
Репутация: 19
По умолчанию

А если релоков нет?
Буду рад услышать более совершенный метод переноса таблицы импорта (со всеми вытекающими).
__________________
- Про опыт говорят: "Мы так свои ошибки называем"
<Gh0St> вне форума   Ответить с цитированием
Старый 23.11.2013, 12:57   #4
JKornev
 
Регистрация: 03.11.2013
Сообщений: 10
Репутация: 0
По умолчанию

Универсальный алгоритм без релоков сложновато придумать, надо наверно дизассемблировать всю кодосекцию и править прямые обращения по адресам, но это больше эвристика чем точный алгоритм. Тут есть идеи именно для частных случаев, вы импорт с какой целью переносили?
JKornev вне форума   Ответить с цитированием
Старый 24.11.2013, 09:12   #5
<Gh0St>
 
Аватар для <Gh0St>
 
Регистрация: 22.03.2012
Сообщений: 75
Репутация: 19
По умолчанию

Исключительно из научного интереса.
Занимаюсь изучением формата PE-файлов и всего с ним связанного.
__________________
- Про опыт говорят: "Мы так свои ошибки называем"
<Gh0St> вне форума   Ответить с цитированием
Ответ

Метки
перенос, exe, таблица импорта, pe формат

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск
Опции просмотра

Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.

Быстрый переход



Powered by vBulletin® Version 3.8.5
Copyright ©2000 - 2019, Jelsoft Enterprises Ltd. Перевод: zCarot