Как писать и выполнять Windows.exe вручную (машинный код с шестнадцатеричным редактором)?

Я хотел бы знать, как можно написать что-то столь же простое, как программа Hello World, просто используя Hex Editor. Я знаю, что я мог бы использовать ассемблер и язык ассемблера для этого на уровне около машины, но я просто хочу поэкспериментировать с написанием машинного кода на примере игрушек, например Hello World.

Это может быть простой файл DOS.COM, который можно запустить в DOSBox. Но было бы неплохо, если бы кто-то мог предоставить пример файла .EXE для его запуска непосредственно на моем ПК с ОС Windows.

Это просто любопытство. Нет... Я не собираюсь писать программы непосредственно в двоичном машинном коде (я даже не пишу код сборки, я просто использую C/С++ в качестве инструментов самого низкого уровня большую часть времени). Я просто хочу посмотреть, возможно ли это сделать, потому что, вероятно, кто-то должен был сделать это в самые ранние дни компьютеров.

P.S.: Я знаю, что есть похожие вопросы по этой теме, но ни один из них не дает рабочего примера. Я просто хочу простой пример, чтобы он мог помочь мне понять, как компиляторы и сборщики генерируют исполняемый файл. Я имею в виду... кто-то должен был сделать это вручную в прошлом для самых первых программ. Кроме того, для формата Windows EXE должен был быть кто-то из Microsoft, который написал первые инструменты для создания формата и того, как Windows сама его читает, а затем выполняет его.

Ответ 1

Там довольно минималистический, но полностью работающий (на Win7 тоже) exe на corkami/wiki/PE101, каждый байт этого объясняется в хорошем графический. Вы можете вводить все это вручную в шестнадцатеричном редакторе, но paddings могут сделать это немного утомительным.

Что касается истории, то кто-то из Microsoft придумал формат exe (старый формат DOS MZ exe), и он (или кто-то еще в Microsoft) написал загрузчик для него и компоновщик, что является тем, что традиционно превращает вывод компилятора ( "объектных файлов" ) в исполняемые файлы. Возможно (и, скорее всего, я бы сказал), что первые программы exe были написаны вручную, ведь они были предназначены только для тестирования нового загрузчика.

Позднее формат AT & T COFF был расширен Microsoft в формате PE, который по-прежнему имеет заголовок MZ и обычно (но, возможно, не в примере corkami, и это может быть что-то действительно) включает небольшую программу DOS просто для печати сообщения "Эта программа не может быть запущена в режиме DOS".

Ответ 2

1).com файл - это самое простое место для запуска и запускается в dosbox, в основном программа начинается с чего-то вроде смещения 0x100 в файле, я думаю, что первый 0x100 может быть любым, не помните

2), хотя верно, что первые программы часто пишутся и собираются вручную в машинный код, мы говорим о том, когда вы добавляете два числа, сохраняя их в памяти, и так счастливы, что вы берете оставшуюся часть выходного дня. программа "привет мир", которая печатает материал на видеокарте, значительно сложнее. Теперь вы можете сделать очень простой, используя системные вызовы dos, и, возможно, это не то, что вас интересует, возможно, это так.

3) на основе 2, что-то более сложное, чем одно или несколько инструкций за один раз для тестирования еще в 1960-х или 1970-х годах, даже когда вы пишете ручную сборку программы, вы пишете свою программу на ассемблере вручную, а затем собираете ее машинный код, затем загрузите его. Сначала изучите язык ассемблера, затем научитесь генерировать машинный код для него, а затем начните вводить эти байты в шестнадцатеричный редактор. Это не тогда 1960-е, если вам не нравится чрезмерная боль, изучите выше, написав asm, используя ассемблер для генерации машинного кода, затем используйте дизассемблер, чтобы разобрать его, и изучите язык ассемблера и машинный код бок о бок, чтобы значительно улучшить сколько времени потребуется, чтобы получить рабочую программу. Если вы работали в компании-чипе до того, как появились операционные системы и наборы инструкций, вы все равно воспользовались бы другими членами команды, разработчиками чипов и т.д., Чтобы понять, как сделать машинный код и организовать его. Вы бы не пришли к этому только с высоким уровнем языкового опыта и сделали все это самостоятельно, надеясь на успех.

4) x86 - это ужасный набор команд, если вы не знаете сборки, я категорически не рекомендую вам не изучать его в первую очередь. наличие x86 - худшее оправдание, которое я слышал, чтобы сначала изучить x86. вы уже упоминали dosbox, так что уже планируете эмулировать/имитировать, поэтому используйте хороший набор команд и имитируйте его или купите это оборудование (до 50 долларов США даже до 20 долларов вы купите вам плату с гораздо лучшими наборами инструкций). Я рекомендую сначала имитировать/эмулировать и параллельно с оборудованием, если вы решите купить их. Если вы действительно хотите, чтобы образование записывало ваш собственный симулятор, это совсем не сложно. Возможно, придумайте свой собственный набор инструкций.

5) У меня есть сборник симуляторов и других голых металлических ресурсов http://github.com/dwelch67 msp430 неплох, вы можете получить аппаратное обеспечение менее 5 долларов США, если вы чувствуете необходимость. Рука хорошая, как на основе 32/16 (малиновый pi, sam7s и т.д.), Так и на 16-битном пальце (на основе коры головного мозга, mbed, клен-мини, обнаружение stm32f4 и т.д.). Янтарный симулятор поступает из процессора opencores, который я имитирую с помощью verilator, поэтому вы можете, если у вас есть преимущество, посмотреть в процессор, чтобы посмотреть, что происходит на уровне сигнала. thumbulator не требует ничего, кроме компилятора c/С++ для его запуска и запуска, "двоичного" формата файла вы можете ввести "машинный код" в шестнадцатеричном виде и просто пойти на него, с шестнадцатеричным редактором вы все равно будете это делать. У меня есть набор симуляторов набора инструкций на выбор, плюс примеры для голого металла, встроенного на некоторые платы стоимостью от $5 до $80.

6) ничто из этого не поможет вам понять, что делает компилятор. Знание языка ассемблера, тогда разобрать вывод компиляторов - ваш лучший путь к этому знанию, машинный код не задействован, нет необходимости запускать программы. Компилятор переходит от языка более высокого уровня к языку более низкого уровня (например, C в asm или С++ в asm). Тогда поймите, что делает ассемблер, есть много разных решений, как из-за истории, так и из-за других причин. Типичным решением сегодня является отдельный компилятор, ассемблер и компоновщик (ваш компилятор называет ассемблер и компоновщик для вас, если вы не скажете, что это не так, три шага скрыты от представления, на самом деле процесс компиляции может быть более чем одной программой, которая для выполнения этой задачи). Ассемблерам, которые выводят двоичный файл, придется разрешить всю программу, ассемблеры, которые выводят на объект, оставят в машинный код для компоновщика заполнение отверстий. Такие вещи, как ветвление или вызов элементов в другом объекте, которые он не может кодировать до тех пор, пока место компоновщика не будет вещи в двоичном формате и знает интервал/адресацию. Также доступ к переменным, которые живут в других объектах.

Вероятно, вы не видите фактических примеров по hex-редактированию программы, потому что сначала это такой широкий вопрос, что нет простого ответа (что работает, система, какие системные вызовы или вы создаете их, какой формат файла, какой hex редактор и т.д.). Кроме того, поскольку это вопрос высокого уровня и проблема, реальные вопросы - вот где я изучаю сборку, где я узнаю о взаимосвязи между сборкой и машинным кодом, где я узнаю о системных вызовах (которые не являются вопросом сборки, они не связаны с обучением asm, вы сами изучаете язык ассемблера, тогда вы научитесь использовать его как инструмент для выполнения системных вызовов, если вы не можете выполнять системные вызовы напрямую с использованием более высокого языка), где я узнаю об исполняемых форматах файлов, таких как .com,.exe, coff, эльф и т.д. Что такое хорошее или простое или какое-то прилагательное, шестнадцатеричный редактор, который работает в операционной системе xyz или в среде. Задайте эти вопросы отдельно, и вы найдете ответы и примеры, и как только у вас появятся ответы, вы узнаете, как сделать программу, используя шестнадцатеричный редактор, вводящий машинный код. Более короткий пример: вы видите шестнадцатеричные примеры полных программ, когда вы видите разборку программы, размещенной в SO, некоторые из них - это полные программы, показанные в шестнадцатеричном формате. и если вы знаете формат файла, вы можете просто ввести этот материал в шестнадцатеричный редактор.

Ответ 3

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

  • Самый простой - это, конечно, формат DOS COM, который вы можете даже ввести в блокнот, или, по крайней мере, очень легко даже для нормального Hello World.

  • EXE (формат не DOS) не требует многого, либо см. здесь.

  • Если вы пытаетесь сделать PE, вы можете сделать TinyPE.

Большинство двоичных файлов должны быть доступны как PE, и EXE и COM.

Ответ 4

Не на месте, но этот урок должен дать вам лучшее представление о том, как сборочные карты для кода machinde (x86 ELF): http://timelessname.com/elfbin/ (особенно посмотрите на нижнюю половину страницы)

Эта страница [...] о моих попытках создать наименьший двоичный файл x86 ELF, который выполнит команду Hello World на Ubuntu Linux. Мои первые попытки, начатые с C, перешли на сборку x86 и, наконец, в hexeditor.

Хорошо анализировать действительно маленькие исполняемые файлы, подобные этим, потому что сопоставление между сборкой и машинным кодом будет легче обнаружить. Это также очень интересная статья по этому вопросу (не совсем связанная с вашим вопросом): http://www.phreedom.org/research/tinype/ (x86 PE)

Ответ 5

вы можете сделать разборку и попытаться выяснить код машины для кодов операций, которые вы используете в своем ассемблере

например

org 0x100
mov dx,msg
mov ah,0x09
int 0x21
ret
msg db 'hello$'

скомпилированный с помощью nasm -fbin./a.asm -o./a.com имеет ndisasm a.com доставить следующую разборку:

00000000  BA0801            mov dx,0x108
00000003  B409              mov ah,0x9
00000005  CD21              int 0x21
00000007  C3                ret
00000008  68656C            push word 0x6c65
0000000B  6C                insb
0000000C  6F                outsw
0000000D  24                db 0x24

00000000 to 00000007 are the instructions

чтобы вы могли играть с машинным кодом ba0801, используя какой-то шестнадцатеричный редактор, попробуйте изменить его на ba0901, и будет напечатано только "ello", вы можете поиграть с вашим шестнадцатеричным редактором и пэдом с NOP, что 0x90 в машинный код, например:

00000000:  ba 50 01 90 90 90 90 90  90 90 90 90 90 90 90 90  [email protected]
00000010:  b4 09 90 90 90 90 90 90  90 90 90 90 90 90 90 90  ................
00000020:  cd 21 90 90 90 90 90 90  90 90 90 90 90 90 90 90  .!..............
00000030:  c3 90 90 90 90 90 90 90  90 90 90 90 90 90 90 90  ................
00000040:  71 77 65 72 74 79 75 69  61 73 64 66 67 68 6a 24  qwertyuiasdfghj$
00000050:  61 73 64 66 67 68 6a 6b  61 73 64 66 67 68 6a 24  asdfghjkasdfghj$
00000060:  -- -- -- -- -- -- -- --  -- -- -- -- -- -- -- --  ----------------

если вы сохраните его с расширением .com, вы можете запустить его в DosBox

Ответ 6

Я написал статью о создании исполняемых двоичных файлов DOS, просто используя ECHO в командной строке. Никакие другие сторонние утилиты HEX или x86 IDE не требуются!

В этой технике используется комбинация клавиш - ALT ASCII-кодов, которые преобразуют OPCODES в двоичный формат, читаемый непосредственно под MSDOS. Вывод представляет собой полностью исполняемый двоичный *.com файл.

http://colinord.blogspot.co.uk/2015/02/extreme-programming-hand-coded.html

Выдержки: Введите следующие команды клавиш в приглашении DOS, чтобы сохранить Left ALT.

c:\>Echo LALT-178 LALT-36 LALT-180 LALT-2 LALT-205 LALT-33 LALT-205 LALT-32 > $.com

Указанные выше коды фактически представляют собой значения кода операции, описывающие программу сборки X86, для печати знака доллара на экране.

Ваше сообщение должно выглядеть примерно так, как показано ниже. Нажмите enter для сборки!

c:\>Echo ▓$┤☻═!═  > $.com

Запустите файл "$.com", и на экране появится один символ доллара ($).

c:\>$.com
$
c:\> 

Поздравляем! Вы только что создали свой первый исполняемый файл с именем $.com.