Brainwallets are Bitcoin wallets generated uniquely from a passphrase that the users keeps in his mind so that it is required and sufficient to move the funds.
But what is actually the process that takes a password and spits a Bitcoin wallet address? Let’s dissect it.
1. From a password to a secret value
So, we have a password, but we need a fixedsize (256bit) secret value to make our private key. This step can be done in a number of ways as it boils down to hashing the password but is crucial to the strength of the resulting brainwallet.
Let’s have a look at how popular Brainwallet generators do it. (As of 20131204)
Generator  Algorithm  Notes 

brainwallet.org  SHA256(password)  
bitaddress.org  SHA256(password)  
eharning.us/brainwalletltc  SHA256(password)  Litecoin wallet 
brainwallet.ltcbbs.com  SHA256(password)  Litecoin wallet 
keybase.io/warp  scrypt(password, salt) XOR PBKDF2(password, salt) 
A lot of them just take the unsalted SHA256 hash of the password. This is wrong. Because SHA256 is fast and that means that an attacker can pregenerate huge tables of all possible brainwallets to monitor and empty them (Spoiler: they do). This kind of thing – turning a human supplied password into a public hash – is exactly what password stretching are for, and not using them here is an oversight as bad as not using them to store website user passwords, if not worse since here the hashes (the addresses) are public by default.
(Hint: use WarpWallet. It’s built by people who know what they are doing, and employs a proper KDF, making attacking your wallet really difficult.)
2. From the secret value to a private key
This is step is trivial. Actually, the output of the hashing above taken as a 256bit unsigned number is already the private key, what is commonly called the secret exponent.
But we are used to see those pretty private keys beginning with a 5, so let’s see how it is encoded. That format is called WIF, Wallet import format, and it is pretty handy as it has checksumming built in and employs a charset without confusing characters (Base58Check) – exactly like a Bitcoin address.
A snippet is worth a thousand words:
1 2 3 4 5 6 7 8 9 10 11 

3. From a private key to a public key
As Wikipedia tells us a ECDSA private key is just the scalar product of a private key (the secret exponent) and the curve – secp256k1 for Bitcoin – base point. How to do that is complex, but let’s just take it for granted, as you’ll either use a librarty for this or research further by yourself.
What we get out of that operation is a pair (x, y) denoting a point on the curve, our public key.
4. From the public key to a Bitcoin address
We’re almost there! Now we just need to turn that ECDSA public key into a standard Bitcoin address.
The process is the same as point 4, executed on the SHA256+RIPEMD160 hash of the packed x and y values. Go go snippet:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 

And it’s done!