ROM personalizadas, certificados y problemas de todo tipo en mi I9100

Custom roms, certificados, problemas de todo tipo en mi I9100

hola gente de Linux Chad, no sé si decir que ésta será mi publicación más importante, pero desde luego es lo más jodido que he hecho en mucho tiempo.

como algunos sabrán, me compré un Samsung Galaxy S2 (GT-I9100) para instalar Replicant. la distribución no me terminó de convencer, sobre todo por temas de conectividad —aunque al final creo que fui algo injusto con ella—. aquí les cuento qué me pasó, cómo lo solucioné y todo el papeleo técnico por si a alguien le sirve.


1) ¿qué pasó después de instalar Replicant?

Al instalar Replicant se borraron varias partes del firmware original sin darme cuenta. eso provocó que no pudiera instalar un recovery “privativo” correctamente. la solución fue recuperar el firmware original.

en mi caso conseguí el firmware aquí:
https://samfw.com/firmware/GT-I9100

comandos que usé con heimdall

Primero, para flashear partes del firmware (siempre con el móvil en modo descarga —volumen abajo + home + encendido—):

heimdall flash --SBL1 Sbl.bin --BOOT boot.bin --KERNEL zImage --PARAM param.lfs

y para recuperar también la caché del sistema:

heimdall flash --CACHE cache.img

con eso quitas Replicant y vuelves al firmware original (más privativo), pero te permite instalar una custom ROM después.


2) custom ROMs y recovery

Descargué varias custom ROMs (lineageos, cyanogenmod, etc.). dentro de los ZIP suele haber un boot.img. yo al final no llegué a instalar lineageos estable; lo que mejor me funcionó fue CyanogenMod 13 (lo encontré en un vídeo de YouTube y por eso hice un torrent para que no se pierda).

el recovery que sí me funcionó fue:
recovery-the.gangster-IsoRec-TWRP-3.0.2-1-i9100
(enlace: recovery-the.gangster-IsoRec-TWRP-3.0.2-1-i9100.zip | by the.gangster for Galaxy S2 )

flashear recovery + boot

Con el teléfono en modo descarga:

heimdall flash --RECOVERY recovery.img --BOOT boot.img

el boot.img que usé venía de una build de lineageos (la versión concreta no importa tanto si está hecha para el i9100).


3) instalación desde el recovery (TWRP) — pasos rápidos

Dentro del recovery configuré idioma español y procedí así:

  1. WipeAdvanced Wipe → seleccionar todo excepto las dos últimas opciones → deslizar y limpiar.

  2. Volver al menú principal → AdvancedInstall → marcar las dos opciones necesarias para adb sideload → deslizar para instalar con adb.

sideload desde el ordenador:

adb -d sideload cm-13.0-20161218-NIGHTLY-i9100.zip

funciona aunque no tenga las animaciones típicas de lineageos y la barra se quede quieta; esperar y dejar que termine.


4) problema gordo: no puedes descargar NADA (certificados SSL)

cuando arrancas la ROM custom te puedes mover por el sistema, pero no puedes descargar nada: el navegador por defecto no permite descargas o fallan las conexiones HTTPS. el problema son los certificados SSL.

estuve 2 días peleando con Claude y ChatGPT, y al final elaboré varios scripts que me funcionaron para generar e instalar un CA sobre el sistema (mitmproxy para generar la CA y luego instalarla en /system/etc/security/cacerts/).

pasos generales que hice

  1. generar certificado CA con mitmproxy (o generarlo manual con openssl si hace falta).

  2. convertir/copiar el PEM a un fichero con nombre HASH.0 (hash = openssl x509 -inform PEM -subject_hash_old -in cert.pem | head -1).

  3. subirlo al dispositivo y colocarlo en /system/etc/security/cacerts/ con permisos correctos y contexto SELinux si es posible.

  4. reiniciar el dispositivo para que Android lo reconozca como certificado de confianza.


5) scripts (los que me funcionaron)

abajo dejo dos scripts que usé: uno para generar el certificado con mitmproxy y preparar la instalación, y otro para forzar la instalación usando su -c y/o Magisk si /system no se puede montar como RW.

nota: los scripts contienen bastante verborrea y comprobaciones —si ves redundancias es porque me funcionó así y no me importa—. úsalos con cuidado y lee lo que hacen antes de ejecutarlos.

Script 1 — Generar CA e instalar (resumen)

#!/bin/bash

echo "🛠️  SETUP COMPLETO CON MITMPROXY"
echo "================================"
echo "mitmproxy es una alternativa gratuita y open source a Charles Proxy"
echo ""

# Función para instalar mitmproxy
install_mitmproxy() {
    echo "1. Instalando mitmproxy..."
    echo "========================="
    
    if command -v mitmproxy >/dev/null 2>&1; then
        echo "✅ mitmproxy ya está instalado"
        mitmproxy --version
        return 0
    fi
    
    echo "Instalando mitmproxy..."
    
    # Detectar sistema operativo
    if command -v apt >/dev/null 2>&1; then
        echo "Sistema: Ubuntu/Debian"
        sudo apt update && sudo apt install -y mitmproxy
    elif command -v dnf >/dev/null 2>&1; then
        echo "Sistema: Fedora"
        sudo dnf install -y mitmproxy
    elif command -v pacman >/dev/null 2>&1; then
        echo "Sistema: Arch Linux"
        sudo pacman -S mitmproxy
    elif command -v pip3 >/dev/null 2>&1; then
        echo "Sistema: Usando pip3"
        pip3 install --user mitmproxy
        echo "⚠️  Asegúrate de que ~/.local/bin esté en tu PATH"
    else
        echo "❌ No se pudo instalar automáticamente"
        echo "Instala manualmente desde: https://mitmproxy.org/"
        return 1
    fi
    
    # Verificar instalación
    if command -v mitmproxy >/dev/null 2>&1; then
        echo "✅ mitmproxy instalado correctamente"
        return 0
    else
        echo "❌ Error en la instalación"
        return 1
    fi
}

# Función para generar certificado con mitmproxy
generate_certificate() {
    echo ""
    echo "2. Generando certificado con mitmproxy..."
    echo "========================================"
    
    # Crear directorio de configuración
    MITM_DIR="$HOME/.mitmproxy"
    mkdir -p "$MITM_DIR"
    
    echo "Directorio de configuración: $MITM_DIR"
    
    # Ejecutar mitmproxy brevemente para generar certificados
    echo "Iniciando mitmproxy para generar certificados..."
    echo "Se cerrará automáticamente en 5 segundos..."
    
    # Usar timeout para cerrar automáticamente
    timeout 5s mitmproxy --set confdir="$MITM_DIR" --quiet >/dev/null 2>&1 || true
    
    # Verificar que se generó el certificado
    CERT_FILE="$MITM_DIR/mitmproxy-ca-cert.pem"
    
    if [ -f "$CERT_FILE" ]; then
        echo "✅ Certificado generado: $CERT_FILE"
        
        # Copiar al directorio actual con nombre estándar
        cp "$CERT_FILE" "./charles-ssl-proxying-certificate.pem"
        echo "✅ Copiado como: charles-ssl-proxying-certificate.pem"
        
        # Mostrar información del certificado
        echo ""
        echo "Información del certificado:"
        subject=$(openssl x509 -inform PEM -subject -noout -in "$CERT_FILE" | cut -d'=' -f2-)
        hash=$(openssl x509 -inform PEM -subject_hash_old -in "$CERT_FILE" | head -1)
        echo "Subject: $subject"
        echo "Hash: $hash"
        
        return 0
    else
        echo "❌ No se pudo generar el certificado"
        echo "Intentando método manual..."
        
        # Método alternativo: generar solo los certificados
        echo "Generando certificados manualmente..."
        cd "$MITM_DIR"
        
        # Generar CA key y cert
        openssl genrsa -out mitmproxy-ca.pem 2048 2>/dev/null
        openssl req -new -x509 -key mitmproxy-ca.pem -out mitmproxy-ca-cert.pem -days 3650 -subj "/CN=mitmproxy" 2>/dev/null
        
        cd - > /dev/null
        
        if [ -f "$CERT_FILE" ]; then
            echo "✅ Certificado generado manualmente: $CERT_FILE"
            cp "$CERT_FILE" "./charles-ssl-proxying-certificate.pem"
            return 0
        else
            return 1
        fi
    fi
}

# Función para instalar certificado en Android
install_to_android() {
    echo ""
    echo "3. Instalando certificado en Android..."
    echo "======================================"
    
    CERT_FILE="charles-ssl-proxying-certificate.pem"
    
    if [ ! -f "$CERT_FILE" ]; then
        echo "❌ No se encuentra el archivo de certificado"
        return 1
    fi
    
    # Verificar ADB
    if ! command -v adb >/dev/null 2>&1; then
        echo "❌ ADB no está instalado"
        echo "Instala con: sudo apt install adb"
        return 1
    fi
    
    # Verificar dispositivo conectado
    if ! adb devices | grep -q "device$"; then
        echo "❌ No hay dispositivos Android conectados"
        echo "Conecta tu dispositivo y habilita USB Debugging"
        return 1
    fi
    
    echo "✅ Dispositivo Android detectado"
    
    # Verificar root
    if ! adb shell "su -c 'whoami'" 2>/dev/null | grep -q "root"; then
        echo "❌ El dispositivo necesita acceso root"
        return 1
    fi
    
    echo "✅ Acceso root verificado"
    
    # Procesar certificado
    hash=$(openssl x509 -inform PEM -subject_hash_old -in "$CERT_FILE" | head -1)
    OUT_FILE="${hash}.0"
    
    # Crear archivo con formato Android
    cp "$CERT_FILE" "$OUT_FILE"
    openssl x509 -inform PEM -text -in "$CERT_FILE" >> "$OUT_FILE"
    
    echo "Archivo preparado: $OUT_FILE"
    
    # Instalar
    echo "Montando /system..."
    adb shell "su -c 'mount -o remount,rw /system'" 2>/dev/null
    
    echo "Subiendo certificado..."
    adb shell "su -c 'mkdir -p /system/etc/security/cacerts/'"
    adb push "$OUT_FILE" /system/etc/security/cacerts/
    
    echo "Configurando permisos..."
    adb shell "su -c 'chmod 644 /system/etc/security/cacerts/$OUT_FILE'"
    adb shell "su -c 'chown root:root /system/etc/security/cacerts/$OUT_FILE'" 2>/dev/null
    
    # Verificar
    if adb shell "su -c 'test -f /system/etc/security/cacerts/$OUT_FILE'"; then
        echo "✅ Certificado instalado correctamente"
        
        # Remontar como solo lectura
        adb shell "su -c 'mount -o ro,remount /system'" 2>/dev/null
        
        # Limpiar
        rm -f "$OUT_FILE"
        
        return 0
    else
        echo "❌ Error en la instalación"
        rm -f "$OUT_FILE"
        return 1
    fi
}

# Función para mostrar instrucciones de uso
show_usage_instructions() {
    echo ""
    echo "4. Instrucciones de uso..."
    echo "========================="
    echo ""
    echo "🎯 CONFIGURAR PROXY EN ANDROID:"
    echo "1. Ve a: Configuración → WiFi"
    echo "2. Mantén presionada tu red WiFi → Modificar"
    echo "3. Opciones avanzadas → Proxy manual"
    echo "4. Servidor: $(ip route get 1.1.1.1 | grep -oP 'src \K\S+' | head -1 || echo 'TU_IP_LOCAL')"
    echo "5. Puerto: 8080"
    echo ""
    echo "🚀 EJECUTAR MITMPROXY:"
    echo "mitmproxy --listen-port 8080"
    echo ""
    echo "O en modo web (interfaz navegador):"
    echo "mitmweb --listen-port 8080"
    echo "# Luego ve a http://127.0.0.1:8081"
    echo ""
    echo "📱 VERIFICAR CERTIFICADO:"
    echo "1. Reinicia tu dispositivo Android"
    echo "2. Ve a: Configuración → Seguridad → Certificados de confianza"
    echo "3. Pestaña 'Sistema' → Busca 'mitmproxy'"
    echo ""
    echo "🔍 INTERCEPTAR TRÁFICO:"
    echo "1. Configura el proxy en Android"
    echo "2. Ejecuta mitmproxy"
    echo "3. Usa aplicaciones en Android"
    echo "4. Ve el tráfico en tiempo real"
}

# EJECUCIÓN PRINCIPAL
echo "Este script configurará mitmproxy como alternativa a Charles Proxy"
echo ""
read -p "¿Continuar con la instalación? (s/N): " -n 1 -r
echo

if [[ ! $REPLY =~ ^[SsYy]$ ]]; then
    echo "Cancelado"
    exit 0
fi

# Instalar mitmproxy
if ! install_mitmproxy; then
    exit 1
fi

# Generar certificado
if ! generate_certificate; then
    echo "❌ Error generando certificado"
    exit 1
fi

# Verificar si hay dispositivo Android para instalar
echo ""
read -p "¿Instalar certificado en dispositivo Android ahora? (s/N): " -n 1 -r
echo

if [[ $REPLY =~ ^[SsYy]$ ]]; then
    if install_to_android; then
        echo ""
        echo "🎉 ¡INSTALACIÓN COMPLETADA!"
        echo "=========================="
        show_usage_instructions
    else
        echo "❌ Error instalando en Android"
        echo "Pero el certificado está disponible en: charles-ssl-proxying-certificate.pem"
    fi
else
    echo "Certificado disponible en: charles-ssl-proxying-certificate.pem"
    echo "Puedes instalarlo manualmente después"
fi

show_usage_instructions

echo ""
echo "📚 RECURSOS ADICIONALES:"
echo "========================"
echo "• Documentación mitmproxy: https://docs.mitmproxy.org/"
echo "• Tutorial Android: https://docs.mitmproxy.org/stable/howto-install-system-trusted-ca-android/"
echo "• Certificado para instalación manual: ./charles-ssl-proxying-certificate.pem"

(el script completo que tengo crea el CA con mitmproxy, genera charles-ssl-proxying-certificate.pem, calcula el hash antiguo con openssl y crea el HASH.0, sube y pone permisos, y da instrucciones de uso del proxy.)

Script 2 — Instalación forzada (resumen)

#!/bin/bash

echo "🔥 INSTALACIÓN FORZADA CON SUPERUSUARIO TOTAL"
echo "============================================="
echo "Este método usa su -c para TODOS los comandos"
echo ""

CERT_FILE="charles-ssl-proxying-certificate.pem"
HASH="c8750f0d"
OUT_FILE="${HASH}.0"

# Verificar que tenemos los archivos
if [ ! -f "$CERT_FILE" ]; then
    echo "❌ No se encuentra $CERT_FILE"
    exit 1
fi

# Preparar archivo si no existe
if [ ! -f "$OUT_FILE" ]; then
    echo "Preparando $OUT_FILE..."
    cp "$CERT_FILE" "$OUT_FILE"
    openssl x509 -inform PEM -text -in "$CERT_FILE" >> "$OUT_FILE"
    echo "✅ Archivo preparado localmente"
fi

echo "Archivo a instalar: $OUT_FILE ($(wc -c < "$OUT_FILE") bytes)"
echo ""

# Verificar dispositivo y root
if ! adb devices | grep -q "device$"; then
    echo "❌ No hay dispositivo conectado"
    exit 1
fi

if ! adb shell "su -c 'whoami'" 2>/dev/null | grep -q "root"; then
    echo "❌ Sin acceso root"
    exit 1
fi

echo "✅ Dispositivo y root verificados"
echo ""

# MÉTODO 1: Subir a /data/local/tmp y usar su -c para todo
echo "🚀 MÉTODO 1: Via /data/local/tmp con su -c total"
echo "==============================================="

echo "1. Subiendo a /data/local/tmp (área writable)..."
if adb push "$OUT_FILE" /data/local/tmp/; then
    echo "✅ Subido a /data/local/tmp/"
    
    echo "2. Ejecutando todos los comandos con su -c..."
    
    # Deshabilitar temporalmente SELinux si es posible
    adb shell "su -c 'setenforce 0'" 2>/dev/null || echo "⚠️  No se pudo cambiar SELinux (normal)"
    
    # Montar /system como RW usando su -c
    echo "3. Montando /system RW..."
    adb shell "su -c 'mount -o remount,rw /system'"
    
    # Verificar montaje
    if adb shell "su -c 'touch /system/.test 2>/dev/null && rm /system/.test 2>/dev/null'"; then
        echo "✅ /system montado como RW"
    else
        echo "⚠️  /system aún protegido, probando métodos alternativos..."
        # Métodos alternativos de montaje
        adb shell "su -c 'mount -o remount,rw \$(mount | grep system | cut -d\\  -f1) /system'" 2>/dev/null
        adb shell "su -c 'mount -o remount,rw /dev/root /system'" 2>/dev/null
        
        if ! adb shell "su -c 'touch /system/.test 2>/dev/null && rm /system/.test 2>/dev/null'"; then
            echo "❌ No se puede hacer /system writable"
            echo "Tu dispositivo tiene protección adicional (dm-verity, etc.)"
            echo ""
            echo "SOLUCIONES ALTERNATIVAS:"
            echo "1. Usar Magisk systemless (recomendado)"
            echo "2. Flashear kernel permisivo"
            echo "3. Usar TWRP para instalar manualmente"
            
            # Intentar instalación systemless
            echo ""
            echo "🎩 Probando instalación Magisk systemless..."
            if adb shell "su -c 'test -d /data/adb/modules'"; then
                echo "Creando módulo Magisk..."
                MODULE_PATH="/data/adb/modules/custom_ca_certs"
                
                # Crear estructura del módulo
                adb shell "su -c 'rm -rf $MODULE_PATH'"
                adb shell "su -c 'mkdir -p $MODULE_PATH/system/etc/security/cacerts/'"
                
                # Copiar certificado
                adb shell "su -c 'cp /data/local/tmp/$OUT_FILE $MODULE_PATH/system/etc/security/cacerts/$OUT_FILE'"
                
                # Crear module.prop
                adb shell "su -c 'cat > $MODULE_PATH/module.prop << EOF
id=custom_ca_certs
name=Custom CA Certificates
version=v1.0
versionCode=1
author=AndroidCertInstaller
description=Install custom CA certificates as system trusted
EOF'"
                
                # Establecer permisos
                adb shell "su -c 'chmod 644 $MODULE_PATH/system/etc/security/cacerts/$OUT_FILE'"
                adb shell "su -c 'chmod 755 $MODULE_PATH'"
                
                # Limpiar tmp
                adb shell "su -c 'rm /data/local/tmp/$OUT_FILE'"
                
                echo "✅ Módulo Magisk creado exitosamente"
                echo "⚠️  REINICIA EL DISPOSITIVO para activar el módulo"
                
                rm -f "$OUT_FILE"
                exit 0
            else
                echo "❌ Magisk no disponible"
                adb shell "su -c 'rm /data/local/tmp/$OUT_FILE'"
                rm -f "$OUT_FILE"
                exit 1
            fi
        fi
    fi
    
    # 4. Crear directorio si no existe
    echo "4. Creando directorio de certificados..."
    adb shell "su -c 'mkdir -p /system/etc/security/cacerts/'"
    
    # 5. Copiar archivo usando su -c
    echo "5. Copiando certificado al sistema..."
    if adb shell "su -c 'cp /data/local/tmp/$OUT_FILE /system/etc/security/cacerts/$OUT_FILE'"; then
        echo "✅ Certificado copiado exitosamente"
        
        # 6. Establecer permisos correctos
        echo "6. Estableciendo permisos..."
        adb shell "su -c 'chmod 644 /system/etc/security/cacerts/$OUT_FILE'"
        adb shell "su -c 'chown root:root /system/etc/security/cacerts/$OUT_FILE'" 2>/dev/null
        
        # 7. Establecer contexto SELinux correcto
        echo "7. Configurando contexto SELinux..."
        adb shell "su -c 'chcon u:object_r:system_file:s0 /system/etc/security/cacerts/$OUT_FILE'" 2>/dev/null || echo "⚠️  SELinux context no cambiado (puede ser normal)"
        
        # 8. Verificar instalación
        echo "8. Verificando instalación..."
        if adb shell "su -c 'test -f /system/etc/security/cacerts/$OUT_FILE'"; then
            echo "✅ Certificado verificado en destino"
            
            # Mostrar información
            echo ""
            echo "Información del certificado instalado:"
            adb shell "su -c 'ls -la /system/etc/security/cacerts/$OUT_FILE'"
            
            # Verificar contenido
            if adb shell "su -c 'head -1 /system/etc/security/cacerts/$OUT_FILE'" | grep -q "BEGIN CERTIFICATE"; then
                echo "✅ Formato correcto verificado"
            else
                echo "⚠️  Formato posiblemente incorrecto"
            fi
            
        else
            echo "❌ Verificación falló"
            adb shell "su -c 'rm /data/local/tmp/$OUT_FILE'"
            rm -f "$OUT_FILE"
            exit 1
        fi
        
        # 9. Limpiar archivos temporales
        echo "9. Limpiando archivos temporales..."
        adb shell "su -c 'rm /data/local/tmp/$OUT_FILE'"
        
        # 10. Remontar /system como RO
        echo "10. Remontando /system como solo lectura..."
        adb shell "su -c 'mount -o ro,remount /system'" 2>/dev/null
        
        # Restaurar SELinux si se cambió
        adb shell "su -c 'setenforce 1'" 2>/dev/null || true
        
        # Limpiar archivo local
        rm -f "$OUT_FILE"
        
        echo ""
        echo "🎉 ¡INSTALACIÓN COMPLETADA EXITOSAMENTE!"
        echo "========================================"
        echo ""
        echo "Certificado instalado en: /system/etc/security/cacerts/$OUT_FILE"
        echo ""
        echo "SIGUIENTE PASO OBLIGATORIO:"
        echo "Reinicia tu dispositivo Android para que el certificado sea reconocido:"
        echo ""
        echo "    adb reboot"
        echo ""
        echo "Después del reinicio:"
        echo "1. Ve a: Configuración → Seguridad → Certificados de confianza → Sistema"
        echo "2. Busca: 'mitmproxy'"
        echo "3. Configura proxy WiFi a tu IP local puerto 8080"
        echo "4. Ejecuta: mitmproxy --listen-port 8080"
        echo ""
        
        # Preguntar si reiniciar ahora
        read -p "¿Reiniciar dispositivo ahora? (s/N): " -n 1 -r
        echo
        if [[ $REPLY =~ ^[SsYy]$ ]]; then
            echo "Reiniciando..."
            adb reboot
        fi
        
    else
        echo "❌ Error copiando archivo"
        adb shell "su -c 'rm /data/local/tmp/$OUT_FILE'"
        rm -f "$OUT_FILE"
        exit 1
    fi
    
else
    echo "❌ No se pudo subir a /data/local/tmp/"
    echo "Verifica que el dispositivo esté conectado correctamente"
    rm -f "$OUT_FILE"
    exit 1
fi

si quieres, pego aquí el script completo tal cual (son unos cuantos cientos de líneas), o te lo dejo listo para que lo copies y lo pegues en un .sh.


6) después de instalar la CA: notas prácticas

  • puede que el navegador por defecto siga sin funcionar y que Google o algunas webs den errores. muchas veces vuelven a la normalidad con el tiempo, pero no te fíes: no podrás descargar APKs desde el navegador.

  • solución práctica: descargar en otro dispositivo la APK de Firefox / Fennec / Aurora Store y pasarla al S2 para instalarla. luego desde Firefox puedes usar f-droid.org para instalar más apps.

  • sobre tiendas y repositorios: f-droid suele ser la mejor opción libre, pero algunos repos no funcionan bien en Android tan antiguo. Aurora Store y droid-ify son alternativas; droid-ify funciona más o menos si activas varios repos y te toca uno que funcione. aurora store da acceso a apps que muchas veces son privativas y pueden dejar de funcionar o perder compatibilidad.


7) torrent y enlaces


8) conclusiones y siguiente paso

ya con esto puedes tener una vida “normal” con el dispositivo, aunque el S2 es viejo y algunas cosas van a fallar. en un rato publicaré (o puedo publicar ahora si quieren) qué aplicaciones he probado y qué funciona y qué no, más detalles de UX y bugs concretos.

Dato final:
es posible que el navegador, ya sea firefox o fennec, no funcione la descarga en un principio, esto es normal, o lo creo que es normal, no se ni ■■■■ idea… tienen varias opciones, intentar descargar otra vez, cerrar la aplicación y volverla a abrir, o reiniciar el dispositivo, luego de ahi deberia funcionar. deberia…

1 me gusta

@isf

XD

3 Me gusta

Yo hubiera vendido ese teléfono cuando tenia Replicant. Pero bueno, jajaja.

1 me gusta

nah, te digo, yo quería algo para mi, personal. no quería dinero en este momento. y mientras me sirva, yo estoy feliz.