10

Насколько я знаю, каждая программа состоит из набора инструкций процессора с некоторыми конкретными переменными данных (float, int, char ...) для работы с регистрами процессора.

Итак, первое, что я подумал об этом (очень давно), это то, что если вы знаете, что значение ASCII %¨#$¨# (просто случайный пример) может быть интерпретировано как адрес регистра указателя стека ( просто пример) процессора x86. Если это так, каждый раз, когда вы находите это "нечитаемое" значение при чтении содержимого двоичного файла, вы можете интерпретировать, что регистр указателя стека используется для управления некоторой переменной данных.

К сожалению, этого не происходит. Ниже приведен пример содержимого программы ping.exe из Windows, открытой с помощью notepad.exe:

Ping.exe в MS Notepad

Это двоичный файл, и его данные непостижимы для нас, людей (для машин это понятно). Это не имеет никакого смысла ни для кого, даже если они знают код ассемблера (самый низкий уровень машинного языка.)

Так что, если я все правильно понял, может кто-нибудь объяснить

  1. Почему бинарный код не может вернуться к коду ассемблера, если он глубоко, то же самое?
  2. Если кто-то понимает ассемблерный код, почему скомпилированный двоичный код, полученный в результате этого кода, больше не "читается"?

3 ответа3

12

Во-первых, регистры не имеют адресов. Каждая инструкция на любом языке ассемблера переводится в код операции. Операционные коды в x86 могут быть одним, двумя, тремя или даже более байтами (в некоторых других процессорах они имеют "фиксированную ширину"). Обычно код операции определяет инструкцию, режим адресации и соответствующие регистры. "Режим адресации" определяет, требуется ли ЦПУ больше, чем код операции, то есть "немедленный" режим адресации означает, что сразу после (или "сразу после") инструкции для этой инструкции есть дополнительные данные - "абсолютные" режимы адресации означают, что адрес памяти следует за инструкцией и используется этой инструкцией.

Вы можете узнать код операции, например, MOV AL,SP или аналогичный, а затем найти его. В x86 есть много инструкций, которые работают с указателем стека.

Но, пожалуйста, выйдите из программы «Блокнот» и используйте вместо этого шестнадцатеричный редактор. Я бы порекомендовал HxD, хотя есть много других.

И Дэвид Шварц прав. Дизассемблер перебирает файл и переводит коды операций обратно в читаемый текст. То, что вы хотите сделать, вполне возможно.

Однако вам нужно знать, где в файле начинаются инструкции, потому что, если вы начинаете с неправильного адреса, некоторые данные, которые должны быть "операндами" для кодов операций (например, инструкции, которые принимают адрес для операнда или "аргумента"), могут быть неправильно истолкованы как коды операций. Знание этого требует знания формата, в котором находится исполняемый файл, для Windows это формат "Portable Executable" или PE (и часто это ELF для систем Linux). Я уверен, что есть дизассемблеры, которые понимают PE и т.д., Но я не знаю ничего лишнего.

11

Так что, если я все правильно понял

Не совсем.

Это бинарный файл и его данные непостижимы для нас, людей

Обычно двоичный файл непонятен человеку и машине, особенно когда цель файла неизвестна. Обратите внимание, что не все двоичные файлы являются исполняемыми файлами. Многие двоичные файлы - это файлы данных, которые не содержат никаких машинных инструкций. Вот почему расширения файлов используются при именовании файлов (в некоторых ОС). . Расширение com использовалось CP/M для обозначения исполняемого файла. . Расширение exe было добавлено MS-DOS для обозначения другого исполняемого формата файла. * nixes используют атрибут execute, чтобы указать, какие файлы могут быть выполнены, хотя это может быть как скрипт, так и код.

Как уже упоминалось другими, двоичные файлы, которые содержат числа, должны просматриваться программой hex dump или редактором hex, а не средством просмотра текста.

есть пример содержимого программы ping.exe

Этот файл на самом деле является перемещаемой программой, и не все данные в этом файле представляют машинный код. Здесь есть информация о программе, например, какие динамические библиотеки ей нужны, какие подпрограммы должны быть связаны, требования к стеку и памяти программ и данных, а также точка входа в программу. Операнды адреса в файле могут быть относительными значениями, которые должны быть рассчитаны до абсолютных значений, или ссылками, которые необходимо разрешить.

"Программный файл", о котором вы, вероятно, думаете, называется двоичным файлом изображения или дампом памяти программы. Такой файл будет содержать только машинный код и данные со всеми адресными ссылками, правильно установленными для выполнения.

даже если они знают ассемблерный код (самый низкий уровень машинного языка.)

Язык ассемблера не совпадает с языком машин. Типичный (исключая компьютеры на языке высокого уровня) процессор принимает машинный код в качестве ввода, по одной инструкции за раз. Операндами являются регистры или числовые адреса памяти. Язык ассемблера - это язык более высокого уровня, который может использовать символические метки для положений команд и переменных, а также заменять числовые коды операций мнемоникой. Программа на языке ассемблера должна быть преобразована в машинный язык / код, прежде чем она может быть фактически выполнена (обычно с помощью утилит, называемых ассемблером, компоновщиком и загрузчиком).

Обратная операция, дизассемблирование, может быть выполнена для программных файлов с некоторым успехом и потерей символической информации. Разборка дампа памяти или файла образа программы - это больше проб и ошибок, так как код и расположение данных должны быть определены вручную.

Кстати, есть люди, которые могут читать и кодировать (числовой) машинный код. Конечно, это намного проще на 8-битном процессоре или микроконтроллере, чем на 32-битном процессоре CISC с дюжиной режимов адресации памяти.

2

Вы не можете видеть правильную, предполагаемую кодировку двоичного файла через Блокнот. Пожалуйста, просмотрите это для дальнейшего использования. Большинство программ редактирования текста не анализируют двоичные форматы кодирования, и ожидается, что они будут анализировать форматирование кода символов ASCII.

Таким образом, открытие двоичного файла в текстовом редакторе даст эквивалентные символы ASCII, которые не имеют никакого смысла в исходном формате двоичных данных, который анализируется текстовым редактором. Как уже упоминалось, шестнадцатеричные редакторы, а некоторые имеют двоичные функции, позволяют просматривать содержимое в чисто двоичном формате.

Вы ошибаетесь в том, что содержимое двоичного файла невозможно понять. Несмотря на то, что они будут сложными, а в современных компьютерных архитектурах чрезвычайно трудно разобрать их вручную от двоичного кода до надлежащих инструкций, распознаваемых ЦП для выполнения (или эмулируемых / виртуальных ЦП) и т.д., Это можно сделать.

Как вы думаете, эмуляторы запрограммированы? Разработчику потребуется знать коды операций, чтобы можно было запрограммировать фиктивную систему на распознавание и поведение, как в некотором роде будет с реальным оборудованием. Документация объясняет многие архитектуры процессоров, и даже графические процессоры имеют их (хотя и более скрытно).

Следует также отметить, что на самом низком уровне, хотя и относительном, "двоичные данные" на самом деле представляют собой не группу нулей и единиц, а высокие и низкие напряжения, усиливаемые / переключаемые через электрическую цепь как ток.

При этом двоичный код обычно равен 1:1, поэтому имеет смысл использовать для него систему счисления.

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .