Kernels abaixo de 4.6 usam stubs de montagem para proteger o gancho de chamadas críticas do sistema, como fork, clone, exec etc. Particularmente falando para execve, o seguinte snippet de Kernel-4.5 mostra o stub de entrada de execve:
ENTRY(stub_execve)
call sys_execve
return_from_execve:
...
END(stub_execve)
O sistema tabela de chamadas contém este O endereço do stub e este stub ainda chamam execve original. Então, para enganchar execve neste ambiente, nós precisamos corrigir call sys_execve
no stub com nossa rotina de hooking e depois de fazer as coisas desejadas chamaremos o execve original. Isso tudo pode ser visto em ação em execmon , um utilitário de monitoramento de execução de processos para o linux. Eu testei o execmon trabalhando com sucesso no Ubuntu 16.04 com o kernel 4.4.
A partir do kernel 4.6, o esquema superior para proteção de chamadas críticas foi alterado. Agora o stub se parece com:
ENTRY(ptregs_\func)
leaq \func(%rip), %rax
jmp stub_ptregs_64
END(ptregs_\func)
onde \func
expandirá para sys_execve
para chamadas execve. Mais uma vez, o sistema tabela de chamadas contém este stub e este stub chama execve original, mas agora de uma maneira mais segura em vez de apenas fazer call sys_execve
.
Este stub mais novo, armazena o endereço da função chamado em RAX
register e salta para outro stub mostrado abaixo (comentários removidos):
ENTRY(stub_ptregs_64)
cmpq $.Lentry_SYSCALL_64_after_fastpath_call, (%rsp)
jne 1f
DISABLE_INTERRUPTS(CLBR_NONE)
TRACE_IRQS_OFF
popq %rax
jmp entry_SYSCALL64_slow_path
1:
jmp *%rax /* called from C */
END(stub_ptregs_64)
Por favor, dê uma olhada em this para veja comentários e outros rótulos referenciados neste stub.
Eu tentei criar uma lógica para superar essa proteção e consertar as chamadas originais com funções de hooking, mas ainda não obtive sucesso. Alguém gostaria de se juntar a mim e ajudar a sair disso?
Tags c kernel-modules hook linux-kernel