51

出于纯粹的教育目的,我想尝试在 Windows 7 上编写我自己的最小 NT 子系统——类似于 Microsoft 的基于 Unix 的应用程序的子系统中的 posix.exe 的基本等价物。

但我似乎找不到关于这个主题的任何公共文档。子系统需要实现什么 API?它是如何在 Windows 中注册的?子系统映像需要如何构建(PE头中需要设置哪些标志等)?

我最想找到一本书或网站,其中包含整个主题的概述,甚至是其他人编写的“hello world”NT 子系统的源代码。但是,如果您能在这里指出我正确的方向,那么任何事情都会受到赞赏......

4

2 回答 2

20

以下是子系统的主要组件:

  • 用户模式服务器。服务器创建一个 (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 的系统调用。

经过一番谷歌搜索,我发现了这个:http ://winntposix.sourceforge.net/ 。我认为它与您正在寻找的非常相似,并且使用了我提到的很多东西。

于 2011-01-11T01:46:43.117 回答
15

我也沉迷于原生 API。:)

我很高兴地说,它远没有某些人认为的那样危险或无证。:]

“Hello, world”没有源代码,因为本机 API 与控制台交互并不容易,因为它是 Win32 子系统的一部分,需要客户端/服务器与端口进行通信。如果您需要编写控制台应用程序,则需要直接与 CSRSS 通信,其消息格式未记录(尽管它的某些格式可以在ReactOS 的源代码中找到——如果您熟悉 ReactOS,它将为您带来很多好处)。

我很快就会在这里发布一个你可能会感兴趣的例子;现在,请注意,您唯一的选择是与 NTDLL.dll 链接,为此,您需要驱动程序开发工具包(因为您需要 lib 文件)。


更新:看看这个!

(我感觉没有人会发布像这样叛逆的东西。用原生 API 显示 GUI?!我一定是疯了!)

#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:

如果您尝试制作自己的 Kernel32 DLL 版本并像 Kernel32 对每个进程所做的那样加载它(因此是一个新的子系统),我只是想让您知道我认为这是不可能的。这与我几天前问的这个问题非常相似,而且似乎您无法扩展 NT PE Loader 以了解新的子系统,所以我认为这不可能。

于 2011-01-09T09:37:29.517 回答