que - Escribir un subsistema Windows NT
windows nt que es (2)
Me gustaría intentar escribir mi propio subsistema NT mínimo en Windows 7 con fines puramente educativos, algo así como un equivalente escueto del posix.exe en el subsistema de Microsoft para aplicaciones basadas en Unix.
Pero parece que no puedo encontrar ninguna documentación pública sobre este tema. ¿Qué API necesita implementar un subsistema? ¿Cómo se registra con Windows? ¿Cómo se debe construir la imagen del subsistema (qué indicadores deben establecerse en el encabezado PE, etc.)?
Me gustaría encontrar un libro o sitio web con una visión general de todo el tema, o incluso el código fuente de un subsistema NT "hello world" que alguien más ha escrito. Pero cualquier cosa sería apreciada si me pueden indicar la dirección correcta aquí ...
Estos son los principales componentes de un subsistema:
- Servidor de modo de usuario. El servidor crea un (A) puerto LPC y escucha y maneja las solicitudes de los clientes.
- DLL de cliente en modo de usuario. En DLL_INIT_ROUTINE, puede conectarse al puerto configurado por el servidor. Esta DLL expondrá la API de su subsistema y algunas funciones requerirán comunicación con el servidor.
- Controlador de soporte en modo kernel (es posible que no lo necesite).
Querrá almacenar el proceso o el estado del hilo en su servidor o controlador. Si lo está almacenando en el servidor, es posible que necesite algo como NtRegisterThreadTerminatePort
para asegurarse de que se limpia cuando sale un proceso o un hilo. Si está utilizando un controlador, necesita PsSetCreateProcessNotifyRoutine .
Y, por último, si tiene XP o menos, puede agregar nuevas llamadas al sistema. Puede hacerlo llamando a KeAddSystemServiceTable
. Para invocar las llamadas al sistema desde el modo de usuario, necesita crear talones como este (para x86):
; XyzCreateFooBar(__out PHANDLE FooBarHandle, __in ACCESS_MASK DesiredAccess, ...)
mov eax, SYSTEM_CALL_NUMBER
mov edx, 0x7ffe0300
call [edx]
retn 4
En Vista y versiones superiores, ya no puede agregar nuevas tablas de servicio del sistema porque solo hay espacio para dos: las llamadas al sistema del kernel y las llamadas al sistema de win32k.
Después de buscar en Google, encontré esto: http://winntposix.sourceforge.net/ . Creo que es muy similar a lo que estás buscando, y usa muchas de las cosas que he mencionado.
También estoy obsesionado con la API nativa. :)
Y me alegra decir que no es tan peligroso ni tan indocumentado como lo hacen algunas personas. :]
No hay un código fuente para "Hola, mundo" porque la API nativa no interactúa tan fácilmente con la consola, ya que es parte del subsistema Win32 y requiere comunicación cliente / servidor con puertos. Si necesita escribir una aplicación de consola, necesita comunicarse directamente con CSRSS, cuyos formatos de mensaje no están documentados (aunque parte de su formato se puede encontrar en la fuente de ReactOS ; le brindaría muchos beneficios si se familiariza con ReactOS).
Voy a publicar un ejemplo aquí pronto que puede encontrar interesante; por ahora, tenga en cuenta que su única opción es vincularse con NTDLL.dll, y para eso necesita el Kit de desarrollo de controladores (ya que necesita el archivo lib).
Actualización : ¡mira esto!
(Tengo la sensación de que nadie más publicará algo tan rebelde como este. Mostrar GUI con la API nativa ?! Debo estar loco!)
#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;
}
¡Si tiene alguna pregunta, sientase con libertad de preguntar! ¡No tengo miedo de la API nativa! :)
Editar 2:
Si está intentando crear su propia versión DLL de Kernel32 y cargarla como lo hace Kernel32 con cada proceso (de ahí un nuevo subsistema), solo quería hacerle saber que no creo que sea posible. Es bastante similar a esta pregunta que hice hace un par de días, y parece que no se puede ampliar el NT PE Loader para conocer nuevos subsistemas, por lo que no creo que sea posible.