Ejecutar un programa antes de que se inicie Windows (y II)

En la entrada anterior hablaba sobre cómo lanzar un programa para que se ejecute antes del inicio de Windows basado en mis propias investigaciones. Tras un comentario de Peni, decidí probar un programa cualquiera… para descubrir que no funciona.

Un sesudo destripe de los dos programas que sé lo hacen, a saber, PDBoot.exe y autochk.exe comenzó a darme una ligera idea de qué es necesario. Para ello el que suscribe abrió una consola de comandos del Visual Studio, se fue a C:WindowsSystem32 y ejecutó el conocido dumpbin sobre dichos programas, a saber:

dumpbin /exports <fichero>

El autochk.exe no exporta nada, pero el otro sí, en general funciones relacionadas con la desfragmentación. Luego hizo lo mismo con las importaciones, y ahí sí que obtuvo algo interesante. Lo siguiente es la importación de funciones de autochk.exe:

ntdll.dll
77F497AB 716 _wcsicmp
77F20011 76A wcsstr
77F3F354 CD NtClose
77F40014 1A1 NtQueryValueKey
77F3FC24 150 NtOpenKey
77F22F50 3B3 RtlInitUnicodeString
77F3FFA4 19A NtQuerySymbolicLinkObject
77F3FCD4 15D NtOpenSymbolicLinkObject
77F1764A 42E RtlPrefixUnicodeString
77F42EF7 33F RtlEqualUnicodeString
77F3FE04 179 NtQueryDirectoryObject
77F3FBC4 149 NtOpenDirectoryObject
77F78664 85 LdrSetMUICacheType
77F40574 20A NtTerminateProcess
77F89B82 4BC RtlUnhandledExceptionFilter
77F02B68 4D0 RtlUnwind

Y sigue así hasta algo más de cien exportaciones. Está claro que el programa está utilizando el API nativo de Windows, no el subsistema Win32 como hacen todos los programas comunes. Además, si lanzamos el programa citado nos dice que no se puede ejecutar bajo Win32.

Así que una en la frente: no se trata de un ejecutable normal y corriente, sino de algo especial. La primera pregunta es: ¿quizás sea el formato ejecutable de un driver, o sólo la obligatoriedad de no realizar llamadas a Win32?

Y aquí es donde el autor de esto decide hacer lo que debió haber hecho desde un primer momento: consultar en Google.

¿Y qué encontró? Pues esto: http://www.microsoft.com/technet/sysinternals/information/NativeApplications.mspx. Entre otras cosas, le dice que necesita el DDK de Windows, y que debe usar funciones como NtDisplayString y no printf. En fin, que como el autor ya tiene suficiente con su trabajo diario como para meterse en camisa de once varas, pues decide detenerse aquí en cuanto al tema de ejecutar programas propios antes del inicio de Windows, de modo que lo publicado hasta ahora solo sirve para lanzar un chequeo de disco, que no es poco.

También ha añadido una nueva función que ha llamado RemoveBootExecuteEntry, y a la de la entrada anterior le ha cambiado el nombre por AddBootExecuteEntry. Un ejemplo completo se puede bajar de aquí. Y eso es todo.

Addenda
Como no quiero que este comentario de Ramón Sola se pierda, lo añado aquí:

Eso se puede observar en la cabecera PE. El valor de subsistema no es 3 (interfaz de consola) ni 2 (interfaz gráfica), sino 1 (nativo, no requiere subsistema). Csrss.exe es el programa nativo responsable del subsistema Windows en modo usuario, siendo Win32k.sys la parte kernel.

Las API nativas de Windows apenas están documentadas. El propósito de esta ocultación de información, según veo yo, es el de evitar el desarrollo de programas que dependan excesivamente de la implementación interna del sistema operativo, ya que puede variar mucho de una versión del sistema operativo a otra (o incluso de un service pack a otro). Esto ha generado acusaciones más o menos fundadas contra Microsoft de no proporcionar igualdad de oportunidades; de aprovecharse del conocimiento del subsistema nativo para provecho de sus propios productos en detrimento de la competencia, que tiene que acogerse forzosamente al subsistema Win32. Si algunas empresas como Raxco o Diskeeper son capaces de desarrollar productos que se apoyan directamente en los servicios nativos, debe de ser porque Microsoft comparte la información con ellas de algún modo, mediante algún acuerdo.

Los módulos nativos en modo usuario enlazan directa o indirectamente a Ntdll.dll y no pueden o no deberían depender de bibliotecas Win32. Los módulos nativos en modo kernel son los drivers, que enlazan a Ntoskrnl.exe, Hal.dll u otros drivers (controladores de minipuerto, por ejemplo).

Por el contrario, el subsistema Win32 depende considerablemente de los servicios nativos y otras rutinas de apoyo que ofrece Ntdll.dll. No tienes más que fijarte en las tablas de importación de Kernel32, User32, Gdi32, Advapi32 y otras DLLs de Windows. Además, en las tablas de exportación de Kernel32 podrás observar incluso «forwards» (no sé cómo traducirlo), entradas que remiten a otras DLLs. Por ejemplo, la llamada a HeapAlloc desde un programa Win32 se resuelve en tiempo de carga a la rutina RtlAllocateHeap en Ntdll.dll.

Versiones de Windows NT anteriores a Windows XP incluyeron otros subsistemas aparte de Win32. Por ejemplo, Windows 2000 incluía un subsistema POSIX, y Windows NT 4 también un subsistema OS/2 que emulaba OS/2 1.x (aplicaciones en modo texto). Parece que no llegaron a ser muy populares.

8 comentarios sobre “Ejecutar un programa antes de que se inicie Windows (y II)”

  1. Eso se puede observar en la cabecera PE. El valor de subsistema no es 3 (interfaz de consola) ni 2 (interfaz gráfica), sino 1 (nativo, no requiere subsistema). Csrss.exe es el programa nativo responsable del subsistema Windows en modo usuario, siendo Win32k.sys la parte kernel.

    Las API nativas de Windows apenas están documentadas. El propósito de esta ocultación de información, según veo yo, es el de evitar el desarrollo de programas que dependan excesivamente de la implementación interna del sistema operativo, ya que puede variar mucho de una versión del sistema operativo a otra (o incluso de un service pack a otro). Esto ha generado acusaciones más o menos fundadas contra Microsoft de no proporcionar igualdad de oportunidades; de aprovecharse del conocimiento del subsistema nativo para provecho de sus propios productos en detrimento de la competencia, que tiene que acogerse forzosamente al subsistema Win32. Si algunas empresas como Raxco o Diskeeper son capaces de desarrollar productos que se apoyan directamente en los servicios nativos, debe de ser porque Microsoft comparte la información con ellas de algún modo, mediante algún acuerdo.

    Los módulos nativos en modo usuario enlazan directa o indirectamente a Ntdll.dll y no pueden o no deberían depender de bibliotecas Win32. Los módulos nativos en modo kernel son los drivers, que enlazan a Ntoskrnl.exe, Hal.dll u otros drivers (controladores de minipuerto, por ejemplo).

    Por el contrario, el subsistema Win32 depende considerablemente de los servicios nativos y otras rutinas de apoyo que ofrece Ntdll.dll. No tienes más que fijarte en las tablas de importación de Kernel32, User32, Gdi32, Advapi32 y otras DLLs de Windows. Además, en las tablas de exportación de Kernel32 podrás observar incluso «forwards» (no sé cómo traducirlo), entradas que remiten a otras DLLs. Por ejemplo, la llamada a HeapAlloc desde un programa Win32 se resuelve en tiempo de carga a la rutina RtlAllocateHeap en Ntdll.dll.

    Versiones de Windows NT anteriores a Windows XP incluyeron otros subsistemas aparte de Win32. Por ejemplo, Windows 2000 incluía un subsistema POSIX, y Windows NT 4 también un subsistema OS/2 que emulaba OS/2 1.x (aplicaciones en modo texto). Parece que no llegaron a ser muy populares.

  2. Muy interesante post!!! Me doy cuenta que se complica iniciar un programita antes de iniciar sesión, pero no me voy a detener acá… Voy a investigar haste que se me atrofie la mente… xD jajaja!!!…Salu2!

  3. yo no se mucho, pero si este programa, que quieres ejecutar antes de loggear, es un servicio no puede funcuionar?

    hay programas que transforman aplicaciones en servicios.
    No se si puede servir, aviso:P

  4. No es lo mismo, pero si quieres pueder ir a tareas programadas, e indicar que se ejecute tu programa al arrancar el equipo. Es decir, antes de iniciar sesión.
    Hasta ahora he hecho pruebas con el 3cdaemon, y funciona. El problema es que cuando inicias sesión no ves la ventana del programa aunque si que aparece en los procesos y funciona.

    Saludos.

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *