Stack smashing is making use of a buffer overflow vulnerability in code using variables on the stack. This type of vulnerability has been known for a long time. This attack was first properly documented in Phrack #49.
Stacks in computing architectures are regions of memory where data is added or removed in a last-in-first-out (LIFO) manner.
The stack is used to pass arguments between functions, to allocate space for fixed variables, and to remember how to get back out of the current function.
For x86 systems the stack grows from the largest memory address up.
.footnote[Borrowed from [wikipedia](https://en.wikipedia.org/wiki/Stack-based_memory_allocation)]
.footnote[Borrowed from [wikipedia](https://en.wikipedia.org/wiki/Stack_buffer_overflow)]
]
---
.left-column[
## How does this work?
]
.right-column.center.middle[
<imgsrc="Stack_Overflow_2.png"width="70%"/>
.footnote[Borrowed from [wikipedia](https://en.wikipedia.org/wiki/Stack_buffer_overflow)]
]
---
.left-column[
## How does this work?
]
.right-column.center.middle[
<imgsrc="Stack_Overflow_3.png"width="70%"/>
.footnote[Borrowed from [wikipedia](https://en.wikipedia.org/wiki/Stack_buffer_overflow)]
]
---
.left-column[
## How does this work?
]
.right-column.center.middle[
<imgsrc="Stack_Overflow_4.png"width="85%"/>
.footnote[Borrowed from [wikipedia](https://en.wikipedia.org/wiki/Stack_buffer_overflow)]
]
---
template: inverse
# Vulnerable functions
---
.left-column[
## Vulnerable functions
]
.right-column[
Anything that doesn't take buffer sizes into account. The big ones being:
- gets
- strcpy
- sprintf
]
---
template: inverse
# Now what can we do with this?
---
.left-column[
## Now what can we do with this?
]
.right-column[
We can change the flow through the program:
- Jump to a different function in a known spot in memory
- Jump to our own shellcode somewhere in the buffer (can also write past the return address)
- Jump to our own shellcode in the environment
*Full nerd: By overwriting the return address we can change to which instructions the Instruction Pointer (`EIP` in 32-bit x86, `RIP` in 64-bit x86) points. `EIP` and `RIP` are so called registers. There are more, like `EBP`/`RBP` which is used for pointing at the stack frame pointer. The other registers are used like variables.*
.footnote[Lots of shellcode [here](http://shell-storm.org/shellcode/)]
]
---
template: inverse
# Shellcode?
---
.left-column[
## Shellcode?
]
.right-column[
In hacking, a shellcode is a small piece of code used as the payload in the exploitation of a software vulnerability. It is called "shellcode" because it typically starts a command shell from which the attacker can control the compromised machine, but any piece of code that performs a similar task can be called shellcode. [1]
As strings in C are NULL terminated, shellcode should not have `\x00` in it.
`\x90` is a NOP (No Operand) in x86. You can use a bunch of those in front of shellcode to increase the chances of ending up in your shellcode. This is called a NOP-sled.
Sometimes swapping out some shellcode for some other shellcode is the trick.
.footnote[[1] Borrowed from [wikipedia](https://en.wikipedia.org/wiki/Shellcode)<br>[2] Shellcode from [shell-storm](http://shell-storm.org/shellcode/files/shellcode-251.php)]
In computing, endianness refers to the order of bytes (or sometimes bits) within a binary representation of a number. It can also be used more generally to refer to the internal ordering of any representation, such as the digits in a numeral system or the sections of a date.
In its most common usage, endianness indicates the ordering of bytes within a multi-byte number. A **big-endian** ordering places the most significant byte first and the least significant byte last, while a **little-endian** ordering does the opposite. For example, consider the unsigned hexadecimal number 0x1234, which requires at least two bytes to represent. In a big-endian ordering they would be `[ 0x12, 0x34 ]`, while in a little-endian ordering, the bytes would be arranged `[ 0x34, 0x12 ]`.
`int 0x80` is a legacy way of doing a syscall to the kernel. See also:
http://www.linfo.org/int_0x80.html As this is a 32-bit program, the list of syscalls can be found here: `/usr/include/asm/unistd_32.h` Which shows the values in decimal: 0x17 = 23 = setuid.
So, whats done here is put 0x17 in EAX, and make EBX (the argument for setgid, see https://faculty.nps.edu/cseagle/assembly/sys_call.html) 0 using a XOR. Then call int 0x80. Resulting in a `setuid 0`.
Not only does that push EBX seem unneeded, removing it has no impact on getting a shell. So in explaining this shellcode I managed to turn it into 36 bytes instead of 37.
Another `int 0x80` here for syscall 0xb = 11 = execve. 0x68732f2f in ASCII chars = `hs//`, but little endian, so read `//sh`. Same for 0x6e69622f, which gets `/bin`. Together this makes for `/bin//sh`. That double `/` is here to fill that 32-bit word. The EDX that is set to 0 and pushed makes up for the null string terminator.
The arguments for execve will not fit in registers, as they're variable size. So instead ECX points at a list of pointers to strings (commandname + arguments) on the stack (ie ARGV in C). EBX points to the command to execute.