Chamadas de sistema no Windows e API nativa?
-
21-09-2019 - |
Pergunta
Recentemente tenho usado muita linguagem Assembly em sistemas operacionais *NIX.Eu queria saber sobre o domínio do Windows.
Convenção de chamada no Linux:
mov $SYS_Call_NUM, %eax
mov $param1 , %ebx
mov $param2 , %ecx
int $0x80
É isso.É assim que devemos fazer uma chamada de sistema no Linux.
Referência de todas as chamadas do sistema no Linux:
Em relação a quais $SYS_Call_NUM e quais parâmetros podemos usar esta referência: http://docs.cs.up.ac.za/programming/asm/derick_tut/syscalls.html
Referência OFICIAL: http://kernel.org/doc/man-pages/online/dir_section_2.html
Convenção de chamada no Windows:
???
Referência de todas as chamadas do sistema no Windows:
???
Não oficial: http://www.metasploit.com/users/opcode/syscalls.html , mas como faço para usá-los em assembly, a menos que eu conheça a convenção de chamada.
OFICIAL:???
- Se você disser, eles não documentaram isso.Então, como alguém escreverá libc para Windows sem conhecer as chamadas do sistema?Como alguém vai fazer a programação do Windows Assembly?Pelo menos na programação do driver é preciso saber isso.certo?
Agora, o que há com a chamada API Nativa?É Native API
& System calls for windows
ambos são termos diferentes referindo-se à mesma coisa?Para confirmar, comparei estes dados de duas fontes NÃO OFICIAIS
Chamadas do sistema: http://www.metasploit.com/users/opcode/syscalls.html
API nativa: http://undocumented.ntinternals.net/aindex.html
Minhas observações:
- Todas as chamadas do sistema começam com letras
Nt
onde a API nativa consiste em muitas funções que não começam com letrasNt
. System Call of windows
são subconjuntos deNative API
.As chamadas do sistema são apenas parte da API nativa.
Alguém pode confirmar isso e explicar.
EDITAR:
Houve outra resposta.Foi uma segunda resposta.Gostei muito, mas não sei por que o respondente o excluiu.Solicito que ele repasse sua resposta.
Solução
Se você estiver fazendo programação de montagem no Windows, não faz syscalls manuais. Você usa o NTDLL e a API nativa para fazer isso por você.
A API nativa é simplesmente um invólucro ao redor do lado do kernelmode das coisas. Tudo o que faz é executar um syscall para a API correta.
Você nunca precisa precisar manualmente, para que toda a sua pergunta seja redundante.
Os códigos Syscall Linux não mudam, o Windows faz, é por isso que você precisa trabalhar através de uma camada extra de abstração (também conhecida como NTDLL).
EDITAR:
Além disso, mesmo se você estiver trabalhando no nível da montagem, ainda tem acesso total à API Win32, não há razão para usar a API do NT para começar! Importações, exportações, etc. Todos funcionam bem em programas de montagem.
Edit2:
Se você realmente deseja fazer syscalls manuais, precisará reverter o NTDLL para cada versão relevante do Windows, adicionar detecção de versão (através do PEB) e executar uma pesquisa Syscall para cada chamada.
No entanto, isso seria bobo. Ntdll está lá por um motivo.
As pessoas já fizeram a parte de engenharia reversa: ver https://j00ru.vexillium.org/syscalls/nt/64/ Para uma tabela de números de chamada do sistema para cada kernel do Windows. (Observe que as linhas posteriores mudam mesmo entre as versões do Windows 10.) Novamente, essa é uma má idéia fora de experimentos somente para uso pessoal em sua própria máquina para aprender mais sobre o ASM e/ou Windows Internals. Não embrulhe o sistema chama para o código que você distribui para mais ninguém.
Outras dicas
A outra coisa que você precisa saber sobre a Convenção do Syscall do Windows é que, como eu entendo, as tabelas Syscall são geradas como parte do processo de construção. Isso significa que eles podem simplesmente mudar - ninguém os rastreia. Se alguém adicionar um novo no topo da lista, isso não importa. O NTDLL ainda funciona, então todo mundo que liga para o NTDLL ainda funciona.
Até o mecanismo usado para realizar syscalls (que int, ou sysenter) não é fixado em pedra e mudou no passado, e acho que uma vez a mesma versão das janelas usava DLLs diferentes que usavam mecanismos de entrada diferentes, dependendo do CPU na máquina.
As chamadas do sistema Windows são executadas chamando DLLs de sistema, como kernel32.dll
ou gdi32.dll
, o que é feito com chamadas de sub -rotina comuns. Os mecanismos para prender a camada privilegiada do sistema operacional não são documentados, mas tudo bem porque as DLLs gostam kernel32.dll
faça isso por você.
E por chamadas do sistema, estou me referindo a pontos de entrada da API do Windows documentados como CreateProcess()
ou GetWindowText()
. Os drivers de dispositivo geralmente usam uma API diferente do Windows DDK.
Eu estava interessado em fazer uma chamada da API do Windows na montagem sem importações (como exercício educacional), então escrevi a seguinte assembly para fazer o que o Ntdll! Ntcreatefile faz. É uma demonstração aproximada da minha versão de 64 bits do Windows (Win10 1803 versão 10.0.17134) e trava após a chamada, mas o valor de retorno do syscall é zero, por isso é bem-sucedido. Tudo está configurado de acordo com a convenção de chamada do Windows X64, o número da chamada do sistema é carregado no RAX e, em seguida, é a instrução de montagem do Syscall para executar a chamada. Meu exemplo cria o arquivo c: helloworldfile_fasm, por isso deve ser executado "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
Eu usei a documentação para o ntdll! Ntcreatefile e também usei o depurador do kernel para olhar e copiar muitos dos 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
);
Convenção de chamada OFICIAL no Windows: http://msdn.microsoft.com/en-us/library/7kcdt6fy.aspx
(espero que este link sobreviva no futuro;caso contrário, basta pesquisar "convenções de software x64" no MSDN).
A convenção de chamada de função difere no Linux e no Windows x86_64.Em ambas as ABIs, os parâmetros são preferencialmente passados através de registradores, mas os registradores utilizados são diferentes.Mais sobre a ABI do Linux pode ser encontrada em http://www.x86-64.org/documentation/abi.pdf