Local

Objective

  • Gain shell access by overflowing a vulnerable buffer.

    • ASLR disabled

Prerequisites

  • Basic knowledge of:

    • C

    • GCC

    • Command line

    • x86

Install

Open terminal and install:

$ sudo apt-get install nasm
$ sudo apt-get install g++-multilib

Exercise

A system with an executable binary that is owned by root, has the suid bit set, and is vulnerable to buffer overflow. We will now exploit it to gain shell access.

Setting the environment:

  1. First we need to create a user <test> without root privilages:

2. Create a file name <vuln.c> in the home directory for <test> user.

3. Let's compile it

For 32 bits systems

For 64 bit systems

*Note

  • -fno-stack-protector allow us to disable the stack protection.

  • -m32 made sure that the compiled binary is 32 bit

  • -z execstack makes the stack executable

4. Setting up permisions

Now let's confirm your file:

5. Disable or Enable ASLR (Address space layout randomization)

When ASLR is turned on the addresses of the stack, etc will be randomized. This causes a lot of difficulty in predicting addresses while exploitation.

  • Disable

  • Enable

6. Shellcode Injection

After we disable ASLR, we need to log into test user.

There is a vulnerability in <vuln.c>. The <strcpy> function does not specifiy a maximum lenght while copying. Let's disassembley using <objdump> and see what we can find

Shellcode injection consists of the following main parts:

  1. The shellcode that is to be injected is crafted.

  2. A possible place is found where we can insert the shellcode.

  3. The program is exploited to transfer execution flow to the location where the shellcode was inserted.

7. Crafting Shellcode

We will create a shellcode that spawns a shell.

To compile it use <nasm>:

Use objdump to get the shellcode bytes:

Extracting the bytes gives us the shellcode:

8. Finding a possible place to inject shellcode

We can insert the shellcode by passing it inside the first parameter while running <vuln>. For that we are going to use GDB.

  • We set a breakpoint at the <func> function.

  • Start the binary with a payload of lenght 116 as argument.

  • Print the address <ebp - 0x6c> and shows the <buf> was located at 0xffffd06c. * This direction may be different at your computer

The length of the payload will have an effect on the location of <buf> as the payload itself is also pushed on the stack(it is part of the arguments).

9. Crafting payload

No we are goint the insert the shellcode at the end of the argument string so its address is equal to the address of <buf> + some length.

  • Length of shellcode = 25 bytes

  • It is also known that return address starts after the first 112 bytes of <buf>

  • We’ll fill the first 40 bytes with NOP instructions

    10. NOP Sled

NOP Sled is a sequence of NOP (no-operation) instructions meant to “slide” the CPU’s instruction execution flow to its final, desired, destination whenever the program branches to a memory address anywhere on the sled.

We will make the processor jump to the address of <buf> (taken from gdb’s output) + 40 bytes to get somewhere in the middle of the NOP sled.

0xffffd06c +40 = ffffd0ac

*You can use http://www.csgnetwork.com/hexaddsubcalc.html to calculate this sum.

We can fill the rest 47(112 - 25 - 40) bytes with random data, say the ‘A’ character.

Final payload structure:

[40 bytes of NOP - sled] [25 bytes of shellcode] [47 times ‘A’ will occupy 49 bytes] [4 bytes pointing in the middle of the NOP - sled: 0xffffce16]

So execute:

Congratulations! We’ve got root access.

*Note in case you segmentation fault, try changing the return address by +- 40. For example:

0xffffd06c +20 = 0xffffd06c + 40 0xffffd06c +80 etc..

Last updated

Was this helpful?