So much of "security research" over the last 10 years has basically danced around a fundamental fact: if you lose control of the runtime memory of your program, you lose control of the whole program.
You could find the address of a JMP %ESP instruction in the victim OS (0x7C8369D8 in XP SP 2) and place it before a NOPsled.
A typical buffer overflow, for example:
[AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA][0x7C8369D8][NOP][shellcode]
You do, of course, need to make sure you don't have any \0 bytes in your shellcode, but that's always been the case.
http://csapp.cs.cmu.edu/public/buflab.pdf
Edit: Changes since 2002
-- Assignment is now individual
-- "For Fun" stage is now mandatory
And here are the other labs: http://csapp.cs.cmu.edu/public/labs.htmlArchitecture lab has fallen by the wayside, and Performance Lab is done sometimes (depending upon the taste of the instructors)
Another tutorial pre-dates this by ~1 year. It was written by mudge.
http://seclists.org/bugtraq/1995/Dec/2
(My business partner co-authored it).
The first shellcode-style buffer overflow (besides the rtm worm) was Thomas Lopatic's HPUX HTTPd vulnerability from a few months earlier:
http://seclists.org/bugtraq/1995/Feb/109
There was a frantic race to get the first overflow out after 8lgm capped off their run of zero-days with an announcement of a Sendmail 8.6.12 remote that relied on a syslog() overflow (yes, in 1995, syslog(3) had an overflow). I was sitting next to Pieter when he wrote part of the tutorial you linked to. I was pretty young (maybe 19?) but even so, it was a pretty electric time to be involved in security.
112,605 documents found
http://citeseerx.ist.psu.edu/search?q=Smashing+The+Stack+For...
large_string[255] = 0;
Would solve that.
This was probably one of the most important things I learned in school.