Como distinguir o formato 'syscalls' int 80h 'ao usar o ptrace

6

Até onde eu sei, o ptrace só pode obter o número syscall por PTRACE_SYSCALL, mas o número syscall é diferente em x86 e x64. Então, há alguma maneira de descobrir onde esta origem real syscall?

Agora estou escrevendo um programa para limitar o syscall de outros usando o número syscall, eu sei o número syscall em x86 e x64, mas alguns dos programas usam 'int 80h' em vez de 'syscall' para que eles possam fazer coisa perigosa que eu limitei em x64. Por exemplo, eu proibi fork () em x64, eles podem usar 'int 80h (2)' (fork ()) e eu acho que eles estão usando 'syscall (2)' (open ()), assim eles podem quebrar o limite . Embora o ptrace possa rastrear ambos e obter o número syscall, não consigo distinguir onde o syscall realmente vem.

    
por Criyle 31.10.2014 / 07:10

2 respostas

1

Parece que, por escrito (2019-02-08), isso é impossível .

E até strace erra .

Editar: Linus Torvalds fala sobre isso aqui , analisando também possíveis (mas comentadas) soluções alternativas no código strace que examinam diretamente as instruções feitas no binário. Este código foi removido aqui como parte do patchset que menciono abaixo. Ele diz It works, but is too complicated, and strictly speaking, unreliable , mas não está claro para mim em quais casos o "estritamente falando, não confiável" se aplica, se isso é apenas no caso de um executável multi-thread reescrevendo-se em tempo de execução (portanto não adequado para proibir determinados syscalls para casos de uso de segurança), ou também em outros casos.

Edit: A parte "não confiável" foi adicionada em este commit .

Edit: Eu tentei a implementação do opcode-peeking do strace (versão v4.25 ), e suspeito que ele estava bugado: Ao ativar esse caminho de código, alterando esta linha para #if 0 e esta linha para #elif 1 , não são impressas syscalls porque scno não está definido. Eu adicionei scno = x86_64_regs.orig_rax; após esta linha para fazer isso funcionar.

Veja a apresentação Como fazer o strace feliz slide 2, problema 2:

There is no reliable way to distinguish between x86_64 and x86 syscalls.

Detalhes mostrados nos slides 4-6. Há uma solução proposta a ser adicionada ao kernel:

Extend the ptrace API with PTRACE_GET_SYSCALL_INFO request

Mas esta solução não é mesclada ao kernel.

O conjunto de caracteres é chamado ptrace: add PTRACE_GET_SYSCALL_INFO request e que ainda está sendo trabalhado em janeiro de 2019 . Espero que em breve seja mesclado.

strace já tem suporte para desde o release 4.26 (mas ele não deve funcionar a menos que você aplique o patch do kernel manualmente):

Implemented obtainment of system call information using PTRACE_GET_SYSCALL_INFO ptrace API.

    
por 08.02.2019 / 05:38
-2

É a chamada do sistema sys_rt_sigtimedwait (desde o kernel 2.2). Veja o manual dele por:

man 2 rt_sigtimedwait

Esse syscall suspende a execução, até que um sinal (ou um conjunto de singals) especificado pelo argumento seja entregue. Um tempo limite também foi dado.

Para ter 100% de certeza de que existe um arquivo chamado unistd_64.h . Procure no seu sistema por esse arquivo. Principalmente está na pasta include ( /usr/include/x86_64-linux-gnu/asm/unistd_64.h ). Existem os números definidos. Aqui a linha relevante no meu caso (é também um sistema de 64 bits, kernel 3.2.0-58):

#define __NR_rt_sigtimedwait                    128
__SYSCALL(__NR_rt_sigtimedwait, sys_rt_sigtimedwait)

Observe que 128 é decimal para 80 em hexadecimal.

    
por 31.10.2014 / 08:08