Algoritmos estándar
Babel Obfuscator incluye tres algoritmos integrados de cifrado de cadenas: XOR, HASH y STREAM. Los tres son autónomos (descifran sin ninguna entrada externa), de modo que elegir entre ellos supone buscar un equilibrio entre el tiempo de carga, el tamaño de la salida y lo difícil que resulta recuperar las cadenas. En esta página se describe cada algoritmo y cómo activarlo; la tabla comparativa del final resume las diferencias.
Algoritmo XOR
El algoritmo XOR que Babel Obfuscator usa para cifrar cadenas es un algoritmo sencillo, que aplica la operación XOR entre los caracteres de la cadena en línea y una clave entera aleatoria. Este método tiene la ventaja de permitir un descifrado más rápido y un tiempo de carga menor que otros algoritmos de cifrado.
Línea de comandos
Para configurar el algoritmo de cifrado XOR en su aplicación con Babel Obfuscator desde la línea de comandos, use este sencillo comando:
babel myapp.exe --string xorEste comando indica a Babel que aplique el cifrado XOR a las cadenas en línea del ejecutable de su aplicación, y aprovecha la sencillez y la rapidez del algoritmo XOR para ofuscar las cadenas de forma segura.
Tarea Babel de MSBuild
Configurar el algoritmo XOR para el cifrado de cadenas en su proyecto con la tarea Babel de MSBuild es sencillo. Basta con añadir a su archivo de proyecto de MSBuild un grupo de propiedades y una tarea Babel con la configuración específica del método de cifrado XOR:
<PropertyGroup>
<StringEncryption>xor</StringEncryption>
</PropertyGroup>
<Babel StringEncryption="$(StringEncryption)" />Con esta configuración, Babel Obfuscator aplica el algoritmo de cifrado XOR a las cadenas de su proyecto, lo que mejora su seguridad y las hace más resistentes a la manipulación y a los intentos de ingeniería inversa.
Algoritmo HASH
El algoritmo HASH de Babel Obfuscator se basa en tablas hash a las que se accede mediante claves enteras. Este algoritmo comprime y cifra los datos de las cadenas, lo que puede ayudar a reducir el tamaño total que esos datos ocupan en el archivo. Sin embargo, como los datos comprimidos de las cadenas deben descifrarse en tiempo de ejecución, puede afectar al tiempo de carga de la aplicación. En comparación con el algoritmo XOR, que aplica la operación XOR entre los caracteres de la cadena en línea y una clave entera aleatoria, el algoritmo HASH ofrece mejor protección frente a los ataques de descifrado de cadenas, pero a costa de un tiempo de carga mayor.
Línea de comandos
Para configurar el cifrado HASH con Babel Obfuscator desde la CLI, use este comando:
babel myapp.exe --string hashTarea Babel de MSBuild
Para activar el cifrado HASH con la tarea de MSBuild de Babel, establezca la propiedad StringEncryption como sigue:
<PropertyGroup>
<StringEncryption>hash</StringEncryption>
</PropertyGroup>
<Babel StringEncryption="$(StringEncryption)" />Con esta integración del algoritmo HASH, las cadenas de su proyecto quedan adecuadamente protegidas durante el proceso de compilación.
Algoritmo STREAM Ultimate
El algoritmo STREAM es la opción moderna y autenticada de cifrado de cadenas de Babel Obfuscator. Cifra cada cadena por separado con un algoritmo de cifrado robusto y estándar del sector, y verifica una etiqueta de autenticación antes de devolverla. Esto da a STREAM cuatro propiedades que los algoritmos anteriores no tienen:
- Descifrado diferido, cadena a cadena. Una cadena solo se descifra la primera vez que se usa realmente, y el resultado se guarda en caché. A diferencia de HASH, STREAM nunca descifra todo el conjunto por adelantado, de modo que un volcado de memoria solo expone las pocas cadenas que la aplicación ya ha usado: no existe ningún momento en el que todas las cadenas estén en memoria en texto sin cifrar.
- Integridad y aleatorización por cadena. La etiqueta de autenticación detecta cualquier manipulación de los datos cifrados, y dos cadenas idénticas se cifran en bytes distintos, lo que anula el análisis de frecuencia y de igualdad al que se presta un esquema XOR sencillo.
- Una clave que nunca se almacena en línea. La clave no se guarda como literal junto a la llamada de descifrado, de modo que un desofuscador automático tiene que ejecutar el código real para recuperar una cadena, en lugar de limitarse a leer una clave situada junto a la llamada.
- Descifrado vinculado al contexto de llamada de su código. Ejecutar el descifrador no basta: solo devuelve una cadena a un llamador que se ejecuta dentro del propio ensamblado protegido (o dentro del entorno de ejecución de .NET, para que LINQ/PLINQ y las rutas asíncronas sigan funcionando). Queda así bloqueada la forma habitual en que un desofuscador automático vuelca de una vez, con un solo comando, todas las cadenas cifradas: vincular un delegado directamente al descifrador e invocarlo por lotes desde su propio ensamblado auxiliar. Esto no hace imposible recuperar las cadenas con un análisis dinámico completo, pero elimina la vía barata de extracción masiva y obliga al atacante a ejecutar el código real de su aplicación.
El descifrador está escrito íntegramente en código administrado, sin dependencia alguna del proveedor criptográfico de la plataforma. Por eso STREAM se ejecuta sin cambios desde .NET Framework 4.x (y 2.0) hasta .NET 10, en Mono/Xamarin y, como no usa Reflection.Emit, en aplicaciones NativeAOT y recortadas. Tampoco le afecta el problema de arranque relacionado con FIPS que pueden sufrir los algoritmos basados en la plataforma.
STREAM es autónomo: igual que XOR y HASH, descifra sin ninguna entrada externa. Al ser un esquema exclusivamente local, no puede hacer imposible la recuperación de las cadenas con un análisis dinámico completo (ningún esquema autónomo puede), pero eleva el coste de la extracción automática y de la ingeniería inversa manual muy por encima del de XOR y HASH.
Compatibilidad con plataformas y frameworks
Como el descifrador es totalmente administrado y no usa Reflection.Emit, código dinámico, recorrido de la pila ni el proveedor criptográfico de la plataforma, STREAM se ha verificado en toda la gama de .NET y en dispositivos móviles:
- De .NET Framework 2.0 / 4.x a .NET 10, .NET Core y Mono / Xamarin.
- Aplicaciones recortadas (ILLink) y NativeAOT: el descifrador inyectado y su tabla de cadenas incrustada sobreviven al enlazado, y el código se compila de forma anticipada, sin JIT.
- Android e iOS: verificado de extremo a extremo con aplicaciones reales ofuscadas en el emulador de Android y en el simulador de iOS, incluidas las compilaciones Release totalmente recortadas. Las cadenas se descifran en tiempo de ejecución y no queda texto sin cifrar en el ensamblado empaquetado. .NET MAUI se basa en estos mismos entornos de ejecución (
net*-android/net*-ios), así que la compatibilidad es la misma. El AOT completo en dispositivos iOS queda cubierto por la compatibilidad con NativeAOT indicada más arriba.
En dispositivos móviles, aplique STREAM en una pasada que solo cifre las cadenas, de modo que los nombres de tipos y miembros queden intactos para la capa de interoperabilidad con Java / Objective-C:
babel MyApp.dll --stringencryption stream --notypes --nomethods --nofields --noproperties --noevents --noparameters --novirtualmembersCuando Babel se ejecuta como un paso de MSBuild dentro de una compilación de .NET para Android / iOS / MAUI, insértelo después de que se compile el ensamblado de la aplicación y antes del empaquetado, para que la aplicación empaquetada lleve el ensamblado ofuscado.
Línea de comandos
Para aplicar el cifrado STREAM desde la línea de comandos:
babel myapp.exe --string streamTarea Babel de MSBuild
Para activar el cifrado STREAM con la tarea de MSBuild de Babel, establezca la propiedad StringEncryption como sigue:
<PropertyGroup>
<StringEncryption>stream</StringEncryption>
</PropertyGroup>
<Babel StringEncryption="$(StringEncryption)" />STREAM funciona junto con las demás protecciones. Puede combinarse con el cifrado de código (MSIL) y con la protección contra manipulación en el mismo ensamblado.
Protección contra manipulación y reescritura posterior a la compilación. La protección contra manipulación graba un hash de integridad de la imagen ofuscada. Cualquier paso que reescriba el ensamblado después de Babel (sobre todo una publicación recortada o NativeAOT, que vuelve a emitir el ensamblado administrado) cambia esos bytes y hace que la comprobación falle de inmediato en el arranque. Esto es inherente a la protección contra manipulación e independiente del algoritmo de cadenas (afecta por igual a XOR, HASH y STREAM): active la protección contra manipulación en las compilaciones que no se recorten ni se reescriban después con AOT, y recurra al cifrado de cadenas (más el cifrado de código) para las salidas recortadas o AOT.
Comparación de los algoritmos
Los tres algoritmos integrados son autónomos (descifran sin ninguna entrada externa), de modo que elegir entre ellos supone buscar un equilibrio entre el tiempo de carga, el tamaño de la salida y lo difícil que resulta recuperar las cadenas.
| XOR | HASH | STREAM | |
|---|---|---|---|
| Cifrado | XOR en línea con una clave entera por cadena | Tabla comprimida y cifrada con el algoritmo de cifrado de la plataforma | Cifrado autenticado por cadena, estándar del sector |
| Cadenas conservadas como literales | Sí (alteradas en su lugar) | No | No |
| Modelo de descifrado | Por cadena, en cada acceso | Anticipado: toda la tabla se descifra en el primer uso | Diferido: cada cadena en su primer uso, y después en caché |
| Texto sin cifrar en memoria | Una cadena cada vez | Toda la tabla, durante toda la ejecución | Solo las cadenas que realmente se usan |
| Etiqueta de integridad por cadena | — | — | Sí |
| Las cadenas idénticas se cifran de forma distinta | No | No | Sí |
| Rechaza el descifrado fuera de contexto (invocación mediante delegado) | — | — | Sí |
| Clave de descifrado | En línea, junto a la llamada | Almacenada en la cabecera del blob | Nunca en línea: se reconstruye en tiempo de ejecución y se entrelaza con el flujo de control |
| Descifrador totalmente administrado (sin proveedor criptográfico de la plataforma; seguro con FIPS) | No | No | Sí |
| Tamaño relativo de la salida | El mayor (los literales permanecen en el ensamblado) | El menor (un único blob comprimido) | Entre XOR y HASH |
| Coste relativo en tiempo de ejecución | El más bajo | Bajo, pero se paga por adelantado para todas las cadenas | Mayor por cadena, y solo se paga por las cadenas que se usan |
Cuál elegir.
- XOR: el más rápido y ligero, pero también el más débil. Las cadenas cifradas permanecen como literales en el ensamblado y junto a cada llamada hay una clave por cadena, de modo que una herramienta automática puede recuperarlas en una sola pasada. Elíjalo cuando el tiempo de carga importe más que la protección.
- HASH: elimina los literales y empaqueta todo el conjunto en un único blob comprimido y cifrado (la salida más pequeña), con protección de la tabla contra manipulación. El coste es que toda la tabla se descifra de forma anticipada en el primer uso, de modo que todas las cadenas permanecen en memoria en texto sin cifrar durante el resto de la ejecución, y que su descifrador depende del proveedor criptográfico de la plataforma (consulte la nota sobre FIPS).
- STREAM: el más resistente de los tres frente al análisis estático y al dinámico, con cifrado autenticado por cadena, sin descifrado global anticipado, sin clave en línea y con un único descifrador totalmente administrado que se publica sin cambios con NativeAOT y con recorte y al que FIPS no afecta. El coste de descifrado por cadena es mayor, pero solo se paga por las cadenas que la aplicación usa realmente, y en ningún momento está en memoria el conjunto completo de cadenas en texto sin cifrar. Prefiera STREAM para .NET moderno, para despliegues AOT, recortados o FIPS, y allí donde más importe la resistencia a la extracción masiva de cadenas.