Пошаговое руководство к исполняемым файлам (EXE) Windows

  • Tutorial


English: PDF JPG SVG
Русский: PDF PNG SVG

Автор: Эндже Альбертини (Ange Albertini)
Перевод на русский: Lyr1k
  • +151
  • 26,8k
  • 39
Поделиться публикацией
Комментарии 39
    +17
    ИМХО, «Подробный разбор исполняемых файлов Windows» больше соответствует теме.
      +1
      Немного не так :) Для подробного разбора тут кое-какие детали упущены, но работа несомненно визуально приятная. Единственный терзающий лично меня вопрос — зачем она?

      Для интересующихся темой:

      www.zotteljedi.de/pub/pe.txt (LUEVELSMEYER, «The PE file format»)
        +2
        Привычный Хард Виздом хоть и устарел, но куда приятней читается и проще понимается.
          0
          Спасибо, хороший материал. Странно что не знал о нем. BTW, а каким годом он датируется?
            0
            Мне он был известен еще в 2004-м. Но сами знаете системный загрузчик описать в мануале сложный, тут лучшей командой послужит IDA. Ну а практика на corcami-файлах только отшлифует полученные знания ;)
      +9
      О. Подходящий случай, чтобы посоветовать несколько годных статей со старичка wasm.
        +9
        Это не руководство, а общая схема. Здесь нет и 10%.
          +4
          Присоединюсь, к примеру не разобраны:
          * TLS
          * Bound-ы
          * Fixups
          * Resourse-ы
          * Delay-импорты
          и др.
          –20
          А потом пишете вири, ломающие половину файлов.
            +2
            Плохой, негодный картинко. Ничего толком не понятно. Я уж было решил, что раз ничего не понимаю, в MZ-PE что-то новое нашли…
              +1
              Помнится, когда я учился в университете, наш преподаватель по информатике обещал поставить зачет автоматом тем, кто скажет, почему все файлы начинаются с 'MZ'… Наконец то я узнал, кто во всем этом виноват :)
                +1
                Возможно Ваш препод хотел знать исторические причины.
                Эти 'MZ' ничто иное как «Марк Збиковски». Когда перед Microsoft встала задача о разработке нового формата для исполнимых файлов, то они задались вопросом: «Раз для пользователей популярным расширением является 'exe', то как пояснить пользователю DOS-приложения, что этот файл не должен запускаться под DOS?». Ответом на этот вопрос был «Надо разработать минимальную программу под DOS с целью вывода надписи и поместить ее в новом формате файла». Именно по этой причине можно наблюдать эту минимальную программу, называемую в простонародье «DOS-стаб». Именно из-за решения о помещении dos-стаба в каждый исполнимый файл формата PE и приходится наблюдать этот рудимент 'MZ'.
                  0
                  Вот только не ясно, почему в Microsoft не сделали подобную заглушку для .NET приложений.
                  Windows XP при отсутствии .NET выдаёт:
                  Application Error
                  The application failed to initialize properly (0xc0000135). Click on OK to terminate the application.

                  И как пользователю догадаться, что нужно установить .NET framework?
                  Интересно, какую ошибку выдаст Windows 7 при отсутствии .NET 4 и попытке запустить программу, использующую последнюю версию фреймворка.
                    0
                    >>почему в Microsoft не сделали подобную заглушку для .NET приложений.
                    Почитайте внимательней мат.часть на предмет развития и появления .NET. Эта технология развилась благодаря COM-технологии. А все эти Ко-Сервера, Ко-Клиенты ничто иное как исполнимые файлы прописанные в реестре.

                    >>И как пользователю догадаться, что нужно установить .NET framework?
                    Это должен разработчик заботится. При написании инсталяционного скрипта для продукта он должен обнаружить нужное и выдать сообщение чего не хватает.
                      0
                      Почитайте внимательней мат.часть на предмет развития и появления .NET. Эта технология развилась благодаря COM-технологии. А все эти Ко-Сервера, Ко-Клиенты ничто иное как исполнимые файлы прописанные в реестре.
                      Не связывался с COM, но хорошо представляю, как загружаются .net приложения. Система вместе с исполняемым файлом загружает mscoree.dll передаёт управление _CorExeMain, а не нативной точке входа в exe файле. На системах до Windows XP, где загрузчик не подозревает о существовании .net, исполняемый файл загружается обычным образом, и для того, чтобы .net приложения могли загружаться и в старых системах, в каждой сборке есть небольшой stub для Windows, состоящий из одной команды:
                      jmp _CorExeMain
                      Так вот что мешает написать вместо этой одной команды небольшую программу, которая бы определяла наличие .net, и при его отсутствии давала бы внятное сообщение об ошибке? А обучив загрузчик Windows XP распознавать и загружать .net сборки без участия этого jmp ничего не мешало также позаботиться о нормальном сообщении об ошибке.
                      Почему исполняемые файлы .net выводят внятную ошибку при попытке запуска под DOS, но под более новой Windows они не могут этого сделать? Для меня это загадка.
                      Это должен разработчик заботится. При написании инсталяционного скрипта для продукта он должен обнаружить нужное и выдать сообщение чего не хватает.
                      Да, так говорит Microsoft. Но пользователю никто не запрещает запустить уже установленную программу после переустановки операционной системы. Писали бы в ошибке тогда «Переустановите программу».
                    0
                    И да, ко всему этому все файлы .NET содержат в себе досовскую заглушку с «This program cannot be run in DOS mode». Хотя, ИМХО, уже давно досовский стаб можно было выкинуть, оставив только MZ заголовок со ссылкой на PE. А вот для Windows без .NET не помешал бы внятный обработчик. А ещё лучше. чтобы он предлагал скачать нужную версию .NET :)
                      0
                      Выкинуть полностью стаб не получится, поскольку его наличие — требование ОС Windows (к EXE), которая в свою очередь полна рудиментов и помимо этого.
                        0
                        Нет такого требования. Необходимо оставить DOS header, но при этом код, который выводит сообщение «This program cannot be run in DOS mode» можно выкинуть. Посмотрите любую демку 64k — там нет стандартной заглушки. Некоторые даже совмещают DOS заголовок и PE заголовок. Вот, поглядите: www.phreedom.org/research/tinype/
                          0
                          O RLY? :) первый же пример: «Smallest possible PE file: 97 bytes» начинается с 0x4D 0x5A
                            0
                            Читайте внимательно. MZ — это часть DOS заголовка. Заглушки, выводящей «This program cannot be run in DOS mode» там нет.
                              0
                              Ох… без MZ ваша «заглушка» и запускаться-то не будет :) Это все (включая MZ) и есть stub-программа… и не важно, есть там потом вывод текста или нет.
                                0
                                Нет, stub-программы там нет, один только DOS заголовок без кода не может являться программой (нечего исполнять).
                                  0
                                  Ok. А зачем DOS-заголовок программе для WIN?
                                    0
                                    Так исторически сложилось. Загрузчик откажется загружать файл без сигнатуры MZ и может быть пары полей в DOS-заголовке.
                                      0
                                      А почему система откажется исполнять файлы без сигнатуры MZ в этом случае?
                                        0
                                        В каком случае? :)
                                          0
                                          В рассматриваемом гипотетическом…
                                            0
                                            Вы издеваетесь? Я же написал: так сложилось исторически.
                                            Загрузчик ищет адрес заголовка PE в DOS заголовке, а перед этим очевидно проверяет корректность самого DOS заголовка (то же наличие сигнатуры MZ). Ну а DOS заголовок (как сложилось исторически) должен быть в начале файла.
                                              0
                                              Все в жизни складывается «исторически», но это не отменяет причинно-следственную связь. Без DOS-заголовка EXE-файл для системы не является исполняемым, т.е. не является «программой». Поэтому система даже и не попытается что-то запустить не увидев эту комбинацию.

                                              DOS-header — это заголовок DOS-программы (а именно ее декларативная часть), которую содержит в себе любой исполняемый EXE-файл в целях обратной совместимости.

                                              К слову, COM-файлы никаких деклараций не содержат и например минимальная программа может занимать два байта (0xCD 0x20). С EXE это не так.

                                              Таким образом, любой исполняемый файл WIN-программы содержит в себе полезного паразита в виде DOS-программы (заглушки, STUB и т.д.), который в системе DOS преспокойно запускается и завершает обработку исполняемого файла (для DOS все эти PE и далее — просто мусор). А в Windows система считывает offset PE, лежащего в зарезервированном поле DOS-заголовка. Но этот факт не дает права называть DOS-заголовок частью WIN-программы. DOS-заголвок — это часть DOS-программы.

                                              p.s. В конце-концов у того же Luevelsmeyer'а: «For PE-files, it is a MS-DOS 2.0 compatible executable… that output an error message such as „this program needs windows NT“. You recognize a DOS-stub by validating the DOS-header, being a struct IMAGE_DOS_HEADER.»
                                                0
                                                Всё верно. Но никто ведь не мешает выкинуть весь код DOS-программы, оставив только DOS-заголовок (а точнее сигнатуру MZ и поле со смещением PE), что и сделано в примере запускаемого под Windows PE файла объёмом 97 байт.
                                                  0
                                                  :) Оставить DOS-заголовок !== выкинуть весь код DOS-программы
                                                    0
                                                    Тут зависит от того, что вы понимаете под программой.
                                                    com-файл — это чисто программный код. exe-файл — это пачка заголовков плюс код. Я понимаю так, что любая программа должна содержать код, а заголовки — это служебная информация. То есть, если мы выкидываем код заглушки для DOS, оставляя лишь заголовок — да, это больше не программа для DOS, это просто заголовок.
                                                    Вы же считаете, что заголовок — это уже программа. Но ведь такая программа не запустится под DOS, потому что у неё некорректная точка входа. Либо 0, либо какой-то случайный мусор (в случае наложения MZ и PE заголовков). Были бы там хотя бы mov ax, 4C00h и int 21h для корректного завершения пустой программы — вопросов бы не было.
                                                    В общем, предлагаю закончить этот глупый спор.
                                                      0
                                                      Программа — это последовательность действий. Но и последовательность может иметь изначальные правила, которые являются неотъемлемой частью.

                                                      Декларация в заголовке — это также часть программы. Без DOS- и/или PE-заголовка ваш код в EXE тоже работать не будет, так как помимо прочего там важные параметры заданы — такие как выравнивания.

                                                      p.s. Я то как раз и не спорю, а пытаюсь показать где именно Вы не правы :)
                            0
                            Еще по теме: www.wasm.ru/print.php?article=1005005

                            (и к слову, не надо отделять заголовок DOS от стаб программы).
                            0
                            Уже не только Windows-specific. Даже в EFI протолкнули ) Так что х.з. когда люди забудут эти 'MZ'…
                            0
                            >>уже давно досовский стаб можно было выкинуть, оставив только MZ
                            Все эти «некрасивости» никак не мешают обычной и штатной работоспособности приложений, а если учесть что обычный стаб даже 200 байт не весит и вспомнив размеры современных жестких, то как-то глупо париться по этому поводу.

                            >>А ещё лучше. чтобы он предлагал скачать нужную версию .NET :)
                            +1, заводи задачу в Мелкософт-баг-трекере!
                          0
                          Либо ZM, абсолютно аналогично
                          –1
                          Отличная работа. Но грузится долго… да и в работе мне вряд ли пригодиться )
                            –1
                            Вот еслиб сделали такое про файлы с байткодом Java, Python или .NET, было бы более актуально.

                          Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                          Самое читаемое