Posts Introduction to Linux 32 bit exploit development
Post
Cancel

Introduction to Linux 32 bit exploit development

Introduction


Hope you are all good, awesome and enjoying your life so far. So, without wasting much time, let’s get started. I am also going to be assuming here that you all are familiar with basics of c programming language, linux command line, assembly, memory and stack architecture and all. So, we will be creating a simple vanilla based buffer overflow exploit for the below c program.

1
2
3
4
5
6
7
8
9
10
11
#include <stdio.h>

void vuln(char *str) {
  char buffer[50];
  strcpy(buffer, str);
}

int main(int argc, char **argv) 
{
  vuln(argv[1]);
}

All the above program does is that it copies the user’s argument (passed through command line) to the buffer character array. Now you may wonder how could one get code execution in this simple program. Let me try to tell a quick summary of how is it possible.

1
2
3
4
5
6
7
8
9
Code Execution means we are able to execute some other code which is not intentionally put to be 
executed in usual cases. Now, you may ask how will we place our code in the program that we want 
it to get executed, the answer to this question is through user input, this program is taking user
input and copying it to the buffer array. Now you may wonder that in this program, it's nowhere 
executing or calling the part where user input is being stored, now the answer to this question 
lies in the fact that we need to make the program redirect to where our input will be placed.
Now maybe your final question will be like, how is the redirection possible to which the answer 
is the fact how the stack frame is being built. Aahh... now you may be like, it's too much, haha.
Don't worry, i hope by the end of this tutorial, your concept will be clear.

So, let’s first compile that program with gcc.

1
gcc vulnerable.c -m32 -fno-stack-protector -z execstack -o vulnerable

Images

You will be shown some warnings like above by gcc saying that strcpy is insecure and bla bla but ignore those errors for now since we are not making some code for production but learning how to exploit such insecure codes.

Now before running the program, let me try to explain the flags that we used with gcc while compiling.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
-m32 : This flag tells gcc to compile the code as 32 bit, i need to explicitly specify this flag since i 
        am using 64 bit linux. If this is your first time compiling 32 bit c program then you may need
        to install the 32 bit libraries which can be done with **sudo apt-get install gcc-multilib** .
        
-fno-stack-protector : This flag tells gcc to not use any stack protection which is stack canary. It makes
                        our exploitation part tough and since this is a basic tutorial, we need to make sure
                        that we are learning with all majori protections off cause i don't want you to get 
                        overwhelmed with so many complexities. But for now just understand that if we compile
                        our code with stack canary protection then it will place a cookie just after ebp 
                        or before (I am confused :P ) and then just before retreiving the return address, it
                        checks the value of the cookie and proceeds fruther only if the cookie value is not 
                        altered.
                        
-z execstack : Now this flag tells gcc to make stack section executable cause we are going to be placing our 
               shellcode on the stack. By default stack section is not executable, the norm is the section 
               which is write is not executable and the section which is executable is not writeable, uffff.
               
 -o : This last flag is the most complex flag which took me more than months to understand. haha, just kidding.
      All this flag does is saves the compiled output as the filename we specify (in this case vulnerable), if 
      we don't specify this flag then the gcc by default saves the compiled program as a.out.

Memory Architecture Fudamentals

Now before running or exploiting the program, let me tell you little bit about the architecture of the memory. Before that let me also tell that i am not a geek in OS architecture or memory architecture, so if i say anything wrong please feel free to correct it. I am guessing everyone reading this blog do play games or must have played some games at some point of their life. Have you ever wondered how are you able to play heavy games like GTA , Call of Duty and other heavy games on a RAM whose capacity is just 8 GB or 16 GB but the game itself is arond 70 GB if i am not wrong. This thing is possible with a concept of Virtual Memory. Virtual Memory as it sounds it not something which is not real memory but maps to the real memory. So all of you who have been thinking all this time that they have been able to see the hardcoded address inside the RAM with gdb or other debuggers, let me tell you one thing, you all are wrong , haha. Jokes apart, the need of virtual memory arose because of the fact that RAM size is limited and at some point we may need to load program into memory which may take more memory or we may need to load more than one program as it’s being done. OS allocates Virtual Memory to each process. So, this is how a virtual memory looks like, apologies before hand for my drawing.

If you like my drawing, you can hire me for your graphic designing work. Jokes apart, that’s how a virtual memory looks like, you can google for better images to understand. The Kernel space is allowed 1 GB of reserved area and the user space code can’t write nor read from that section. Next is the Stack section where functions’ local variables, argument and return address resides. After that we have free space and then Heap section where dynamically allocated(using malloc) variables reside. BSS section where uninitialized data gets stored, Data section where the initialized data gets stored and finally Code section where the executable code resides. One more thing you can see in the image is arrows which shows the direction of growth, using the image we can understand that stack grows downward and heap grow upward. So, i guess this much knowledge of virtual memory is enough to understand the exploitation part although now we won’t be looking into virtual memory anymore but will look into the Stack area only. So, now let me show you the step by step execution of the program inside gdb. We had already compiled our program, now just load it into the gdb. Here i am using the gef gdb extension, you can also use peda or pwndbg. I will leave the installation part of it upto you.

Images

I forgot to tell one thing, compile the code again now with extra -g flag which will add some debugging symbols to our binary which will make the debugging process easy.

1
gcc vulnerable.c -fno-stack-protector -z execstack -g -o vulnerable

Now if you type list inside the gdb, you can see the source code of the program.

Image

Let’s set the breakpoint at line 13 with the command break 13 and then run the program with argument ABCD123.

Image

The gef will also output the state registers, stack, disassembly and code info. Now type disas main which will output the disassembly code of the main program along with the arrow pointing where we have reached after hitting the breakpoint.

Image

Let’s continue the program by typing continue Image

As can be seen it exited normall since all our program did was copy command line argument into the buffer variable and then exit (We didn’t print anything on the screen).

Enough with the analysis, now let’s jump straight into the exploitation part.

This post is licensed under CC BY 4.0 by the author.