¿Cómo evito la inyección de DLL?

Entonces, el otro día, vi esto:

http://www.edgeofnowhere.cc/viewtopic.php?p=2483118

y revisa tres métodos diferentes de inyección de DLL. ¿Cómo puedo prevenir esto del proceso? O, como mínimo, ¿cómo evito la primera?

Estaba pensando que tal vez un controlador Ring 0 podría ser la única forma de detener los tres, pero me gustaría ver qué piensa la comunidad.

La mejor solución técnica sería hacer algo que haga que el código del cargador no pueda ejecutarse correctamente después de que se inicialice el proceso. Una forma de hacerlo es tomar el locking del cargador NT, que evitará efectivamente que se produzca cualquier acción del cargador. Otras opciones incluyen parchear el código del cargador directamente en la memoria para hacer que las llamadas a LoadLibrary fallen para el atacante (por ejemplo, insertar un punto de interrupción int3 y autodetección para manejar los casos esperados).

Pero hablando como un hacker (uno que administra el sitio al que se vinculó, de hecho), nunca impedirá que la gente obtenga código en su proceso, de una forma u otra. LoadLibrary resulta ser un atajo práctico, pero hay muchas maneras diferentes de cargar código manualmente que nunca podrías esperar detener por completo, salvo algún código ring0 extremadamente complicado. E incluso si vas a ring0, los hackers estarán a tu lado.

Además, hay muchos usos legítimos para la inyección de DLL. Los progtwigs temáticos, las herramientas de accesibilidad y varios progtwigs que amplían la funcionalidad del sistema operativo pueden potencialmente usar inyección DLL para brindar funcionalidad adicional a cualquier progtwig.

Cómo defenderse contra esas 3 técnicas:

CreateRemoteThread

Puede evitar la primera técnica (CreateRemoteThread que llama a LoadLibrary) conectando LoadLibrary. En su gancho se compara con una lista de nombres DLL que sabe que son parte del proceso y que pueden estar cargados, o puede consultar una lista de archivos DLL conocidos que no desea cargar.

Cuando encuentre un archivo DLL, no desea cargar SetLastError (ERROR_ACCESS_DENIED) y luego devolver NULL. Configuré el último error para que las personas que escriben código buscando un código de error obtengan uno. Esto parece funcionar, tal vez un código diferente puede ser más apropiado.

Eso evitará que se cargue la DLL.

SetWindowsHookEx

Creo que la misma técnica para el locking CreateRemoteThread funcionará para SetWindowsHookEx, pero solo si puede instalar su hook antes de que la técnica SetWindowsHookEx haya comenzado a cargar su código (que suele ser cuando se crea la primera ventana en una aplicación, tan temprano en su vida útil) )

Code Cave

Buena técnica. No visto eso antes. Puede defenderse de esto, pero deberá conectar el punto de entrada LoadLibrary (no la tabla IAT) ya que Code Cave llama directamente a LoadLibrary.

Como comentó el autor del artículo, hay muchas maneras en que puede ser atacado y probablemente le resulte difícil derrotarlos a todos. Pero a menudo solo quiere defenderse contra ciertas cargas de DLL (como una DLL de terceros particular que es incompatible con su software porque la DLL de terceros no se escribió correctamente para acomodar el hecho de que también puede estar presente otro gancho, por lo que bloquea de la carga).

La mejor manera sería garantizar que ningún proceso que no sea de confianza obtenga acceso de administrador o se ejecute como la misma cuenta de usuario que su aplicación. Sin este acceso, la inyección de código en su aplicación no es posible; y una vez que tal proceso obtiene ese acceso, puede causar todo tipo de daños sin necesidad de inyectarse en otro proceso: la inyección simplemente lo hace más fácil de ocultar.

Dado que este cartel alude que está invirtiendo juegos anti-piratería, déjenme arrojar algo de luz sobre lo que pienso. Como un ex tramposo.

Solo un puntero sobre el juego anti-piratería.

La mejor manera es dejar que el servidor ejecute la lógica del juego principal . Por ejemplo, en un shooter en primera persona, controle los movimientos que los clientes envían al servidor. No les permita moverse al azar. Deje que el servidor le diga a los clientes dónde cada jugador se basa en su propia lógica . No solo reenvíes comandos. Podrían ser falsos.

A quién le importa si el hacker hackea a su propio cliente? simplemente rechazarlo en los otros y todo está bien. Para starcraft maphacks, la solución es simple. No revele el estado del juego por áreas que deberían ser desconocidas. También ahorra ancho de banda.

Fui un gran tramposo en Delta Force (es un juego antiguo). El truco principal que utilicé fue deformar en cualquier parte del juego modificando directamente la memoria del proceso. ¡No se requiere DLL!

¿Estás buscando una solución Ring3 entonces? Si es así, quiere crear funcionalidades adicionales en el sistema que actualmente (al menos que yo sepa) no están actualizadas, por lo que requerirá un poco de trabajo. Además, esto es posible desde un controlador, de hecho la mayoría de su software AV realiza este tipo de actividad regularmente.

En cuanto a detener los métodos anteriores desde el modo de usuario, se vuelve un poco más complicado ya que no puede registrarse como una callback para procesar la creación o la carga de DLL. Sin embargo, si supone que su proceso ha comenzado antes que el suyo, enganche CreateRemoteThread y funciones similares de forma global y realice este tipo de comprobación usted mismo.

Entonces, en realidad, querría comprobar dónde CreateRemoteThread desea crear un hilo y devolver un error si no está satisfecho con él.

Esto negaría los primeros dos métodos. Para el tercer método, si tiene valores hash válidos del progtwig original en el disco, entonces siempre puede verificar el hash antes de cargarlo. Si no tiene valores hash, al menos puede verificar algunos de los lugares simples en los que alguien agregaría ese tipo de código y buscará archivos DLL que no espera que estén allí (por ejemplo, el IAT, o ejecute cadenas).

No es infalible, pero parece brindar la funcionalidad que solicitó.

¿Por qué quieres prevenir esto? ¿Es una necesidad real de ‘negocio’, o simplemente estás interesado en un ‘truco’ para oponerse al ‘truco’?

Si los derechos del usuario lo permiten, es por diseño: el sistema operativo proporciona la instalación a todos los usuarios que usted , el administrador del sistema, haya asignado a las cuentas bajo las cuales se ejecutan.

Raymond Chen se va a vincular aquí pronto …

Solo breves pensamientos para discusión 🙂

El uso de una cueva de código para inyectar una verificación de CRC en su propio código tal vez ralentizará a otros el uso de otras cuevas de código.

Sondear la lista del módulo de proceso para que se carguen dll desconocidos podría ayudar a ralentizar a la gente que acaba de inyectar cualquier cosa antigua con adjuntar subprocesos y enganches de mensajes.

No estoy íntimamente familiarizado con la API de Windows, pero puedo darte algunos consejos más generalizados:

  1. Vea si puede usar Windows Data Execution Prevention (DPE). Probablemente no funcione para todas las situaciones (leer: la mayoría), porque el proceso descrito en su enlace es un proceso válido desde el punto de vista del sistema operativo. Defensa en profundidad, aunque

  2. Asegúrese de que sus métodos de proceso confirmen los permisos de seguridad en toda la aplicación

  3. Asigne de forma estática el espacio de memoria para que los hilos nuevos generados en él fallarán o sobrescribirán el espacio de memoria existente; sin embargo, necesitarás un buen trozo de lógica para detectar y corregir esto.

  4. Factorice su código en un controlador de dispositivo u otro proceso de tipo de bajo nivel que pueda cubrirse bajo el paraguas de protección de archivos de Windows.

Acabo de ver la respuesta de Cthulon (¡lindo nombre, por cierto!) Y me temo que probablemente sea cierto: cualquiera que quiera realizar la inyección de código en su aplicación encontrará la manera de hacerlo. Los pasos anteriores podrían simplemente hacerlo un poco más difícil.

Espero que esto ayude