Nota: Este post es una traducción personal (reconvertida en tutorial) de las explicaciones dadas por Bill Leach (CTO de Preemptive Solutions), en este vídeo grabado para Channel 9.
Introducción
En este artículo se describen los pasos necesarios para proteger el código fuente de aplicaciones Windows Phone (tanto XNA como Silverlight), e incluir en ellas la generación de informes sobre su utilización.
Para ello, se utilizará la herramienta Dotfuscator Windows Phone Edition en su versión 4.9, recientemente lanzada por Preemptive Solutions en colaboración con Microsoft.
En primer lugar, es necesario registrarse y descargar la herramienta desde esta página web. Una vez se recibe por email el número de serie necesario para activar el programa, solo resta lanzar la aplicación: Inicio –> Programas –> Preemptive Solutions –> Dotfuscator.
Interfaz de usuario
Aunque Dotfuscator Professional puede integrarse dentro de Visual Studio 2010, como un tipo de proyecto más, Dotfuscator Windows Phone Edition es una aplicación independiente, con su propio interfaz de usuario:
Como puede apreciarse en la imagen, el funcionamiento es sencillo. Consta de:
- Menú principal y barra de herramientas con las opciones típicas para cargar y salvar un proyecto de ofuscación
- Botón con el símbolo de Play en verde, en la barra de herramientas, el cual comienza la ofuscación del código que se haya seleccionado y genera las versiones protegidas de los ensamblados o programas.
- Pestañas de configuración:
- Settings: Configuración general de la aplicación
- Input: Selección de qué ensamblados o ejecutables queremos proteger en el proyecto.
- El resto: propiedades de configuración para cada una de las funcionalidades que ofrece Dotfuscator
Añadiendo ensamblados o ejecutables
Para empezar a trabajar, lo primero es indicar a Dotfuscator qué ensamblados o ejecutables debe proteger. Para ello, solo hay que ir a la pestaña Input y pulsar sobre el icono de abrir carpeta. Aparecerá el clásico cuadro de diálogo de selección de archivos, donde es posible seleccionar:
- Ensamblados (librerías) de tipo .DLL
- Ejecutables (aplicaciones) de tipo .EXE
- Paquetes de despliegue de Windows Phone (contienen librerias DLL, contenidos, etc), de tipo .XAP. Esta será la opción que se utilizará en el ejemplo que nos ocupa.
Nota: Si, como es el caso, estamos trabajando con proyecto Windows Phone (y archivos XAP), Dotfuscator solo trabajará con los ensamblado que encuentre en dichos archivos. Los contenidos no serán protegidos ni modificados en absoluto.
Una vez se selecciona el paquete XAP a proteger, aparecerán sus contenidos en la ventana inferior, en forma de árbol desplegable:
Si se despliega cualquiera de las DLLs del paquete, aparecerán algunas propiedades de ofuscación activadas, en forma de CheckBoxes. Una de las más relevantes, según los objetivos que persigue este artículo, es la llamada Library:
Manteniendo esta opción marcada (viene marcada por defecto), Dotfuscator deja todos los nombres de los tipos y métodos públicos sin renombrar (sin ofuscar). Los tipos privados sí se renombrarán, y todo el contenido de los métodos se ofuscará, pero los nombres que sean visibles desde fuera permanecerán inalterados.
Esto es necesario cuando una librería, a pesar de estar ofuscada, va a ser utilizada por cualquier otro software después. Si se cambiaran los nombres de los tipos públicos, el interfaz de la librería sería distinto, por lo que dejaría de ser utilizable desde fuera.
Output de la aplicación
Dotfuscator genera versiones protegidas de lo que se selecciona en la pestaña Input:
- Para ensamblados (DLL), genera DLLs protegidas
- Para ejecutables (EXE), genera EXEs protegidos
- Para paquetes Windows Phone (XAP), genera paquetes XAP protegidos
Por defecto, el directorio de salida es el mismo donde se encuentra el ensamblado de entrada, más una sub-carpeta creada por el programa con el nombre Dotfuscated. No obstante, este comportamiento se puede cambiar en la pestaña Settings -> Project Properties -> ConfigDir.
Aplicando una protección básica
Una vez se han seleccionado los Inputs del proyecto, es necesario seleccionar qué tipo de protección ha de aplicarse.
Aunque cada tipo de protección puede ser configurada en profundidad (en sus respectivas pestañas), pudiendo incluso aplicar comportamientos distintos para cada método o propiedad, primero se aplicará una configuración genérica en la pestaña Settings.
Por defecto, todas las protecciones están deshabilitadas, apareciendo de la siguiente forma:
- Disable Control Flow: Yes
- Disable Linking: Yes
- Disable PreMark: Yes
- Disable Removal: Yes
- Disable Renaming: Yes
- Disable String Encryption: Yes
Para una protección básica, lo indispensable es activar la ofuscación de Control Flow y el Renaming. En algunos casos, también puede ser interesante activar el String Encryption, sobre todo si la aplicación a proteger contiene strings con contenido sensible.
Para activar cada funcionalidad, debemos indicar a Dotfuscator que NO las deshabilite, es decir, poner valores como: Disable Control Flow: No y Disable Renaming: No.
Control Flow
La ofuscación del flujo de control se encarga de hacer más difícil la comprensión del código, mediante cambios en el flujo del programa. Aunque el resultado final siga siendo equivalente, a nivel funcional, hace cambios para que no sea nada obvio interpretar por donde va a transcurrir la ejecución, y así dificultar las tareas de ingeniería inversa.
Renombrado
El renombrado se encarga de cambiar el nombre a todos los tipos privados, cambiando los descriptivos nombres originales por valores como: “a”, “b”, “c”, etc. En la pestaña Renaming se pueden excluir a mano, uno por uno, métodos o propiedades que explícitamente se quieran dejar fuera del renombrado. No obstante, para un uso básico, esto normalmente no es necesario.
Con estas funcionalidades activadas, ya se cuenta con una protección básica del código fuente. Ahora se describirá como incluir informes en aplicaciones Windows Phone.
Añadir instrumentación, o Code Analytics
Además de protección y ofuscación, Dotfuscator puede añadir Instrumentación a los programas.
Ambas funcionalidades son independientes. Es decir, se pueden aplicar las dos a la vez, se puede aplicar protección pero no instrumentación, y vice-versa.
La instrumentación utiliza una plataforma de Preemptive Solutions denominada como: Runtime Intelligence. Lo que hace es inyectar en el programa que procesa ciertas líneas de código cuya misión es generar informes de uso del mismo cada vez que este se ejecuta, y subirlos al portal de Runtime Intelligence (u otro), al que cada desarrollador registrado tiene acceso protegido por nombre y contraseña.
Se trata de un comportamiento muy similar al que ofrecen otras plataformas de análisis en otros sectores, como Google Analytics para WebSites, blogs, etc.
La instrumentación se activa/desactiva desde la pestaña Settings, apartado Instrumentation (debemos dejar todas las opciones activadas –Yes-)
Identificando la empresa y la aplicación en los informes
Obviamente, el generador de informes debe saber para qué aplicación está reportando, y para que empresa. Ambas cosas se identifican en la pestaña Instrumentation.
En ella, es necesario expandir el nodo de la DLL que contenga la clase principal de la aplicación:
- Para una aplicación XNA, será aquella DLL que contenga la clase de tipo Game
- Para una aplicación Silverlight, será aquella DLL que contenga la clase App
Una vez desplegado dicho nodo, aparecerá una lista de atributos por defecto, como los de la siguiente imagen (para un ejemplo en XNA).
Para que la instrumentación funcione, es necesario añadirle dos más, pulsando con el botón derecho sobre el nombre de la DLL y seleccionando la opción: Add Attribute. Una vez hecho esto, se abrirá una ventana que pregunta el tipo de atributo a añadir, con una serie de valores predefinidos:
Los dos que hay que añadir son:
BusinessAttribute
Este atributo identificará a la empresa desarrolladora del software, mediante un Company Key único, proporcionado vía email por Preemptive Solutions cuando se efectuó el registro en el portal de Runtime Intelligence. También se puede encontrar en el Dashboard del portal una vez hecho login.
Resulta recomendable incluir además un nombre de empresa.
ApplicationAttribute
Para identificar la aplicación, es necesario proporcionar la siguiente información:
- Application Type: Tipo de aplicación (se puede dejar en blanco)
- Guid: Identificador del ensamblado principal de la aplicación. Debe ser único, ya que será utilizado en el portal para identificar a esta aplicación. En este campo se puede utilizar el Guid del proyecto, disponible en su Assembly Info (accesible en Visual Studio desde el Solution Explorer o desde la ventana de propiedades del proyecto –> Assembly Info).
- Name: Nombre de la aplicación (se puede dejar en blanco, aunque no es muy recomendable)
- Version: Versión de la aplicación (si se deja en blanco, el Reporter tratará de extraerla de los meta-datos del ensamblado).
Indicando dónde se debe inyectar el código
Para indicar a Dotfuscator dónde inyectar el código que genera los informes, solo hay que navegar (sin salir de la pestaña Instrumentation) un poquito hacia abajo, y expandir el contenido aún más la DLL de la parte inferior (en el siguiente ejemplo, la DLL Silverlight: WindowsPhoneApplication1.dll):
Expandiendo uno tras otro los sucesivos nodos, solo resta navegar hasta la clase principal de la aplicación.
- En el caso de un juego XNA, ésta será la clase Game del juego
- En caso de ser una aplicación Silverlight, ésta será la clase App
Informe de comienzo de ejecución
Para informar sobre el comienzo de una ejecución, se busca un método que se ejecute UNA SOLA VEZ en el proceso de inicialización.
En el caso de aplicaciones SilverLight, un candidato perfecto es el evento Application_Launching de la clase App. En caso de una aplicación XNA, una buena opción puede ser el método Initializing de la clase Game.
Una vez seleccionado el método, se pincha con el botón derecho sobre su nombre, y se selecciona la opción Add Attribute. De nuevo, se solicitará el tipo de atributo a añadir, aunque esta vez la lista de opciones es distinta:
El atributo a elegir esta vez es SetupAttribute, el cual tiene bastantes parámetros que se pueden dejar con sus valores por defecto. Aun así, cabe remarcar estos dos:
- Custom Endpoint: En lugar de enviar los informes al EndPoint por defecto (el del portal de Runtime Intelligence), aquí se puede especificar otro EndPoint personalizado
- Use SSL: Activa protección SSL para las comunicaciones
Generar los informes de comienzo en un thread aparte
Si la aplicación que estamos desarrollando tarda cierto tiempo en cargar (algo típico en juegos XNA), lo normal (o más bien lo recomendado) es tener la carga inicial de contenidos separada en un Thread aparte, para que mientras dicha carga se produce, se pueda mostrar un icono animado de tipo Loading….
En estos casos, es recomendable incluir la inyección del código de informes en dicho thread, por si la generación del report se demora un poquito por motivos de red, o cualquier otro (aunque no debería). De esta forma la experiencia de usuario no se verá entorpecida.
Si se observa el siguiente ejemplo, en el que se está protegiendo un juego XNA, dicho punto ejecutado en un thread aparte es el método denominado CreateAssets:
Informe de fin de ejecución
Si también se desea que los informes indiquen cuando se dejó de utilizar la aplicación, habrá que seguir un procedimiento muy similar, añadiendo un atributo a un método que se ejecute cuando la aplicación está terminando.
- En el caso de juegos XNA, el método perfecto para esto es OnExiting, de la clase Game.
- Para aplicaciones SilverLight, una buena opción es el evento Application_Closing, de la clase App
En este caso, el tipo de atributo a añadir es TearDownAttribute, el cual se puede dejar con sus parámetros por defecto.
Y con esto y un bizcocho, code-analytics a las ocho