@s2sk

Как понимать бинарные файлы?

Всем привет.

Стало интересно как можно парсить бинарные файлы. Везде как зайду в документацию к ним там какая-то подобная фигня (на скрине .3ds):

cx0n3W8.png

Мне именно интересно что значат эти все цифры (0x4D4D, 0x0002 и т.д.), а не "открываешь файл в бинарном режиме и читаешь". Можно, пожалуйста, доходчиво объяснить что все эти цифры значат, а не заумными словами, знаю вас быдлокодеров)00) И желательно с каким-нибудь простеньким примером на плюсах
  • Вопрос задан
  • 750 просмотров
Решения вопроса 1
reverse_kacejot
@reverse_kacejot
Junior C++ Developer, bachelor of Applied Math
Как гласит страничка википедии для того же формата .3ds - "The first two bytes of the chunk are its ID". У каждого формата - свое бинарное представление со своими чанками. Типичным примером могут быть исполнимые файлы Windows - PE и для Linux - ELF. Для ELF-файлов есть хорошая спецификация, которая объясняет какие чанки бывают, какие у них заголовки, какие поля у заголовков, какой размер у чанком (если он не переменный).
Еще есть spool файлы принтеров - у них тоже своих заголовки.

Из общего, что можно вынести:
В бинарном представлении информация не хранится в голом виде, а чаще всего обернута в блоки с заголовками. У заголовков могут быть идентификаторы (как те циферки, о которых ты спросил), размер блока и другая вспомогательная информация, которая зависит от спецификации заголовка.

Обещанные ссылки на спеки бинарей:
ELF - Executable and Linkable format
EMFSPL
EMF
PE

Вот нашел свой парсер секций для Portable Executable
#include <stdio.h>
#include <windows.h>

#define RTN_OK 0
#define RTN_FAILURE 1

const size_t expected_count = 1;

char* read_file_name(int argc, char** argv);

int main(int argc, char** argv)
{
	// Parsing command line args
	char* file_name = read_file_name(argc, argv);
	
	// Opening our executable
	FILE* portable_executable = fopen(file_name, "r");

	// Reading dos header
	IMAGE_DOS_HEADER dos_header_buffer;
	fread(&dos_header_buffer, sizeof(IMAGE_DOS_HEADER), expected_count, portable_executable);

	// Setting offset for reading PE header
	fseek(portable_executable, (long)dos_header_buffer.e_lfanew, SEEK_SET)

	// Reading signature field from PE header
	DWORD signature = 0;
	fread(&signature, sizeof(DWORD), expected_count, portable_executable);

	// Reading file header
	IMAGE_FILE_HEADER file_header_buffer;
	fread(&file_header_buffer, sizeof(IMAGE_FILE_HEADER), expected_count, portable_executable);

	// Reading optinal header
	IMAGE_OPTIONAL_HEADER optional_header_buffer;
	fread(&optional_header_buffer, file_header_buffer.SizeOfOptionalHeader, expected_count, portable_executable);

	// Get info about all the sections
	for (int i = 0; i < file_header_buffer.NumberOfSections; ++i)
	{
		// Reading each section header
		IMAGE_SECTION_HEADER section_header_buffer;
		fread(&section_header_buffer, sizeof(IMAGE_SECTION_HEADER), expected_count, portable_executable);
		
		printf("Section name: %7s, Raw data size: %10d, Pointer to raw data: %10d\n",
			section_header_buffer.Name,
			section_header_buffer.SizeOfRawData,
			section_header_buffer.PointerToRawData);
	}

	fclose(portable_executable);
}

char* read_file_name(int argc, char** argv)
{
	if (argc != 2)
	{
		return NULL;
	}

	return argv[1];
}
Ответ написан
Комментировать
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы