Как стать автором
Обновить
103
0
Евгений Гречников @grechnik

Пользователь

Отправить сообщение
> 00400000 00400104
Выглядит как 260 байт.
ntvdm.exe тоже загружает kernel32.
Как MZ-stub, ага. В Process Monitor посмотрите — ntvdm.exe там запускается.
Это для совсем старых систем, до какого-то сервиспака XP. На XP SP3 и позже уже минимум 252 байта (4 + sizeof(IMAGE_NT_HEADERS32)).
Ну включите флаг IMAGE_FILE_RELOCS_STRIPPED = 1 в IMAGE_FILE_HEADER.Characteristics (смещение +16h от начала PE-заголовка, 2 -> 3). Будет работать и с принудительным ASLR.
Теоретически — должен. Если SectionAlignment < PageSize, то ядро маппит вообще всё, начиная с заголовка, как PAGE_EXECUTE_READWRITE. 32-битный загрузчик из WOW64-подсистемы потом пытается исправить атрибуты секций (из-за чего файлы, просто собранные с /align:16, и падают), но не трогает заголовок.
Практически — не проверял.
Теоретически минимальный размер файла, способного запускаться на x64, — 268 байт (4 + sizeof(IMAGE_NT_HEADERS64)). И если «не стесняться кромсать всё, что создал компилятор» и вообще делать PE-файл руками, то такой файл сделать можно: code.google.com/archive/p/corkami/wikis/PE.wiki, «universal tiny PE» (там есть ссылка «nightly builds», ведущая на dropbox, в котором есть архив pe.rar, в котором есть файл tiny.exe). Он выводит строку " * 268b universal tiny PE" вместо «Hello, World!».
Там сравнение хэша от имени с магической константой.
Возьмите любой драйвер.
Если настаиваете именно на exe-шнике — вот банальный MessageBox с FileAlignment = SectionAlignment = 0x20: yadi.sk/d/385e5Lhqnkybi. На 32-битной XP точно работает.
Хм, интересно. Win8.1, говорите?
На Win7 ожидаемо фейлится с STATUS_OBJECT_TYPE_MISMATCH:
Картинка


Восьмёрки под рукой нет. Посмотрел в 32-битной Win10, и там таки действительно консольный хэндл — настоящий ядерный хэндл на объект \Device\ConDrv, WriteFile не делает специальных проверок и просто вызывает NtWriteFile, а GetConsoleMode и прочие реализованы через NtDeviceIoControlFile вместо LPC к winsrv.dll (XP-)/conhost.exe (Vista+).

Значит, MS таки глобально переписала консоль в районе восьмёрки. Тогда да, ваш код на восьмёрке и десятке работать будет. (Априори мне версия со столь существенными изменениями от MS показалась менее вероятной, чем версия, что вы просто не проверили код. Приношу свои извинения.) Интересно, зачем… Гугль первым результатом по \Device\ConDrv выдаёт статью с описанием обхода песочницы Хрома через него.
А это у MS спрашивать надо. Если 32-битный бинарник собран с выравниванием меньше размера страницы (и некоторыми дополнительными ограничениями), то 32-битная система его загрузит, а 64-битная — нет.
#pragma comment(linker, "/FILEALIGN:16")
#pragma comment(linker, "/ALIGN:16")// Merge sections

… и получить файл, не работающий на x64.
Рабочий для NtWriteFile? Проверяли? Что он рабочий для WriteFile, сомнений нет.
Хэндлы бывают разные. Вы пробовали запустить код от mark_ablov?

#include <stdio.h>
#include <intrin.h>

int main()
{
	printf("%08x\n", ((int**)__readfsdword(0x30))[0x10/4][0x1C/4]);
	return 0;
}

Win7 WOW64:
C:\> test | more
0000006C
C:\> test
0000000F

Первый запуск — перенаправление вывода, 0x6C — нормальный ядерный хэндл. Второй запуск — вывод напрямую на консоль, хэндл, как легко видеть, ненормальный (ядерные хэндлы всегда делятся на 4).
И что, правда работает с выводом на консоль (если не перенаправлять вывод в файл)?
Для консоли это не будет работать, у консоли вообще нет ядерного хэндла. WriteFile, обнаружив kernel32-хэндл консоли, вызывает WriteConsole, WriteConsole работает в конечном счёте через RPC к модулю winsrv.dll в процессе csrss. (В частности, из-за такой схемы в XP консольные окна не подхватывали темы оформления — грузить абы что в системный процесс csrss MS не хотела. В Vista для этого в цепочку добавили ещё один процесс conhost.exe, вызываемый из csrss).
Как по мне, такая операция была бы очень полезна в наборе инструкций процессора, особенно который предназначен для реализации логики в разных играх. Сама инструкция могла бы иметь виде SUBBITS a, v, где a — некоторое число, v — битовая маска, которая указывает на то, какие биты следует оставить и перенести в младшие разряды. Например, SUBBITS 0xFF00FF, 0x111111 должна дать на выходе 1100112: оставляем биты с номерами 0, 4, 8, 12, 16, 20 и переносим нулевой бит в нулевую позиции, четвёртый — в первую, восьмой — во вторую,…
У Intel есть такая инструкция, начиная с Haswell, называется PEXT. Часть BMI2. Только у неё три аргумента, третий — куда записывать результат.
Установщик пишет временный файл на 130M, делает это одним вызовом WriteFile на 130M данных, под виндой это у него получается, под ReactOS NtWriteFile выдаёт отлуп STATUS_INVALID_USER_BUFFER.
Эм. А чего вы хотели, сказав просто отправить массив байт в поток? Хотите конвертации по дороге — так и говорите:
#include <iostream>
#include <locale>
#include <codecvt>
int main() {
    // вариант 1: просто конвертируем строку wchar_t -> utf8
    std::cout << std::wstring_convert<std::codecvt_utf8<wchar_t>>().to_bytes(L"привет, мир\n");
    // вариант 2: объясняем потоку, чтобы он конвертировал wchar_t -> utf8 при выводе
    std::wcout.imbue(std::locale(std::wcout.getloc(), new std::codecvt_utf8<wchar_t>()));
    std::wcout << L"привет, мир\n";
}
Ну да, копирует на stdout строку в той же кодировке, в которой она введена в исходнике. (Если вы намекаете на виндовую консоль с её legacy cp866 — перенаправьте вывод в файл.) Для этого поддержка unicode не нужна вообще.

Информация

В рейтинге
Не участвует
Откуда
Москва, Москва и Московская обл., Россия
Работает в
Дата рождения
Зарегистрирован
Активность