How do wallets work? It may seem like a vague question, but what I understand so far is, you have a public key (address) which people can send coins too, and then you have the private key which you need to send coins to someone else.
My question is, how does the program itself work?
Does it create a public key based of private? maybe on the wallet.dat file? How would you be prevented from getting a private key if you have the public key? and what stops someone from looping over a bunch of private keys to find one with some coins in?
Does it create a public key based of private?

Yes, a cryptographic routine exists that computes the public key from the private key.

maybe on the wallet.dat file?

All modern wallet software generates keys derministically from some sort of master key, or seed phrase. That master key is stored in the wallet, and all other private keys are derived from it, and the public keys are derived from that. For every new receive address, a distinct key is used. The fact that they're all computed from one piece of data means that a backup of your wallet allows generation of all future addresses - even the ones created after the backup was made.

How would you be prevented from getting a private key if you have the public key?

Cryptography. The function to compute the public key from the private is fairly efficient in one direction (~50 microseconds on a modern desktop CPU), but the best known algorithm for going the other way around (Pollard's rho) would take around 300 trillion times the age of the universe on the same computer. With many computers it becomes faster of course, but even billions of times faster isn't remotely close to being able to realistically break any key. The security is based on the assumed hardness of a number theoretical problem, the elliptic curve discrete logarithm problem (ECDLP).

and what stops someone from looping over a bunch of private keys to find one with some coins in?

There are 115792089237316195423570985008687907852837564279074904382605163141518161494336 valid private keys (that's the actual number). Attempts to brute force them are futile due to the sheer number. The duration I gave above doesn't rely on brute force - it uses a much more efficient algorithm. Brute force would be 600 trillion trillion trillion times slower still.