Basic Linux Exploit – Buffer Overflow – Part 2 – Creating shells with buffer overflow

Tram Ho

Hi everyone, following part 1, part 2, I will exploit buffer overflow error to get shell using python3’s pwntools library. Below is the C code of the previous mining program.

You compile the program with the following code (part 1):

1. Introduction to the pwntools library

  • How to install on python3

You can read more about the library here: https://docs.pwntools.com/en/stable/install.html

  • Some basic functions:

Packing, unpacking string:

  • p32(), p64(): packing 32bits and 64bits, ex: p32(0xdeadbeef) = b"xefxbexadxde"
  • u32(), u64(): unpacking 32bits and 64bits, ex: hex(u32( b"xefxbexadxde")) = 0xdeadbeef

Assemble and disassemble code:

  • asm(): Ex: asm('nop') = b'x90'
  • disasm(): Ex: disasm(b'x8bx45xfc') = 0: 8b 45 fc mov eax, DWORD PTR [ebp - 0x4]

2. Get the shell with pwntools and shellcode

I have shellcode to create a shell as follows:

In this series I will guide you to write your own shellcode, but not in this article.

Exploiting:

As mentioned in the previous post, after using gdb to debug, we calculate the number of bytes to add to the buffer to control the return pointer (eip) in the stack:

số bytes = 64 bytes array + 4 bytes ebx + 4 bytes ebp + 4 bytes eip = 76 bytes

First, I calculate the number of bytes of shellcode using printf and wc:

So the shellcode is 40 bytes long. Then I create a file exploit.py to exploit:

exploit.py

However, we have a problem, which is the return address (return address needs to be calculated, pointing to the beginning of the shellcode (or pointing to nop)). Talking a little about nop, is a “do nothing” command, when encountered this command, will simply slide to the next command.

If we use gdb to debug, we can know the starting address of the buffer, but this address and the running address in our python program are different, because of the different running environment. So I use the C program below to calculate the command level between gdb and python.

find_start.c

Compile the program: gcc -m32 find_start.c -o find_start

  • Calculate find_start in gdb: Open gdb victim, create breakpoint and run the program as follows:

So the program will run with the argument ./find_start, we need to know the value of find_start stored in the stack. Proceed to disassemble main. We get:

Notice the function strcpy@plt at 0x565561b3. Create a breakpoint right after to see the result, because find_start is copied to the buffer.

Continuing to run the program, we get the following results in the stack:

So in gdb ./find_start = 0xffffd094

Next, slightly modify the python program to print the find_start result:

The following results:

So ./find_start in python is 0xffffd138 => The command between the 2 environments is: python - gdb = 0xffffd138 - 0xffffd094 = 164 => python = gdb + 164

Next, debugging with gdb we found the start of the shellcode by running the program with 76 bytes of input. r python2 -c 'print("A"*76)'

So the result in gdb is 0xffffd054 => Ok, we have the complete python program as follows:

exploit.py

Result received:

So we have 1 shell. In the next part, I will show you how to get a shell with a small buffer, not enough to contain the input shell.

Share the news now

Source : Viblo