Комментарии 18
Разместите вторую gif-ку покадрово, пожалуйста.
Эх. Помню я как-то я журнале ZX-формат соревновались у кого меньше байт будет для плавной гасилки экрана. Вот были времена, когда программу в 21 байт укладывали.
А где текст самой программы? Наверняка, общими усилиями сможем сделать меньше
Ещё не всё прочитал, но навскидку:
Существующие примеры программ размером 268 байт не содержат ни одной секции, и фактически, целиком помещаются внутри заголовка PE, для загрузки которого Windows выделяет одну страницу памяти (4КБ).Для загрузки заголовка выделяется
ALIGN_UP(SizeOfHeaders, max(SectionAlignment, PAGE_SIZE))
. Так что можно поставить SizeOfHeaders больше страницы и без секций обойтись.На WinXP моя программа, к сожалению, не работает: та отказывается загружать программы, у которых в каталоге менее 0xD записей.Там просто часть кода поддержки совместимости смотрит на Directories[DEBUG].Size, не проверяя, что DEBUG действительно есть. Если выставить соответствующий dword в нуль, всё будет работать.
Минуточку. На XP SP3 оно вполне работает. (DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].Size у вас хоть и не 0, но 3, но пока оно меньше 0x1C, это нормально.) При отсутствии IMAGE_DIRECTORY_ENTRY_IAT = 0xC в XP есть засада, что таблица импорта должна быть в какой-нибудь секции, не в заголовке, но это проблема, только если делать программу целиком в заголовке без секций.
Как-то странно оно работает. Один и тот же файл запускаю — то запускается нормально, то выскакивает «Application Error: The application failed to initialize properly (0xc000007b). Click on OK to terminate the application.»
Поди, опять что-нибудь связанное с файловым кэшем.
(Всё равно спасибо за подсказку! Исправил пост, чтобы указать, что на WinXP программа иногда работает.)
Поди, опять что-нибудь связанное с файловым кэшем.
(Всё равно спасибо за подсказку! Исправил пост, чтобы указать, что на WinXP программа иногда работает.)
У меня на виртуалке запускается совершенно стабильно. Ошибка явно от юзермодного загрузчика, ему на файловый кэш должно быть ну совсем пофиг.
WinDbg на машине есть?
WinDbg на машине есть?
WinDbg есть, но не помогает — ошибка вываливается ещё до

Не исключено, что это шалит стоящий на машине антивирус (Symantec), но с ним я сделать ничего не могу — машина не моя, я только запустил программу.
DbgBreakPoint
внутри LdrpInitializeProcess
:
Не исключено, что это шалит стоящий на машине антивирус (Symantec), но с ним я сделать ничего не могу — машина не моя, я только запустил программу.
У WinDbg в настройках можно включить Debug -> Event filters -> Create process -> enabled, перезагрузить процесс, сделать bu ntdll!LdrInitializeThunk, g, и отлаживать совсем с начала.
Но у меня появилась мысль, что может быть не так.
Но у меня появилась мысль, что может быть не так.
часть таблицы импорта (последние 0x16 её байт нулевые, и в файле не хранятся)Если честно добить файл нулями, проблема будет воспроизводиться?
Окей, исключение прилетает отсюда:
Выше по стеку вызовов — только
Да.
ntdll!_LdrpInitialize+0x178: 7c84a446 57 push edi 7c84a447 e85e530100 call ntdll!LdrpInitializationFailure (7c85f7aa) 7c84a44c 57 push edi 7c84a44d e890e0fdff call ntdll!RtlRaiseStatus (7c8284e2) 7c84a452 cc int 3
Выше по стеку вызовов — только
ntdll!KiUserApcDispatcher+0x25
Если честно добить файл нулями, проблема будет воспроизводиться?
Да.
Естественно. LdrpInitializeProcess возвращает 0xC000007B, а уже верхний уровень бросает исключение.
Тупой способ выяснить, откуда оно — после останова на LdrInitializeThunk выполнить команду
подождать, посмотреть, где остановилось, и посмотреть команды перед этим — чтобы понять, почему управление дошло до этой ветки кода.
Более интеллектуальный — настроить символы
(папку c:\symcache потом можно почистить), поставить
Тупой способ выяснить, откуда оно — после останова на LdrInitializeThunk выполнить команду
r;t;z(eax!=c000007b)
подождать, посмотреть, где остановилось, и посмотреть команды перед этим — чтобы понять, почему управление дошло до этой ветки кода.
Более интеллектуальный — настроить символы
.sympath SRV*c:\symcache*http://msdl.microsoft.com/download/symbols
.reload
(папку c:\symcache потом можно почистить), поставить
bp ntdll!LdrpSnapIAT
, дождаться второго срабатывания (первый вызов — для kernel32 -> ntdll) и запустить команду выше уже с этого момента.При отсутствии IMAGE_DIRECTORY_ENTRY_IAT = 0xC в XP есть засада, что таблица импорта должна быть в какой-нибудь секции, не в заголовке, но это проблема, только если делать программу целиком в заголовке без секций.
Возвращаясь к старой теме: у меня на Windows 10, если нет секций и загружается только заголовок, то импорты не резолвятся. Получается, что программу без секций вообще нет смысла делать: десять лишних IMAGE_DATA_DIRECTORY занимают намного больше места, чем одна IMAGE_SECTION_HEADER.
Для загрузки заголовка выделяется ALIGN_UP(SizeOfHeaders, max(SectionAlignment, PAGE_SIZE)). Так что можно поставить SizeOfHeaders больше страницы и без секций обойтись.
А можно пример? А то у меня с
SizeOfHeaders
больше 0x1000 прога напрочь отказывается загружаться.На XP и семёрке, казалось бы, никаких проблем: yadi.sk/d/4yHs4lWioPtmW
В восьмёрке добавили несколько странную проверку, что EntryPoint должна быть либо 0, либо не меньше SizeOfHeaders, причём 0 для exe-шника — валидное значение (MZ = dec ebp, pop edx), так что можно так: yadi.sk/d/jY0Tn_lSoPvGc
Но вообще формула выше — таки только для ветки с SectionAlignment >= PAGE_SIZE, на ветке с SectionAlignment < PAGE_SIZE весь файл просто маппится одним куском, так что можно просто сделать ImageSize побольше и даже не менять SizeOfHeaders: yadi.sk/d/c_Oc3oyooPwS8
В восьмёрке добавили несколько странную проверку, что EntryPoint должна быть либо 0, либо не меньше SizeOfHeaders, причём 0 для exe-шника — валидное значение (MZ = dec ebp, pop edx), так что можно так: yadi.sk/d/jY0Tn_lSoPvGc
Но вообще формула выше — таки только для ветки с SectionAlignment >= PAGE_SIZE, на ветке с SectionAlignment < PAGE_SIZE весь файл просто маппится одним куском, так что можно просто сделать ImageSize побольше и даже не менять SizeOfHeaders: yadi.sk/d/c_Oc3oyooPwS8
если хотя бы одна секция объявлена, то FileAlignment должен быть не меньше 0x200, а SectionAlignment должен быть 0x1000
Строго говоря, можно. Например, если размеры всех секций кратны 0x1000, то проблем не будет и при SectionAlignment, меньшем размера страницы. (Вообще-то, соответствующий код в подсистеме WOW64 писался не под энтузиастов минимизации вроде нас с вами, а ровно под такую ситуацию. Конкретно — эмуляция x86 на Itanium, где винда использует размер страницы 0x2000.) Но не очень полезно — если честно записывать все дополняющие нули в файл, то о минимизации размера можно забыть, а если не писать, то винда от такой наглости может даже в BSOD выпасть. (ЕМНИП починили где-то между XP SP1 и SP2. Это к вопросу о винтажности. Хотя, конечно, истинно винтажная система — Windows 95.)
Зарегистрируйтесь на Хабре, чтобы оставить комментарий
«Digital Rain» для Windows в 314 байтах