Saltar al contenido

¿Llamadas al sistema en Windows y API nativa?

Hacemos una revisión profunda cada escrito en nuestro espacio con la meta de enseñarte siempre información certera y certera.

Solución:

Si está haciendo programación de ensamblaje en Windows, no realiza llamadas al sistema manuales. Utiliza NTDLL y la API nativa para hacerlo por usted.

La API nativa es simplemente un envoltorio alrededor del lado del modo kernel de las cosas. Todo lo que hace es realizar una llamada al sistema para la API correcta.

NUNCA debería necesitar llamar al sistema manualmente para que toda su pregunta sea redundante.

Los códigos de llamada al sistema de Linux no cambian, los de Windows sí, es por eso que necesita trabajar a través de una capa de abstracción adicional (también conocida como NTDLL).

EDITAR:

Además, incluso si está trabajando en el nivel de ensamblaje, todavía tiene acceso completo a la API de Win32, ¡no hay razón para usar la API de NT para empezar! Las importaciones, exportaciones, etc. funcionan muy bien en los programas de ensamblaje.

EDIT2:

Si REALMENTE desea realizar llamadas de sistema manuales, necesitará invertir NTDLL para cada versión de Windows relevante, agregar detección de versión (a través de PEB) y realizar una búsqueda de llamada de sistema para cada llamada.

Sin embargo, eso sería una tontería. NTDLL está ahí por una razón.

La gente ya ha hecho la parte de ingeniería inversa: consulte https://j00ru.vexillium.org/syscalls/nt/64/ para obtener una tabla de números de llamadas al sistema para cada kernel de Windows. (Tenga en cuenta que las últimas filas cambian incluso entre versiones de Windows 10). Nuevamente, esta es una mala idea fuera de los experimentos de uso personal en su propia máquina para aprender más sobre asm y/o las partes internas de Windows. No conviertas las llamadas del sistema en línea en código que distribuyas a nadie más.

La otra cosa que necesita saber acerca de la convención syscall de Windows es que, según tengo entendido, las tablas syscall se generan como parte del proceso de compilación. Esto significa que simplemente pueden cambiar, nadie los rastrea. Si alguien agrega uno nuevo al principio de la lista, no importa. NTDLL aún funciona, por lo que todos los demás que llaman a NTDLL aún funcionan.

Incluso el mecanismo utilizado para realizar syscalls (que int, o sysenter) no está fijado en piedra y ha cambiado en el pasado, y creo que alguna vez la misma versión de Windows usaba diferentes DLL que usaban diferentes mecanismos de entrada dependiendo del CPU en la máquina.

Estaba interesado en hacer una llamada a la API de Windows en ensamblado sin importaciones (como un ejercicio educativo), así que escribí el siguiente ensamblado FASM para hacer lo que hace NtDll!NtCreateFile. Es una demostración aproximada en mi versión de Windows de 64 bits (Win10 1803, versión 10.0.17134) y se bloquea después de la llamada, pero el valor de retorno de la llamada al sistema es cero, por lo que tiene éxito. Todo está configurado según la convención de llamadas de Windows x64, luego el número de llamada del sistema se carga en RAX y luego es la instrucción de ensamblado syscall para ejecutar la llamada. Mi ejemplo crea el archivo c:HelloWorldFile_FASM, por lo que debe ejecutarse “como administrador”.

format PE64 GUI 4.0


entry start


section '.text' code readable executable


 start: 
 ;puting the first four parameters into the right registers

                            mov rcx, _Handle
                            mov rdx, [_access_mask]
                            mov r8, objectAttributes
                            mov r9, ioStatusBlock

 ;I think we need 1 stack word of padding:

                            push 0x0DF0AD8B


 ;pushing the other params in reverse order:

                            push [_eaLength]
                            push [_eaBuffer]
                            push [_createOptions]
                            push [_createDisposition]
                            push [_shareAcceses]
                            push [_fileAttributes]
                            push [_pLargeInterger]

 ;adding the shadow space (4x8)

 ;                               push 0x0
 ;                               push 0x0
 ;                               push 0x0
 ;                               push 0x0

 ;pushing the 4 register params into the shadow space for ease of debugging

                            push r9
                            push r8
                            push rdx
                            push rcx

 ;now pushing the return address to the stack:

                            push endOfProgram

                            mov r10, rcx ;copied from ntdll!NtCreateFile, not sure of the reason for this
                            mov eax, 0x55
                            syscall

 endOfProgram:
                            retn




 section '.data' data readable writeable

 ;parameters------------------------------------------------------------------------------------------------

 _Handle                         dq      0x0
 _access_mask                    dq      0x00000000c0100080
 _pObjectAttributes              dq      objectAttributes        ; at 00402058
 _pIoStatusBlock                 dq           ioStatusBlock
 _pLargeInterger                 dq      0x0
 _fileAttributes                 dq      0x0000000000000080
 _shareAcceses                   dq      0x0000000000000002
 _createDisposition              dq      0x0000000000000005
 _createOptions                  dq      0x0000000000000060
 _eaBuffer                       dq      0x0000000000000000       ; "optional" param
 _eaLength                       dq      0x0000000000000000

 ;----------------------------------------------------------------------------------------------------------


                            align   16
 objectAttributes:
 _oalength                       dq      0x30
 _rootDirectory                  dq      0x0
 _objectName                     dq           unicodeString
 _attributes                     dq      0x40
 _pSecurityDescriptor            dq      0x0
 _pSecurityQualityOfService      dq      securityQualityOfService


 unicodeString:
 _unicodeStringLength            dw      0x34
 _unicodeStringMaxumiumLength    dw      0x34, 0x0, 0x0
 _pUnicodeStringBuffer           dq      _unicodeStringBuffer


 _unicodeStringBuffer            du      '??c:HelloWorldFile_FASM'       ; may need to "run as adinistrator" for the file create to work.



 ioStatusBlock:
 _status_pointer                 dq      0x0
 _information                    dq      0x0


 securityQualityOfService:
 _sqlength                       dd      0xC
 _impersonationLevel             dd      0x2
 _contextTrackingMode            db      0x1
 _effectiveOnly                  db      0x1, 0x0, 0x0

Usé la documentación para Ntdll!NtCreateFile, y también usé el depurador del kernel para mirar y copiar muchos de los parámetros.

__kernel_entry NTSTATUS NtCreateFile(
  OUT PHANDLE                      FileHandle,
  IN ACCESS_MASK                   DesiredAccess,
  IN POBJECT_ATTRIBUTES            ObjectAttributes,
  OUT PIO_STATUS_BLOCK             IoStatusBlock,
  IN PLARGE_INTEGER AllocationSize OPTIONAL,
  IN ULONG                         FileAttributes,
  IN ULONG                         ShareAccess,
  IN ULONG                         CreateDisposition,
  IN ULONG                         CreateOptions,
  IN PVOID EaBuffer                OPTIONAL,
  IN ULONG                         EaLength
);

Comentarios y valoraciones del artículo

Agradecemos que desees ayudar nuestro cometido mostrando un comentario y dejando una puntuación te estamos agradecidos.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

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