There are some techniques for system-level security at the software level as well.
#### ASLR
Address Space Layout Randomization makes it difficult for attacker to find the right addresses to read from or write to. This makes buffer overflow harder.
#### NX or DX bits
A non-executable stack can be achieved by setting Never Execute (NX) or Disable Execute (DX) bits. It stops the attacker from running malicious code from the stack, but a buffer overflow is still possible by using ret-to-libc attack.