1 | | - | #!/usr/bin/env python3 |
2 | | - | # |
3 | | - | # Muris Kurgas aka j0rgan |
4 | | - | # j0rgan [at] remote-exploit [dot] org |
5 | | - | # http://www.remote-exploit.org |
6 | | - | # http://www.azuzi.me |
7 | | - | # |
8 | | - | # See 'docs/LICENSE' and 'docs/README' for more information. |
9 | | - | """Common User Passwords Profiler""" |
10 | | - | __author__ = 'Muris Kurgas' |
11 | | - | __license__ = 'GPL' |
12 | | - | __version__ = '3.1.0-alpha' |
13 | | - | |
14 | | - | import argparse |
15 | | - | import configparser |
16 | | - | import csv |
17 | | - | import ftplib |
18 | | - | import functools |
19 | | - | import gzip |
20 | | - | import os |
21 | | - | import sys |
22 | | - | from urllib.request import urlopen |
23 | | - | |
24 | | - | try: |
25 | | - | import readline |
26 | | - | except ImportError: |
27 | | - | pass |
28 | | - | |
29 | | - | COW_BANNER = """ ___________ |
30 | | - | \033[07m cupp.py! \033[27m # Common |
31 | | - | \\ # User |
32 | | - | \\ \033[1;31m,__,\033[1;m # Passwords |
33 | | - | \\ \033[1;31m(\033[1;moo\033[1;31m)____\033[1;m # Profiler |
34 | | - | \033[1;31m(__) )\\ \033[1;m |
35 | | - | \033[1;31m ||--|| \033[1;m\033[05m*\033[25m\033[1;m Muris Kurgas <[email protected]> |
36 | | - | |
37 | | - | |
38 | | - | """ |
39 | | - | CONFIG = {} |
40 | | - | FTP_CONFIG = {} |
41 | | - | LEET_CONFIG = {} |
42 | | - | |
43 | | - | def main(): |
44 | | - | """Command-line interface to the cupp utility""" |
45 | | - | |
46 | | - | args = get_parser().parse_args() |
47 | | - | |
48 | | - | read_config() |
49 | | - | if not args.quiet: |
50 | | - | print(COW_BANNER) |
51 | | - | |
52 | | - | if args.version: |
53 | | - | version() |
54 | | - | elif args.interactive: |
55 | | - | interactive() |
56 | | - | elif args.download_wordlist: |
57 | | - | download_wordlist() |
58 | | - | elif args.alecto: |
59 | | - | alectodb_download() |
60 | | - | elif args.improve: |
61 | | - | improve_dictionary(args.improve) |
62 | | - | |
63 | | - | |
64 | | - | # Separate into a function for testing purposes |
65 | | - | def get_parser(): |
66 | | - | """Create and return a parser (argparse.ArgumentParser instance) for main() |
67 | | - | to use""" |
68 | | - | parser = argparse.ArgumentParser(description='Common User Passwords Profiler') |
69 | | - | group = parser.add_mutually_exclusive_group(required=True) |
70 | | - | group.add_argument('-i', '--interactive', action='store_true', |
71 | | - | help='Interactive questions for user password profiling') |
72 | | - | group.add_argument('-w', dest='improve', metavar='FILENAME', |
73 | | - | help='Use this option to improve existing dictionary,' |
74 | | - | ' or WyD.pl output to make some pwnsauce') |
75 | | - | group.add_argument('-l', dest='download_wordlist', action='store_true', |
76 | | - | help='Download huge wordlists from repository') |
77 | | - | group.add_argument('-a', dest='alecto', action='store_true', |
78 | | - | help='Parse default usernames and passwords directly' |
79 | | - | ' from Alecto DB. Project Alecto uses purified' |
80 | | - | ' databases of Phenoelit and CIRT which were merged' |
81 | | - | ' and enhanced') |
82 | | - | group.add_argument('-v', '--version', action='store_true', |
83 | | - | help='version of this program') |
84 | | - | parser.add_argument('-q', '--quiet', action='store_true', |
85 | | - | help="Quiet mode (don't print banner)") |
86 | | - | |
87 | | - | return parser |
88 | | - | |
89 | | - | |
90 | | - | def version(): |
91 | | - | """Display version and exit.""" |
92 | | - | print("\n \033[1;31m[ cupp.py ] v3.1.0-alpha\033[1;m\n") |
93 | | - | print(" * Hacked up by j0rgan - [email protected]") |
94 | | - | print(" * http://www.remote-exploit.org\n") |
95 | | - | print(" Take a look ./README.md file for more info about the program\n") |
96 | | - | sys.exit() |
97 | | - | |
98 | | - | |
99 | | - | def read_config(filename='cupp.cfg'): |
100 | | - | """Read the given configuration file and update global variables to reflect |
101 | | - | changes (CONFIG, FTP_CONFIG, LEET_CONFIG).""" |
102 | | - | #global CONFIG, FTP_CONFIG, LEET_CONFIG |
103 | | - | |
104 | | - | # Reading configuration file |
105 | | - | config = configparser.ConfigParser() |
106 | | - | config.read(filename) |
107 | | - | |
108 | | - | CONFIG.update({ |
109 | | - | 'years': config.get('years', 'years').split(','), |
110 | | - | 'chars': config.get('specialchars', 'chars').split(','), |
111 | | - | |
112 | | - | 'numfrom': config.getint('nums', 'from'), |
113 | | - | 'numto': config.getint('nums', 'to'), |
114 | | - | |
115 | | - | 'wcfrom': config.getint('nums', 'wcfrom'), |
116 | | - | 'wcto': config.getint('nums', 'wcto'), |
117 | | - | |
118 | | - | 'threshold': config.getint('nums', 'threshold'), |
119 | | - | 'alectourl': config.get('alecto', 'alectourl') |
120 | | - | }) |
121 | | - | |
122 | | - | # 1337 mode configs, well you can add more lines if you add it to the |
123 | | - | # config file too. |
124 | | - | leet = functools.partial(config.get, 'leet') |
125 | | - | LEET_CONFIG.update(dict(a=leet('a'), e=leet('e'), g=leet('g'), i=leet('i'), |
126 | | - | o=leet('o'), s=leet('s'), t=leet('t'), z=leet('z'))) |
127 | | - | |
128 | | - | ftp_config = functools.partial(config.get, 'downloader') |
129 | | - | FTP_CONFIG.update(dict(name=ftp_config('ftpname'), |
130 | | - | url=ftp_config('ftpurl'), |
131 | | - | path=ftp_config('ftppath'), |
132 | | - | user=ftp_config('ftpuser'), |
133 | | - | password=ftp_config('ftppass'))) |
134 | | - | |
135 | | - | |
136 | | - | def interactive(): |
137 | | - | """Implementation of the -i switch. Interactively question the user and |
138 | | - | create a password dictionary file based on the answer.""" |
139 | | - | print() |
140 | | - | print("[+] Insert the information about the victim to make a dictionary") |
141 | | - | print("[+] If you don't know all the info, just hit enter when asked! ;)\n") |
142 | | - | |
143 | | - | # We need some information first! |
144 | | - | |
145 | | - | name = input("First Name: ").lower().strip() |
146 | | - | while not name: |
147 | | - | print("\n[-] You must enter a name at least!", file=sys.stderr) |
148 | | - | name = input("Name: ").lower().strip() |
149 | | - | |
150 | | - | surname = input("Surname: ").lower() |
151 | | - | nick = input("Nickname: ").lower() |
152 | | - | birthdate = input("Birthdate (DDMMYYYY): ").strip() |
153 | | - | while len(birthdate) not in (0, 8): |
154 | | - | print("\n[-] You must enter 8 digits for birthday!", file=sys.stderr) |
155 | | - | birthdate = input("Birthdate (DDMMYYYY): ").strip() |
156 | | - | |
157 | | - | print("\n") |
158 | | - | |
159 | | - | wife = input("Partner's name: ").lower() |
160 | | - | wifen = input("Partner's nickname: ").lower() |
161 | | - | wifeb = input("Partner's birthdate (DDMMYYYY): ").strip() |
162 | | - | while len(wifeb) not in (0, 8): |
163 | | - | print("\n[-] You must enter 8 digits for birthday!", file=sys.stderr) |
164 | | - | wifeb = input("Partner's birthdate (DDMMYYYY): ").strip() |
165 | | - | |
166 | | - | print("\n") |
167 | | - | |
168 | | - | kid = input("Child's name: ").lower() |
169 | | - | kidn = input("Child's nickname: ").lower() |
170 | | - | kidb = input("Child's birthdate (DDMMYYYY): ").strip() |
171 | | - | while len(kidb) not in (0, 8): |
172 | | - | print("\n[-] You must enter 8 digits for birthday!", file=sys.stderr) |
173 | | - | kidb = input("Child's birthdate (DDMMYYYY): ").strip() |
174 | | - | |
175 | | - | print("\n") |
176 | | - | |
177 | | - | pet = input("Pet's name: ").lower().strip() |
178 | | - | company = input("Company name: ").lower().strip() |
179 | | - | print("\n") |
180 | | - | |
181 | | - | prompt = "Do you want to add some key words about the victim? Y/[N]: " |
182 | | - | words1 = input(prompt).lower().strip() |
183 | | - | words2 = '' |
184 | | - | if words1 == 'y': |
185 | | - | prompt = ("Please enter the words, comma-separated." |
186 | | - | " [i.e. hacker,juice,black], spaces will be removed: ") |
187 | | - | words2 = input(prompt).replace(' ', '') |
188 | | - | words = words2.split(',') |
189 | | - | |
190 | | - | spechars = [] |
191 | | - | prompt = "Do you want to add special characters at the end of words? Y/[N]: " |
192 | | - | spechars1 = input(prompt).lower() |
193 | | - | if spechars1 == "y": |
194 | | - | for spec1 in CONFIG['chars']: |
195 | | - | spechars.append(spec1) |
196 | | - | for spec2 in CONFIG['chars']: |
197 | | - | spechars.append(spec1+spec2) |
198 | | - | for spec3 in CONFIG['chars']: |
199 | | - | spechars.append(spec1+spec2+spec3) |
200 | | - | |
201 | | - | randnum = input("Do you want to add some random numbers at the end of words? Y/[N]: ").lower() |
202 | | - | leetmode = input("Leet mode? (i.e. leet = 1337) Y/[N]: ").lower().strip() |
203 | | - | |
204 | | - | |
205 | | - | print("\n[+] Now making a dictionary...") |
206 | | - | |
207 | | - | # Now me must do some string modifications |
208 | | - | |
209 | | - | # Birthdays first |
210 | | - | |
211 | | - | birthdate_yy, birthdate_yyy = birthdate[-2:], birthdate[-3:] |
212 | | - | birthdate_yyyy = birthdate[-4:] |
213 | | - | birthdate_xd, birthdate_xm = birthdate[1:2], birthdate[3:4] |
214 | | - | birthdate_dd, birthdate_mm = birthdate[:2], birthdate[2:4] |
215 | | - | |
216 | | - | wifeb_yy = wifeb[-2:] |
217 | | - | wifeb_yyy = wifeb[-3:] |
218 | | - | wifeb_yyyy = wifeb[-4:] |
219 | | - | wifeb_xd = wifeb[1:2] |
220 | | - | wifeb_xm = wifeb[3:4] |
221 | | - | wifeb_dd = wifeb[:2] |
222 | | - | wifeb_mm = wifeb[2:4] |
223 | | - | |
224 | | - | kidb_yy = kidb[-2:] |
225 | | - | kidb_yyy = kidb[-3:] |
226 | | - | kidb_yyyy = kidb[-4:] |
227 | | - | kidb_xd = kidb[1:2] |
228 | | - | kidb_xm = kidb[3:4] |
229 | | - | kidb_dd = kidb[:2] |
230 | | - | kidb_mm = kidb[2:4] |
231 | | - | |
232 | | - | |
233 | | - | # Convert first letters to uppercase... |
234 | | - | nameup = name.title() |
235 | | - | surnameup = surname.title() |
236 | | - | nickup = nick.title() |
237 | | - | wifeup = wife.title() |
238 | | - | wifenup = wifen.title() |
239 | | - | kidup = kid.title() |
240 | | - | kidnup = kidn.title() |
241 | | - | petup = pet.title() |
242 | | - | companyup = company.title() |
243 | | - | wordsup = [words1.title() for words1 in words] |
244 | | - | word = words+wordsup |
245 | | - | |
246 | | - | # reverse a name |
247 | | - | |
248 | | - | rev_name = name[::-1] |
249 | | - | rev_nameup = nameup[::-1] |
250 | | - | rev_nick = nick[::-1] |
251 | | - | rev_nickup = nickup[::-1] |
252 | | - | rev_wife = wife[::-1] |
253 | | - | rev_wifeup = wifeup[::-1] |
254 | | - | rev_kid = kid[::-1] |
255 | | - | rev_kidup = kidup[::-1] |
256 | | - | |
257 | | - | reverse = [rev_name, rev_nameup, rev_nick, rev_nickup, rev_wife, |
258 | | - | rev_wifeup, rev_kid, rev_kidup] |
259 | | - | rev_n = [rev_name, rev_nameup, rev_nick, rev_nickup] |
260 | | - | rev_w = [rev_wife, rev_wifeup] |
261 | | - | rev_k = [rev_kid, rev_kidup] |
262 | | - | # Let's do some serious work! This will be a mess of code, but who cares? :) |
263 | | - | |
264 | | - | # Birthdays combinations |
265 | | - | bds = [birthdate_yy, birthdate_yyy, birthdate_yyyy, birthdate_xd, |
266 | | - | birthdate_xm, birthdate_dd, birthdate_mm] |
267 | | - | bdss = [] |
268 | | - | |
269 | | - | for bds1 in bds: |
270 | | - | bdss.append(bds1) |
271 | | - | for bds2 in bds: |
272 | | - | if bds.index(bds1) != bds.index(bds2): |
273 | | - | bdss.append(bds1 + bds2) |
274 | | - | for bds3 in bds: |
275 | | - | condition = (bds.index(bds1) != bds.index(bds2) and |
276 | | - | bds.index(bds2) != bds.index(bds3) and |
277 | | - | bds.index(bds1) != bds.index(bds3)) |
278 | | - | if condition: |
279 | | - | bdss.append(bds1+bds2+bds3) |
280 | | - | |
281 | | - | |
282 | | - | # For a woman... |
283 | | - | wbds = [wifeb_yy, wifeb_yyy, wifeb_yyyy, wifeb_xd, wifeb_xm, wifeb_dd, wifeb_mm] |
284 | | - | wbdss = [] |
285 | | - | |
286 | | - | for wbds1 in wbds: |
287 | | - | wbdss.append(wbds1) |
288 | | - | for wbds2 in wbds: |
289 | | - | if wbds.index(wbds1) != wbds.index(wbds2): |
290 | | - | wbdss.append(wbds1+wbds2) |
291 | | - | for wbds3 in wbds: |
292 | | - | condition = (wbds.index(wbds1) != wbds.index(wbds2) and |
293 | | - | wbds.index(wbds2) != wbds.index(wbds3) and |
294 | | - | wbds.index(wbds1) != wbds.index(wbds3)) |
295 | | - | if condition: |
296 | | - | wbdss.append(wbds1+wbds2+wbds3) |
297 | | - | |
298 | | - | |
299 | | - | # and a child... |
300 | | - | kbds = [kidb_yy, kidb_yyy, kidb_yyyy, kidb_xd, kidb_xm, kidb_dd, kidb_mm] |
301 | | - | kbdss = [] |
302 | | - | |
303 | | - | for kbds1 in kbds: |
304 | | - | kbdss.append(kbds1) |
305 | | - | for kbds2 in kbds: |
306 | | - | if kbds.index(kbds1) != kbds.index(kbds2): |
307 | | - | kbdss.append(kbds1+kbds2) |
308 | | - | for kbds3 in kbds: |
309 | | - | condition = (kbds.index(kbds1) != kbds.index(kbds2) and |
310 | | - | kbds.index(kbds2) != kbds.index(kbds3) and |
311 | | - | kbds.index(kbds1) != kbds.index(kbds3)) |
312 | | - | if condition: |
313 | | - | kbdss.append(kbds1+kbds2+kbds3) |
314 | | - | |
315 | | - | # string combinations |
316 | | - | kombinaac = [pet, petup, company, companyup] |
317 | | - | kombina = [name, surname, nick, nameup, surnameup, nickup] |
318 | | - | kombinaw = [wife, wifen, wifeup, wifenup, surname, surnameup] |
319 | | - | kombinak = [kid, kidn, kidup, kidnup, surname, surnameup] |
320 | | - | |
321 | | - | kombinaa = [] |
322 | | - | for kombina1 in kombina: |
323 | | - | kombinaa.append(kombina1) |
324 | | - | for kombina2 in kombina: |
325 | | - | condition = (kombina.index(kombina1) != kombina.index(kombina2) and |
326 | | - | kombina.index(kombina1.title()) != kombina.index(kombina2.title())) |
327 | | - | if condition: |
328 | | - | kombinaa.append(kombina1+kombina2) |
329 | | - | |
330 | | - | kombinaaw = [] |
331 | | - | for kombina1 in kombinaw: |
332 | | - | kombinaaw.append(kombina1) |
333 | | - | for kombina2 in kombinaw: |
334 | | - | condition = (kombinaw.index(kombina1) != kombinaw.index(kombina2) and |
335 | | - | kombinaw.index(kombina1.title()) != kombinaw.index(kombina2.title())) |
336 | | - | if condition: |
337 | | - | kombinaaw.append(kombina1+kombina2) |
338 | | - | |
339 | | - | kombinaak = [] |
340 | | - | for kombina1 in kombinak: |
341 | | - | kombinaak.append(kombina1) |
342 | | - | for kombina2 in kombinak: |
343 | | - | condition = (kombinak.index(kombina1) != kombinak.index(kombina2) and |
344 | | - | kombinak.index(kombina1.title()) != kombinak.index(kombina2.title())) |
345 | | - | if condition: |
346 | | - | kombinaak.append(kombina1+kombina2) |
347 | | - | |
348 | | - | |
349 | | - | komb1 = list(komb(kombinaa, bdss)) |
350 | | - | komb2 = list(komb(kombinaaw, wbdss)) |
351 | | - | komb3 = list(komb(kombinaak, kbdss)) |
352 | | - | komb4 = list(komb(kombinaa, CONFIG['years'])) |
353 | | - | komb5 = list(komb(kombinaac, CONFIG['years'])) |
354 | | - | komb6 = list(komb(kombinaaw, CONFIG['years'])) |
355 | | - | komb7 = list(komb(kombinaak, CONFIG['years'])) |
356 | | - | komb8 = list(komb(word, bdss)) |
357 | | - | komb9 = list(komb(word, wbdss)) |
358 | | - | komb10 = list(komb(word, kbdss)) |
359 | | - | komb11 = list(komb(word, CONFIG['years'])) |
360 | | - | komb12 = komb13 = komb14 = komb15 = komb16 = komb21 = [] |
361 | | - | if randnum == "y": |
362 | | - | komb12 = list(concats(word, CONFIG['numfrom'], CONFIG['numto'])) |
363 | | - | komb13 = list(concats(kombinaa, CONFIG['numfrom'], CONFIG['numto'])) |
364 | | - | komb14 = list(concats(kombinaac, CONFIG['numfrom'], CONFIG['numto'])) |
365 | | - | komb15 = list(concats(kombinaaw, CONFIG['numfrom'], CONFIG['numto'])) |
366 | | - | komb16 = list(concats(kombinaak, CONFIG['numfrom'], CONFIG['numto'])) |
367 | | - | komb21 = list(concats(reverse, CONFIG['numfrom'], CONFIG['numto'])) |
368 | | - | komb17 = list(komb(reverse, CONFIG['years'])) |
369 | | - | komb18 = list(komb(rev_w, wbdss)) |
370 | | - | komb19 = list(komb(rev_k, kbdss)) |
371 | | - | komb20 = list(komb(rev_n, bdss)) |
372 | | - | komb001 = komb002 = komb003 = komb004 = komb005 = komb006 = [] |
373 | | - | if spechars1 == "y": |
374 | | - | komb001 = list(komb(kombinaa, spechars)) |
375 | | - | komb002 = list(komb(kombinaac, spechars)) |
376 | | - | komb003 = list(komb(kombinaaw, spechars)) |
377 | | - | komb004 = list(komb(kombinaak, spechars)) |
378 | | - | komb005 = list(komb(word, spechars)) |
379 | | - | komb006 = list(komb(reverse, spechars)) |
380 | | - | |
381 | | - | print("[+] Sorting list and removing duplicates...") |
382 | | - | |
383 | | - | sets = [set(komb1), set(komb2), set(komb3), set(komb4), set(komb5), |
384 | | - | set(komb6), set(komb7), set(komb8), set(komb9), set(komb10), |
385 | | - | set(komb11), set(komb12), set(komb13), set(komb14), set(komb15), |
386 | | - | set(komb16), set(komb17), set(komb18), set(komb19), set(komb20), |
387 | | - | set(komb21), set(kombinaa), set(kombinaac), set(kombinaaw), |
388 | | - | set(kombinaak), set(word), set(komb001), set(komb002), set(komb003), |
389 | | - | set(komb004), set(komb005), set(komb006)] |
390 | | - | |
391 | | - | uniqset = set() |
392 | | - | for s in sets: |
393 | | - | uniqset.update(s) |
394 | | - | |
395 | | - | uniqlist = bdss + wbdss + kbdss + reverse + list(uniqset) |
396 | | - | |
397 | | - | unique_lista = sorted(set(uniqlist)) |
398 | | - | unique_leet = [] |
399 | | - | if leetmode == "y": |
400 | | - | for x in unique_lista: |
401 | | - | unique_leet.append(leet_replace(x)) |
402 | | - | |
403 | | - | unique_list = unique_lista + unique_leet |
404 | | - | |
405 | | - | unique_list_finished = [x for x in unique_list if CONFIG['wcfrom'] < len(x) < CONFIG['wcto']] |
406 | | - | unique_list_finished.sort() |
407 | | - | |
408 | | - | with open(name + '.txt', 'w') as f: |
409 | | - | f.write(os.linesep.join(unique_list_finished)) |
410 | | - | with open(name + '.txt') as f: |
411 | | - | lines = len(list(f)) # shorter, but possibly more memory expensive |
412 | | - | |
413 | | - | message = ("[+] Saving dictionary to \033[1;31m%s.txt\033[1;m, counting" |
414 | | - | " \033[1;31m%i\033[1;m words.") |
415 | | - | print(message % (name, lines)) |
416 | | - | message = ("[+] Now load your pistolero with \033[1;31m%s.txt\033[1;m and" |
417 | | - | " shoot! Good luck!") |
418 | | - | print(message % name) |
419 | | - | sys.exit() |
420 | | - | |
421 | | - | |
422 | | - | def download_ftp_files(ftp_dir, *filenames): |
423 | | - | """Helper function for download_wordlist(). Download the given files from |
424 | | - | the ftp directory.""" |
425 | | - | |
426 | | - | print("\n[+] connecting...\n") |
427 | | - | ftp = ftplib.FTP(FTP_CONFIG['url'], FTP_CONFIG['user'], FTP_CONFIG['password']) |
428 | | - | #ftp.login(FTP_CONFIG['user'], FTP_CONFIG['password']) |
429 | | - | ftp.cwd(FTP_CONFIG['path']) |
430 | | - | ftp.cwd(ftp_dir) |
431 | | - | dir_prefix = 'dictionaries/%s/' % ftp_dir |
432 | | - | |
433 | | - | if not os.path.isdir(dir_prefix): |
434 | | - | os.mkdir(dir_prefix) |
435 | | - | |
436 | | - | def handle_download(target, block): |
437 | | - | "Callback for retrbinary. Prints a progress bar as well." |
438 | | - | target.write(block) |
439 | | - | print('.', end=' ') |
440 | | - | |
441 | | - | for filename in filenames: |
442 | | - | with open(dir_prefix + filename, 'wb') as outfile: |
443 | | - | print("\n[+] downloading %s..." % filename) |
444 | | - | callback = functools.partial(handle_download, outfile) |
445 | | - | ftp.retrbinary('RETR %s' % filename, callback) |
446 | | - | print(' done.') |
447 | | - | |
448 | | - | print('[+] file(s) saved to %s' % dir_prefix) |
449 | | - | ftp.quit() |
450 | | - | |
451 | | - | |
452 | | - | def download_wordlist(): |
453 | | - | """Implementation of -l switch. Download wordlists from ftp repository as |
454 | | - | defined in the configuration file.""" |
455 | | - | |
456 | | - | if not os.path.isdir('dictionaries'): |
457 | | - | os.mkdir('dictionaries') |
458 | | - | |
459 | | - | menu = """ |
460 | | - | 1 Moby 14 french 27 places |
461 | | - | 2 afrikaans 15 german 28 polish |
462 | | - | 3 american 16 hindi 39 random |
463 | | - | 4 aussie 17 hungarian 30 religion |
464 | | - | 5 chinese 18 italian 31 russian |
465 | | - | 6 computer 19 japanese 32 science |
466 | | - | 7 croatian 20 latin 33 spanish |
467 | | - | 8 czech 21 literature 34 swahili |
468 | | - | 9 danish 22 movieTV 35 swedish |
469 | | - | 10 databases 23 music 36 turkish |
470 | | - | 11 dictionaries 24 names 37 yiddish |
471 | | - | 12 dutch 25 net 38 exit program |
472 | | - | 13 finnish 26 norwegian |
473 | | - | |
474 | | - | """ |
475 | | - | print("\n Choose the section you want to download:\n") |
476 | | - | print(menu) |
477 | | - | print("\n Files will be downloaded from %s repository" % FTP_CONFIG['name']) |
478 | | - | print("\n Tip: After downloading wordlist, you can improve it with -w option\n") |
479 | | - | |
480 | | - | option = input("Enter number: ") |
481 | | - | while not option.isdigit() or int(option) > 38: |
482 | | - | print("\n[-] Invalid choice.", file=sys.stderr) |
483 | | - | option = input("Enter number: ") |
484 | | - | |
485 | | - | option = int(option) |
486 | | - | |
487 | | - | if option == 38: |
488 | | - | print('[-] Leaving.', file=sys.stderr) |
489 | | - | sys.exit() |
490 | | - | |
491 | | - | # integer indexed dict to maintain consistency with the menu shown to the |
492 | | - | # user. plus, easy to inadvertently unorder things up with lists |
493 | | - | arguments = { # the first items of the tuples are the ftp directories. |
494 | | - | # Do Not Change. |
495 | | - | 1: ('Moby', 'mhyph.tar.gz', 'mlang.tar.gz', 'moby.tar.gz', |
496 | | - | 'mpos.tar.gz', 'mpron.tar.gz', 'mthes.tar.gz', 'mwords.tar.gz'), |
497 | | - | 2: ('afrikaans', 'afr_dbf.zip'), |
498 | | - | 3: ('american', 'dic-0294.tar.gz'), |
499 | | - | 4: ('aussie', 'oz.gz'), |
500 | | - | 5: ('chinese', 'chinese.gz'), |
501 | | - | 6: ('computer', 'Domains.gz', 'Dosref.gz', 'Ftpsites.gz', 'Jargon.gz', |
502 | | - | 'common-passwords.txt.gz', 'etc-hosts.gz', 'foldoc.gz', |
503 | | - | 'language-list.gz', 'unix.gz'), |
504 | | - | 7: ('croatian', 'croatian.gz'), |
505 | | - | 8: ('czech', 'czech-wordlist-ascii-cstug-novak.gz'), |
506 | | - | 9: ('danish', 'danish.words.gz', 'dansk.zip'), |
507 | | - | 10: ('databases', 'acronyms.gz', 'att800.gz', |
508 | | - | 'computer-companies.gz', 'world_heritage.gz'), |
509 | | - | 11: ('dictionaries', 'Antworth.gz', 'CRL.words.gz', 'Roget.words.gz', |
510 | | - | 'Unabr.dict.gz', 'Unix.dict.gz', 'englex-dict.gz', |
511 | | - | 'knuth_britsh.gz', 'knuth_words.gz', 'pocket-dic.gz', |
512 | | - | 'shakesp-glossary.gz', 'special.eng.gz', 'words-english.gz'), |
513 | | - | 12: ('dutch', 'words.dutch.gz'), |
514 | | - | 13: ('finnish', 'finnish.gz', 'firstnames.finnish.gz', 'words.finnish.FAQ.gz'), |
515 | | - | 14: ('french', 'dico.gz'), |
516 | | - | 15: ('german', 'deutsch.dic.gz', 'germanl.gz', 'words.german.gz'), |
517 | | - | 16: ('hindi', 'hindu-names.gz'), |
518 | | - | 17: ('hungarian', 'hungarian.gz'), |
519 | | - | 18: ('italian', 'words.italian.gz'), |
520 | | - | 19: ('japanese', 'words.japanese.gz'), |
521 | | - | 20: ('latin', 'wordlist.aug.gz'), |
522 | | - | 21: ('literature', 'LCarrol.gz', 'Paradise.Lost.gz', 'aeneid.gz', |
523 | | - | 'arthur.gz', 'cartoon.gz', 'cartoons-olivier.gz', 'charlemagne.gz', |
524 | | - | 'fable.gz', 'iliad.gz', 'myths-legends.gz', 'odyssey.gz', 'sf.gz', |
525 | | - | 'shakespeare.gz', 'tolkien.words.gz'), |
526 | | - | 22: ('movieTV', 'Movies.gz', 'Python.gz', 'Trek.gz'), |
527 | | - | 23: ('music', 'music-classical.gz', 'music-country.gz', 'music-jazz.gz', |
528 | | - | 'music-other.gz', 'music-rock.gz', 'music-shows.gz', |
529 | | - | 'rock-groups.gz'), |
530 | | - | 24: ('names', 'ASSurnames.gz' 'Congress.gz', 'Family-Names.gz', |
531 | | - | 'Given-Names.gz', 'actor-givenname.gz', 'actor-surname.gz', |
532 | | - | 'cis-givenname.gz', 'cis-surname.gz', 'crl-names.gz', 'famous.gz', |
533 | | - | 'fast-names.gz', 'female-names-kantr.gz', 'female-names.gz', |
534 | | - | 'givennames-ol.gz', 'male-names.gz', 'movie-characters.gz', |
535 | | - | 'names.french.gz', 'names.hp.gz', 'other-names.gz', |
536 | | - | 'shakesp-names.gz', 'surnames-ol.gz', 'surnames.finnish.gz', |
537 | | - | 'usenet-names.gz'), |
538 | | - | 25: ('net', 'hosts-txt.gz', 'inet-machines.gz', 'usenet-loginids.gz', |
539 | | - | 'usenet-machines.gz', 'uunet-sites.gz'), |
540 | | - | 26: ('norwegian', 'words.norwegian.gz'), |
541 | | - | 27: ('places', 'Colleges.gz', 'US-counties.gz', 'World.factbook.gz', |
542 | | - | 'Zipcodes.gz', 'places.gz'), |
543 | | - | 28: ('polish', 'words.polish.gz'), |
544 | | - | 29: ('random', 'Ethnologue.gz', 'abbr.gz', 'chars.gz', 'dogs.gz', |
545 | | - | 'drugs.gz', 'junk.gz', 'numbers.gz', 'phrases.gz', 'sports.gz', |
546 | | - | 'statistics.gz'), |
547 | | - | 30: ('religion', 'Koran.gz', 'kjbible.gz', 'norse.gz'), |
548 | | - | 31: ('russian', 'russian.lst.gz', 'russian_words.koi8.gz'), |
549 | | - | 32: ('science', 'Acr-diagnosis.gz', 'Algae.gz', 'Bacteria.gz', |
550 | | - | 'Fungi.gz', 'Microalgae.gz', 'Viruses.gz', 'asteroids.gz', |
551 | | - | 'biology.gz', 'tech.gz'), |
552 | | - | 33: ('spanish', 'words.spanish.gz'), |
553 | | - | 34: ('swahili', 'swahili.gz'), |
554 | | - | 35: ('swedish', 'words.swedish.gz'), |
555 | | - | 36: ('turkish', 'turkish.dict.gz'), |
556 | | - | 37: ('yiddish', 'yiddish.gz'), |
557 | | - | } |
558 | | - | |
559 | | - | download_ftp_files(*(arguments[option])) |
560 | | - | |
561 | | - | |
562 | | - | def alectodb_download(): |
563 | | - | """Download csv from alectodb and save into local file as a list of |
564 | | - | usernames and passwords""" |
565 | | - | url = CONFIG['alectourl'] |
566 | | - | local_file_name = url.split('/')[-1] |
567 | | - | |
568 | | - | print("\n[+] Checking if alectodb is not present...") |
569 | | - | if not os.path.isfile('alectodb.csv.gz'): |
570 | | - | print("[+] Downloading alectodb.csv.gz...") |
571 | | - | web_file = urlopen(url) |
572 | | - | local_file = open(local_file_name, 'w') |
573 | | - | local_file.write(web_file.read()) |
574 | | - | web_file.close() |
575 | | - | local_file.close() |
576 | | - | |
577 | | - | f = gzip.open(local_file_name, 'rb') |
578 | | - | |
579 | | - | data = csv.reader(f) |
580 | | - | |
581 | | - | usernames = [] |
582 | | - | passwords = [] |
583 | | - | for row in data: |
584 | | - | usernames.append(row[5]) |
585 | | - | passwords.append(row[6]) |
586 | | - | gus = sorted(set(usernames)) |
587 | | - | gpa = sorted(set(passwords)) |
588 | | - | f.close() |
589 | | - | |
590 | | - | print("\n[+] Exporting to alectodb-usernames.txt and alectodb-passwords.txt") |
591 | | - | with open('alectodb-usernames.txt', 'w') as usernames_file: |
592 | | - | usernames_file.write(os.linesep.join(gus)) |
593 | | - | |
594 | | - | with open('alectodb-passwords.txt', 'w') as passwords_file: |
595 | | - | passwords_file.write(os.linesep.join(gpa)) |
596 | | - | print("[+] Done.") |
597 | | - | |
598 | | - | |
599 | | - | def concats(seq, start, stop): |
600 | | - | "Helper function for concatenations." |
601 | | - | for s in seq: |
602 | | - | for num in range(start, stop): |
603 | | - | yield s + str(num) |
604 | | - | |
605 | | - | |
606 | | - | def komb(seq, start): |
607 | | - | "Helper function for sorting and making combinations." |
608 | | - | for mystr in seq: |
609 | | - | for mystr1 in start: |
610 | | - | yield mystr + mystr1 |
611 | | - | |
612 | | - | def leet_replace(s): |
613 | | - | """Replace all instances of a character in a string with their 1337 |
614 | | - | counterpart as defined in LEET_CONFIG""" |
615 | | - | for c, n in LEET_CONFIG.items(): |
616 | | - | s = s.replace(c, n) |
617 | | - | return s |
618 | | - | |
619 | | - | |
620 | | - | def improve_dictionary(filename): |
621 | | - | """Implementation of the -w option. Improve a dictionary by |
622 | | - | interactively questioning the user.""" |
623 | | - | with open(filename) as fajl: |
624 | | - | listic = fajl.readlines() |
625 | | - | linije = len(listic) |
626 | | - | |
627 | | - | listica = [] |
628 | | - | for x in listic: |
629 | | - | listica.extend(x.split()) |
630 | | - | |
631 | | - | print() |
632 | | - | print(" *************************************************") |
633 | | - | print(" * \033[1;31mWARNING!!!\033[1;m *") |
634 | | - | print(" * Using large wordlists in some *") |
635 | | - | print(" * options bellow is NOT recommended! *") |
636 | | - | print(" *************************************************\n") |
637 | | - | |
638 | | - | prompt = "Do you want to concatenate all words from wordlist? Y/[N]: " |
639 | | - | conts = input(prompt).lower().strip() |
640 | | - | |
641 | | - | if conts == 'y' and linije > CONFIG['threshold']: |
642 | | - | print("\n[-] Maximum number of words for concatenation is %i" % CONFIG['threshold']) |
643 | | - | print("[-] Check configuration file for increasing this number.\n") |
644 | | - | conts = input(prompt).lower().strip() |
645 | | - | cont = [] |
646 | | - | if conts == 'y': |
647 | | - | for cont1 in listica: |
648 | | - | for cont2 in listica: |
649 | | - | if listica.index(cont1) != listica.index(cont2): |
650 | | - | cont.append(cont1+cont2) |
651 | | - | |
652 | | - | spechars = [] |
653 | | - | prompt = "Do you want to add special chars at the end of words? Y/[N]: " |
654 | | - | spechars1 = input(prompt).lower() |
655 | | - | if spechars1 == "y": |
656 | | - | for spec1 in CONFIG['chars']: |
657 | | - | spechars.append(spec1) |
658 | | - | for spec2 in CONFIG['chars']: |
659 | | - | spechars.append(spec1+spec2) |
660 | | - | for spec3 in CONFIG['chars']: |
661 | | - | spechars.append(spec1+spec2+spec3) |
662 | | - | |
663 | | - | prompt = "Do you want to add some random numbers at the end of words? Y/[N]: " |
664 | | - | randnum = input(prompt).lower().strip() |
665 | | - | leetmode = input("Leet mode? (i.e. leet = 1337) Y/[N]: ").lower().strip() |
666 | | - | |
667 | | - | |
668 | | - | kombinacija1 = list(komb(listica, CONFIG['years'])) |
669 | | - | kombinacija2 = [] |
670 | | - | if conts == "y": |
671 | | - | kombinacija2 = list(komb(cont, CONFIG['years'])) |
672 | | - | kombinacija3 = [] |
673 | | - | kombinacija4 = [] |
674 | | - | if spechars1 == "y": |
675 | | - | kombinacija3 = list(komb(listica, spechars)) |
676 | | - | if conts == "y": |
677 | | - | kombinacija4 = list(komb(cont, spechars)) |
678 | | - | kombinacija5 = [] |
679 | | - | kombinacija6 = [] |
680 | | - | if randnum == "y": |
681 | | - | kombinacija5 = list(concats(listica, CONFIG['numfrom'], CONFIG['numto'])) |
682 | | - | if conts == "y": |
683 | | - | kombinacija6 = list(concats(cont, CONFIG['numfrom'], CONFIG['numto'])) |
684 | | - | |
685 | | - | print("\n[+] Now making a dictionary...") |
686 | | - | |
687 | | - | print("[+] Sorting list and removing duplicates...") |
688 | | - | |
689 | | - | sets = [set(kombinacija1), set(kombinacija2), set(kombinacija3), |
690 | | - | set(kombinacija4), set(kombinacija5), set(kombinacija6), |
691 | | - | set(listica), set(cont)] |
692 | | - | |
693 | | - | uniqset = set() |
694 | | - | for s in sets: |
695 | | - | uniqset.update(s) |
696 | | - | |
697 | | - | unique_lista = sorted(uniqset) |
698 | | - | unique_leet = [] |
699 | | - | if leetmode == "y": |
700 | | - | for x in unique_lista: |
701 | | - | unique_leet.append(leet_replace(x)) |
702 | | - | |
703 | | - | unique_list = unique_lista + unique_leet |
704 | | - | |
705 | | - | unique_list_finished = [x for x in unique_list if CONFIG['wcfrom'] < len(x) < CONFIG['wcto']] |
706 | | - | unique_list_finished.sort() |
707 | | - | |
708 | | - | with open(filename+'.cupp.txt', 'w') as f: |
709 | | - | f.write(os.linesep.join(unique_list_finished)) |
710 | | - | |
711 | | - | with open(filename+'.cupp.txt') as f: |
712 | | - | lines = len(list(f)) |
713 | | - | |
714 | | - | message = ("[+] Saving dictionary to \033[1;31m%s.cupp.txt\033[1;m, counting" |
715 | | - | " \033[1;31m%i words.\033[1;m") |
716 | | - | print(message % (filename, lines)) |
717 | | - | message = ("[+] Now load your pistolero with \033[1;31m%s.cupp.txt\033[1;m" |
718 | | - | " and shoot! Good luck!") |
719 | | - | print(message % filename) |
720 | | - | |
721 | | - | |
722 | | - | if __name__ == '__main__': |
723 | | - | main() |
724 | | - | |