BookinglyTech News
Ciberseguridad

Reversan el PRNG de Factorio y pueden predecir la calidad de cada objeto

Un analisis de ingenieria inversa sobre el binario del juego confirma que usa el generador taus88 de Boost y que conocer su estado permite anticipar los resultados.

2 min de lecturaLobsters0 vistas

Factorio 2.0 construye toda su aleatoriedad sobre taus88, el generador de la libreria Boost, y quien conozca el algoritmo y el estado interno puede predecir los resultados antes de que ocurran: que fabricacion va a salir con calidad superior, por ejemplo. Un analisis de ingenieria inversa sobre el binario del juego lo demuestra, apoyandose en los simbolos de depuracion que Wube distribuye junto al ejecutable. En Factorio 2.1 el truco se rompe: los desarrolladores cambiaron la forma en que se consume el generador, aunque la parte teorica sigue en pie.

El origen de todo esta en el DLC Space Age y su mecanica de calidades. Por defecto los objetos salen comunes; si se colocan modulos de calidad en la maquina de fabricacion, hay una probabilidad pequena de obtener uno mejor. La diferencia es tangible: un edificio de mas calidad fabrica mas rapido, un modulo da un mejor bonus, un poste de energia cubre mas distancia y un insertador se mueve mas rapido. Para conseguir volumen, los propios desarrolladores dijeron que esto es 'basicamente estadistica': con produccion suficiente, la distribucion observada se acerca a la esperada.

Ahi esta el detalle. Factorio es determinista, y su azar no es azar: es un PRNG, un algoritmo que produce una secuencia que lo parece. Si se conocen el algoritmo y su estado, se ejecutan las mismas cuentas en paralelo al juego y se sabe lo que va a salir antes de que salga.

Del foro al binario

El autor empezo buscando en internet. En el foro de Factorio encontro un hilo de hace once anos con la respuesta de Cube, ex desarrollador de Wube: eligieron taus88 por ser el generador mas rapido de Boost, y descarto quitar uno de los tres LFSR, que habria acelerado el proceso cerca de un 40%, porque los numeros aleatorios no eran un cuello de botella. En Boost, taus88 son tres registros de desplazamiento con retroalimentacion lineal de 32 bits cuyas salidas se combinan con XOR.

Como ese mensaje ya tenia ocho anos cuando arranco el trabajo, no se fio y fue a la fuente mas precisa, el binario. El juego es de codigo cerrado, pero Wube publica un archivo .pdb con los simbolos de depuracion, y eso permite generar una descompilacion anotada. Con Ghidra primero y Binary Ninja despues, localizo la clase RandomGenerator y su getInt(): tres semillas y una ronda de desplazamientos, mascaras y XOR que cuadra con el algoritmo de la libreria. Despues publico los cuadernos con las demostraciones.

Que la aleatoriedad de un juego sea predecible no sorprende a quien trabaja con PRNG, pero el caso deja una leccion util: un binario cerrado deja de ser opaco cuando su autor envia los simbolos de depuracion. Y recuerda que cualquier mecanica presentada como azar dentro de software determinista es, en el mejor de los casos, azar para quien no mira debajo. Queda por ver si el cambio de la 2.1 aguanta el proximo intento o solo mueve el problema de sitio.