2009-02-21 8 views
25

En mi anterior empleador utilizamos un componente de terceros que, básicamente, era solo una DLL y un archivo de encabezado. Ese módulo en particular manejó la impresión en Win32. Sin embargo, la compañía que hizo el componente fue bankcrupt, así que no pude reportar un error que encontré.¿Cuál es tu truco favorito contra la depuración?

Así que decidí corregir el error y lancé el depurador. Me sorprendió encontrar el código anti-depuración en casi todas partes, lo usual IsDebuggerPresent, pero lo que me llamó la atención fue la siguiente:

; some twiddling with xor 
    ; and data, result in eax 
    jmp eax 
    mov eax, 0x310fac09 
    ; rest of code here 

A primera vista me acaba de caminar sobre la rutina que se llama dos veces, luego las cosas simplemente se fue plátanos. Después de un tiempo, me di cuenta de que el resultado de los giros cortos siempre era el mismo, es decir, el jmp eax siempre saltaba directamente a la instrucción mov eax, 0x310fac09. Analicé los bytes y allí estaba, 0f31, la instrucción rdtsc que se usó para medir el tiempo pasado entre algunas llamadas en la DLL.

Así que mi pregunta a SO es: ¿Cuál es su truco favorito contra la depuración?

+10

En mi opinión, realmente no quiero que se ejecute código en mi sistema que haya hecho cosas para evitar la depuración. Muestra que no se puede confiar en el autor del código. – bruceatk

+1

Estoy de acuerdo con bruceatk, especialmente para las DLL y otros componentes que uso para compilar mi aplicación. Me preocupan menos las aplicaciones completas que uso. No me sorprende que la compañía se haya bancarizado :) - sería mejor dedicar tiempo a producir un buen código que protegerlo. – Michael

+0

@bruceatk para que no ejecute Windows? El sistema operativo en sí contiene algunos trucos anti-depuración para ayudar a ocultar algunos de sus mecanismos de protección más interesantes. – mrduclaw

Respuesta

27

Mi truco favorito es escribir un emulador de instrucciones simple para un microprocesador oscuro.

La protección contra copia y parte de la funcionalidad básica se compilará para el microprocesador (GCC es una gran ayuda aquí) y se vinculará al programa como un blob binario.

La idea detrás de esto es que la protección contra copia no existe en el código x86 ordinario y, como tal, no se puede desmontar.Tampoco puedes eliminar todo el emulador porque esto eliminaría la funcionalidad principal del programa.

La única posibilidad de hackear el programa es realizar una ingeniería inversa de lo que hace el emulador de microprocesador.

He usado MIPS32 para la emulación porque era muy fácil de emular (tomaba solo 500 líneas de código C simple). Para hacer las cosas aún más oscuras, no usé los códigos de operación MIPS32 en bruto. En cambio, cada código de operación fue desviado con su propia dirección.

El binario de la protección de copia parecía basura.

¡Muy recomendable! Pasó más de 6 meses antes de que saliera una grieta (era para un proyecto de juego).

+0

¿Así que básicamente pasaste por todo ese trabajo sabiendo que finalmente fallarías? – fow

+0

Seis meses es mucho tiempo cuando hablamos de descifrar una aplicación. – Irwin

+3

Yo diría que pasaron 6 meses antes de que alguien lo intentara. No vale la pena el esfuerzo. Estoy seguro de que todo lo que hiciste fue fácilmente ignorado por algo en lo que nunca pensaste. – bruceatk

0

El uso de nop para eliminar el ensamblaje a través del depurador es un truco útil. ¡Por supuesto, devolver el código es mucho más difícil!

+1

Dependiendo del depurador debería haber una función 'deshacer'. OllyDbg tiene uno, solo selecciona los bytes modificados y presiona ALT + RETROCESO. – Irwin

6

He sido miembro de muchas comunidades de RCE y he tenido una buena parte de la piratería & cracking. Desde mi época, me he dado cuenta de que esos trucos endebles suelen ser volátiles y bastante inútiles. La mayoría de los trucos genéricos contra la depuración son específicos del sistema operativo y no son 'portátiles' en absoluto.

En el ejemplo mencionado anteriormente, presumiblemente está utilizando el ensamblado en línea y una función naked__declspec, ambas no admitidas por MSVC al compilar en la arquitectura x64. Por supuesto, todavía hay formas de implementar el truco antes mencionado, pero cualquiera que haya estado retrocediendo el tiempo suficiente podrá detectar y vencer ese truco en cuestión de minutos.

Por lo general, sugeriría que no se utilicen trucos contra la depuración fuera del uso de la API IsDebuggerPresent para la detección. En cambio, sugiero que codifique un apéndice y/o una máquina virtual. Codifiqué mi propia máquina virtual y la he estado mejorando durante muchos años y honestamente puedo decir que ha sido la mejor decisión que he tomado con respecto a la protección de mi código hasta ahora.

2

En segundo lugar la sugerencia de la máquina virtual. Implementé un simulador MIPS I que (ahora) puede ejecutar binarios generados con mipsel-elf-gcc. Agregue a ese código/capacidades de cifrado de datos (AES o con cualquier otro algoritmo de su elección), la capacidad de auto-simulación (para que pueda tener simuladores anidados) y tiene un buen ofuscador de código.

La buena característica de elegir MIPS I es que 1) es fácil de implementar, 2) Puedo escribir código en C, depurarlo en mi escritorio y simplemente compilarlo para MIPS cuando esté listo. No hay necesidad de depurar códigos de operación personalizados o escribir código manualmente para una máquina virtual personalizada.

+0

Wtf - ¿Usas MIPS también? Pensé que era el único que lo hacía de esta manera. –

+0

Bueno, primero quise diseñar un conjunto de instrucciones personalizadas, pero rápidamente se me ocurrió que me condenaría a escribir y depurar código manualmente. Así que fui a buscar una CPU simple compatible con gcc :-) – zvrba

3

El método de ofuscación más moderno parece ser la máquina virtual.

Básicamente toma parte de su código de objeto y lo convierte a su propio formato de bytecode. Luego, agrega una pequeña máquina virtual para ejecutar este código. La única manera de depurar correctamente este código será codificar un emulador o desensamblador para el formato de instrucción de su máquina virtual. Por supuesto, también debes pensar en el rendimiento. Demasiado bytecode hará que tu programa se ejecute más lento que el código nativo.

La mayoría de los viejos trucos son inútiles ahora:

  • IsDebuggerPresent: muy cojo y fácil de parche
  • Otros Depurador/detecciones de punto de interrupción
  • cosas Ring0: los usuarios no les gusta instalar los controladores, es posible que en realidad, romper algo en su sistema, etc.
  • Otras cosas triviales que todo el mundo conoce, o que hacen que su software sea inestable. recuerda que incluso si un crack hace que tu programa sea inestable pero aún funciona, esta inestabilidad será culpable de ti.

Si realmente desea codificar la solución de VM usted mismo (hay buenos programas para la venta), no use solo un formato de instrucción. Haz que sea polimórfico, para que puedas tener diferentes partes del código que tengan un formato diferente. De esta forma, no se puede romper todo el código escribiendo solo un emulador/desensamblador. Por ejemplo, la solución MIPS que algunas personas ofrecen parece que se puede romper fácilmente porque el formato de instrucción MIPS está bien documentado y las herramientas de análisis como IDA ya pueden desensamblar el código.

List of instruction formats supported by IDA pro disassembler

1

Calculado saltos en medio de una legítima mirando pero en realidad esconde una instrucción instrucciones reales son mis favoritos. De todos modos, son bastante fáciles de detectar para los humanos, pero las herramientas automatizadas a menudo lo estropean.

También reemplazar una dirección de retorno en la pila hace que sea una buena pérdida de tiempo.

3

Preferiría que la gente escriba software que sea sólido, confiable y que haga lo que se anuncia. Que también lo venden a un precio razonable con una licencia razonable.

Sé que he perdido demasiado tiempo tratando con proveedores que tienen esquemas de licencias complicados que solo causan problemas para los clientes y los proveedores. Siempre es mi recomendación evitar a esos vendedores. Trabajando en una planta de energía nuclear, nos vemos obligados a utilizar ciertos productos de vendedores y, por lo tanto, nos vemos obligados a tener que lidiar con sus esquemas de licencia.Ojalá hubiera una manera de recuperar el tiempo que personalmente he perdido tratando con sus intentos fallidos de darnos un producto licenciado que funcione. Parece una pregunta pequeña, pero parece ser algo difícil para las personas que se vuelven demasiado astutas para su propio bien.

+0

Ofensivo? Me encantaría que quien decidiera etiquetar esta ofensiva se ponga en contacto conmigo y me explique qué es ofensivo al respecto. [email protected] – bruceatk

+0

+1 Para contrarrestar la "ofensiva". +1 punto virtual para problemas de energía nuclear. –

+1

No te señalé como ofensivo, pero te califiqué porque tu publicación está realmente fuera del tema. – rhinovirus

6

Spin off un proceso hijo que se conecta al padre como un depurador & modifica las variables clave. Puntos de bonificación para mantener al proceso hijo residente y utilizar las operaciones de memoria del depurador como una especie de IPC para ciertas operaciones clave.

En mi sistema, no puede adjuntar dos depuradores al mismo proceso.

Lo bueno de esto es que a menos que traten de alterarlo, nada se rompe.

2

Mi favorita fue en el Amiga, donde hay un coprocesador (el Blitter) haciendo de datos grande transferencias independientes del procesador; este chip sería instruido para borrar toda la memoria y reiniciar desde un IRQ de temporizador.

Cuando conectó un cartucho de Action Replay, detener la CPU significaría que el Blitter continuaría borrando la memoria.

Cuestiones relacionadas