GNU/Linux >> Linux Esercitazione >  >> Linux

Chiamate di sistema in Windows e API native?

Ero interessato a eseguire una chiamata API di Windows in assembly senza importazioni (come esercizio didattico), quindi ho scritto il seguente assembly FASM per fare ciò che fa NtDll!NtCreateFile. È una dimostrazione approssimativa sulla mia versione a 64 bit di Windows (Win10 1803 versione 10.0.17134) e si arresta in modo anomalo dopo la chiamata, ma il valore restituito della chiamata di sistema è zero, quindi ha esito positivo. Tutto è impostato secondo la convenzione di chiamata di Windows x64, quindi il numero della chiamata di sistema viene caricato in RAX e quindi è l'istruzione dell'assembly syscall a eseguire la chiamata. Il mio esempio crea il file c:\HelloWorldFile_FASM, quindi deve essere eseguito "come amministratore".

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

Ho usato la documentazione per Ntdll!NtCreateFile e ho anche usato il debugger del kernel per guardare e copiare molti dei parametri.

__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
);

Se stai programmando in assembly sotto Windows, non esegui chiamate di sistema manuali. Usa NTDLL e l'API nativa per farlo per te.

L'API nativa è semplicemente un involucro attorno al lato kernelmode delle cose. Tutto ciò che fa è eseguire una chiamata di sistema per l'API corretta.

Non dovresti MAI aver bisogno di chiamare manualmente il sistema, quindi l'intera domanda è ridondante.

I codici delle chiamate di sistema di Linux non cambiano, lo fanno quelli di Windows, ecco perché è necessario lavorare attraverso un ulteriore livello di astrazione (noto anche come NTDLL).

MODIFICA:

Inoltre, anche se stai lavorando a livello di assembly, hai ancora pieno accesso all'API Win32, non c'è motivo di utilizzare l'API NT per cominciare! Le importazioni, le esportazioni, ecc. funzionano tutte bene nei programmi assembly.

EDIT2:

Se vuoi DAVVERO eseguire chiamate di sistema manuali, dovrai invertire NTDLL per ogni versione di Windows pertinente, aggiungere il rilevamento della versione (tramite PEB) ed eseguire una ricerca di chiamate di sistema per ogni chiamata.

Tuttavia, sarebbe sciocco. NTDLL esiste per un motivo.

Le persone hanno già fatto la parte del reverse engineering:vedi https://j00ru.vexillium.org/syscalls/nt/64/ per una tabella di numeri di chiamata di sistema per ogni kernel di Windows. (Si noti che le righe successive cambiano anche tra le versioni di Windows 10.) Ancora una volta, questa è una cattiva idea al di fuori degli esperimenti di solo uso personale sulla propria macchina per saperne di più su asm e/o sugli interni di Windows. Non incorporare chiamate di sistema nel codice che distribuisci a qualcun altro.


L'altra cosa che devi sapere sulla convenzione syscall di Windows è che, a quanto ho capito, le tabelle syscall vengono generate come parte del processo di compilazione. Ciò significa che possono semplicemente cambiare:nessuno li tiene traccia. Se qualcuno ne aggiunge uno nuovo in cima alla lista, non importa. NTDLL funziona ancora, quindi tutti gli altri che chiamano NTDLL funzionano ancora.

Anche il meccanismo utilizzato per eseguire le chiamate di sistema (quale int, o sysenter) non è fisso ed è cambiato in passato, e penso che una volta la stessa versione di Windows utilizzasse DLL diverse che utilizzavano meccanismi di accesso diversi a seconda del CPU nella macchina.


Le chiamate di sistema di Windows vengono eseguite chiamando le DLL di sistema come kernel32.dll o gdi32.dll , che viene eseguita con normali chiamate di subroutine. I meccanismi per l'intrappolamento nel livello privilegiato del sistema operativo non sono documentati, ma va bene perché DLL come kernel32.dll fallo per te.

E per chiamate di sistema, mi riferisco a punti di ingresso API di Windows documentati come CreateProcess() o GetWindowText() . I driver di dispositivo generalmente utilizzano un'API diversa da Windows DDK.


Linux
  1. Comprensione delle chiamate di sistema su Linux con strace

  2. Linux:come trovare le implementazioni delle chiamate di sistema del kernel Linux?

  3. Comando per inviare il contenuto del file a Stdout?

  4. Indagare su un server Windows compromesso

  5. Differenza tra le chiamate di sistema statvfs() e statfs()?

Come salvare il tuo sistema Windows o Linux con Rescatux

Sysmon:un monitor di sistema Linux (come Task Manager di Windows)

Creazione di un sistema ibrido Linux-Windows con Cygwin

Windows vs MacOS vs Linux – Manuale del sistema operativo

Che cosa sono le chiamate di sistema Linux e le funzioni di libreria?

I 15 migliori emulatori Linux per sistemi Windows