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:

  1. 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 letras Nt.
  2. System Call of windows são subconjuntos de Native 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.

Foi útil?

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

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top