Чем открыть файл bytes
Советы по открытию файла BYTES
Не удается открыть файл BYTES? Ты не единственный. Тысячи пользователей ежедневно сталкиваются с подобными проблемами. Ниже вы найдете советы по открытию файлов BYTES, а также список программ, поддерживающих файлы BYTES.
BYTES расширение файла
Файл BYTES поддерживается в операционных системах 1. В зависимости от вашей операционной системы вам может потребоваться другое программное обеспечение для обработки файлов BYTES. Ниже приводится сводка количества программ, которые поддерживают и открывают файл BYTES на каждой системной платформе.
Операционные системы
Что такое файл BYTES?
Как открыть файл BYTES?
Часто повторяющаяся проблема с Unity Binary Text Asset Data Format заключается в том, что BYTES не связан с правильным программным файлом. Это приводит к тому, что файл BYTES открывается системными приложениями, не предназначенными для этой цели, или отображает сообщение об отсутствии связанной программы. Эту проблему легко исправить.
Первое, что вам нужно сделать, это просто «дважды щелкнуть » по значку файла BYTES, который вы хотите открыть. Если в операционной системе есть соответствующее приложение для ее поддержки, а также существует связь между файлом и программой, файл следует открыть.
Шаг 1. Установите Unity
Программы для открытия файла BYTES
Не забывайте загружать программы, поддерживающие файлы BYTES, только из проверенных и безопасных источников. Предлагаем использовать сайты разработчиков программного обеспечения.
Unity
Шаг 2. Создайте ассоциацию Unity с файлами BYTES.
Шаг 3. Обновите Unity до последней версии.
Если, однако, после привязки Unity к Unity Binary Text Asset Data Format проблемы все равно остались, вам следует обновить программу до последней версии. Это можно сделать с помощью приложения (если оно предоставляет такие возможности) или с веб-сайта Unity Technologies и установить последнюю версию.
Шаг 4. Проверьте наличие следующих проблем с файлом BYTES.
Если описанные выше действия не помогли, вы можете предположить, что сам файл неправильный. Наиболее частые проблемы с файлами:
Как открыть большие текстовые файлы в Windows
Если вы пытаетесь загрузить большой текстовый файл размером, например, больше 10 Гб в Windows, то у вас ничего не получится. Классический Блокнот и Wordpad поддерживают только небольшие документы. И даже такие хорошие сторонние альтернативы, как Notepad ++, имеют ограничения в размере файлов.
Многогибайтные документы, конечно, редкость. За всю мою практику мне всего лишь несколько раз приходилось искать софт, чтобы открыть какие-то огромные текстовые файлы с логами. К очередному такому случаю и захотелось написать заметку на память.
Программы для открытия больших текстовых файлов в Windows:
Итак, здесь только бесплатный софт. Покупать программу ради открытия одного файла совершенно не рационально.
Спасибо, что читаете! Подписывайтесь на мои каналы в Telegram, Яндекс.Мессенджере и Яндекс.Дзен. Только там последние обновления блога и новости мира информационных технологий.
Респект за пост! Спасибо за работу!
Хотите больше постов? Узнавать новости технологий? Читать обзоры на гаджеты? Для всего этого, а также для продвижения сайта, покупки нового дизайна и оплаты хостинга, мне необходима помощь от вас, преданные и благодарные читатели. Подробнее о донатах читайте на специальной странице.
Заранее спасибо! Все собранные средства будут пущены на развитие сайта. Поддержка проекта является подарком владельцу сайта.
Чтение файла по байтам (file to byte array)?
Доброго времени суток.
Ломаю голову уже который день.
Облазил инет, облазил форумы, но не нашел для себя даже примерка как правильно сделать.
Собственно что мне надо:
Есть файл который необходимо считывать байтами к примеру с позиции 0 ( 2 байта) это одно с позиции 2 но (1 байт) это другое с позиции 3 но (4 байта) это ещё что-то.
Может кто кинуть скрипт который хотя бы первые 2 байта прочтет и вернёт значение которое там стоит.
Я не понимаю как открывается такой файл и как считывать байты.
convert string of byte 2 byte array
Есть длиииный стринг ’00 05 0F 7B’ и тд и тп, нада все это дело запихать в байтный массив (чтобы.
Конвертирование HEX array в BYTE array
Собственно сабж. Накопипастил. И слепил это. Скажите а можно лаконичнее? //Художественный.
unsafe byte array to struct array
Есть массив байт размером N. Есть структура, внутри которой enum поле размером в 1 байт. Как.
Чтение файла в array of Extended
На строчке read(q,a); ошибка EInOutError: Invalid numeric input var z, q,: TextFile; i.
Я создал файл формата txt в него написал «123» я думал считать 1 байт и вставить в memo «1» или «2» или «3» но почему-то в memo пишет «49»
Добавлено через 3 минуты
Делфи ругается на System.Types, System.IOUtils;
Добавлено через 1 минуту
На txt файле я хочу потренироваться чтобы в мемо мне вставилось 123 вычитав это по байтно О_о
А потому уже перейти к хардкорному файлу который я ничем открыть не могу, но знаю структуру как читать по байтам.
С текстовым файлом вроде чуть более мение разобрался при чтение одного байта выдаёт 1 при чтение 3 байт выдаёт 123
Да чё-то всё не то =)
Если файл который я хочу распарсить открыть блокнотом то в начале стоит Щт по сути я должен увидеть число когда возьму два первых байта но нет мой скрипт возвращает Щт ваще грусть тоска *(
Где мне ещё по изучать этот вопрос?
До меня не доходит как верно считывать файл *(
Добавлено через 1 час 6 минут
Да уж не судьба мне распарсить файл ASN.1 =)))
Добавлено через 54 секунды
и сразу же получаем рабочий код из поста #2
D1973, я установил FinalBuilder 7 Embarcadero Edition подскажите пожалуйста куда вставлять данный код, если можно скриншотом. +)
Добавлено через 23 минуты
Чёт без лицензии не запускается ))) блин
Вам же была дана ссылка на нормальный полнофункциональный и бесплатный продукт Delphi Tokyo 10.2.3 Comunity Edition. Вы же начали фантазировать неизвестно в какую сторону.
Эта вещь на которую дали ссылку не ставиться выдаёт после инстала ошибку missing bds.exe
Весь день с ней боролся но так и не победил.
Да уж не судьба видимо.
Я тут подумал что у меня из файла беруться не биты а прям значения так как корявые буквы и значки вставляються в поле memo тоесть я биру всё же не байты.
что-то не так подскажите где я ошибся.
1) мне надо брать байты «определённое количество»
2) конвертировать из байтов в значение.
Добавлено через 2 минуты
Нет у меня 7-ка 64 разрядная.
Добавлено через 48 секунд
Может я не то ставлю +)
Я там зарегался и скачал этот RAD 10.2 ключ пришел на почту и всё я заинсталил но увы и ах.
Добавлено через 2 минуты
Может проблема в этом? AnsiString(Buffer) может перед вставкой надо как-то перевести в hex? ))
Добавлено через 49 секунд
глядя разные примеры в инете часто вижу этот Hex но не пойму чё с ним делать мне надо читать файл в hex формате? Как это сделать?
если вы установили 10.2 то почему не использовали код из второго поста??
какие биты?
вам в массив скачивается содержимое файла
что еще не так?
Добавлено через 7 минут
кроме того, в вашем исходном коде тоже все работает за исключением того, что цикл по Count, который равен 0
пусть i=0
вот вы прочли в массив один байт и показали его значение
Короче я написал программку и что я могу сказать 7 дней гугления. Просто 60 галимых часов гугла у меня чуть мозг не лопнул и пукан тоже.
BlockRead(f, byteArray, 1); это не работает оно читает сразу символ который занимает байт, символ, а не сами байты.
Вы понимаете байты это FF A0 54 и т.д. и т.п.
Так вот в 44 первых байтах у меня зашифровано 16 значений включая «Transmission check sum» и названия и всякую всячину.
Я конечно не крутой прогер но прога получилась аж на 800 строк.
Ключевой момент в том чтобы файл открыть как TFileStream
Если есть вопросы я конечно отвечу, но не быстро так как пока лень и я отдыхаю =)
все испробованные вами способы работали ПРАВИЛЬНО
вся эта арифметика годится для версий делфи до 2009
после этого CHAR стал не ANSI а Unicode и теперь занимает уже не один а 2 байта
в остальном идея та же самая
PE (Portable Executable): На странных берегах
Введение
PE формат — это формат исполняемых файлов всех 32- и 64- разрядных Windows систем. На данный момент существует два формата PE-файлов: PE32 и PE32+. PE32 формат для x86 систем, а PE32+ для x64. Описанные структуры можно наблюдать в заголовочном файле WINNT.h, который поставляется вместе SDK. Описание сего формата от microsoft можно скачать здесь, а я же пока оставлю здесь небольшое схематическое представление. Просто пробегитесь глазами, в процессе статьи вы начнёте схватывать и всё разложится по полочкам.
Любой файл, это есть лишь последовательность байт. А формат, это как специальная карта (сокровищ) для него. То есть показывает что где находится, где острова с кокосами, где с бананами, где песчаные берега, а где Сомалийские, куда лучше-бы не соваться. Так давайте же изучим широкие просторы этого океана. Отдать швартовы!
«Сейчас вы услышите грустную истори. о мальчике Бобби»
(Остров сокровищ)
Dos-Header (IMAGE_DOS_HEADER) и Dos-stub
Dos заголовок. Это самая первая структура (самый первый островок который нам встретился на пути) в файле и она имеет размер 64 байта. В этой структуре наиболее важные поля это e_magic и e_lfnew. Посмотрим как выглядит структура:
Изучать все поля на данном этапе ни к чему, т.к. особой смысловой нагрузки они не несут. Рассмотрим только те, которые необходимы для загрузки и представляют особенный интерес. (Дальше и ниже по тексту, формат описания полей будет вида name: TYPE — description).
e_magic: WORD — сигнатура находящаяся по смещению 0 от начала файла и равная “MZ”. Поговаривают, что MZ сокращение от Марк Збиновски — самый злобный пират на всём водном пространстве ведущий разработчик MS DOS и EXE формата. Если данная сигнатура не равна MZ, то файл не загрузится.
e_lfnew: DWORD — смещение PE заголовка относительно начала файла. PE заголовок должен начинаться с сигнатуры (характерная запись/подпись) PE\x0\x0. PE заголовок может располагаться в любом месте файла. Если посмотреть на структуру, то можно увидеть, что e_lfnew находится по смещению 0x3C (60 в десятичной). То есть чтобы прочитать это значение, мы должны от указателя на начало файла (введём обозначение — ptrFile) “плюсануть” 60 байт и тогда мы встанем face to face перед e_lfnew. Читаем это значение (пусть будет peStep) и плюсуем к ptrFile значение peStep. Mission completed — мы на месте шеф, это должен быть PE заголовок. А узнать это наверняка мы можем сверив первые четыре байта этого заголовка. Как было сказано выше, они должны равняться PE\x0\x0.
После 64 первых байт файла стартует dos-stub (пираты также называют его dos заглушка). Эта область в памяти которая в большинстве своём забита нулями. (Взгляните ещё раз на структуру — заглушка лежит после dos-header(а) и перед PE заголовком) Служит она только для обратной совместимости, нынешним системам она ни к чему. В неё может быть записана мини версия dos программы ограниченную в 192 байта (256 — конец заглушки, 64 — размер dos заголовка). Но легче найти Access Point в Зимбабве, нежели такую программу. Стандартное поведение, если запустить программу на dos, то она выведет сообщения вида “This program cannot be run in DOS mode.” или “This program must be run under win32”. Если увидите эти строки, это значит что вы попали… в далёкий 85-ый.
“-К чёрту деньги, я говорю о бумагах Флинта!”
(Остров сокровищ)
PE-Header (IMAGE_NT_HEADER)
Прочитали e_lfnew, отступили от начала файла на peStep байт. Теперь мы может начинать анализировать PE заголовок. Это новый для нас остров и он должен располагаться на просторах следующих 0x18 байт. Структура представлена ниже:
Это интересная структура, т.к. она содержит в себе подструктуры. Если представить PE файл как океан, каждая структура это материк (или остров). На материках расположены государства, которые могут рассказать о своей территории. А рассказ складывается из истории отдельных городов (полей) в этом государстве. Так вот — NT Header — это материк, которой содержит такие страны, как Signature (город-государство), FileHeader, OptionalHeader. Как уже было сказано, Signature: DWORD — содержит 4-ёх байтовую сигнатуру, характеризующую формат файла. Рассмотрим что ещё может поведать нам этот материк.
File-Header (IMAGE_FILE_HEADER)
Это страна где вечно стреляют, торгуют наркотиками и занимаются проституцией где каждый город рассказывает в каком идеальном государстве он расположен. Это что касается неформального описания, а формальное заключается в следующем — набор полей, описывающий базовые характеристики файла. Давайте рассмотрим данную державу структуру:
Я лишь сухо опишу данные поля, т.к. названия интуитивно понятные и представляют из себя непосредственные значения, а не VA, RVA, RAW и прочие страшные интригующие штуки, о которых пока, мы только слышали от старых пиратов. Хотя с RAW мы уже сталкивались — это как раз смещения относительно начала файла (их ещё называют сырыми указателями или file offset). То есть если мы имеем RAW адрес, это значит что нужно шагнуть от начала файла на RAW позиций (ptrFile + RAW). После можно начинать читать значения. Ярким примером данного вида является e_lfnew — что мы рассмотрели выше в Dos заголовке.
*Machine: WORD — это число (2 байта) задаёт архитектуру процессора, на которой данное приложение может выполняться.
NumberOfSections: DWORD — количество секций в файле. Секции (в дальнейшем будем называть таблицей секций) следуют сразу после заголовка (PE-Header). В документации сказано что количество секций ограничено числом 96.
TimeDateStamp: WORD — число хранящее дату и время создания файла.
PointerToSymbolTable: DWORD — смещение (RAW) до таблицы символов, а SizeOfOptionalHeader — это размер данной таблицы. Данная таблица призвана служить для хранения отладочной информации, но отряд не заметил потери бойца с самого начала службы. Чаще всего это поле зачищается нулями.
SIzeOfOptionHeader: WORD — размер опционального заголовка (что следует сразу за текущим) В документации указано, что для объектного файла он устанавливается в 0…
*Characteristics: WORD — характеристики файла.
* — поля, которые определены диапозоном значений. Таблицы возможных значений представлены в описании структуры на оф. сайте и приводиться здесь не будут, т.к. ничего особо важного для понимая формата они не несут.
Оставим этот остров! Нам нужно двигаться дальше. Ориентир — страна под названием Optional-Header.
“— Где карта, Билли? Мне нужна карта.”
(Остров сокровищ)
Optional-Header (IMAGE_OPTIONAL_HEADER)
Название сего материка заголовка не очень удачное. Этот заголовок является обязательным и имеет 2 формата PE32 и PE32+ (IMAGE_OPTIONAL_HEADER32 и IMAGE_OPTIONAL_HEADER64 соответственно). Формат хранится в поле Magic: WORD. Заголовок содержит необходимую информацию для загрузки файла. Как всегда:
* Как всегда, мы изучим только основные поля, которые имеют наибольшее влияние на представление о загрузке и того, как двигаться дальше по файлу. Давайте условимся — в полях данной структуры, содержаться значения с VA (Virtual address) и RVA (Relative virtual address) адресами. Это уже адреса не такие как RAW, и их нужно уметь читать (точнее считать). Мы непременно научимся это делать, но только для начала разберём структуры, которые идут друг за другом, чтобы не запутаться. Пока просто запомните — это адреса, которые после расчётов, указывают на определённое место в файле. Также встретится новое понятие — выравнивание. Его мы рассмотрим в купе с RVA адресами, т.к. эти они довольно тесно связаны.
Рассмотрим что из себя представляет структура IMAGE_DATA_DIRECTORY:
Что мы имеем? Мы имеем массив из 16 элементов, каждый элемент которого, содержит адрес и размер (чего? как? зачем? всё через минуту). Встаёт вопрос чего именно это характеристики. Для этого, у microsoft имеется специальные константы для соответствия. Их можно увидеть в самом конце описания структуры. А пока:
Ага! Мы видим, что каждый элемент массива, отвечает за прикреплённую к нему таблицу. Но увы и ах, пока эти берега недосягаемы для нас, т.к. мы не умеем работаться с VA и RVA адресами. А для того чтобы научиться, нам нужно изучить что такое секции. Именно они расскажут о своей структуре и работе, после чего станет понятно для чего нужны VA, RVA и выравнивания. В рамках данной статьи, мы затронем только экспорт и иморт. Предназначение остальных полей можно найти в оф. документации, либо в книжках. Так вот. Собственно поля:
VirtualAddress: DWORD — RVA на таблицу, которой соответствует элемент массива.
Size: DWORD — размер таблицы в байтах.
Итак! Чтобы добраться до таких экзотических берегов как таблицы импорта, экспорта, ресурсов и прочих, нам необходимо пройти квест с секциями. Ну что ж юнга, взглянем на общую карту, определим где мы сейчас находимся и будем двигаться дальше:
“- Ты низложен, Сильвер! Слезай с бочки!”
(Остров сокровищ)
Section-header (IMAGE_SECTION_HEADER)
Сразу за массивом DataDirectory друг за другом идут секции. Таблица секций представляет из себя суверенное государство, которое делится на NumberOfSections городов. Каждый город имеет своё ремесло, свои права, а также размер в 0x28 байт. Количество секций указано в поле NumberOfSections, что хранится в File-header-е. Итак, рассмотрим структуру:
Name: BYTE[IMAGE_SIZEOF_SHORT_NAME] — название секции. На данный момент имеет длину в 8 символов.
VirtualSize: DWORD — размер секции в виртуальной памяти.
SizeOfRawData: DWORD — размер секции в файле.
VirtualAddress: DWORD — RVA адрес секции.
SizeOfRawData: DWORD — размер секции в файле. Должен быть кратен FileAligment.
PointerToRawData: DWORD — RAW смещение до начала секции. Также должен быть кратен FileAligment…
Characteristics: DWORD — атрибуты доступа к секции и правила для её загрузки в вирт. память. Например атрибут для определения содержимого секции (иниц. данные, не инициал. данные, код). Или атрибуты доступа — чтение, запись, исполнение. Это не весь их спектр. Характеристики задаются константами из того-же WINNT.h, которые начинаются с IMAGE_SCN_. Более подробно ознакомится с атрибутами секций можно здесь. Также хорошо описаны атрибуты в книгах Криса Касперски — список литературы в конце статьи.
Секции, это такая область, которая выгружается в виртуальную память и вся работа происходит непосредственно с этими данными. Адрес в виртуальной памяти, без всяких смещений называется Virtual address, сокращённо VA. Предпочитаемый адрес для загрузки приложения, задаётся в поле ImageBase. Это как точка, с которой начинается область приложения в виртуальной памяти. И относительно этой точки отсчитываются смещения RVA (Relative virtual address). То есть VA = ImageBase + RVA; ImageBase нам всегда известно и получив в своё распоряжение VA или RVA, мы можем выразить одно через другое.
Тут вроде освоились. Но это же виртуальная память! А мы то находимся в физической. Виртуальная память для нас сейчас это как путешествие в другие галактики, которые мы пока можем лишь только представлять. Так что в виртуальную память нам на данный момент не попасть, но мы можем узнать что там будет, ведь это взято из нашего файла.
Выравнивание
Для того чтобы правильно представлять выгрузку в вирт. память, необходимо разобраться с таким механизмом как выравнивание. Для начала давайте взглянем на схему того, как секции выгружаются в память.
Как можно заметить, секция выгружается в память не по своему размеру. Здесь используются выравнивания. Это значение, которому должны быть кратен размер секции в памяти. Если посмотреть на схему, то мы увидим, что размер секции 0x28, а выгружается в размере 0x50. Это происходит из-за размера выравнивания. 0x28 “не дотягивает” до 0x50 и как следствие, будет выгружена секция, а остальное пространство в размере 0x50-0x28 занулится. А если размер секции был бы больше размера выравнивания, то что? Например sectionSize = 0x78, а sectionAligment = 0x50, т.е. остался без изменений. В таком случае, секция занимала бы в памяти 0xA0 (0xA0 = 0x28 * 0x04) байт. То есть значение которое кратно sectionAligment и полностью кроет sectionSize. Следует отметить, что секции в файле выравниваются аналогичным образом, только на размер FileAligment. Получив необходимую базу, мы можем разобраться с тем, как конвертировать из RVA в RAW.
“Здесь вам не равнина, здесь климат иной.”
(В.С. Высоцкий)
Небольшой урок арифметики
Перед тем как начать выполнение, какая то часть программы должна быть отправлена в адресное пространство процессора. Адресное пространство — это объём физически адресуемой процессором оперативной памяти. “Кусок” в адресном пространстве, куда выгружается программа называется виртуальным образом (virtual image). Образ характеризуется адресом базовой загрузки (Image base) и размером (Image size). Так вот VA (Virtual address) — это адрес относительно начала виртуальной памяти, а RVA (Relative Virtual Address) относительно места, куда была выгружена программа. Как узнать базовый адрес загрузки приложения? Для этого существует отдельное поле в опциональном заголовке под названием ImageBase. Это была небольшая прелюдия чтобы освежить в памяти. Теперь рассмотрим схематичное представление разных адресаций:
Дак как же всё таки прочитать информацию из файла, не выгружая его в виртуальную память? Для этого нужно конвертировать адреса в RAW формат. Тогда мы сможем внутри файла шагнуть на нужный нам участок и прочитать необходимые данные. Так как RVA — это адрес в виртуальной памяти, данные по которому были спроецированы из файла, то мы можем произвести обратный процесс. Для этого нам понадобится ключ девять на шестнадцать простая арифметика. Вот несколько формул:
Как видно, чтобы высчитать RAW, нам нужно определить секцию, которой принадлежит RVA. Для этого нужно пройти по всем секциям и проверить следующие условие:
Сложив все пазлы, получим вот такой листинг:
УРА! Разобрались. Теперь мы можем отправится в края ресурсов, библиотек импорта и экспорта и вообще куда душа желает. Мы ведь только что научились работать с новым видом адресации. В путь!
“-Неплохо, неплохо! Всё же они получили свой паёк на сегодня!”
(Остров сокровищ)
Export table
В самом первом элементе массива DataDirectory хранится RVA на таблицу экспорта, которая представлена структурой IMAGE_EXPORT_DIRECTORY. Эта таблица свойственна файлам динамических библиотек (.dll). Основной задачей таблицы является связь экспортируемых функций с их RVA. Описание представлено в оф. спецификикации:
Эта структура содержит три указателя на три разные таблицы. Это таблица имён (функций) (AddressOfNames), ординалов(AddressOfNamesOrdinals), адресов(AddressOfFunctions). В поле Name хранится RVA имени динамической библиотеки. Ординал — это как посредник, между таблицей имён и таблицей адресов, и представляет из себя массив индексов (размер индекса равен 2 байта). Для большей наглядности рассмотрим схему:
Рассмотрим пример. Допустим i-ый элемент массива имён указывает на название функции. Тогда адрес этой функции можно получить обратившись к i-му элементу в массиве адресов. Т.е. i — это ординал.
Внимание! Если вы взяли к примеру 2-ой элемент в таблице ординалов, это не значит 2 — это ординал для таблиц имён и адресов. Индексом является значение, хранящееся во втором элементе массива ординалов.
Количество значений в таблицах имён (NumberOfNames) и ординалов равны и не всегда совпадают с количеством элементов в таблице адресов (NumberOfFunctions).
“За мной пришли. Спасибо за внимание. Сейчас, должно быть, будут убивать!”
(Остров сокровищ)
Import table
Таблица импорта неотъемлемая часть любого приложения, которая использует динамические библиотеки. Данная таблица помогает соотнести вызовы функций динамических библиотек с соответствующими адресами. Импорт может происходить в трёх разных режимах: стандартный, связывающем (bound import) и отложенном (delay import). Т.к. тема иморта достаточно многогранна и тянет на отдельную статью, я опишу только стандартный механизм, а остальные опишу только «скелетом».
Стандартный импорт — в DataDirectory под индексом IMAGE_DIRECTORY_ENTRY_IMPORT(=1) хранится таблица импорта. Она представляет собой массив из элементов типа IMAGE_IMPORT_DESCRIPTOR. Таблица импорта хранит (массивом) имена функций/ординалов и в какое место загрузчик должен записать эффективный адрес этой функций. Этот механизм не очень эффективен, т.к. откровенно говоря всё сводится к перебору всей таблицы экспорта для каждой необходимой функции.
Малость осветив методы импорта, перейдём непосредственно к таблице импорта.
“-Это моряк! Одежда у него была морская. — Да ну? А ты думал найти здесь епископа?”
(Остров сокровищ — Джон Сильвер)
Import-descriptor (IMAGE_IMPORT_DESCRIPTOR)
Для того чтобы узнать координаты таблицы импорта, нам нужно обратиться к массиву DataDirectory. А именно к элементу IMAGE_DIRECTORY_ENTRY_IMPORT (=1). И прочитать RVA адрес таблицы. Вот общая схема пути, который требуется проделать:
Затем из RVA получаем RAW, в соответствии с формулами приведёнными выше, и затем “шагаем” по файлу. Теперь мы впритык перед массивом структур под названием IMAGE_IMPORT_DESCRIPTOR. Признаком конца массива служит “нулевая” структура.
Я не смог выудить на msdn ссылку на описание структуры, но вы можете наблюдать её в файле WINNT.h. Начнём разбираться.
OriginalFirstThunk: DWORD — RVA таблицы имён импорта (INT).
TimeDateStamp: DWORD — дата и время.
ForwarderChain: DWORD — индекс первого переправленного символа.
Name: DWORD — RVA строки с именем библиотеки.
FirstThunk: DWORD — RVA таблицы адресов импорта (IAT).
Тут всё несколько похоже на экспорт. Также таблица имён (INT) и и тоже рубище на нём адресов (IAT). Также RVA имени библиотеки. Только вот INT и IAT ссылаются на массив структур IMAGE_THUNK_DATA. Она представлена в двух формах — для 64- и для 32-ый систем и различаются только размером полей. Рассмотрим на примере x86:
Важно ответить, что дальнейшие действия зависят от старшего бита структуры. Если он установлен, то оставшиеся биты представляют из себя номер импортируемого символа (импорт по номеру). В противном случае (старший бит сброшен) оставшиеся биты задают RVA импортируемого символа (импорт по имени). Если мы имеем импорт по имени, то указатель хранит адрес на следующую структуру:
Здесь Hint — это номер функции, а Name — имя.
Для чего это всё? Все эти массивы, структуры… Рассмотрим для наглядности замечательную схему с exelab:
Что здесь происходит… Поле OriginalFirstThunk ссылается на массив, где хранится информация по импортируемым функциям. Поле FirstThunk ссылается на аналогичный массив той же размерности, но разве что заполняется он во время загрузки эффективным адресами функций. Т.е. загрузчик анализирует OriginalFirstThunk, определяет реальный адрес функции для каждого его элемента и заносит этот адрес в FirstThunk. Другими словами происходит связывание импортируемых символов.
“-Мне не нравится эта экспедиция! Мне не нравятся эти матросы! И вообще… что. А, да! Нет! Мне вообще ничего не нравится, сэр!”
(Остров сокровищ — Капитан Смоллетт)
За бортом
В статье была представлена лишь самая база по исполняемым файлам. Не затронуты другие виды импорта, поведение при конфликтующих (например физический размер секции, больше виртуального) или неоднозначных (в том же импорте — вопрос к какому методу прибегнуть) ситуациях. Но это всё уже для более детально изучения и зависит от конкретных загрузчиков в ОС и компиляторов, которые собрали программу. Также не затронуты каталоги ресурсов, отладки и прочих. Тем кому стало интересно, можно почитать более подробные руководства представленные в списке литературы в конце статьи.
“-Скажи, Окорок, долго мы будем вилять, как маркитантская лодка? Мне до смерти надоел капитан. Хватит ему командовать! Я хочу жить в его каюте.”
(Остров сокровищ)
Заключение
После того как мы вернулись из путешествия, немного подытожу, что мы увидели и что вынесли. Сегодня мы многое поняли А именно опишу процесс загрузки приложения в общих словах.
Для более чёткого понимания можно порекомендовать поизучать диаграммы. Это действительно даёт более полную картину происходящего внутри. В качестве примера могу предложить вот эту статью пользователя alizar или более общие схемы в гугле. Надеюсь вам понравилось наше путешествие.