colloide

[historical] Web directory bruteforce script
git clone git://mcdim.xyz/colloide.git
Log | Files | Refs | README | LICENSE

colloide.py (13164B)


      1 #!/usr/bin/python
      2 
      3 import sys
      4 import os
      5 import argparse
      6 import random
      7 import string
      8 import http.client
      9 import socket
     10 import urllib.request, urllib.error, urllib.parse
     11 import requests
     12 from urllib.request import Request, urlopen
     13 from urllib.error import URLError, HTTPError
     14 import colorama
     15 from colorama import Fore, Back, Style
     16 
     17 
     18 version = "v1.4"
     19 
     20 
     21 def logo(): #logo - patorjk.com
     22 	print("MCD's")
     23 	print("_________        .__  .__         .__    .___     ")
     24 	print("\_   ___ \  ____ |  | |  |   ____ |__| __| _/____  ")
     25 	print("/    \  \/ /  _ \|  | |  |  /  _ \|  |/ __ |/ __ \ ")
     26 	print("\     \___(  <_> )  |_|  |_(  <_> )  / /_/ \  ___/")
     27 	print(" \______  /\____/|____/____/\____/|__\____ |\___  >")
     28 	print("        \/                                \/    \/ ")
     29 
     30 def checkasciilogo():
     31 	check_value = open(".ascii_disable_option_value.txt","r")
     32 	checkvalue = check_value.read(1)
     33 	if checkvalue == "0":
     34 		logo()
     35 	check_value.close()
     36 
     37 def banner(): #banner with logo - patorjk.com
     38 	checkasciilogo()
     39 	print("MCD's")
     40 	print("Colloide %s" % version)
     41 	print("by MCD 2017-2020\n\n")
     42 
     43 def opts():
     44 	print("  --status        Use the HTTP status code method (Faster)")
     45 	print("  --urlerror      Use the HTTP/URL error method (More reliable)")
     46 	print("    -h --help     Display the help panel (Shown right now)")
     47 	print("    -u --URL      The URL to the website")
     48 	print("    -f --folder   Directory to search in")
     49 	print("    -p --pages    Path to the wordlist with the page names / links")
     50 	print("    -s --save     Save pages on a text file (name of the file)")
     51 	print("    -l --limit    Add limit to the pages (Integer)")
     52 	print("    -v --verbose  Show all attempts")
     53 	print("    -a --agent    Change User-Agent headers\n")
     54 	print("    -L --legals   License & legal disclaimer")
     55 	print("    -A --ascii    Enable/Disable ASCII\n\n")
     56 
     57 def legals():
     58 	#License
     59 	print("MCD's Colloide version %s is free software. It can be re-distributed " % version)
     60 	print("and / or modified under the terms of the GNU General Public License")
     61 	print("as published by the Free Software Foundation; For more information")
     62 	print("read the GNU General Public License that comes")
     63 	print("along with this program.\n\n")
     64 
     65 def wolf():
     66 	#prints the ASCII colloide wolf
     67 	print(" ___________________      ,     ,")
     68 	print("[ COLLOIDE MISSION! ]     |\---/|       __--__")
     69 	print("                         /      [     ,:',.  (`. ")
     70 	print("                    __.-'|      /    |  `'_.   .|")
     71 	print("           __ ___.-'         \__)   |   _ : () _ |")
     72 	print("        .-'  '        :   :  _/      |    .  .  |")
     73 	print("       / ,    .        .   _ |        ':_)  ,_|'")
     74 	print("      :  ;    :        :   _/             --   ")
     75 	print("      |  |   .'     __:   /      ")
     76 	print("      |  :   /'----'| \  |              __________")
     77 	print("      \  |\  |      | /| |_______,-----'")
     78 	print("       '.'| /__,----| \ | ")
     79 	print("_______| /|.'       '.l \\\_")
     80 	print("       || ||             '-'")
     81 	print("       '-''-'\n")
     82 
     83 def checkasciiwolf():
     84 	check_value = open(".ascii_disable_option_value.txt","r")
     85 	checkvalue = check_value.read(1)
     86 	if checkvalue == "0":
     87 		wolf()
     88 	else:
     89 		print(" ___________________ ")
     90 		print("[ COLLOIDE MISSION! ]\n\n")
     91 	check_value.close()
     92 
     93 def scan_start():
     94 	print(Fore.RED + Style.BRIGHT + "[!] Report bugs: /MichaelDim02/colloide.py/issues \n" + Style.RESET_ALL)
     95 	print(Fore.RED + Style.BRIGHT + "[!] Press Ctrl + C to terminate the process.\n" + Style.RESET_ALL)
     96 
     97 def check_names(infile):    #Checking the path to the wordlist
     98 	if os.path.exists(infile):
     99 		if status_method:
    100 			banner()    #calls the banner function
    101 			checkasciiwolf()      #calls the sexy ASCII wolf wallpaper
    102 			scan_start()
    103 			statusfindAdmin() #calls the function that basically does the job
    104 			print(Fore.RED + Style.BRIGHT + "\n[+] Rock bottom;\n" + Style.RESET_ALL)
    105 		elif error_method:
    106 			banner()
    107 			checkasciiwolf()
    108 			scan_start()
    109 			findAdmin()
    110 			print(Fore.RED + Style.BRIGHT + "\n[+] Rock bottom;\n" + Style.RESET_ALL)
    111 	else: #in case wordlist cant be found
    112 		banner()
    113 		opts()
    114 		print(Fore.RED + Style.BRIGHT + "[-] Invalid path to the wordlist. File could not be found.\n" + Style.RESET_ALL)
    115 
    116 # THIS IS THE STATUS CODE METHOD
    117 def statusfindAdmin():
    118 	if txt:
    119 		tfilename = txt
    120 		f = open(str(tfilename) ,'w+')
    121 		f.write("Colloide %s\n" % version)
    122 		print("\n")
    123 	try:
    124 		IP = socket.gethostbyname(URL)
    125 		print(Fore.RED + Style.BRIGHT + "[!] Scanning host: ", IP, " - ", URL, "\n" + Style.RESET_ALL)
    126 		print(Fore.RED + Style.BRIGHT + "[+] Status method\n" + Style.RESET_ALL) 
    127 		if txt:
    128 			f.write("Scanning:\n")
    129 			f.write("\n")
    130 			f.write(str(URL))
    131 			f.write("\n")
    132 			f.write(str(IP))
    133 			f.write("\n\n")
    134 	except socket.gaierror:
    135 		print(Fore.RED + Style.BRIGHT + "[!] Invalid URL address. Connection could not be established;\n" + Style.RESET_ALL)
    136 		sys.exit(1)
    137 	#### 404 TESTING #### # # # # # # # #  #  #  #  #  #  #   #   #   #   #    #    #     #      #       #          # 
    138 	print(Fore.GREEN + "[-] Testing a random string;" + Style.RESET_ALL)
    139 	random_digits_for_test = ''.join(random.choice(string.ascii_lowercase + string.digits) for _ in range(10))
    140 	test_string = "colloide-" + random_digits_for_test
    141 	test_con_link = "http://" + URL + "/" + test_string
    142 	test_con_ = requests.head(test_con_link)
    143 	test_int_status_code_ = test_con_.status_code
    144 	if test_int_status_code_ != 404:
    145 		print(Fore.RED + Style.BRIGHT + "[!] Testing link " + test_con_link + " did not return 404;" + Style.RESET_ALL)
    146 		test_option_ = str.lower(input(Fore.RED + Style.BRIGHT + "[?] Do you want to Switch methods (recommended), Abort or Force? [S/A/F] " + Style.RESET_ALL))
    147 		if test_option_ == "a":
    148 			print(Fore.RED + Style.BRIGHT + "[!] Aborting...\n" + Style.RESET_ALL)
    149 			exit(0)
    150 		elif test_option_ == "f":
    151 			print(Fore.RED + Style.BRIGHT + "[!] Forcing the Status method. This might not work.\n" + Style.RESET_ALL)
    152 		elif test_option_ == "s":
    153 			print(Fore.RED + Style.BRIGHT + "[!] Switching method.\n" + Style.RESET_ALL)
    154 			findAdmin()
    155 			print(Fore.RED + Style.BRIGHT + "\n[+] Rock bottom;\n" + Style.RESET_ALL)				
    156 			exit(0)
    157 	elif test_int_status_code_ == 404:
    158 		print(Fore.GREEN + "[+] Testing link " + Style.NORMAL + test_con_link + " returned 404" + Style.NORMAL + ";" + Style.RESET_ALL)
    159 		print(Fore.GREEN + "[+] The Status method is possible; Starting now..\n" + Style.RESET_ALL)
    160 	##################### # # # # # # # #  #  #  #  #  #  #   #   #   #   #    #    #     #      #       #          #  
    161 	fi = open(links,"r");
    162 	found = 0
    163 	while (found <= int(limit)):
    164 		try:
    165 			sub_link = fi.readline().strip() #Page name
    166 			if not sub_link:
    167 				break
    168 			link = URL #website name
    169 			req_link = "http://"+link+"/"+sub_link #Final link for attempt
    170 			if directory:
    171 				req_link = "http://"+link+directory+sub_link
    172 			if agent:
    173 				user_agent = "Mozilla/5.0 (Windows NT 5.1; rv:31.0) Gecko/20100101 Firefox/31.0"
    174 				headers = { "User-Agent": user_agent}
    175 				con_ = requests.head(req_link, headers=headers)
    176 			else:
    177 				con_ = requests.head(req_link)
    178 			int_status_code_ = con_.status_code
    179 			status_code_ = str(int_status_code_)
    180 			notworking = "[ATTEMPT] - "+ status_code_ + " - " + req_link
    181 			unauth = "[ANAUTHORIZED] - "+ status_code_+ " - " + req_link
    182 			forbid = "[FORBIDDEN] - " + status_code_ + " - " + req_link
    183 			if status_code_.startswith("4"):
    184 				if ver:
    185 					if int_status_code_ == 401:
    186 						print(Fore.RED + unauth.rstrip() + Style.RESET_ALL)
    187 					elif int_status_code_ == 403:
    188 						print(Fore.RED + forbid.rstrip() + Style.RESET_ALL)
    189 					else:
    190 						print(Fore.GREEN + notworking.rstrip() + Style.RESET_ALL)
    191 					#notworking.rstrip() So it does not print lines between attempt output line
    192 					#identifies links that show up HTTP error
    193 			else:
    194 				if ver != True:
    195 					print("[+] Link Found" + " - " + status_code_ +" -"+ " -> " + req_link + "")
    196 					# if verbose if off
    197 				if ver:
    198 					print("\n[+] Link Found" + " - " + status_code_ +" -"+ " -> " + req_link + "\n")
    199 					#because in verbose mode failed attempts don't have \n at the end
    200 				found = found + 1
    201 				if txt:
    202 					f = open(str(tfilename) ,'a')
    203 					f.write(req_link + "\n")
    204 				else:
    205 					pass
    206 		except KeyboardInterrupt:
    207 			print(Fore.RED + Style.BRIGHT + "\n[!] Process has been terminated - Ctrl + C has been pressed.\n" + Style.RESET_ALL)
    208 			if txt:
    209 				print("All working pages have been saved at: ", tfilename, "\n")
    210 			sys.exit(0)
    211 	if found > int(limit):
    212 		print(Fore.RED + Style.BRIGHT + "[!] Process has been terminated due to the limitation that has been set\n" + Style.RESET_ALL)
    213 	if txt:
    214 		print("[+] All working pages have been saved at: ", tfilename, "\n")
    215 		f.close()
    216 
    217 # THIS IS THE HTTP/URL ERROR METHOD
    218 def findAdmin():
    219 	if txt:
    220 		tfilename = txt
    221 		f = open(str(tfilename) ,'w+')
    222 		f.write("MCD's Colloide %s\n" % version)
    223 		f.write("greekhacking.gr\n")
    224 		print("\n")
    225 	try:
    226 		IP = socket.gethostbyname(URL)
    227 		print(Fore.RED + Style.BRIGHT + "[!] Scanning host: ", IP, " - ", URL, "\n" + Style.RESET_ALL)
    228 		print(Fore.RED + Style.BRIGHT + "[+] URL Error method\n" + Style.RESET_ALL)
    229 		if txt:
    230 			f.write("Scanning:\n")
    231 			f.write("\n")
    232 			f.write(str(URL))
    233 			f.write("\n")
    234 			f.write(str(IP))
    235 			f.write("\n\n")
    236 	except socket.gaierror:
    237 		print(Fore.RED + Style.BRIGHT + "[!] Invalid URL address. Connection could not be established;\n" + Style.RESET_ALL)
    238 		sys.exit(1)
    239 	fi = open(links,"r");
    240 	found = 0
    241 	while (found <= int(limit)):
    242 		try:
    243 			sub_link = fi.readline() #Page name
    244 			if not sub_link:
    245 				break
    246 			link = URL #website name
    247 			req_link = "http://"+link+"/"+sub_link #Final link for attempt
    248 			if directory:
    249 				req_link = "http://"+link+directory+sub_link
    250 			if agent:
    251 				user_agent = "Mozilla/5.0 (Windows NT 5.1; rv:31.0) Gecko/20100101 Firefox/31.0"
    252 				headers = { "User-Agent": user_agent}
    253 				req = Request(req_link, headers=headers)
    254 			else:
    255 				req = Request(req_link)
    256 			if ver:
    257 				notworking = "[ATTEMPT] - " + req_link
    258 				#notworking.rstrip() So it does not print lines between attempt output line
    259 			#identifies links that show up HTTP error
    260 			try:
    261 				response = urlopen(req)
    262 			except HTTPError as e:
    263 				if ver:
    264 					print(Fore.GREEN + notworking.rstrip() + Style.RESET_ALL) 
    265 				continue
    266 			except URLError as e:
    267 				if ver:
    268 					print(Fore.GREEN + notworking.rstrip() + Style.RESET_ALL)
    269 				continue
    270 			else: #prints working link
    271 				if ver != True:
    272 					print("[+] Link Found" + " -> " + req_link + "")
    273 					# if verbose if off
    274 				if ver:
    275 					print("\n[+] Link Found" + " -> " + req_link + "")
    276 					#because in verbose mode failed attempts don't have \n at the end
    277 				found = found + 1
    278 				if txt:
    279 					f = open(str(tfilename) ,'a')
    280 					f.write(req_link + "\n")
    281 				else:
    282 					pass
    283 		except KeyboardInterrupt:
    284 			print(Fore.RED + Style.BRIGHT + "\n[!] Process has been terminated - Ctrl + C has been pressed.\n" + Style.RESET_ALL)
    285 			if txt:
    286 				print("All working pages have been saved at: ", tfilename, "\n")
    287 			sys.exit(0)
    288 	if found > int(limit):
    289 		print(Fore.RED + Style.BRIGHT + "[!] Process has been terminated due to the limitation that has been set\n" + Style.RESET_ALL)
    290 	if txt:
    291 		print("[+] All working pages have been saved at: ", tfilename, "\n")
    292 
    293 def change_ascii():
    294 	ascii_file = open(".ascii_disable_option_value.txt", "r")
    295 	checkascii = ascii_file.read(1)
    296 	ascii_file.close()
    297 	changeascii = open(".ascii_disable_option_value.txt", "w")
    298 	if checkascii == "1":
    299 		changeascii.write("0")
    300 		print("[+] ASCII enabled")
    301 	elif checkascii == "0":
    302 		changeascii.write("1")
    303 		print("[+] ASCII disabled")
    304 
    305 #Argument parsing
    306 parser = argparse.ArgumentParser()
    307 parser.add_argument("--status", action="store_true", help="Use the HTTP status code method")
    308 parser.add_argument("--urlerror", action="store_true", help="Use the HTTP/URL error method")
    309 parser.add_argument("-u", "--URL", help="The URL to the website")
    310 parser.add_argument("-f", "--folder", help="Directory to search in (must end and start with '/')")
    311 parser.add_argument("-p", "--pages", help="Path to the wordlist with the page names / links")
    312 parser.add_argument("-L", "--legals", action='store_true', help="License & legal disclaimer")
    313 parser.add_argument("-s", "--save", help="Save all working pages on a text file")
    314 parser.add_argument("-l", "--limit", help="Add limit to the pages. Integer", default="10")
    315 parser.add_argument("-v", "--verbose", help="Show all attempts", action="store_true")
    316 parser.add_argument("-a", "--agent", help="Change User-Agent headers", action="store_true")
    317 parser.add_argument("-A", "--ascii", help="Enable/Disable ASCII", action="store_true")
    318 
    319 #Declaring Argument Variables
    320 args = parser.parse_args()
    321 status_method = args.status
    322 error_method = args.urlerror
    323 links = args.pages
    324 URL = args.URL
    325 directory = args.folder
    326 agent = args.agent
    327 txt = args.save
    328 limit = args.limit
    329 ver = args.verbose
    330 ascii = args.ascii
    331 
    332 if error_method:
    333 	status_method = False
    334 elif error_method == False:
    335 	status_method = True
    336 
    337 if args.URL and args.pages:
    338 	check_names(links)
    339 elif args.legals:
    340 	banner()
    341 	legals()
    342 elif args.ascii:
    343 	change_ascii()
    344 else:
    345 	banner()
    346 	opts()
    347 print("Usage:  python colloide100.py --[method] -u [URL] -p [WORDLIST] -s [TEXT FILE] -l [NUMBER] -v -a")