
Syscalls indiretas limpas com adulteração de syscalls.
SyscallRevenant é um novo método para realizar syscalls indiretas limpas.
O componente principal resolve System Service Numbers (SSNs) e endereços da instrução syscall dinamicamente.
Isso é feito habilitando a trap flag durante a execução.
O componente secundário é a manipulação via substituição de parâmetros antes de uma syscall.
Essa combinação é projetada para contornar hooks em userland durante a invocação subsequente da syscall, ao mesmo tempo que substitui os parâmetros inicialmente apresentados.
Aviso legal: O propósito disto é apenas para fins educacionais e de teste. Não use isto em máquinas que você não tem permissão para usar. Não use isto para alavancar e se comunicar com máquinas que você não tem autorização para usar.
Syscalls indiretas são um método de executar instruções syscall em espaço de userland confiável.
Se um usuário encontrar uma instrução syscall, ele pode saltar para ela indiretamente.
Um evento habilitado durante uma sessão de rastreamento pode revelar o endereço de retorno imediatamente após a instrução.
Isso não leva em conta os hooks de userland do Endpoint Detection & Response (EDR).
Um EDR pode inserir hooks em ntdll.dll, depreciando assim o processo de busca por SSNs e instruções syscall.
Entrar em um hook beneficiará a thread proprietária, não elevando uma pontuação maliciosa.
Observar uma entrada em uma função e observar a operação resultante são coisas diferentes.
RevenantSyscalls investiga essa lacuna.
As seções a seguir descrevem os dois componentes principais do projeto.
O primeiro componente resolve endereços de funções a partir de ntdll.dll carregada pelo processo.
Uma trap walk pode então ser realizada se informações de syscall forem necessárias.
O segundo componente realiza um salto indireto para as informações de função salvas.
A leitura do registrador de segmento pode recuperar o Process Environment Block (PEB).
O LoaderData é um campo no PEB que contém dados carregados com cada processo.
LoaderData contém informações sobre módulos carregados junto com cada processo.
Nomes de módulos e endereços base existem nas entradas de módulo.
As informações de exportação de uma Dynamically Linked Library (DLL) descrevem os símbolos que ela exporta. Os metadados de exportação auxiliam na localização de símbolos exportados. O índice de uma função se aplica apenas a nomes e ordinais de nomes. Fazer hash do nome de uma função é o melhor para ambientes com pouca memória.
Um vectored exception handler é um mecanismo de tratamento de exceções que captura exceções de qualquer lugar dentro de um processo.
Habilitar a trap flag causa uma exceção EXCEPTION_SINGLE_STEP na próxima instrução executada.
Um vectored exception handler personalizado pode inspecionar o RIP e verificar por uma syscall.
Ao redefinir repetidamente a trap flag, o endereço da syscall será descoberto e a SSN salva.
Busca de Syscall
|
Execução de Syscall
|
Cada syscall tem a busca inicial de informações da syscall; Hooks serão acionados para recuperar informações da syscall. Prosseguindo, um salto indireto será feito para a syscall. Haverá um RIP spoof associado (a partir da entrada original). Com a reentrada, os parâmetros iniciais foram manipulados.
Da perspectiva do Event Tracing for Windows (ETW), os eventos possivelmente emitidos são: SysEnter, SysExit e StackWalk para ambos.
Se um EDR construir eventos semelhantes e comparáveis, estes parecerão quase idênticos.
As únicas diferenças estarão em carimbos de tempo do Query Performance Counter (QPC) drasticamente diferentes.
src/AsmRevenant.asm REAL_RTN: DQ 0
FAKE_RTN: DQ 0
; If a syscall information lookup is in progress, the
; initial entry return address needs to be preserved.
MOV RAX, QWORD PTR [RSP]
MOV QWORD PTR [FAKE_RTN], RAX
; Once the re-entry is made, the real return is saved,
; and the current is spoofed with initial return.
MOV RAX, QWORD PTR [RSP]
MOV QWORD PTR [REAL_RTN], RAX
MOV RAX, QWORD PTR [FAKE_RTN]
MOV QWORD PTR [RSP], RAX
src/Revenant.cLONG VectoredExceptionHandler(EXCEPTION_POINTERS *BreakPoint) {
...
// If a syscall information lookup is being made, the
// syscall instruction address is saved, the SSN is
// saved, and the return is rerouted.
if (LookupInProgress && *(USHORT*)BreakPoint->Address == 0x050F) {
SyscallInstruction = BreakPoint->Address;
SyscallSSN = BreakPoint->Context->Rax;
BreakPoint->Context->Rip = SyscallExit;
}
// When re-entered, if the previous instruction was
// a syscall, reset return address, and exit.
if (!LookupInProgress && *(USHORT*)(BreakPoint->Address - 2) == 0x050F) {
*(VOID**)BreakPoint->Context->Rsp = REAL_RTN;
BreakPoint->Context->Rip = SyscallExit;
}
...
}