
Scanner de pilha de chamadas que identifica IOCs de agentes C2 descompactados ou injetados analisando comportamento ocioso de threads, memória não mapeada, module stomping, APCs, timers e spoofing de endereço de retorno.
Este projeto é (principalmente) um scanner de callstack que tenta identificar IOCs indicando um agente C2 desempacotado ou injetado.
Todas as verificações baseiam-se na observação de que agentes C2 esperam entre seus callbacks, fazendo com que a thread dos beacons fique ociosa, e esta ferramenta visa analisar o que potencialmente causou a ociosidade da thread.
Isso inclui IOCs tradicionais, como memória sem suporte (unbacked memory) ou módulos stomped, mas também tenta detectar múltiplas implementações de sleepmasks usando APCs ou Timers. O último é feito tanto analisando a callstack quanto enumerando timers e seus callbacks exatos a partir do userland.
(Quase) nenhum desses IOCs pode ser considerado 100% verdadeiro positivo, a detecção de module stomping, por exemplo, é muito propensa a falsos positivos. No entanto, os resultados podem levantar suspeitas sobre o comportamento de um processo.
Binários DotNet e 32 bits são ignorados.

Uma página privada r(w)x em uma callstack pode indicar um beacon que foi desempacotado ou injetado em tempo de execução.
Múltiplos Sleepmasks alteram as permissões da página do beacon para não executável. Isso leva a uma página não executável suspeita na callstack.
Frequentemente, beacons evitam páginas de memória privada carregando e sobrescrevendo um módulo legítimo do disco. Graças ao mecanismo copy on write, imagens manipuladas podem ser identificadas verificando o campo VirtualAttributes.SharedOriginal de MEMORY_WORKING_SET_EX_INFORMATION. Se alguma página na callstack não for privada e SharedOriginal == 0, é considerado um IOC.
Esta é provavelmente a detecção mais propensa a falsos positivos. :'(
Múltiplas implementações de sleepmasks enfileiram uma série de APCs para Ntdll!NtContinue, uma das quais aciona a execução de Ntdll!WaitForSingleObject. Assim, se Ntdll!KiUserApcDispatcher puder ser encontrado na callstack para uma função bloqueante, esta ferramenta considera um IOC.
Semelhante ao uso suspeito de APCs, esta ferramenta também verifica ntdll!RtlpTpTimerCallback na callstack para uma função bloqueante a fim de detectar sleepmasks baseados em timer.
Pelo que entendi, os Timers são implementados sobre ThreadPools. Como Alon Leviev demonstrou, eles podem ser enumerados usando NtQueryInformationWorkerFactory com WorkerFactoryBasicInformation.
A struct WORKER_FACTORY_BASIC_INFORMATION incorpora um FULL_TP_POOL que, por sua vez, se liga a uma lista duplamente ligada TimerQueue. Percorrer essa lista de PFULL_TP_TIMER permite acessar cada callback registrado. Se algum callback for encontrado apontando para um conjunto de chamadas de API suspeitas, como ntdll!ntcontinue, pode ser considerado um IOC forte.

Originalmente, o module proxying foi introduzido como um método para contornar callstacks suspeitas. Embora o bypass funcione, ele introduz outro IOC forte, já que a NTAPI é usada para chamar a WINAPI. Isso é estranho, pois a WINAPI é uma abstração para a NTAPI. Assim, se uma callstack for observada na qual uma sequência de ntdll.dll->kernel32.dll->ntdll.dll termina chamando uma função bloqueante, pode ser considerado um IOC.
A maioria das implementações de spoofing de endereço de retorno que conheço usam uma técnica em que a função chamada retorna para um gadget jmp [Nonvolatile-Register]. Este projeto simplesmente itera sobre cada endereço de retorno nas callstacks e procura por padrões indicando o retorno para um gadget jmp.

_ _ _____ ______
| | | | / ___| | ___ \
| |_| | \ `--. | |_/ /
| _ | `--. \ | ___ \
| | | | /\__/ / | |_/ /
\_| |_/ \____/ \____/
Hunt-Sleeping-Beacons | @thefLinkk
-p / --pid {PID}
--dotnet | Define para incluir também processos dotnet. ( Propenso a falsos positivos )
--commandline | Habilita a saída da linha de comando para processos suspeitos
-h / --help | Imprime esta mensagem?