Hay formas matemáticas de obtener números pseudo-aleatorios, esto es, que no son aleatorios en realidad. En general, eligen un número (llamado seed/semilla) y un N, con los que se realizan operaciones para dar un pseudoaleatorio. Se pueden operar múltiples veces para obtener cada vez un aleatorio distinto, hasta N veces, momento en el que se repetirá el primer número, por lo que se intenta que N sea lo mayor posible. Para ello hay varios algoritmos y ahora mismo no recuerdo ninguno, miraría los apuntes pero están "muy escondidos en el cajón".
Por ejemplo en C tienes la función rand(), que dará un número distinto cada vez que se ejecute en el mismo programa. Para que la semilla sea más o menos aleatoria, se inicializa con algún valor relacionado con el tiempo del sistema, por ejemplo con srand(time(NULL));. El programa siguiente dará valores distintos si se ejecuta en segundos distintos, pero si lo ejecutas varias veces en el mismo segundo dará el mismo número.
#include <stdio.h>
#include <time.h>
main(){
int r;
srand(time(NULL));
r = rand();
printf("%i\n", r);
}
El resultado de ejecutarlo 3 veces en mi ordenador, 2 en el mismo segundo y la 3ª un poco después:
samuel@linux:/tmp 15:09:44 $ ./a.out
2032613962
samuel@linux:/tmp 15:09:44 $ ./a.out
2032613962
samuel@linux:/tmp 15:09:46 $ ./a.out
46611799
Para elegir un número entre A y B pues habrá algoritmos para elegir un número entre A y B, otros para elegir entre 0 y B-A y luego se le suma A, o generar aleatorios hasta que esté dentro de los límites.
En fin, no sé qué algoritmo será el más usado ni cuál implementa el rand() de C. Ya te digo que esto lo dí hace años y casi no me acuerdo.
Seguramente haya métodos más complejos y eficaces, y alguien te los podrá explicar bastante mejor que yo

No creo que sea muy difícil encontrar información de esto en cualquier buscador.
Saludos