Как читать / писать.exe машинный код вручную?

Я не очень хорошо знаком с магией компилятора. Акт преобразования читаемого человеком кода (или не действительно читабельной инструкции по сборке) в машинный код, для меня, ракетостроение в сочетании с магией.

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

есть ли простой способ чтения машинного кода? Открывая exe как файловый поток и читая его байт за байтом, как можно превратить эти отдельные байты в сборку? Существует ли прямое отображение между этими инструкция байт а инструкция по сборке?

Как это .написано ехе? Четыре байта на инструкцию? Еще? Меньше? Я заметили, что некоторые приложения могут создавать исполняемые файлы точно так же: например, в ACD See вы можете экспортировать серию изображений в слайд-шоу. Но это не обязательно должно быть слайд-шоу SWF, ACD See также способен создавать исполняемые презентации. Как это делается?

Как я могу понять, что происходит внутри EXE-файл?

12 ответов


OllyDbg является удивительным инструментом, который разбирает EXE в читаемые инструкции и позволяет выполнять инструкции один за другим. Он также сообщает вам, какие функции API использует программа и, если возможно, аргументы, которые она предоставляет (пока аргументы находятся в стеке).

вообще говоря, инструкции CPU имеют переменную длину, некоторые из них один байт, другие два, некоторые три, некоторые четыре и т. д. Это в основном зависит от типа данных, которые инструкция ожидает. Некоторые инструкции обобщены, например "mov", который говорит процессору переместить данные из регистра процессора в место в памяти или наоборот. На самом деле существует много различных инструкций "mov", для обработки 8-битных, 16-битных, 32-битных данных, для перемещения данных из разных регистров и так далее.

вы можете забрать доктора Пола Картера PC Assembly Language Tutorial это бесплатная книга начального уровня, которая рассказывает о сборке и о том, как Intel 386 CPU работает. Большинство из них применимо даже к современным процессорам Intel.

формат EXE специфичен для Windows. Точка входа (т. е. первая исполняемая инструкция) обычно находится в одном и том же месте в EXE-файле. Все это трудно объяснить сразу, но ресурсы, которые я предоставил, должны помочь вылечить хотя бы часть вашего любопытства! :)


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


исполняемый файл, который вы видите, имеет формат Microsofts PE (Portable Executable). Это, по сути, контейнер, который содержит некоторые данные операционной системы о программе, а сами данные программы разделены на несколько разделов. Например, код, ресурсы, статические данные хранятся в отдельных разделах.

формат раздела зависит от того, что в нем. Раздел кода содержит машинный код в соответствии с исполняемой целевой архитектурой. В наиболее распространенных случаях это является Intel x86 или AMD-64 (так же, как EM64T) для двоичных файлов Microsoft PE. Формат машинного кода-CISC и начинается с 8086 и более ранних версий. Важным аспектом CISC является то, что его размер инструкции не является постоянным, вы должны начать читать в нужном месте, чтобы получить что-то ценное из него. Intel публикует хорошие руководства по набору инструкций x86/x64.

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

и затем есть MSIL EXE: исполняемые файлы .NET, содержащие промежуточный язык Microsofts, они не содержат машинного кода, но .NET CIL-код. Спецификации для этого доступны онлайн на ECMA.

эти можно осмотреть с инструментом как рефлектор.


содержимое EXE-файла описано в Портативный Исполняемый Файл. Он содержит код, данные и инструкции для ОС о том, как загрузить файл.

существует сопоставление 1:1 между машинным кодом и сборкой. Программа disassembler выполнит обратную операцию.

на i386 нет фиксированного количества байтов на инструкцию. Некоторые из них представляют собой один байт, некоторые намного длиннее.


вы можете использовать debug из командной строки, но это сложно.

C:\WINDOWS>debug taskman.exe
-u
0D69:0000 0E            PUSH    CS
0D69:0001 1F            POP     DS
0D69:0002 BA0E00        MOV     DX,000E
0D69:0005 B409          MOV     AH,09
0D69:0007 CD21          INT     21
0D69:0009 B8014C        MOV     AX,4C01
0D69:000C CD21          INT     21
0D69:000E 54            PUSH    SP
0D69:000F 68            DB      68
0D69:0010 69            DB      69
0D69:0011 7320          JNB     0033
0D69:0013 7072          JO      0087
0D69:0015 6F            DB      6F
0D69:0016 67            DB      67
0D69:0017 7261          JB      007A
0D69:0019 6D            DB      6D
0D69:001A 206361        AND     [BP+DI+61],AH
0D69:001D 6E            DB      6E
0D69:001E 6E            DB      6E
0D69:001F 6F            DB      6F

Если это так же чуждо вам, как кажется, я не думаю, что отладчик или дизассемблер поможет - вам нужно сначала изучить программирование ассемблера; изучить архитектуру процессора (много документации, загружаемой из Intel). И затем, поскольку большинство машинного кода генерируется компиляторами, вам нужно понять, как компиляторы генерируют код - самый простой способ написать много небольших программ, а затем разобрать их, чтобы увидеть, во что превращается ваш C/C++.

A пара книг, которые помогут вам понять:-


чтобы получить идею, установите точку останова на каком-то интересном коде, а затем перейдите в окно CPU.

Если вас интересует больше, проще скомпилировать короткие фрагменты со свободным Паскалем, используя параметр-al.

FPC позволяет выводить сгенерированный ассемблер во множестве форматов ассемблера (TASM,MASM,GAS ) с помощью параметра-A, и вы можете иметь исходный код pascal, чередующийся в комментариях (и более) для удобства перекрестной связи.

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


Win32 exe формат на MSDN

Я бы предложил взять немного исходного кода Windows C и построить и начать отладку в Visual Studio. Переключитесь в режим разборки и выполните команды. Вы можете увидеть, как код C был скомпилирован в машинный код, и наблюдать, как он выполняется шаг за шагом.


просто касаясь этого вопроса, кто-нибудь все еще читает такие вещи, как CD 21?

Я вспомнил Сандру Буллок в одном шоу, на самом деле читая экран, полный шестнадцатеричных чисел и выяснить, что делает программа. Что-то вроде текущей версии кода матрицы чтения.

Если Вы читаете такие вещи, как CD 21, Как вы помните различные различные комбинации?


и ваше любопытство, и ваш уровень понимания-это именно то, где я был в какой-то момент. Я!--1-->очень рекомендую код: скрытый язык компьютерного оборудования и программного обеспечения. Это не ответит на все вопросы, которые вы задаете здесь, но прольет свет на некоторые из совершенно черных магических аспектов компьютеров. Книга толстая, но читабельная.


ACD See, вероятно, использует этот факт .EXE-файлы не проверяют длину файла или что-либо за пределами длины ожидаемой части файла. Из-за этого вы можете сделать.EXE-файл, который откроет себя и загрузит все за пределами данной точки в качестве данных. Это полезно, потому что вы можете сделать a.EXE, который работает на заданном наборе данных, просто лавируя эти данные в конце подходяще написанного .EXE

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


знакомство с низкоуровневой сборкой (и я имею в виду низкоуровневую сборку, а не "макросы" и этот бык), вероятно, является обязательным. Если вы действительно хотите прочитать сам исходный машинный код напрямую, обычно для этого используется шестнадцатеричный редактор. Однако, чтобы понять, что делают инструкции, большинство людей будут использовать дизассемблер для преобразования этого в соответствующие инструкции по сборке. Если вы принадлежите к меньшинству, которое хочет понять сам машинный язык, я думаю, вы захотите руководства разработчика программного обеспечения Intel® 64 и IA-32 Architectures. Раздел 2 в частности, охватывает набор инструкций, который относится к вашему запросу о том, как читать сам машинный код и как сборка относится к нему.