In the Metasploit Framework, an exploit is called an "exploit module".

Exploit modules are located by default in:
C:\Program Files\Metasploit\Framework3\home\framework\modules\exploits\
(also check C:\Documents and Settings\<Your User Name>\Application Data\msf3\modules\exploits if you do not find in above path)

Exploit modules are classified by platforms (OSes) and then by types (protocols).

To understand how to write an exploit module for the Metasploit Framework, we'll write an exploit for an easily exploitable vulnerability in WarFTPD version 1.5 [2].(Note that the exploit module for this vulnerability already exists in the Metasploit Framework, but we are trying to build our own exploit.)
We download and install WarFTPD in our local Windows machine.
We start WarFTPD Daemon.
We uncheck the "No anonymous logins" checkbox.
We start the FTP server (click on the "Go Online/Offline" button)

We first reproduce the vulnerability.
For this, we directly use the Metasploit Framework.
We create the file:
C:\Program Files\Metasploit\Framework3\home\framework\modules\exploits\windows\ftp\warftpd.rb

To see what happens when the server crashes, we use a debugger.
We launch again WarFTPD Daemon and attach our debugger to it.
=> In OllyDbg, we use "File/Attach", choose the WarFTPD process, click Ok and after it has been loaded, we press the F9 key to have it Running.

We launch our exploit again.
We can now look at our debugger.
We see that an access violation is triggered.
EIP is overwriten with our evil string (41414141 is the hexadecimal equivalent for AAAA)

We use the pattern_create() function to generate a string of non-repeating alpha-numeric text string. We use this function by calling the following script: C:\Program Files\Metasploit\Framework3\msf3\tools\pattern_create.rb

The result "485" is displayed. It means that we should have a space of 485 bytes to store our payload.

We add this value in our PoC code: We modify this line:

'Space' => 1000, #We actually don't know the correct value for this

for:

'Space' => 485,

In this way, when we will load our exploit in the Metasploit Framework (with the "use" command), it will automatically search and display the available payloads with a size lower than 485 (with the "show PAYLOADS" command).

We have now to find a reliable return address.
The best way is to take a return address directly in our target. (in the vulnerable executable itself or in one of the DLLs it uses)
It avoids problems with various versions of Windows and Service Packs, locales, hotfixes...
It would make our exploit universal.
But it is not always so easy.

One way for this is to use the search in memory functionality of OllyDbg.

We have now to find and prevent badchars.
We should not include terminating null character in our shellcode as it would break out of the execution.We have already done this with this in our exploit: 'BadChars' => "\x00"

Additionally, a target application will often modify the data received before the application will work with the data.
An example is an application that will change all characters to uppercase.
As this will modify our shellcode, we have to deal with it.
For this, the Metasploit Framework will encode our shellcode to obtain one without any specified badchars.
We just have to specify the list of badchars in our exploit code.

So, to find the badchars, we will send a string containing all the characters of the ASCII table, with both printable and non-printable ones.
The string will look like this:

@ We edit our exploit code and put the above string in it.
Then, having our target application running and our debugger attached to its process; we relaunch our exploit.
Under the debugger, after the access violation is triggered, we right click on the esp register and choose the option "follow in dump".
We will now see our string and check what are the missing or modified characters at the end of the string.
It is our first badchars. (note it)

We remove it in our exploit code, and do it@ again...
until we see all the characters sended in our debugger.

Now we write, in the badchars section of our exploit, the characters found as badchars (removed or modified by the application).