Хочу заразить файл внедрением в заголовок между последним элементом таблицы объектов и смещением первой секции. Но таких файлов (у которых есть такое место) немного. Решил: - открываю файл - резервирую заданный кусок памяти - добавляю в выделенную память : DOS Stub + PE Header + Object Table + НУЖНЫЙ МНЕ ОБЪЕМ ПАМЯТИ + Section 1 ... N - Сохряняю файл - Теперь внедряю в него код Вопрос: Какие поля нужно изменить в PE Header и Object Entry этого файла чтобы так вот добавить к нему нужный объем. Или как-то можно проще, ведь то что на диске - это не то что в памяти. Думаю нужно изменять тут: Код (Text): PE Header --------------------------------- 50h DWord Image Size виртуальный размер в байтах всего загружаемого образа, вместе с заголовками, кратен Object align 54h DWord Header Size общий размер всех заголовков: Код (Text): Object Entry --------------------------------- 14h DWord Physical Offset физическое смещение относительно начала EXE файла, выровнено на границу File align поля заголовка PE Header. Смещение используется загрузчиком как seek значение. ... может что-то еще ?
Структура PE формата предельно проста. MZ заголовок, досовский стаб после, далее по смещению IMAGE_DOS_HEADER::e_lfanew идут NT-headers (file & optional header). В file header есть размер optional header - IMAGE_FILE_HEADER::SizeOfOptionalHeader (размер массива в хвосте optional header может варьироваться), размер file header фиксирован. после optional header идет IMAGE_FILE_HEADER::NumberOfSections заголовков секций (IMAGE_SECTION_HEADER), а далее неиспользуемоме пространство вплоть до следующего выравнивания на IMAGE_OPTIONAL_HEADAER::FileAlignment. После идут данные секций. Размер заголовков (суммарный), каждой секции и указатель начала каждой секции должен быть кратен FileAlignment, в памяти они выравниваются на SectionAlignment (соотв. VirtualAddress должен быть кратен SectionAlignment). Если они совпадают, то файл будет загружен так же, как и лежит на диске. (про секции с VirtualSize > SizeOfRawData, то бишь неинициализированные, я не умомянул - там некуда внедряться). Не уверен, что хорошая идея внедряться в заголовок (насчет того, чтобы поле SizeOfHeaders двигать - не уверен, хотя можно попробовать добавить к нему, разумеется, кратное FileAlignment значение). Еще можно расширить какую-нибудь секцию. Наиболее просто - последнюю, тогда не придется двигать остальные. Можно расширить и первую, тогда нужно будет пройтись по таблице секций и добавить во все поля PointerToRawData дельту в размере. Но немногие секции в середине можно будет расширить - только до границы на SectionAlignment вверх. Если ее пересечь, изменится виртуальный размер секции и полетят все ссылки на последующие секции в коде. Но поскольку у многих ехе SectionAlignment сильно больше FileAlignment, то лишние два-три кило присунуть можно всяко. Ну это если я ниче не перепутал, чето спать хочется, мог и намудрить где-нибудь.
Если не двигать секции в памяти и расчитывать только на выравнивание то IMAGE_FILE_HEADER.SizeOfOptionalHeader IMAGE_SECTION_HEADER[].PointerToRawData Если двигать секции в памяти IMAGE_FILE_HEADER.SizeOfOptionalHeader IMAGE_OPTIONAL_HEADER.SizeOfHeaders IMAGE_OPTIONAL_HEADER.SizeOfImage IMAGE_OPTIONAL_HEADER.AddressOfEntryPoint; IMAGE_OPTIONAL_HEADER.BaseOfCode; IMAGE_OPTIONAL_HEADER.BaseOfData; IMAGE_DATA_DIRECTORY[].VirtualAddress IMAGE_SECTION_HEADER[].VirtualAddress IMAGE_SECTION_HEADER[].PointerToRawData IMAGE_SECTION_HEADER[].PointerToRelocations +поправить фиксапы вроде все
Двигать секции можно только с учетом, что их виртуальные адреса останутся прежними. А значит, нельзя вылезать за границу SectionAlignment. То есть дописать в секцию можно только ALIGN_UP(SizeOfRawData,SectionAlignment) - SizeOfRawData. Иначе изменится виртуальный размер, придется двигать виртуаьлные адреса и везде менять ссылки - почти нереально. Даже если в ехе есть релоки (что будет весьма странно).
В посте нет ничего ни о наличии релоков ни о типе PE Если релоки есть, либо есть возможность их восстановить, то адреса секций сменить можно
Раздвинуть хидер без всяких правок можно только если размер хидера будет меньше чем RVA первой секции. Для этого достаточно будет прописать новый размер SizeOfHeaders (ну и ессно физически пододвинуть все секции в файле). А вот если размер заголовка будет налезать на RVA первой секции, то придется двигать все секции ниже по памяти - тут без пересчета RVA секций, директорий, релоков и прочих радостей уже не обойтись.
Код (Text): // IMAGE_FIRST_SECTION doesn't need 32/64 versions since the file header is the same either way. #define IMAGE_FIRST_SECTION( ntheader ) ((PIMAGE_SECTION_HEADER) \ ((ULONG_PTR)ntheader + \ FIELD_OFFSET( IMAGE_NT_HEADERS, OptionalHeader ) + \ ((PIMAGE_NT_HEADERS)(ntheader))->FileHeader.SizeOfOptionalHeader \ ))