martes, 22 de septiembre de 2015

C# AntiHack! Evitando que hackeen tu juego

Después de un verano y sindrome posvacacional vuelvo a la carga!

Antes de comenzar con esta entrada aprovecho para decir que la mayoría del código que vaya haciendo lo iré colgando en GitHub, así se tendrá más fácil acceso al contenido, si bien estará comentado todo en inglés, no te preocupes, aquí lo explicaré en español y paso a paso.

Una de las formas de hacking de videojuegos mas comunes, editar la memoria RAM
Como en este caso, la clase que he creado para encriptar variables en la memoria RAM.

En primer lugar, ¿Para qué quiero encriptar las variables en memoria?
Hay ciertos datos que nos gustaría que bajo ningún concepto pudiesen editar ya que, si por ejemplo tenemos un juego en el que puedes comprar monedas con dinero real, pues si acceden al valor en memoria del dinero y lo editan podrían tener dinero infinito con el cual podrían acceder a todo el contenido y los desarrolladores no ganarían el dinero por el esfuerzo de dicho desarrollo, y ese tipo de datos suele ser mucho más sensible, así como datos que se envíen a servidores en un MMORPG por ejemplo para evitar que los modifiquen e intenten añadir código malicioso o que les dé ventaja respecto a los demás y por supuesto pues los motivos internos de cada desarrollo.

 Dicho esto, el código está en mi cuenta de GitHub, solo hay que descargar el archivo CryptedData.cs y usarlo es muy sencillo, en un script que creemos nosotros añadimos esta línea:

CryptedData<int> cryptedInt = new CryptedData<int>(3);

Creamos un objeto de tipo CryptedData diciendo de que tipo será el objeto o valor que nos va a retornar, ya podría ser un int,  un string, un objeto de cualquier tipo de clase que nosotros necesitemos, en este caso un int de valor 3 por defecto ya que es el valor que le hemos pasado como parámetro.

Dicho dato, evidentemente, debe de ser del mismo tipo que el que ponemos entre los símbolos de mayor y menor que (< >).

Y para editarlo es tan sencillo como acceder a su valor de esta manera, ya sea para modificarlo o usarlo.

cryptedInt.value = 10;
Debug.Log(cryptedInt.value); 

Y con esto tendremos bajo una seguridad compleja de descifrar aunque a la vez bastante rápida.

He de remarcar que con el cifrado que he usado, los objetos pesarán el doble en memoria, ya que usará una clave de cifrado internamente del mismo tamaño que el objeto, así que hay que intentar no excederse y usarlo solo para lo imprescindible si no queremos saturar la memoria ram.

En principio usar esta clase podría parecer que estamos usando variables normales y corrientes pero internamente lo está ocultando en la memoria ram, si quieres probarlo e incluso encontrar fallos de seguridad o mejorar el algoritmo, por supuesto puedes sentirte en plena libertad de aportar, a partir de ahora subiré todas las clases que vaya creando y considere interesantes a mi repositorio.

Si quieres saber como funciona pues en otra ocasión destriparé la clase aquí paso a paso para ver el proceso, esta clase, si bien no tiene que ver con videojuegos directamente, si con la seguridad de los mismos, seguramente no será el último código que añada sobre seguridad aquí ya que es algo que también me apasiona.

4 comentarios:

  1. He estado viendo la implementación que has realizado en Github y según explicas aquí el temor es que alguien pueda leer el valor de una variable en la memoria RAM, pues bien, con tu sistema veo que creas una KEY de la misma longitud que el tamaño en bytes del dato a encriptar y luego para calcular el dato encriptado haces: encrypted = plain XOR key y en efecto esto encripta el valor. Pero esto no evita tu temor de que alguien pueda leer de la RAM la key y el valor cifrado. Si alguien es capaz de leer la KEY y el valor encriptado (de la RAM) simplemente haciendo plain = encripted XOR key daría con el valor original y por supuesto, si posee la KEY es capaz de modificar ese valor y el sistema critográfico que te has montado no servirá para nada. Diseñar una medida efectiva contra lo que comentas es complejo porque la clave debe ser siempre secreta y en el momento que alguien pueda leer la RAM (y te aseguro que la clave estará en algún momento en la RAM) tendrá acceso a todo, un algoritmo más complejo sin duda le pondrá las cosas más dificiles al atacante.

    ResponderEliminar
    Respuestas
    1. Muy bien visto por tu parte, pero ahora te planteo el siguiente problema, ¿Que es más difícil? ¿Encontrar un número que tienes de referencia en pantalla así como tu vida o tu dinero, o el nombre de tu personaje? ¿O bytes dispersos en memoria que tendrías que relacionar y hacer el XOR ordenando correctamente dichos bytes? Hay programas para hacer dump de memoria, pero normalmente no te ponen Bytes ya que todos son Bytes, solo que no todos son números, letras, etc...

      Igualmente este sistema desde luego se podría mejorar, pero he partido de la base de que, es suficientemente complicado para que sea difícil de rastrear en memoria siendo a la par, sencillo de procesar.

      Podría usar algoritmos de cifrado mas complejo como por ejemplo AES, pero en cuanto a rendimiento desde luego sería mucho mas complejo que esto.

      No es el mejor algoritmo, pero para sacarlo de la RAM es suficientemente costoso como para descartar a muchos usuarios y a varios programas antihack, por otra parte si, si quien lo hace es un profesional, seguramente podría hayar la forma bastante fácil, a lo cual se podría ofuscar más ya sea con algoritmos mas fuertes o tan sencillo como invertir los bytes, usar la key a la inversa en vez de en la misma dirección, invertir los bits y su orden, y cualquier otra cosa que haga más complicada la encriptación siempre y cuando no sufra mucho el rendimiento.

      Quiero recordar que esto es para un videojuego, que ya de por sí es de lo que más rendimiento necesita en una máquina ya sea una consola o un PC.

      ¡Gracias por tu comentario!

      Eliminar
  2. Sin ánimos de incomodar a alguien, creo que, en este tipo de cosas, no existe la seguridad perfecta. Pienso que sólo hay que complicársela lo más posible sin sacrificar demasiado el rendimiento. Por lo que tu aportación me parece EXCELENTE!!! Gracias.

    ResponderEliminar