
Escáner de pila de llamadas que identifica IOCs de agentes C2 desempaquetados o inyectados mediante el análisis del comportamiento inactivo de hilos, memoria no respaldada, módulos pisoteados, APC, temporizadores y suplantación de direcciones de retorno.
Este proyecto es (principalmente) un escáner de callstack que intenta identificar IOCs que indican un agente C2 desempaquetado o inyectado.
Todas las comprobaciones se basan en la observación de que los agentes C2 esperan entre sus callbacks, lo que provoca que el hilo del beacon se detenga, y esta herramienta tiene como objetivo analizar qué pudo haber causado esa detención.
Esto incluye IOCs tradicionales, como memoria no respaldada o módulos sobrescritos, pero también intenta detectar múltiples implementaciones de sleepmasks que usan APCs o Timers. Esto último se hace tanto analizando el callstack como enumerando timers y sus callbacks exactos desde el espacio de usuario.
(Casi) ninguno de esos IOCs puede considerarse un 100% positivo verdadero; la detección de sobrescritura de módulos, por ejemplo, es muy propensa a falsos positivos. Aun así, los resultados pueden generar sospechas sobre el comportamiento de un proceso.
Los binarios .NET y de 32 bits se ignoran.

Una página privada r(w)x en un callstack podría indicar un beacon que fue desempaquetado o inyectado en tiempo de ejecución.
Varios sleepmasks cambian los permisos de página de la página del beacon a no ejecutable. Esto produce una página no ejecutable sospechosa en el callstack.
A menudo, los beacons evitan las páginas de memoria privadas cargando y sobrescribiendo un módulo legítimo del disco.
Gracias al mecanismo de copy on write, las imágenes manipuladas pueden identificarse verificando el campo VirtualAttributes.SharedOriginal de MEMORY_WORKING_SET_EX_INFORMATION. Si alguna página del callstack no es privada y SharedOriginal == 0, se considera un IOC.
Esta es probablemente la detección más propensa a falsos positivos. :'(
Varias implementaciones de sleepmasks encolan una serie de APCs a Ntdll!NtContinue, uno de los cuales desencadena la ejecución de Ntdll!WaitForSingleObject. Por lo tanto, si se encuentra Ntdll!KiUserApcDispatcher en el callstack de una función bloqueante, esta herramienta lo considera un IOC.
De manera similar al uso sospechoso de APCs, esta herramienta también verifica la presencia de ntdll!RtlpTpTimerCallback en el callstack de una función bloqueante para detectar sleepmasks basados en timers.
Según mi entendimiento, los Timers están implementados sobre ThreadPools. Como Alon Leviev demostró, estos pueden enumerarse usando NtQueryInformationWorkerFactory con WorkerFactoryBasicInformation.
La estructura WORKER_FACTORY_BASIC_INFORMATION incorpora un FULL_TP_POOL que a su vez enlaza a una lista doblemente enlazada TimerQueue. Recorrer esa lista de PFULL_TP_TIMER permite acceder a cada callback registrado. Si se encuentra algún callback que apunte a un conjunto de llamadas API sospechosas, como ntdll!ntcontinue, puede considerarse un IOC fuerte.

Originalmente, el module proxying se introdujo como método para evitar callstacks sospechosos. Si bien el bypass funciona, introduce otro IOC fuerte, ya que se usa NTAPI para llamar a WINAPI. Esto es extraño, pues WINAPI es una abstracción de NTAPI. Por lo tanto, si se observa un callstack en el que aparece una secuencia ntdll.dll->kernel32.dll->ntdll.dll que termina llamando a una función bloqueante, puede considerarse un IOC.
La mayoría de las implementaciones de Return Address Spoofing que conozco utilizan una técnica en la que la función llamada retorna a un gadget jmp [Nonvolatile-Register]. Este proyecto simplemente itera cada dirección de retorno en los callstacks y busca patrones que indiquen el retorno a un gadget jmp.

_ _ _____ ______
| | | | / ___| | ___ \
| |_| | \ `--. | |_/ /
| _ | `--. \ | ___ \
| | | | /\__/ / | |_/ /
\_| |_/ \____/ \____/
Hunt-Sleeping-Beacons | @thefLinkk
-p / --pid {PID}
--dotnet | Set to also include dotnet processes. ( Prone to false positivies )
--commandline | Enables output of cmdline for suspicious processes
-h / --help | Prints this message?