En el hacking, un código de shell es un pequeño trozo de códigos que se utiliza como carga útil en la explotación. Se llama “código de shell” porque típicamente inicia un shell de comandos desde el cual un atacante puede controlar la máquina comprometida.
Una vulnerabilidad comúnmente inyectará un código de shell en el proceso, antes o al mismo tiempo que explota una vulnerabilidad para ganar control sobre el contador del programa. Una vez que el contador de programas se ajusta para apuntar al código de shell, el código de shell se ejecuta y realiza su tarea.
Una de las famosas hazañas de este tipo es Eternal Blue. Mucha gente todavía puede sentir frío al escuchar EternalBlue, ya que es la misma hazaña que se usará en WannaCry, un rescate que impacto en 200.000 ordenadores de 150 países en 2017.
EternalBlue explota una vulnerabilidad en la implementación del protocolo Server Message Block (SMB) de Microsoft, conocido como MS17-010. La implementación de Windows SMBv1 es vulnerable al desbordamiento de búferes en la memoria del Gran Pool de Núcleos no paginados a través del procesamiento de Atributos Extendidos de Ficheros (FEA) en la función del núcleo, srv!SrvOs2FeaListToNt.EternalBlue ha sido utilizado no sólo en el rescate de WannaCry, sino también en EternalRocks, un gusano de Bloque de Mensaje de Servidor (SMB), y Adylkuzz, malware de minería de criptografía en 2017.
Aquí está el ejemplo de cómo explotamos el MS17-010 con RidgeBot™. Con esta explotación incorporada, los clientes de RidgeBot™ pueden probar si su sistema es inmune a los ataques de WannaCry.
El mecanismo de la explotación de EternalBlue:
La función srv!SrvOs2FeaListToNt llamará a srv!SrvOs2FeaListSizeToNt para calcular el tamaño de la FEA LIST recibida antes de convertirla a la lista NTFEA (Windows NT FEA). La siguiente secuencia de operaciones ocurre:
srv!SrvOs2FeaListSizeToNt calculará el tamaño de la Lista FEA y actualizará el tamaño de la Lista FEA recibida
El tamaño del FEA resultante es mayor que el valor original debido a un reparto de WORD equivocado.
Cuando la Lista FEA se itera para ser convertida en LISTA NTFEA, habrá un desbordamiento en el listado de no-páginas porque el tamaño total original de la lista está mal calculado.
Implementación del código de Shell:
7 pasos de código de barras usados aquí para finalmente lograr el RCE:
- Enganche la función de entrada del sysenter kifastercallentry:
Sysenter utiliza tres registros MSR (Model Specific Register) para especificar la dirección del objetivo de salto y la ubicación de la pila. El sistema operativo establece estos tres registros a través de la instrucción privilegiada rdmsr / wrmsr en el modo de kernel, que por supuesto debe completarse durante la inicialización del sistema (antes de que se produzca la primera llamada al sistema). Si leemos la dirección de la función kifastercallentry a través de la instrucción rdmsr, y reemplazamos la dirección de la función kifastcallentry por la dirección del código de shell, entonces secuestramos con éxito el sistema.
- Encuentra la dirección de inicio en el módulo ntkrpamp.exe
Con la ejecución del código asm anterior, podemos ver cuando la dirección de la función KiFastCallentry es 805416e0, y el módulo ntkrpamp.exe se encuentra en [804d7000, 806e5000].
- Según la dirección del módulo ntkrpamp.exe, calcula dinámicamente las direcciones de algunas funciones clave.
- Obtenga el objeto eprocess del proceso lsass.exe
- Obtenga la cadena de hilos para el objeto eprocess
- Trate de inyectar llamada APC en cadena de hilo de eProcess
Cuando la función KinsertQueue se realiza con éxito, el indicador UserApcPending se establece en 1.
- Cuando el hilo en estado alterable, la llamada APC de inyección se ejecutaría.