Подтвердить что ты не робот

Написание подсистемы Windows NT

Я хотел бы попробовать написать свою минимальную подсистему NT в Windows 7 для чисто образовательных целей - что-то вроде эквивалента barex-костей posix.exe в подсистеме Microsoft для Unix-приложений.

Но я не могу найти публичную документацию по этой теме. Какой API необходимо реализовать подсистеме? Как он регистрируется в Windows? Как создать образ подсистемы (какие флаги должны быть установлены в заголовке PE и т.д.)?

Мне больше всего хотелось бы найти книгу или веб-сайт с обзором всего предмета или даже исходным кодом для подсистемы NT "hello world", которую кто-то написал. Но все было бы оценено, если вы можете указать мне в правильном направлении здесь...

4b9b3361

Ответ 1

Вот основные компоненты подсистемы:

  • Сервер пользовательского режима. Сервер создает порт (A) LPC и слушает и обрабатывает клиентские запросы.
  • Пользовательская DLL-клиент. В DLL_INIT_ROUTINE вы можете подключиться к порту, настроенному сервером. Эта DLL представит ваш подсистемный API, а некоторые функции потребуют связи с сервером.
  • Драйвер поддержки в режиме ядра (возможно, вам это не понадобится).

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

И, наконец, если вы находитесь на XP и ниже, вы можете добавить новые системные вызовы. Вы можете сделать это, вызвав KeAddSystemServiceTable. Чтобы вызвать системные вызовы из пользовательского режима, вам необходимо создать такие заглушки (для x86):

; XyzCreateFooBar(__out PHANDLE FooBarHandle, __in ACCESS_MASK DesiredAccess, ...)
mov     eax, SYSTEM_CALL_NUMBER
mov     edx, 0x7ffe0300
call    [edx]
retn    4

В Vista и выше вы больше не можете добавлять новые таблицы системных сервисов, потому что есть только место для двоих: системные вызовы ядра и системные вызовы win32k.

После немного Googling я нашел это: http://winntposix.sourceforge.net/. Я думаю, что он очень похож на то, что вы ищете, и использует много вещей, о которых я говорил.

Ответ 2

Я тоже одержим собственным API.:)

И я рад сказать, что он нигде не так опасен или как недокументирован, как это делают некоторые люди.:]

Нет исходного кода для "Hello, world", потому что собственный API не так легко взаимодействует с консолью, так как он является частью подсистемы Win32 и требует взаимодействия клиент/сервер с портами. Если вам нужно написать консольное приложение, вам нужно напрямую связаться с CSRSS, форматы сообщений которого недокументированы (хотя некоторые из его форматов можно найти в Источник ReactOS - это принесет вам много преимуществ, если вы познакомитесь с ReactOS).

Я скоро отправлю вам пример, который вы могли бы найти интересным; на данный момент, помните, что ваш единственный вариант когда-либо связывается с NTDLL.dll, и для этого вам нужен комплект разработки драйверов (так как вам нужен файл lib).


Обновить: проверьте это!

(У меня есть чувство, что никто другой не опубликует что-то совершенно такое же бунтарное, как это. Показывая GUI с помощью собственного API?! Я должен быть сумасшедшим!)

#include <Windows.h>

typedef DWORD NTSTATUS;

//These are from ReactOS
typedef enum _HARDERROR_RESPONSE_OPTION
{
    OptionAbortRetryIgnore,
    OptionOk,
    OptionOkCancel,
    OptionRetryCancel,
    OptionYesNo,
    OptionYesNoCancel,
    OptionShutdownSystem
} HARDERROR_RESPONSE_OPTION, *PHARDERROR_RESPONSE_OPTION;

typedef enum _HARDERROR_RESPONSE
{
    ResponseReturnToCaller,
    ResponseNotHandled,
    ResponseAbort,
    ResponseCancel,
    ResponseIgnore,
    ResponseNo,
    ResponseOk,
    ResponseRetry,
    ResponseYes,
    ResponseTryAgain,
    ResponseContinue
} HARDERROR_RESPONSE, *PHARDERROR_RESPONSE;

typedef struct _UNICODE_STRING {
    USHORT  Length;
    USHORT  MaximumLength;
    PWSTR  Buffer;
} UNICODE_STRING, *PUNICODE_STRING;

//You'll need to link to NTDLL.lib
//which you can get from the Windows 2003 DDK or any later WDK
NTSYSAPI VOID NTAPI RtlInitUnicodeString(IN OUT PUNICODE_STRING DestinationString,
    IN PCWSTR SourceString);
NTSYSAPI NTSTATUS NTAPI NtRaiseHardError(IN NTSTATUS ErrorStatus,
    IN ULONG NumberOfParameters, IN ULONG UnicodeStringParameterMask,
    IN PULONG_PTR Parameters,
    IN HARDERROR_RESPONSE_OPTION ValidResponseOptions,
    OUT PHARDERROR_RESPONSE Response);
#define STATUS_SERVICE_NOTIFICATION_2 0x50000018

int main()
{
    HARDERROR_RESPONSE response;
    ULONG_PTR items[4] = {0};
    UNICODE_STRING text, title;
    RtlInitUnicodeString(&text,
        L"Hello, NT!\r\nDo you like this?\r\n"
        L"This is just about as pretty as the GUI will get.\r\n"
        L"This message will self-destruct in 5 seconds...");
    RtlInitUnicodeString(&title, L"Native Message Box!");
    items[0] = (ULONG_PTR)&text;
    items[1] = (ULONG_PTR)&title;
    items[2] = (ULONG_PTR)OptionYesNo;
    items[3] = (ULONG_PTR)5000;
    NtRaiseHardError(STATUS_SERVICE_NOTIFICATION_2, ARRAYSIZE(items),
        0x1 | 0x2 /*First two parameters are UNICODE_STRINGs*/, items,
        OptionOk /*This is ignored, since we have a custom message box.*/,
        &response);
    return 0;
}

Если у вас есть вопросы, не стесняйтесь спрашивать! Я не боюсь родного API!:)


Изменить 2:

Если вы пытаетесь создать свою собственную DLL-версию Kernel32 и загрузите ее, как Kernel32, с каждым процессом (следовательно, с новой подсистемой), я просто хотел сообщить вам, что я не думаю, что это возможно. Это довольно похоже на этот вопрос, который я задал пару дней назад, и кажется, что вы не можете расширить загрузчик NT PE, чтобы узнать о новых подсистемах, поэтому я не думайте, что это будет возможно.