writeup

altstore no podía iniciar sesión. apple devolvía una página html.

kisnner obando · septiembre de 2026 · altserver 1.6.2–1.7.5 · macos 27 / windows · el hilo

un informe de la rotura del inicio de sesión de altstore en septiembre de 2026: cómo un error de "los datos no están en el formato correcto" resultó ser una página html 503 entregada a un lector de plist, cómo mis propios reintentos me dieron una respuesta equivocada y cómo el arreglo terminó siendo el cambio de una cadena de 39 caracteres dentro de binarios firmados en macos y windows.

fue un esfuerzo comunitario en altstoreio/AltStore#1699. los arreglos oficiales que salieron los escribieron otras personas, acreditadas abajo. lo mío fue el diagnóstico, los parches binarios para quien no podía esperar un release y un segundo fallo, distinto (-80009), que introdujo el primer apaño.

resumen

el síntoma

NSCocoaErrorDomain 3840
Debug Description: Encountered unknown tag html on line 1
AltServer could not sign in with your Apple ID. The data is not in the correct format.

suena a problema de credenciales. la gente creaba apple ids nuevos, cambiaba de vpn, de región. nada ayudaba, porque el mensaje no hablaba de su cuenta.

1. mirar el tráfico real

inyecté una dylib en el altserver original para registrar sus llamadas NSURLSession y capturé el intercambio de grandslam contra POST https://gsa.apple.com/grandslam/GsService2:

Request.o=init       ->  200  text/x-xml-plist
Request.o=complete   ->  200  text/x-xml-plist     <-- srp auth succeeds
Request.o=apptokens  ->  503  text/html            <-- "503 Service Temporarily Unavailable"

apple aceptó la contraseña y los datos de anisette. solo se rechazó la tercera llamada, y volvió como página de error html. altsign no maneja un cuerpo que no sea plist, así que el html va directo a PropertyListSerialization, que falla con <html> en la línea 1. ese es todo el mensaje de error.

eso también explicó por qué nada de lo que probaba la gente importaba. reproduje el mismo resultado en mi isp de casa, en el hotspot de un iphone y en una salida de vpn en eeuu, con seis servidores de anisette distintos y dos identidades de cliente. otros reportes del hilo sumaron un apple id recién creado y windows con anisette de icloud para windows. mismo 503 siempre.

2. mi primera conclusión era falsa

añadí reintentos automáticos: seis intentos en unos siete segundos, todos 503. publiqué que el rechazo era determinista.

no lo era. cada reintento reutilizaba la misma NSURLSession, así que cada intento volvía por la misma conexión del pool, fijada al mismo backend de apple que fallaba. seis reintentos en una conexión son una muestra, no seis. @Calvin-Zikakis había descrito exactamente ese bug en AltSign#49. publiqué una corrección en el hilo, porque "apple lo ha cerrado" era lo que no debía llevarse la gente.

3. la causa: un user-agent de 2019

@FrakesH identificó el desencadenante: altsign envía

akd/1.0 CFNetwork/978.0.7 Darwin/18.7.0

un user-agent de macos mojave escrito a mano. los servidores de apple empezaron a rechazarlo en apptokens.

para comprobarlo antes de tocar ningún binario, apliqué los dos arreglos en tiempo de ejecución al altserver 1.7.2 original (build 90) con la dylib inyectada. reescribía User-Agent en las peticiones a *.apple.com y ejecutaba cada petición en una URLSession efímera nueva. el inicio de sesión y la instalación funcionaron de punta a punta. en macos 27 además necesité el arreglo de anisette de @kimziro para la etapa de AOSKit -45070 / machineID vacío.

4. parchear los binarios

una dylib no es algo que la mayoría pueda usar. la cadena de reemplazo tiene la misma longitud que la vieja, 39 caracteres, así que un cambio directo de bytes funciona sin mover nada:

akd/1.0 CFNetwork/978.0.7 Darwin/18.7.0
AuthKit/1 (com.apple.dt.Xcode/3594.4.1)

macos

la cadena no está en AltServer, sino en el framework de altsign, en ascii, dos veces: AltSign-Dynamic es un binario universal y cada arquitectura tiene su copia.

AltServer.app/Contents/Frameworks/AltSign-Dynamic.framework/Versions/A/AltSign-Dynamic
  0x62920   -> x86_64 slice
  0x10E210  -> arm64 slice

las dos están junto a X-MMe-Client-Info. la misma disposición vale en 1.6.2 y 1.7.2. descargué un 1.6.2 original del cdn de apple para verificarlo.

el problema es la firma de código. la app original tiene firma de developer id con hardened runtime (flags=0x10000(runtime)). editar el framework la invalida:

AltServer.app: invalid signature (code or signature have been modified)

así que el parche tiene que terminar con una re-firma ad-hoc:

APP="/Applications/AltServer.app"
F="$APP/Contents/Frameworks/AltSign-Dynamic.framework/Versions/A/AltSign-Dynamic"
cp -R "$APP" ~/Desktop/AltServer-backup.app
perl -pi -e 's/akd\/1\.0 CFNetwork\/978\.0\.7 Darwin\/18\.7\.0/AuthKit\/1 (com\.apple\.dt\.Xcode\/3594\.4\.1)/g' "$F"
codesign --force --deep --sign - "$APP"
codesign --verify --deep --strict "$APP" && echo OK

@angel-knights lo confirmó en 1.6.2 bajo macos 10.15, una combinación que no pude probar.

windows

había dicho que los usuarios de windows no tenían camino porque altserver para windows no es de código abierto. era falso: cambiar una cadena no necesita el código fuente. no tengo una máquina con windows, así que desarmé el instalador oficial (altinstaller.zip → AltInstaller.msi → cab incrustado) y leí AltServer.exe 1.7.4.0 directamente:

publiqué un script de powershell que hace copia de seguridad, se niega a correr salvo que encuentre exactamente una aparición y escribe los bytes nuevos en su sitio. @akgang-rgb y @BorbushArtem lo confirmaron en windows. la versión de @BorbushArtem era mejor que la mía: revisa las dos rutas de program files, comprueba que la longitud coincide antes de escribir y busca con una ida y vuelta por iso-8859-1 en lugar de mi bucle de bytes. mandé a la gente a la suya.

la app altstore del teléfono lleva su propia copia de altsign, así que parchear altserver arregla el inicio de sesión solo en el ordenador. @spaceace90 encontró el cambio equivalente dentro del ipa.

5. el release que no lo arregló

altserver 1.7.5 salió el 8 de sep. lo bajé del feed oficial de sparkle y lo comprobé:

AltServer.app/Contents/MacOS/AltServer
  0x111070  -> x86_64 slice   akd/1.0 CFNetwork/978.0.7 Darwin/18.7.0
  0x27E6D0  -> arm64 slice    akd/1.0 CFNetwork/978.0.7 Darwin/18.7.0

la misma cadena vieja. altsign ahora estaba enlazado de forma estática, así que el objetivo del parche había pasado del framework al ejecutable principal. y como sparkle reemplaza la app entera, actualizar deshacía en silencio el parche de cualquiera. AltSign#52, el arreglo de reutilización de conexión, se había fusionado siete horas después de cortar la 1.7.5, así que todavía no estaba en ningún release.

6. un segundo bug, causado por el apaño

algunas personas que usaron un altserver recompilado empezaron a recibir -80009 MID is invalid. es un fallo distinto: apple no acepta la identidad de la máquina.

sondeé directamente las tres llamadas de aoskit en macos 27:

retrieveOTPHeadersForDSID:  ->  {}            (broken)
machineSerialNumber         ->  <real serial> (still works)
machineUDID                 ->  <real udid>   (still works)

solo una estaba rota. el arreglo de anisette para macos 27 incluido en esa build engancha solo retrieveOTPHeadersForDSID: y provisiona una identidad sintética, que en mi máquina tenía serialNumber: "0" y un deviceID aleatorio. altserver enviaba entonces ese machineID sintético junto al serial y el udid reales del mac anfitrión. la petición describía dos máquinas distintas, y apple la rechazó.

@oddharsh ya había encontrado ese hueco en anisette-fix#4, que engancha también el serial y el udid para que todo el conjunto describa una sola identidad. la medición mostró por qué hacía falta: enganchar una llamada de tres deja la identidad mitad real y mitad sintética.

cómo terminó

errores míos en público

lo que me llevo

enlaces