Lab 6.2 Remote Linux Buffer Overflow With Listening Shell
Lab 6.2 Remote Linux Buffer Overflow With Listening Shell
)
What You Need
A 32-bit x86 Kali 2 Linux machine, real or virtual. The project works in a very similar manner on Kali 1.
Purpose
To develop a very simple buffer overflow exploit in Linux. This will give you practice with these techniques:
Disabling ASLR
We'll disable ASLR to make this project easier.
./p4-server
You need two Terminal windows for this project--a "SERVER WINDOW" and a "CLIENT WINDOW", as labelled below.
nc 127.0.0.1 4001
You see a "Welcome to my server!" banner. Type in the message HELLO and press Enter.
The server echoes back your input and asks for another message, as shown below.
gdb p4-server
list
You see ten lines of source code for the server, as shown below. This server was compiled with symbols included, which is not typical, but it makes this project easier.
The source code shows the start of the main() function, which calls the socket() function at line 29 to open a listening process.
In line 26, you can see that the main() function uses a buffer 4096 bytes long.
list 11,20
You see the source code for a copier() function, which uses a buffer only 1024 characters long, as shown below.
This suggests that the main() function will allow you to put in more than 1024 characters, and that will overflow a buffer in the copier() function.
nano p4-b1
#!/usr/bin/python
ls -l p4-e1
The file should be 1101 bytes long, as shown below--1100 'A' characters followed by a line feed.
./p4-server
In the CLIENT WINDOW, execute this command to send the exploit to the server:
Somewhere between 1024 and 1100 bytes are the bytes that will end up in $eip. To find them, we'll put a nonrepeating pattern of bytes in the last 100 bytes of the exploit.
nano p4-b2
#!/usr/bin/python
pattern = ''
for i in range(0, 5):
for j in range(0, 10):
pattern += str(i) + str(j)
ls -l p4-e2
cat p4-e2
The file should be 1101 bytes long, as shown below--1000 'A' characters, then 50 two-digit numbers counting up, followed by a line feed.
Debugging the Server
In the SERVER WINDOW, execute these commands to run the server in the gdb debugging environment:
gdb p4-server
run
In the CLIENT WINDOW, type this command to send the exploit to the server, but don't press Enter yet:
info registers
This shows $eip at the point of the crash. It contains 0x39313831, as shown below.
Hex Char
--- ----
30 0
31 1
32 2
33 3
34 4
35 5
36 6
37 7
38 8
39 9
So the $eip is 0x39313831 because the bytes in RAM were the characters 1819. The order is reversed because the ANSI text is interpreted as a little-endian register
value.
The server has already crashed. In the SERVER WINDOW, press q, Enter, y, Enter to exit gdb.
nano p4-b3
#!/usr/bin/python
ls -l p4-e3
cat p4-e3
The file should be 1101 bytes long, as shown below, with these sections:
gdb p4-server
run
In the CLIENT WINDOW, type this command to send the exploit to the server:
The server crashes with a "Segmentation Fault" error, as shown below. It's complaining about a bad address of "0x44434241", but we don't necessarily know it was
because that address was in the $eip yet.
In the SERVER WINDOW, execute this command:
info registers
This shows $eip at the point of the crash. It contains 0x44434241, as shown below, as it should--we now control the $eip!
Press the PrintScrn key to copy the whole desktop to the clipboard.
Save the document with the filename "YOUR NAME Proj 4a", replacing "YOUR NAME" with your real name.
quit
nano p4-b4
#!/usr/bin/python
Getting Shellcode
The shellcode is the payload of the exploit. It can do anything you want, but it must not contain any null bytes (00) because they would terminate the string prematurely
and prevent the buffer from overflowing.
Also, it cannot contain Line Feed (0A) or Carriage Return (0D) characters, because we are inputting it at a prompt, and those would terminate the input line prematurely.
In the SERVER WINDOW, execute this command, which shows the exploits available for a Linux platform, which bind a shell to a listening TCP port:
Troubleshooting
In June, 2018, the "--payload-options" option was changed to "--list-options", so if you have a recent version of Metasploit, use this command instead:
The top portion of the output shows the Basic options. The only parameter we really need is "LPORT" -- the port to listen on, and it defaults to 4444.
The resulting payload isn't useful for us, because it contains a null byte ("\x00"), as shown below.
That null byte will terminate the string, preventing the shellcode from entering the buffer.
We could use the "-b" switch to avoid bad characters, but since we have plenty of room (1000 bytes or so), we can use the "-e x86/alpha_mixed" switch, which will
encode the exploit using only letters and numbers.
When I first developed this exploit, it spawned a listening process, but it crashed as soon as I connected to it. By trial and error, I discovered that the 'AppendExit=true'
switch fixed that problem. I don't really know why.
This payload is longer--232 bytes. Highlight the Python code and copy it to the clipboard, as shown below:
Constructing the Exploit
In the SERVER WINDOW, execute this command:
nano p4-b4
Remove the "INSERT PAYLOAD HERE" text and paste in the exploit code produced by msfvenom.
The end of your program should now look like the image below.
ls -l p4-e4
gdb p4-server
run
In the CLIENT WINDOW, type this command to send the exploit to the server:
info registers
This shows $eip at the point of the crash. It contains 0x44434241, as shown below, as it should.
list 11,20
As shown below, the buffer overflow occurs in line 14, calling the notorious strcpy() command. We want to break at line 15, immediately after the buffer overflow, before
the program attempts to return from copier().
In the SERVER WINDOW, execute these commands to quit dbg, restart it, set the breakpoint and start the server:
gdb p4-server
break 15
run
Troubleshooting
When you restart the server, you may see "ERROR on binding: Address already in use", as shown below:
That's because a connection to address 4001 hasn't timed out yet. To see it, exit the debugger and cancel "nc" if it's running.
A live display shows all connections to port 4001. If you see a process in the TIME-WAIT state like this:
NOTE: the error message indicates that the local variable "str" can no longer be found because the stack has been corrupted. This doesn't mean the server has crashed--it
just means that gdb cannot provide all the information it is trying to.
info registers
As shown below, $eip points to <copier+30>, which is correct because the program has not yet crashed.
The $ebp and $esp values are also correct at this point, so we can examine the stack.
x/260x $esp
The first page of the stack is filled with '\x41' bytes, ANSI for 'A', as shown below:
Press Enter to see the second page. It's all '\x41' bytes too.
Press Enter to see the third page. Here you see the last of the '\x41' bytes and the start of the '\x90' values. This is the NOP sled.
Press Enter to see the fourth page. Here you see the end of the NOP sled, followed by the shellcode, highlighted in the image below.
Press Enter to see the fifth and last page of the stack.
Here you see the last three words of the shellcode (highlighted in the image below), and the address which will be placed in $eip. At present, this address is
'\x41\x42\x43\x44' in reverse order, a dummy value of 'ABCD' we placed there just to mark the spot.
cp p4-b4 p4-b5
nano p4-b5
ls -l p4-e5
gdb p4-server
run
In the CLIENT WINDOW, type this command to send the exploit to the server:
Nothing appears to happen. The server doesn't crash--it just sits there, as shown below.
This is because the exploit worked! It opened another shell on port 4444.
To see it, open a third Terminal window and execute this command:
You can now execute Linux commands from the shell. Try these commands, as shown in the image above:
whoami
pwd
Press the PrintScrn key to copy the whole desktop to the clipboard.
Save the document with the filename "YOUR NAME Proj 4b", replacing "YOUR NAME" with your real name.
q
y
./p4-server
The exploit should work, so you see no visible change, as a new process spawns listing on port 4444.
Troubleshooting
If your exploit works in gdb but not in the normal shell, that probably means that ASLR is on. Execute this command to turn it off:
Leave both the SERVER WINDOW and CLIENT WINDOW as they are. In a third Terminal window, execute this command:
Connecting Remotely
In the third Terminal window, execute this command:
ifconfig
From the host machine, or some other convenient machine, connect to your Linux box on port 4444. You can use nc on a Mac or Linux box, as shown below. On a
Windows box, either install the optional 'telnet' client Windows feature in Control Panel and use that, or install Nmap and use "Ncat".
Saving a Screen Image
Make sure you can see a connection to a real IP address, not 127.0.0.1, and the root answer to "whoami", as shown above.
Press the PrintScrn key to copy the whole desktop to the clipboard.
Save the document with the filename "YOUR NAME Proj 4c", replacing "YOUR NAME" with your real name.
Sources
How to use msfvenom