Shield - Guía de Integración de Shield

Android (Kotlin/Java) & iOS (Swift/Objective-C)


Tabla de Contenidos


Introducción

Shield es una suite integral de protección para aplicaciones móviles que proporciona ofuscación de código, anti-debugging, anti-tampering y protecciones de seguridad para aplicaciones Android e iOS.

Esta guía está dirigida a desarrolladores y organizaciones que desean integrar la protección de Shield en sus aplicaciones móviles. Shield es un producto comercial disponible a través de ByteHide.


Integración Android (Kotlin/Java)

Instalación

Paso 1: Añadir el Repositorio Maven de ByteHide

Añade el repositorio de Shield a tu settings.gradle.kts:

Kotlin
pluginManagement {
    repositories {
        maven {
            url = uri("https://maven.bytehide.com/releases")
        }
        google()
        mavenCentral()
    }
}

dependencyResolutionManagement {
    repositories {
        maven {
            url = uri("https://maven.bytehide.com/releases")
        }
        google()
        mavenCentral()
    }
}

Paso 2: Aplicar el Plugin de Shield

Añade el plugin de Shield al build.gradle.kts de tu módulo app:

Kotlin
plugins {
    id("com.android.application")
    id("org.jetbrains.kotlin.android")
    id("com.bytehide.shield") version "1.0.0"
}

Uso

Shield para Android puede configurarse de dos formas:

Opción 1: Configuración Directa en Gradle (DSL)

Configura Shield directamente en tu archivo build.gradle.kts:

Kotlin
shield {
    enabled = true

    protections {
        stringEncryption = true
        constantMutation = true
        debugRemoval = true
        nameObfuscation = true
        controlFlowObfuscation = false
        antiDebug = true
        antiTamper = true
    }

    excludedPackages = listOf(
        "android",
        "androidx",
        "kotlin",
        "kotlinx",
        "com.google"
    )

    excludedClasses = listOf(
        "com.myapp.models.User",
        "com.myapp.api.ApiResponse"
    )

    verbose = true
}

Opción 2: Archivo de Configuración JSON

Crea un archivo shield-config.json en el directorio de tu módulo app:

JSON
{
  "enabled": true,
  "protections": {
    "stringEncryption": true,
    "constantMutation": true,
    "debugRemoval": true,
    "nameObfuscation": true,
    "controlFlowObfuscation": false,
    "antiDebug": true,
    "antiTamper": true
  },
  "excludedPackages": [
    "android",
    "androidx",
    "kotlin",
    "kotlinx",
    "com.google"
  ],
  "excludedClasses": [
    "com.myapp.models.User",
    "com.myapp.api.ApiResponse"
  ],
  "verbose": true
}

Shield detectará y usará automáticamente shield-config.json si está presente en el directorio de tu módulo app.


Configuración

Project Token (Requerido)

Para conectar tu aplicación al dashboard de ByteHide y habilitar la validación en la nube, necesitas configurar tu project token:

Opción 1: Configuración directa en build.gradle.kts

Kotlin
shield {
    enabled = true
    setProjectToken("bh_zU5jY5dfZCnfyqUtggndngBfJwUNF1PQQ")  // REQUIRED for cloud validation
}

Opción 2: Variable de Entorno (Recomendado para CI/CD)

Kotlin
shield {
    enabled = true
    setProjectToken(System.getenv("SHIELD_PROJECT_TOKEN"))
}

Luego configura la variable de entorno:

Bash
export SHIELD_PROJECT_TOKEN="bh_zU5jY5dfZCnfyqUtggndngBfJwUNF1PQQ"

Opción 3: Local Properties (Recomendado para desarrollo local)

Añade a tu archivo local.properties (este archivo está en gitignore por defecto):

Properties
shield.projectToken=bh_zU5jY5dfZCnfyqUtggndngBfJwUNF1PQQ

Luego referéncialo en tu build.gradle.kts:

Kotlin
shield {
    enabled = true

    val properties = Properties()
    properties.load(project.rootProject.file("local.properties").inputStream())
    setProjectToken(properties.getProperty("shield.projectToken"))
}

Protection Secret (Opcional)

El protection secret es una clave personalizada utilizada para encriptar los stack traces. Esto te permite posteriormente recuperar y desofuscar las excepciones de tu aplicación protegida usando la API de ByteHide.

¿Por qué usar un Protection Secret?

Cuando tu aplicación está ofuscada, los stack traces se vuelven ilegibles. Al configurar un protection secret:

  • Los stack traces se encriptan con tu clave personalizada
  • Puedes usar la API de ByteHide para buscar y recuperar excepciones
  • Desofuscar los stack traces de vuelta a su forma original usando tu archivo de mapeo

Configuración:

Kotlin
shield {
    enabled = true
    setProjectToken("bh_YOUR_PROJECT_TOKEN")
    setProtectionSecret("mi-secret-personalizado-123")  // OPTIONAL
}

Usando variables de entorno:

Kotlin
shield {
    enabled = true
    setProjectToken(System.getenv("SHIELD_PROJECT_TOKEN"))
    setProtectionSecret(System.getenv("SHIELD_PROTECTION_SECRET"))
}

Recuperando excepciones vía API de ByteHide:

Una vez configurado, puedes usar el dashboard o la API de ByteHide para:

  1. Buscar excepciones por tu protection secret
  2. Ver stack traces encriptados
  3. Desofuscarlos usando tu archivo de mapeo
  4. Analizar crashes de tu aplicación en producción

Exclusión de Clases y Paquetes

¿Por qué Excluir?

Deberías excluir ciertos paquetes y clases de la protección para evitar problemas con:

  • Serialización (JSON, XML, Parcelable)
  • Frameworks basados en reflexión
  • Clases del sistema Android/AndroidX
  • Librerías de terceros
  • Modelos de API que necesitan nombres consistentes

Excluir por Paquete

Excluye paquetes completos (incluyendo sub-paquetes):

Kotlin
shield {
    excludedPackages = listOf(
        "android",           // Android framework
        "androidx",          // AndroidX libraries
        "kotlin",            // Kotlin stdlib
        "kotlinx",           // Kotlin extensions
        "com.google",        // Google libraries
        "com.myapp.api",     // Your API models
        "com.myapp.models"   // Your data models
    )
}

Excluir por Clase

Excluye clases específicas:

Kotlin
shield {
    excludedClasses = listOf(
        "com.myapp.MainActivity",
        "com.myapp.models.User",
        "com.myapp.api.ApiResponse",
        "com.myapp.serialization.CustomSerializer"
    )
}

Patrones con Wildcards

Usa wildcards para exclusión flexible:

Kotlin
shield {
    excludedClasses = listOf(
        "com.myapp.models.*",      // Todas las clases del paquete
        "com.myapp.*Activity",     // Todas las activities
        "**/*Serializer"           // Todas las clases serializer
    )
}

Exclusión mediante Anotaciones

Shield respeta automáticamente las anotaciones en tu código. No necesitas configuración adicional - simplemente añade las anotaciones a tus clases:

Anotaciones estándar:

Kotlin
import androidx.annotation.Keep

@Keep
class UserModel {
    @Keep
    var name: String = ""

    @Keep
    fun importantMethod() {
        // Este método no será ofuscado
    }
}

Otras anotaciones soportadas automáticamente:

Kotlin
// Serialización
@JsonProperty("user_name")     // Jackson
@SerializedName("user_name")   // Gson

// JPA/Hibernate
@Entity
@Column(name = "username")

// Spring
@Component
@Service
@Repository
@Controller

Shield detecta estas anotaciones automáticamente y excluye las clases/métodos/campos anotados de la protección.

Integración con ProGuard

Si ya tienes reglas de ProGuard en tu proyecto (proguard-rules.pro), Shield las respeta. Puedes seguir usando tus reglas de ProGuard existentes:

proguard-rules.pro:

ProGuard
# Mantener modelos de datos
-keep class com.myapp.models.** { *; }

# Mantener clases de API
-keep class com.myapp.api.** { *; }

# Mantener nombres de métodos nativos
-keepclasseswithmembernames class * {
    native <methods>;
}

Shield integra estas reglas con su propio sistema de exclusión, por lo que no perderás tus exclusiones existentes al adoptar Shield.


Configuración por Variante de Build

Configura diferentes niveles de protección para builds Debug y Release:

Kotlin
android {
    buildTypes {
        debug {
            // Debug configuration
        }
        release {
            isMinifyEnabled = true
            proguardFiles(
                getDefaultProguardFile("proguard-android-optimize.txt"),
                "proguard-rules.pro"
            )
        }
    }
}

shield {
    enabled = true

    // Debug: minimal protection for faster builds
    debugProtections {
        stringEncryption = true
        constantMutation = false
        debugRemoval = false
        nameObfuscation = false
        controlFlowObfuscation = false
        antiDebug = false
    }

    // Release: maximum protection
    releaseProtections {
        stringEncryption = true
        constantMutation = true
        debugRemoval = true
        nameObfuscation = true
        controlFlowObfuscation = true
        antiDebug = true
        antiTamper = true
    }
}

Compilar tu Aplicación

Compila tu aplicación normalmente - Shield procesará automáticamente las clases durante la compilación:

Bash
# Build Debug (protección mínima)
./gradlew assembleDebug

# Build Release (protección completa)
./gradlew assembleRelease

# Ver tareas de Shield
./gradlew tasks --all | grep shield

Salida de la Compilación:

CODE
> Task :app:transformReleaseClassesWithShield
[Shield] ========================================
[Shield] Shield Protection - Variant: release
[Shield] ========================================
[Shield] Loading classes...
[Shield] Loaded 847 classes (245 app classes, 602 dependencies)
[Shield] Applying String Encryption...
[Shield]   - Encrypted 1,284 strings
[Shield] Applying Constant Mutation...
[Shield]   - Mutated 456 constants
[Shield] Applying Name Obfuscation...
[Shield]   - Renamed 123 classes, 567 methods, 234 fields
[Shield] Shield protection completed in 12.3s

Integración iOS (Swift/Objective-C)

Instalación

Instala Shield iOS vía pip:

Bash
pip install bytehide-shield-ios

# Verificar instalación
bytehide-shield --version

Opciones de Uso

Shield iOS ofrece dos métodos de integración:

  1. Método CLI - Protege archivos IPA directamente desde línea de comandos
  2. Integración con Xcode - Protección automática durante los builds de Xcode

Opción 1: Método CLI

Paso 1: Crear Archivo de Configuración

Genera una configuración por defecto:

Bash
bytehide-shield init

Esto crea shield.json:

JSON
{
  "projectToken": "bh_YOUR_PROJECT_TOKEN_HERE",
  "protections": {
    "anti_debug": true,
    "anti_jailbreak": true,
    "string_encryption": true,
    "symbol_renaming": true,
    "swift_stripping": true,
    "control_flow": "medium"
  },
  "code_signing": {
    "identity": "iPhone Distribution: Your Company",
    "provisioning_profile": "/path/to/profile.mobileprovision",
    "skip_if_not_macos": true
  },
  "output": {
    "suffix": "_protected"
  }
}

Paso 2: Protege tu IPA

Bash
# Protección básica (usa shield.json en el directorio actual)
bytehide-shield protect MyApp.ipa

# Archivo de configuración personalizado
bytehide-shield protect MyApp.ipa --config custom-config.json

# Ruta de salida personalizada
bytehide-shield protect MyApp.ipa --output MyApp_secured.ipa

# Salida detallada
bytehide-shield protect MyApp.ipa --verbose

Salida del CLI:

CODE
🛡️  Shield iOS v1.0.0

✓ Validación en la nube exitosa!
✓ IPA desempaquetado: MyApp
✓ Aplicando protección anti-debug...
✓ Aplicando detección anti-jailbreak...
✓ Encriptando 1,847 strings...
✓ Renombrando 234 símbolos...
✓ Ofuscando flujo de control...
✓ Firma de código con: iPhone Distribution
✓ IPA protegido: MyApp_protected.ipa

✓ Tu aplicación iOS ahora está protegida! 🛡️

Opción 2: Integración con Xcode

Protege tu aplicación automáticamente durante los builds de Xcode.

Paso 1: Instalar Shield iOS

Bash
pip install bytehide-shield-ios

Paso 2: Copiar Script de Build

Copia el script de integración de Xcode a tu proyecto:

Bash
cd YourXcodeProject
curl -o shield-xcode.sh https://xcode.shield..bytehide.com/install.sh
chmod +x shield-xcode.sh

Paso 3: Añadir Run Script Phase en Xcode

  1. Abre tu proyecto en Xcode
  2. Selecciona tu target
  3. Ve a la pestaña Build Phases
  4. Haz clic en + → New Run Script Phase
  5. Nómbralo "Shield iOS Protection"
  6. Arrástralo DESPUÉS de "Compile Sources" y ANTES de "Copy Bundle Resources"
  7. Añade este script:
Bash
bash "${PROJECT_DIR}/shield-xcode.sh"

Paso 4: Crear Archivo de Configuración

Crea shield.json en la raíz de tu proyecto:

JSON
{
  "projectToken": "bh_YOUR_PROJECT_TOKEN",
  "protections": {
    "anti_debug": true,
    "anti_jailbreak": true,
    "string_encryption": true,
    "symbol_renaming": true,
    "swift_stripping": true,
    "control_flow": "medium"
  },
  "build_integration": {
    "skip_debug": true,
    "skip_simulator": true
  }
}

Paso 5: Compilar tu Aplicación

Compila normalmente en Xcode:

Bash
# En Xcode: Product → Build (⌘B)
# O vía línea de comandos:
xcodebuild -project MyApp.xcodeproj -scheme MyApp -configuration Release

¡Shield protegerá automáticamente tu aplicación durante el build! 🎉


Configuración

Project Token

El Project Token es obligatorio y conecta tu aplicación con el dashboard de ByteHide para validación en la nube.

JSON
{
  "projectToken": "bh_zU5jY5dfZCnfyqUtggndngBfJwUNF1PQQ"
}

¿Dónde obtener tu token?

  1. Ve a https://cloud.bytehide.com
  2. Crea o selecciona un proyecto
  3. Copia el token (formato: bh_...)

Protection Secret (Opcional)

El Protection Secret es una clave opcional que Shield usa para encriptar los stack traces de tu aplicación.

JSON
{
  "projectToken": "bh_YOUR_PROJECT_TOKEN",
  "protectionSecret": "mi-secret-personalizado-123"
}

¿Por qué usar Protection Secret?

Cuando tu aplicación protegida crashea, los stack traces estarán ofuscados (nombres de clases/métodos renombrados). El Protection Secret te permite:

  1. Encriptar stack traces - Shield encripta los stack traces usando tu secret
  2. Desofuscar remotamente - ByteHide API puede desencriptar y mapear los símbolos originales
  3. Debugging post-producción - Analiza crashes sin exponer tu código fuente

Ejemplo de uso:

JSON
{
  "projectToken": "bh_YOUR_PROJECT_TOKEN",
  "protectionSecret": "MiSecretSeguro2024!",
  "protections": {
    "symbol_renaming": true,
    "string_encryption": true
  }
}

Sin el secret, los stack traces estarán ofuscados pero no podrás mapearlos de vuelta a los nombres originales.


Excluir Clases de la Protección

Puedes excluir clases específicas del renombrado de símbolos mediante configuración:

JSON
{
  "protections": {
    "symbol_renaming": {
      "enabled": true,
      "exclude": [
        "AppDelegate",
        "SceneDelegate",
        "*Delegate",              // Wildcard: todos los delegates
        "MyViewController",
        "NetworkManager"
      ]
    }
  }
}

Patrones soportados:

  • Nombres exactos: "AppDelegate", "MyViewController"
  • Wildcards: "*Delegate" (todos los nombres que terminen en Delegate)
  • Prefijos: "Test*" (todos los nombres que empiecen con Test)

Opciones de Integración con Build

Controla cuándo Shield se ejecuta durante los builds de Xcode:

JSON
{
  "build_integration": {
    "skip_debug": true,       // Omitir protección para builds Debug
    "skip_simulator": true,   // Omitir protección para builds Simulator
    "verbose": false          // Mostrar salida detallada
  }
}

Configuraciones diferentes para Debug/Release:

Crea bytehide-shield-debug.json:

JSON
{
  "protections": {
    "anti_debug": false,
    "string_encryption": true
  }
}

Crea bytehide-shield-release.json:

JSON
{
  "protections": {
    "anti_debug": true,
    "anti_jailbreak": true,
    "string_encryption": true,
    "control_flow": "medium"
  }
}

Actualiza tu Run Script Phase:

Bash
if [ "${CONFIGURATION}" = "Debug" ]; then
    CONFIG="bytehide-shield-debug.json"
else
    CONFIG="bytehide-shield-release.json"
fi

bytehide-shield protect "${APP}" --config "${PROJECT_DIR}/${CONFIG}"

Integración CI/CD

Android - GitHub Actions

YAML
name: Build Android App

on:
  push:
    branches: [main]

jobs:
  build:
    runs-on: ubuntu-latest

    steps:
      - uses: actions/checkout@v3

      - name: Set up JDK 11
        uses: actions/setup-java@v3
        with:
          java-version: '11'
          distribution: 'temurin'

      - name: Build con Shield
        env:
          SHIELD_PROJECT_TOKEN: ${{ secrets.SHIELD_PROJECT_TOKEN }}
        run: |
          ./gradlew assembleRelease

      - name: Subir APK
        uses: actions/upload-artifact@v3
        with:
          name: app-release
          path: app/build/outputs/apk/release/app-release.apk

iOS - GitHub Actions

YAML
name: Build iOS App

on:
  push:
    branches: [main]

jobs:
  build:
    runs-on: macos-latest

    steps:
      - uses: actions/checkout@v3

      - name: Instalar Shield iOS
        run: pip install bytehide-shield-ios

      - name: Compilar IPA
        run: |
          xcodebuild archive \
            -project MyApp.xcodeproj \
            -scheme MyApp \
            -configuration Release \
            -archivePath MyApp.xcarchive

          xcodebuild -exportArchive \
            -archivePath MyApp.xcarchive \
            -exportPath . \
            -exportOptionsPlist ExportOptions.plist

      - name: Proteger App
        env:
          SHIELD_TOKEN: ${{ secrets.SHIELD_PROJECT_TOKEN }}
        run: |
          cat > shield-config.json << EOF
          {
            "projectToken": "$SHIELD_TOKEN",
            "protections": {
              "anti_debug": true,
              "string_encryption": true,
              "control_flow": "medium"
            }
          }
          EOF
          bytehide-shield protect MyApp.ipa --config shield-config.json

      - name: Subir IPA
        uses: actions/upload-artifact@v3
        with:
          name: app-protected
          path: MyApp_protected.ipa

GitLab CI

Android:

YAML
build_android:
  stage: build
  image: gradle:7.6-jdk11
  script:
    - ./gradlew assembleRelease
  artifacts:
    paths:
      - app/build/outputs/apk/release/app-release.apk

iOS:

YAML
build_ios:
  stage: build
  image: macos-12-xcode-14
  script:
    - pip install bytehide-shield-ios
    - xcodebuild archive ...
    - bytehide-shield protect MyApp.ipa --config shield-config.json
  artifacts:
    paths:
      - MyApp_protected.ipa

Protecciones Disponibles

Shield ofrece un conjunto completo de protecciones de seguridad para tus aplicaciones móviles en Android e iOS:


1. Encriptación de Strings

Encripta todas las cadenas de texto en tu código para evitar que sean legibles en el binario. Las strings se desencriptan en tiempo de ejecución solo cuando se necesitan.

Configuración Android:

Kotlin
protections {
    stringEncryption = true
}

Configuración iOS:

JSON
{
  "protections": {
    "string_encryption": true
  }
}

Qué protege: Evita que atacantes extraigan URLs, API keys, mensajes, y otras strings sensibles del APK o IPA descompilado.


2. Ofuscación de Nombres

Renombra clases, métodos, campos y propiedades con nombres cortos y sin sentido (a, b, c, aa, ab...) manteniendo la funcionalidad completa de la aplicación.

Configuración Android:

Kotlin
protections {
    nameObfuscation = true
}

Configuración iOS:

JSON
{
  "protections": {
    "symbol_renaming": true
  }
}

Qué protege: Dificulta enormemente la lectura del código descompilado al eliminar nombres descriptivos que revelan la arquitectura y lógica de tu aplicación.


3. Ofuscación de Flujo de Control

Reestructura el flujo de ejecución del código insertando saltos, condiciones opacas y bloques de código falsos, haciendo extremadamente difícil seguir la lógica del programa.

Configuración Android:

Kotlin
protections {
    controlFlowObfuscation = true
}

Configuración iOS:

JSON
{
  "protections": {
    "control_flow": "medium"
  }
}

Qué protege: Hace extremadamente difícil seguir la lógica del programa, incluso con decompiladores avanzados. Esta es la protección más intensiva computacionalmente.


4. Mutación de Constantes

Transforma valores constantes en expresiones calculadas en tiempo de ejecución, haciendo más difícil entender la lógica del código.

Configuración Android:

Kotlin
protections {
    constantMutation = true
}

Configuración iOS:

JSON
{
  "protections": {
    "constant_mutation": true
  }
}

Qué protege: Oculta valores numéricos, booleanos y constantes que podrían revelar lógica de negocio, límites de sistema o parámetros de seguridad.


5. Anti-Debug

Detecta y bloquea intentos de debugging en tiempo de ejecución, evitando que atacantes analicen tu app con debuggers.

Configuración Android:

Kotlin
protections {
    antiDebug = true
}

Configuración iOS:

JSON
{
  "protections": {
    "anti_debug": true
  }
}

Qué protege: Previene análisis dinámico con herramientas como Android Studio Debugger, LLDB, Frida, JDWP, y otros frameworks de debugging y hooking.


6. Anti-Jailbreak/Root

Detecta dispositivos jailbroken (iOS) o rooteados (Android) y puede terminar la app o alertar al servidor.

Configuración Android:

Kotlin
protections {
    antiRoot = true
}

Configuración iOS:

JSON
{
  "protections": {
    "anti_jailbreak": true
  }
}

Qué protege: Evita que tu app se ejecute en entornos comprometidos donde existen herramientas avanzadas de hacking como Magisk, Xposed, Cydia o Sileo.


7. Eliminación de Información de Debug

Elimina toda la información de debugging, logs, símbolos de depuración y metadatos del binario compilado.

Configuración Android:

Kotlin
protections {
    debugRemoval = true
}

Configuración iOS:

JSON
{
  "protections": {
    "strip_debug": true
  }
}

Qué protege: Elimina trazas, logs, símbolos y metadatos que facilitan el análisis y reversing del código.


8. Swift Symbol Stripping

Elimina metadatos de reflexión y nombres de símbolos Swift del binario, específicamente diseñado para código Swift en iOS.

Configuración iOS:

JSON
{
  "protections": {
    "swift_stripping": true
  }
}

Qué protege: Reduce el tamaño del binario y elimina nombres de tipos Swift, metadatos de reflexión y nombres de protocolos que son valiosos para atacantes.


9. Reference Proxy

Crea clases y métodos proxy intermediarios que redirigen todas las llamadas a métodos y accesos a campos, añadiendo una capa de indirección que dificulta el análisis estático del código.

Configuración Android:

Kotlin
protections {
    referenceProxy = true
}

Configuración iOS:

JSON
{
  "protections": {
    "reference_proxy": true
  }
}

Qué protege: Hace extremadamente difícil rastrear el flujo de datos y las llamadas entre componentes. Los decompiladores muestran proxies en lugar de las referencias directas reales.


10. Inyección de Código Inválido

Inserta código bytecode sintácticamente válido pero semánticamente inválido que nunca se ejecuta. Este código confunde y rompe herramientas de análisis estático y decompiladores.

Configuración Android:

Kotlin
protections {
    invalidCodeInjection = true
}

Configuración iOS:

JSON
{
  "protections": {
    "invalid_code": true
  }
}

Qué protege: Muchos decompiladores y herramientas de análisis fallan al encontrar este código, mostrando errores o código ilegible. Esto previene el análisis automatizado del binario.


Shield es un producto comercial de ByteHide. Visita https://bytehide.com para más información.