🔬 Auditoría APK University Days S1 (KoGa3 Ep17)

Veredicto: APK oficial, sin indicadores de malware y sin tráfico de red atribuible al juego

Se auditó el port University Days S1 — Ep17 de KoGa3 en dos fases: análisis estático completo del APK y prueba dinámica controlada en un perfil de trabajo de Android, sin tocar el perfil personal.

  • 📦 Paquete: com.koga3.universitydaysseason1 · versión 17.3 (versionCode 1752348644)
  • 🔐 SHA-256: cc15e58224dc02795f914eca2c89ae00b18c8b794568e60b3a52a755079d2d51
  • 📱 Prueba: Moto G9 Play · Android 10 · Shelter 1.9.1 · usuario Android 10
  • 🧪 Herramientas: JADX 1.5.6 · unrpyc 2.0.3 · apksigner · androguard 4.1.4 · PCAPdroid 2.0.2 · NetGuard 2.337
  • 🧭 MOC: 🐧 Linux Mint, Android & Herramientas de Sistema · ⚡ MOC Raíz

📊 Ficha técnica

ParámetroValor
Archivocom.koga3.universitydaysseason1-Ep17.apk
Tamaño622.212.696 bytes (593,4 MiB)
SHA-256cc15e58224dc02795f914eca2c89ae00b18c8b794568e60b3a52a755079d2d51
SHA-1127939d79d37f5c9ad63988356f72e26ae21c83e
MD560dc0a0381e8d5504c8bdb43b5621891
Package / Versióncom.koga3.universitydaysseason1 · 17.3
SDKmin 21 · target 29 · compile 35
MotorRen’Py 8.3.7 · Python 3.9.10 embebido
Firmav1 + v2 válidas · 1 firmante · CN=KoGa3 (autofirmado)
OrigenMediaFire oficial de KoGa3 · quickkey go4bp3b8l7y9u0d
Actividad principalorg.renpy.android.PythonSDLActivity

El hash y el tamaño coinciden con el file_info del enlace oficial de MediaFire, subido por Karl Schnabl el 12/07/2025. La página del port es koga3.bplaced.net.


🧭 Contexto y metodología

flowchart LR
    A["APK oficial<br/>MediaFire KoGa3"] --> B["Hash + firma"]
    B --> C["JADX / DEX"]
    B --> D["unrpyc / Ren'Py"]
    B --> E["readelf / .so"]
    C --> F["Sin código propio<br/>sospechoso"]
    D --> G["Sin APIs peligrosas"]
    E --> H["Build oficial Ren'Py"]
    F --> I["Prueba dinámica<br/>perfil de trabajo"]
    G --> I
    H --> I
    I --> J["PCAPdroid<br/>observar red"]
    I --> K["NetGuard<br/>bloquear red"]
    I --> L["logcat<br/>errores y permisos"]
    J --> M["Veredicto"]
    K --> M
    L --> M

La prueba se hizo en un perfil de trabajo creado con Shelter (usuario Android 10), separado del perfil personal. El APK se instaló solo ahí con adb install --user 10. La sesión se documentó con adb logcat, PCAPdroid para observar tráfico y NetGuard para bloquear la red del juego. NetGuard y PCAPdroid no se usaron a la vez: Android solo permite un VPN activo.


🛡️ Fase 1 — Análisis estático

1. Integridad y procedencia

ComprobaciónResultado
SHA-256 vs. MediaFire oficial✅ Coincide
Tamaño vs. MediaFire oficial✅ Coincide
apksigner verify v1✅ Válida
apksigner verify v2✅ Válida
v3 / v3.1 / v4No presentes
Firmantes1 · CN=KoGa3
Certificado SHA-2562A:85:2F:70:30:50:A4:5A:1F:6C:D9:6C:E1:9D:03:94:6E:9F:1D:6C:BD:42:72:1F:AC:37:0B:01:18:45:3B:32
Clave públicaRSA 2048 · SHA-384 con RSA

La firma demuestra que el archivo es el que publicó KoGa3 y que no se modificó después. Al ser un certificado autofirmado, la confianza real viene de la coincidencia del hash con el enlace oficial, no de una CA.

2. Permisos declarados

PermisoUsoLectura
WAKE_LOCKMantener CPU/pantalla durante el juegoNormal en Ren’Py
READ_EXTERNAL_STORAGELeer saves y URMNecesario
WRITE_EXTERNAL_STORAGEGuardar partidas en DocumentsNecesario
MANAGE_EXTERNAL_STORAGEAcceso amplio al almacenamiento compartido⚠️ Más de lo que el juego necesita
INTERNETRedSin código propio que la use
POST_NOTIFICATIONSNotificacionesNormal
VIBRATEVibraciónNormal
FOREGROUND_SERVICE + FOREGROUND_SERVICE_DATA_SYNCServicio en primer planoPlay Core / extracción

No pide cámara, micrófono, contactos, SMS, ubicación, accesibilidad, administración de dispositivos ni instalación de paquetes. El manifiesto declara requestLegacyExternalStorage="true" y allowBackup="true".

El permiso que sí importa

MANAGE_EXTERNAL_STORAGE permite leer y escribir en todo el almacenamiento compartido, aunque el juego solo use Documents/RenPy_Saves. En Android 10 no se concede como permiso runtime y no amplía el acceso real más allá del almacenamiento legacy. En Android 11+ sí sería relevante.

3. Interior del APK

ComponenteDetalle
classes.dex5,14 MB · 4.140 class_defs · 34.380 métodos
lib/arm64-v8a/librenpython.so27,9 MB · ELF ARM64 · stripped
lib/armeabi-v7a/librenpython.so26,3 MB · ELF ARM · stripped
lib/x86_64/librenpython.so32,1 MB · ELF x86-64 · stripped
assets/private.mp34,3 MB · en realidad tar.gz con 1.139 entradas
assets/x-game/48 .rpyc · 6.154 .webp · 134 .webm · 106 .mp3
assets/x-renpy/86 scripts comunes de Ren’Py

No hay .rpa, .jar, .apk, .dex ni ejecutables PE/ELF escondidos en los assets. Tampoco rutas .., absolutas ni enlaces raros dentro del tar.

4. Java, librerías nativas y trackers

  • 4.140 clases, casi todas AndroidX, Kotlin, Coroutines, Google Play Core/GMS, SLF4J y SDL/Ren’Py.
  • El único código propio es com.koga3.universitydaysseason1.R (recursos). No hay lógica Java del mod.
  • Sin Runtime.exec, ProcessBuilder, clientes HTTP propios, DexClassLoader, PackageInstaller ni DownloadManager en código propio.
  • Los tres .so son builds de Ren’Py: solo JNI de org.libsdl/org.renpy, sin system, exec*, socket, connect, dlopen, ptrace ni setuid.
  • Las cadenas de compilación apuntan a /home/tom/ab/renpy-build-fix/..., la ruta oficial del SDK de Ren’Py 8.3.7.
  • Trackers: 0 SDKs de analytics, ads, attribution o crash reporting. Las 3 referencias a Firebase son clases de excepción usadas por Play Core, no Firebase Analytics.

5. Scripts Ren’Py y main.py

Se descompilaron 135/135 archivos con unrpyc: 109 .rpy + 26 .rpym (19 MB). Los scripts propios son historia, UI, galería, replay y ajustes del mod (x-script*.rpy, x-options.rpy, x-guiAndroid.rpy, x-Z_KoGa3ModAndroid.rpy, x-gallery.rpy, etc.).

No aparecen en el juego:

  • os.system, subprocess, Popen
  • urllib, requests, socket, http.client
  • shutil.copy/move/rmtree ni open() sobre rutas arbitrarias
  • eval/exec/__import__/marshal/pickle.loads
  • ctypes, jnius, pyjnius
  • renpy.open_url, webbrowser, base64.b64decode

config.developer = True está activo, pero config.console = False; no queda consola de Python accesible.

main.py es el estándar de Ren’Py con añadidos de KoGa3:

  1. Calcula GameName desde el basedir.
  2. Guarda en Documents/RenPy_Saves/<GameName> (fuera del sandbox, para que las partidas sobrevivan a desinstalar).
  3. Crea Documents/RenPy_Saves/MULTIPERSISTENT si no existe.
  4. Si existe Documents/0x52_URM.rpa, lo copia a Documents/RenPy_Saves/<GameName>/game/ y lo añade al searchpath.
  5. Añade Documents/RenPy_Saves/<GameName>/game al searchpath si existe.

Vector real de riesgo: mods en almacenamiento compartido

Cualquier .rpyc, .rpa o .rpy colocado en Documents/RenPy_Saves/com.koga3.universitydaysseason1/game se carga al iniciar y se ejecuta con los permisos del juego. Es el mismo mecanismo del URM. No es un fallo del APK, pero es la razón para no meter mods de fuentes desconocidas. El APK no incluye 0x52_URM.rpa; solo lo copia si el usuario lo pone ahí.

6. Señales externas

SeñalLectura
VirusTotal aportado por el usuario0/63 detecciones · último análisis 2025-07-21
obfuscatedHeurística genérica; el APK usa el compresor UAGC (assets x-), no ofuscación real
contains-elfNormal: las tres librenpython.so
checks-gps / telephonyClases AndroidX presentes pero sin uso propio ni permisos de ubicación/telefonía
reflectionNormal en AndroidX, Kotlin y GMS

No se subió el APK a VirusTotal; el análisis fue aportado por el usuario.


🧪 Fase 2 — Prueba dinámica

Montaje

ElementoDetalle
DispositivoMotorola Moto G9 Play · Android 10
AislamientoPerfil de trabajo con Shelter 1.9.1 · usuario Android 10
Juegocom.koga3.universitydaysseason1 17.3 · instalado solo en usuario 10
Observación de redPCAPdroid 2.0.2 (VPN local)
Bloqueo de redNetGuard 2.337 (Wi-Fi y datos bloqueados solo al juego)
Logsadb logcat -v threadtime
Permisos runtimeSolo READ_EXTERNAL_STORAGE + WRITE_EXTERNAL_STORAGE

PCAPdroid y NetGuard se usaron en pasadas separadas porque Android solo admite un VPN activo a la vez.

Pasada 1 — PCAPdroid (observar)

  • PCAPdroid activó su VPN local y capturó el tráfico del perfil de trabajo.
  • En la lista de conexiones solo aparecieron Google Play Store, Servicios de Google Play y DNS del sistema:
    • android.clients.google.com
    • play.googleapis.com
    • play-fe.googleapis.com
    • connectivitycheck.gstatic.com
    • deviceintegritytokens-pa.googleapis.com
  • University Days no apareció ni una vez.
  • dumpsys netstats no registró ninguna entrada ni byte para el UID del juego (1010500).

Pasada 2 — NetGuard (bloquear)

  • Se activó NetGuard y se bloquearon Wi-Fi y datos móviles solo para University Days.
  • Se cerró y reabrió el juego con el bloqueo puesto.
  • El juego arrancó y llegó al menú principal sin red y sin errores.
  • En el log del proceso no hay UnknownHostException, ConnectException, SocketTimeoutException ni timeouts.
  • Los únicos errores de red del log son de otras apps (Messenger/Facebook) bloqueadas por NetGuard, no del juego.
  • El juego usó TextToSpeech local de Android; es un servicio local, no una conexión a Internet.

Logcat y permisos

ComprobaciónResultado
Primera sesión08:49:18–08:54:13 · ~5 min de juego
Segunda sesión (NetGuard)10:30+ · arranque completo hasta el menú
FATAL EXCEPTIONNinguno del juego
TracebackNinguno
Permission DenialNinguno
Guardado al pasar a segundo plano✅ python: Saving.
Ruta de guardado/storage/emulated/10/Documents/RenPy_Saves/com.koga3.universitydaysseason1
Permisos runtime concedidosSolo lectura/escritura de almacenamiento
Cámara, ubicación, contactos, SMS, accesibilidadNo concedidos
MANAGE_EXTERNAL_STORAGESin operaciones runtime en Android 10

Evidencia

ArtefactoRuta
Informe completoinforme-auditoria-universitydays.md
Resultado de la pruebaauditoria-universitydays/pruebas/RESULTADO-PRUEBA.md
Guía del kitauditoria-universitydays/pruebas/LEEME.md
Scripts 01–06auditoria-universitydays/pruebas/
Código Java descompiladoauditoria-universitydays/codigo/java/
Scripts Ren’Pyauditoria-universitydays/codigo/renpy/
Manifiesto y recursosauditoria-universitydays/codigo/recursos/
Logs temporales/tmp/opencode/uni-test/session.log · offline.log

⚠️ Riesgos y salvedades

HallazgoRiesgoComentario
MANAGE_EXTERNAL_STORAGEMedio (privacidad)El juego solo usa Documents/RenPy_Saves, pero el permiso habilita más
Carga de .rpyc/.rpa desde DocumentsMedio (local)Cualquier script dejado ahí se ejecuta con permisos del juego
URM copiado desde Documents/0x52_URM.rpaMedio (local)El APK no lo incluye; usa solo el URM oficial
INTERNET sin código de redBajoNo hay endpoints, clientes HTTP ni sockets en código propio
requestLegacyExternalStorage + targetSdk 29Bajo/medioExplica el guardado en Documents; sin scoped storage moderno
allowBackup=trueBajoLas partidas podrían entrar en un backup
config.developer=TrueBajoSin consola accesible (config.console=False)
Firma autofirmada sin timestampBajoNormal en mods; la autenticidad se apoya en el hash oficial
Sesión dinámica corta (~5 min)BajoUn dispositivo y Android 10; no es garantía absoluta

Lo que esta auditoría no cubre

No se auditó 0x52_URM.rpa porque no se proporcionó. No se hizo comparación binaria completa de las tres ABIs. No se probaron mods externos. La prueba dinámica confirma que este APK concreto no intentó conectarse a nada, no que cualquier mod de la misma escena sea seguro.


🧹 Estado actual y limpieza

El perfil de trabajo sigue existiendo con University Days, NetGuard y PCAPdroid instalados. NetGuard está activo bloqueando Wi-Fi y datos al juego; PCAPdroid está detenido. No se borró nada porque el usuario quiere probar el juego después.

Limpieza cuando ya no se necesite

# Desinstalar solo del perfil de trabajo (usuario 10)
adb shell pm uninstall --user 10 com.koga3.universitydaysseason1
adb shell pm uninstall --user 10 eu.faircode.netguard
adb shell pm uninstall --user 10 com.emanuelef.remote_capture

Después, borrar el perfil desde Shelter → menú → Remove work profile. Eso elimina apps, datos y partidas del perfil de trabajo; el perfil personal no se toca.


🔁 Cómo reproducirlo

Comandos esenciales

# 1. Verificar integridad
sha256sum com.koga3.universitydaysseason1-Ep17.apk
 
# 2. Ver dispositivos y perfiles
adb devices -l
adb shell pm list users
 
# 3. Instalar solo en el perfil de trabajo (ID 10)
adb install --user 10 -r com.koga3.universitydaysseason1-Ep17.apk
 
# 4. Lanzar el juego
adb shell am start --user 10 \
  -n com.koga3.universitydaysseason1/org.renpy.android.PythonSDLActivity
 
# 5. Capturar log
adb logcat -c
adb logcat -v threadtime > session.log
 
# 6. Ver tráfico acumulado del UID del juego
adb shell dumpsys netstats detail | grep -A 6 'uid=1010500'
 
# 7. Ver permisos runtime
adb shell dumpsys package com.koga3.universitydaysseason1 \
  | sed -n '/runtime permissions:/,/User 10:/p'

Para la prueba de red: instalar PCAPdroid y activar su VPN → jugar 5–10 min → revisar conexiones. Después desactivar PCAPdroid, abrir NetGuard, bloquear Wi-Fi y datos solo a University Days → reabrir el juego y comprobar que funciona. Nunca ambos VPN a la vez.


✅ Conclusión

El APK es el oficial de KoGa3, firmado por él, con hash idéntico al de MediaFire. No contiene código Java propio sospechoso, no ejecuta comandos, no carga código dinámico y no se conecta a ningún sitio. Los scripts Ren’Py no usan APIs peligrosas y el escaneo de trackers da 0 SDKs.

La prueba dinámica lo confirma: 0 bytes de red para el UID del juego, ninguna conexión visible en PCAPdroid, arranque y partida sin errores incluso con NetGuard bloqueando Wi-Fi y datos. No hay indicadores de malware.

El riesgo real es de privacidad y permisos (MANAGE_EXTERNAL_STORAGE) y de carga de mods desde almacenamiento compartido (.rpyc, .rpa, URM), no de malware detectado. Para uso normal, con instalación desde el enlace oficial y sin mods desconocidos, el riesgo es bajo.


🔗 Enlaces relacionados