- What is the difference and which one is better to use?
The second one you cite is coming from a historical paper ("Smashing The Stack For Fun And Profit" by Aleph One in Phrack #49, 1996) (note that you removed the final '/bin/sh' which ruins totally the shellcode). It is probably the most well known explanation of what is a buffer-overflow and how to exploit it. The article itself comes with this shellcode which has been used as it is by numerous people to learn and to exploit in the wild.
Nowadays, this shellcode will be detected if sent in clear on the network by most of the IDS (Intrusion Detection Systems) and stopped before it reaches its target. Moreover, it is an educational shellcode (read the paper, AlephOne explain how to build such a shellcode), so it is a bit big for a shellcode.
So, the second shellcode is well-known and big, two reasons to not use it except if you want to understand what it does and how to write such thing.
The first shellcode you pointed, is designed to take the less space possible (only 28 bytes compared to 46 with the second). It may be useful to have a small shellcode because sometimes you will have only a small memory space to write it. So, if your shellcode is too big, it won't execute properly.
- Can you explain in detail what each of them do? For example why there is a push
$0x68732f2f
in the first link? If this is an address then how can you know it before run time if we have things like ASLR and PIE?
This is not an address, it is the string //sh
(in little-endian), look at the character 0x2f
which is /
(in ASCII code) repeated twice and, then, sh
.
Concerning ASLR and PIE, these security mechanisms came a few years after shellcodes. ASLR was designed to prevent easy exploitation of buffer-overflow by randomizing addresses. This is not the worst thing against buffer-overflow exploitation and shellcodes, in fact. The worst is NX (non-executable stack). And, in fact, since NX is here we are now using ROP (Return-Oriented Programming) better than shellcode (but I guess this will be your next step once you understand these shellcodes).
If you want to understand fully the shellcode, read the Aleph One paper...
This is the best explanation I know about it.
- Why are these shellcodes so much different if they do the same thing?
They vary in shapes and size because of the IDS, once a shellcode is common, it can be scanned and found in TCP/IP packets and stopped during an attack through the network. That is why there exists a great variety of it (some are self-encrypted with various keys to evade IDS).
And, then, you also have to take into account the way you inject the shellcode in the program, you may have several limitations (only ASCII or UTF-8 characters for examples). This will give another set of shellcodes (for example, see this article).
Finally, as I said at the beginning you may have size constraints. Which tends to try to have the smallest shellcode possible.