Imported Upstream version 3.1
Devon Kearns
9 years ago
0 | Pipal, Password Analyser | |
1 | ======================== | |
2 | ||
3 | Copyright(c) 2012, Robin Wood <[email protected]> | |
4 | ||
5 | On most internal pen-tests I do I generally manage to get a password dump from | |
6 | the DC. To do some basic analysis on this I wrote Counter and since I originally | |
7 | released it I've made quite a few mods to it to generate extra stats that are | |
8 | useful when doing reports to management. | |
9 | ||
10 | Recently a good friend, n00bz, asked on Twitter if anyone had a tool that he | |
11 | could use to analyse some passwords he had. I pointed him to Counter and said if | |
12 | he had any suggestions for additions to let me know. He did just that and over | |
13 | the last month between us we have come up with a load of new features which we | |
14 | both think will help anyone with a large dump of cracked passwords to analyse. | |
15 | We also got some input from well known password analysts Matt Weir and Martin | |
16 | Bos who I'd like to give a big thanks to. | |
17 | ||
18 | I have to point out before going on, all this tool does is to give you the stats | |
19 | and the information to help you analyse the passwords. The real work is done by | |
20 | you in interpreting the results, I give you the numbers, you tell the story. | |
21 | ||
22 | Seeing as there have been so many changes to the underlying code I also decided | |
23 | to change the name (see below) and do a full new release. | |
24 | ||
25 | So, what does this new version do? The best way to describe it is to see some | |
26 | examples so go to the Pipal project page at www.digininja.org/projects/pipal.php | |
27 | for a full walk through of a sample analysis. | |
28 | ||
29 | Install / Usage | |
30 | =============== | |
31 | The app will only work with Ruby 1.9.x, if you try to run it in any previous | |
32 | versions you will get a warning and the app will close. | |
33 | ||
34 | Pipal is completely self contained and requires no gems installing so should | |
35 | work on any vanilla Ruby install. | |
36 | ||
37 | Usage is fairly simple, -? will give you full instructions: | |
38 | ||
39 | $ ./pipal.rb -? | |
40 | pipal 2.0 Robin Wood ([email protected]) (www.digininja.org) | |
41 | ||
42 | Usage: pipal [OPTION] ... FILENAME | |
43 | --help, -h: show help | |
44 | --top, -t X: show the top X results (default 10) | |
45 | --output, -o : output to file | |
46 | --external, -e : external file to compare words against | |
47 | --gkey <Google Maps API key>: to allow zip code lookups (optional) | |
48 | ||
49 | FILENAME: The file to count | |
50 | ||
51 | When you run the app you'll get a nice progress bar which gives you a rough idea | |
52 | of how long the app will take to run. If you want to stop it at any point | |
53 | hitting ctrl-c will stop the parsing and will dump out the stats generated so | |
54 | far. | |
55 | ||
56 | The progress bar is based on a line count from the file which it gets this using | |
57 | the wc command. If it can't find wc it will make a guess at the number of lines | |
58 | based on the file size and an average line length of 8 bytes so the progress bar | |
59 | may not be fully accurate but should still give you an idea. | |
60 | ||
61 | The Google Maps API key is supposed to be used by Google to only allow access to | |
62 | their API to registered users. I assumed this was true and registered for a key | |
63 | but in putting together this release I found that it will take any value and | |
64 | still do the look up. This may be a bug at the Google end or deliberate and may | |
65 | change any any time so I'd suggest grabbing a key just in case. To use it you | |
66 | can either edit the script and put the key into the constant on line 35 or you | |
67 | can pass it on the command line every time. If you are going to hope that you | |
68 | don't need a valid key then just put X in as the value as without something | |
69 | Pipal won't try to perform a look up. | |
70 | ||
71 | Version History | |
72 | =============== | |
73 | ||
74 | Version 2 - Two big changes, the first a massive speed increase. This patch was | |
75 | submitted by Stefan Venken who said a small mention would be good enough, I want | |
76 | to give him a big mention. Running through the LinkedIn lists would have taken | |
77 | many many hours on version 1, version 2 went through 3.5 million records in | |
78 | about 15 minutes. Thank you. | |
79 | ||
80 | Second change is the addition of US area and zip code lookups. This little | |
81 | feature gives some interesting geographical data when ran across password lists | |
82 | originating in the US. The best example I've seen of this is the dump from the | |
83 | Military Singles site where some passwords could be obviously seen to be grouped | |
84 | around US military bases. People in the UK don't have the same relationship with | |
85 | phone numbers so I know this won't work here but if anyone can suggest any other | |
86 | areas where this might be useful then I'll look at building in some kind of | |
87 | location awareness feature so you can specify the source of the list and get | |
88 | results customized to the correct area or just run every area and see if a | |
89 | pattern emerges. | |
90 | ||
91 | A non-code-base change is for version 2 is the move from hosting the code myself | |
92 | to github. This is my first github hosted project so I may get things wrong, if | |
93 | I do, sorry. A number of people asked how they could submit patches so this | |
94 | seems like the best way to do it, lets hope it works out. | |
95 | ||
96 | Version 1 - Was a proof of concept, written fairly in a fairly verbose way so not | |
97 | very optimised. Took off way more than I expected it would and gathered a lot of | |
98 | community support. | |
99 | ||
100 | Feedback/Todo | |
101 | ============= | |
102 | ||
103 | If you have a read through the source for Pipal you'll notice that it isn't very | |
104 | efficient at the moment. The way I built it was to try to keep each chunk of | |
105 | stats together as a distinct group so that if I wanted to add a new, similar, | |
106 | group then it was easy to just copy and paste the group. Now I've got a working | |
107 | app and I know roughly what I need in the different group types I've got an idea | |
108 | on how to rewrite the main parser to make it much more efficient and hopefully | |
109 | multi-threaded which should speed up the processing by a lot for large lists. | |
110 | ||
111 | I could have made these changes before releasing version 1.0 but I figured | |
112 | before I do I want to get as much feedback as possible from users about the | |
113 | features already implemented and about any new features they would like to see | |
114 | so that I can bundle all these together into version 2. So, please get in touch | |
115 | if there is a set of stats that you'd like to see included. | |
116 | ||
117 | One other thing I know needs fixing, Pipal doesn't handle certain character | |
118 | encodings very well. If anyone knows how to correctly deal with different | |
119 | encoding types, especially with regards to regular expressions, please let me | |
120 | know. | |
121 | ||
122 | Licence | |
123 | ======= | |
124 | This project released under the Creative Commons Attribution-Share Alike 2.0 | |
125 | UK: England & Wales | |
126 | ||
127 | ( http://creativecommons.org/licenses/by-sa/2.0/uk/ ) |
0 | Pipal, Password Analyser | |
1 | ======================== | |
2 | ||
3 | Copyright(c) 2014, Robin Wood <[email protected]> | |
4 | ||
5 | On most internal pen-tests I do, I generally manage to get a password dump from | |
6 | the DC. To do some basic analysis on this I wrote Counter and since I originally | |
7 | released it I've made quite a few mods to it to generate extra stats that are | |
8 | useful when doing reports to management. | |
9 | ||
10 | Recently a good friend, n00bz, asked on Twitter if anyone had a tool that he | |
11 | could use to analyse some passwords he had. I pointed him to Counter and said if | |
12 | he had any suggestions for additions to let me know. He did just that and over | |
13 | the last month between us we have come up with a load of new features which we | |
14 | both think will help anyone with a large dump of cracked passwords to analyse. | |
15 | We also got some input from well known password analysts | |
16 | [Matt Weir](http://reusablesec.blogspot.com/) and Martin Bos who I'd like to give | |
17 | a big thanks to. | |
18 | ||
19 | I have to point out before going on, all this tool does is to give you the stats | |
20 | and the information to help you analyse the passwords. The real work is done by | |
21 | you in interpreting the results, I give you the numbers, you tell the story. | |
22 | ||
23 | Seeing as there have been so many changes to the underlying code I also decided | |
24 | to change the name (see below) and do a full new release. | |
25 | ||
26 | So, what does this new version do? The best way to describe it is to see some | |
27 | examples so go to the [Pipal project page](http://digi.ninja/projects/pipal.php) | |
28 | for a full walk through of a sample analysis. | |
29 | ||
30 | Install / Usage | |
31 | =============== | |
32 | ||
33 | The app will only work with `Ruby 1.9.x`, if you try to run it in any previous | |
34 | versions you will get a warning and the app will close. | |
35 | ||
36 | Pipal is completely self contained and requires no gems installing so should | |
37 | work on any vanilla Ruby install. | |
38 | ||
39 | Usage is fairly simple, -? will give you full instructions: | |
40 | ||
41 | ```ruby | |
42 | $ ./pipal.rb -? | |
43 | pipal 2.0 Robin Wood ([email protected]) (http://digi.ninja) | |
44 | ||
45 | Usage: pipal [OPTION] ... FILENAME | |
46 | --help, -h: show help | |
47 | --top, -t X: show the top X results (default 10) | |
48 | --output, -o : output to file | |
49 | --external, -e : external file to compare words against | |
50 | --gkey <Google Maps API key>: to allow zip code lookups (optional) | |
51 | ||
52 | FILENAME: The file to count | |
53 | ``` | |
54 | ||
55 | When you run the app you'll get a nice progress bar which gives you a rough idea | |
56 | of how long the app will take to run. If you want to stop it at any point | |
57 | hitting Ctrl-c will stop the parsing and will dump out the stats generated so | |
58 | far. | |
59 | ||
60 | The progress bar is based on a line count from the file which it gets this using | |
61 | the wc command. If it can't find wc it will make a guess at the number of lines | |
62 | based on the file size and an average line length of 8 bytes so the progress bar | |
63 | may not be fully accurate but should still give you an idea. | |
64 | ||
65 | [The Google Maps API](https://developers.google.com/maps/) key is supposed to be | |
66 | used by Google to only allow access to their API to registered users. | |
67 | I assumed this was true and registered for a key | |
68 | but in putting together this release I found that it will take any value and | |
69 | still do the look up. This may be a bug at the Google end or deliberate and may | |
70 | change any any time so I'd suggest grabbing a key just in case. To use it you | |
71 | can either edit the script and put the key into the constant on line 35 or you | |
72 | can pass it on the command line every time. If you are going to hope that you | |
73 | don't need a valid key then just put X in as the value as without something | |
74 | Pipal won't try to perform a look up. | |
75 | ||
76 | Version History | |
77 | =============== | |
78 | ||
79 | Version 2 - Two big changes, the first a massive speed increase. This patch was | |
80 | submitted by Stefan Venken who said a small mention would be good enough, I want | |
81 | to give him a big mention. Running through the LinkedIn lists would have taken | |
82 | many many hours on version 1, version 2 went through 3.5 million records in | |
83 | about 15 minutes. Thank you. | |
84 | ||
85 | Second change is the addition of US area and zip code lookups. This little | |
86 | feature gives some interesting geographical data when ran across password lists | |
87 | originating in the US. The best example I've seen of this is the dump from the | |
88 | Military Singles site where some passwords could be obviously seen to be grouped | |
89 | around US military bases. People in the UK don't have the same relationship with | |
90 | phone numbers so I know this won't work here but if anyone can suggest any other | |
91 | areas where this might be useful then I'll look at building in some kind of | |
92 | location awareness feature so you can specify the source of the list and get | |
93 | results customized to the correct area or just run every area and see if a | |
94 | pattern emerges. | |
95 | ||
96 | A non-code-base change is for version 2 is the move from hosting the code myself | |
97 | to github. This is my first github hosted project so I may get things wrong, if | |
98 | I do, sorry. A number of people asked how they could submit patches so this | |
99 | seems like the best way to do it, lets hope it works out. | |
100 | ||
101 | Version 1 - Was a proof of concept, written fairly in a fairly verbose way so not | |
102 | very optimised. Took off way more than I expected it would and gathered a lot of | |
103 | community support. | |
104 | ||
105 | Feedback/Todo | |
106 | ============= | |
107 | ||
108 | If you have a read through the source for Pipal you'll notice that it isn't very | |
109 | efficient at the moment. The way I built it was to try to keep each chunk of | |
110 | stats together as a distinct group so that if I wanted to add a new, similar, | |
111 | group then it was easy to just copy and paste the group. Now I've got a working | |
112 | app and I know roughly what I need in the different group types I've got an idea | |
113 | on how to rewrite the main parser to make it much more efficient and hopefully | |
114 | multi-threaded which should speed up the processing by a lot for large lists. | |
115 | ||
116 | I could have made these changes before releasing version 1.0 but I figured | |
117 | before I do I want to get as much feedback as possible from users about the | |
118 | features already implemented and about any new features they would like to see | |
119 | so that I can bundle all these together into version 2. So, please get in touch | |
120 | if there is a set of stats that you'd like to see included. | |
121 | ||
122 | One other thing I know needs fixing, Pipal doesn't handle certain character | |
123 | encodings very well. If anyone knows how to correctly deal with different | |
124 | encoding types, especially with regards to regular expressions, please let me | |
125 | know. | |
126 | ||
127 | Licence | |
128 | ======= | |
129 | ||
130 | This project released under the | |
131 | [Creative Commons Attribution-Share Alike 2.0 UK: England & Wales](http://creativecommons.org/licenses/by-sa/2.0/uk/) |
0 | Pipal Goes Modular | |
1 | ================== | |
2 | ||
3 | Copyright(c) 2013, Robin Wood <[email protected]> | |
4 | ||
5 | This is a short doc to explain how the new modular checker and splitter system | |
6 | works. It isn't finished yet so may well still change so I'll try to keep this | |
7 | guide up-to-date. | |
8 | ||
9 | Please get in touch if you have any questions, suggestions or general comments | |
10 | about this new modular approach. | |
11 | ||
12 | Checkers | |
13 | -------- | |
14 | Checkers are the most important part of Pipal, they take the passwords and | |
15 | perform the analysis on them. Originally they were all built into the main | |
16 | script so were hard to maintain and it was even harder to add new ones so I | |
17 | broke them out into their own modules called Checkers. | |
18 | ||
19 | They are set up in the same style as Apache handles vhosts in some Linux | |
20 | distributions, there is a checkers_available directory and a checkers_enabled | |
21 | directory. To enable a checker simply symlink it into the enabled directory and | |
22 | it will be used by the system. This will allow users who don't care about, say | |
23 | Hashcat masks, to not have to spend processor cycles generating them. On a small | |
24 | list this probably won't make much difference but it will on a large one. | |
25 | ||
26 | To create a symlink you can use the following commands: | |
27 | ||
28 | # Enable the basic checker | |
29 | ||
30 | cd checkers_enabled | |
31 | ln -s ../checkers_available/basic.rb . | |
32 | ||
33 | # Enable the basic checker and make sure it is ran first (assuming no 00 files) | |
34 | ||
35 | ln -s ../checkers_available/basic.rb 01basic.rb | |
36 | ||
37 | # Enable all checkers | |
38 | ||
39 | ln -s ../checkers_available/*rb . | |
40 | ||
41 | The other good thing about the way Checkers now work is that it is easy to write | |
42 | new ones. To see how simple a Checker can be take a look at the | |
43 | windows_complexity_checker.rb file in checkers_available. 25 lines get you a | |
44 | checker for default Windows complexity, to change this to cover your own rules | |
45 | simply clone the file, update the regex, the name and a few bits of copy and | |
46 | then symlink it into place. | |
47 | ||
48 | If you want to check for a list of items then this is even easier, check out | |
49 | colour_checker.rb, it is just 15 lines long. Give it a name, the list and a | |
50 | description and the rest is taken care of for you. | |
51 | ||
52 | The --list-checkers parameter will show you a list of all Checkers which are | |
53 | available along with a brief description. I'd like to extend this so each | |
54 | Checker will also contain a more detailed description which can also be | |
55 | requested. | |
56 | ||
57 | Splitters | |
58 | --------- | |
59 | What about if you want to process a file that doesn't just contain passwords, | |
60 | maybe it has usernames in it as well. The default action is to treat each new | |
61 | line in the file as a password but with a custom Splitter you can now define | |
62 | what is the password and what is extra data. You can then write a custom Checker | |
63 | which can understand the extra data and off you go. Any existing Checkers which | |
64 | don't care about extra data will just ignore it but your custom one will be able | |
65 | to handle it. | |
66 | ||
67 | As an example of this I've created a Splitter called pipe_pass_user.rb, as it | |
68 | sounds, this is a pipe (|) separated file with the password first followed by | |
69 | the username. The code again is fairly simple, a class with a static method | |
70 | called split, that takes the line from the file and splits it down to the | |
71 | password and the username. The password is returned on its own with the username | |
72 | going in an associative array. The Checker username.rb is the only one which | |
73 | currently understands how to handle the username field in the extras array and | |
74 | it will take it and do various comparisons between the username and the | |
75 | password. | |
76 | ||
77 | Only a single splitter can be used at once. To do this symlink the Splitter you | |
78 | want to use to a file called custom_splitter.rb in the main Pipal directory. It | |
79 | will then be picked up automatically. |
0 | class Checker | |
1 | attr_writer :cap_at | |
2 | attr_reader :description | |
3 | attr_reader :cli_params | |
4 | attr_writer :verbose | |
5 | ||
6 | def initialize | |
7 | @cap_at = 10 | |
8 | @total_words_processed = 0 | |
9 | @description = "No description given" | |
10 | @cli_params = nil | |
11 | @verbose = false | |
12 | end | |
13 | ||
14 | # Return any extra usage parameters added by the checker | |
15 | def usage | |
16 | return nil | |
17 | end | |
18 | ||
19 | def parse_params opts | |
20 | end | |
21 | ||
22 | def process_word (word, extras = nil) | |
23 | end | |
24 | ||
25 | def get_results (total_words_processed) | |
26 | end | |
27 | end |
0 | # encoding: utf-8 | |
1 | register_checker("FR_area_Code_Checker") | |
2 | ||
3 | FR_area_codes = {} | |
4 | ||
5 | #http://fr.wikipedia.org/wiki/Code_officiel_g%C3%A9ographique | |
6 | #The hashcode is a string because 0x is the octal notation and bug with 08 and 09 | |
7 | FR_area_codes["01"] = ["Ain"] | |
8 | FR_area_codes["02"] = ["Aisne"] | |
9 | FR_area_codes["03"] = ["Allier"] | |
10 | FR_area_codes["04"] = ["Alpes-de-Haute-Provence"] | |
11 | FR_area_codes["05"] = ["Hautes-Alpes"] | |
12 | FR_area_codes["06"] = ["Alpes-Maritimes"] | |
13 | FR_area_codes["07"] = ["Ardèche"] | |
14 | FR_area_codes["08"] = ["Ardennes"] | |
15 | FR_area_codes["09"] = ["Ariège"] | |
16 | FR_area_codes["10"] = ["Aube"] | |
17 | FR_area_codes["11"] = ["Aude"] | |
18 | FR_area_codes["12"] = ["Aveyron"] | |
19 | FR_area_codes["13"] = ["Bouches-du-Rhône"] | |
20 | FR_area_codes["14"] = ["Calvados"] | |
21 | FR_area_codes["15"] = ["Cantal"] | |
22 | FR_area_codes["16"] = ["Charente"] | |
23 | FR_area_codes["17"] = ["Charente-Maritime"] | |
24 | FR_area_codes["18"] = ["Cher"] | |
25 | FR_area_codes["19"] = ["Corrèze"] | |
26 | #FR_area_codes["2A"] = ["Corse-du-Sud"] | |
27 | #FR_area_codes["2B"] = ["Haute-Corse"] | |
28 | FR_area_codes["21"] = ["Côte-d’Or"] | |
29 | FR_area_codes["22"] = ["Côtes-d’Armor"] | |
30 | FR_area_codes["23"] = ["Creuse"] | |
31 | FR_area_codes["24"] = ["Dordogne"] | |
32 | FR_area_codes["25"] = ["Doubs"] | |
33 | FR_area_codes["26"] = ["Drôme"] | |
34 | FR_area_codes["27"] = ["Eure"] | |
35 | FR_area_codes["28"] = ["Eure-et-Loir"] | |
36 | FR_area_codes["29"] = ["Finistère"] | |
37 | FR_area_codes["30"] = ["Gard"] | |
38 | FR_area_codes["31"] = ["Haute-Garonne"] | |
39 | FR_area_codes["32"] = ["Gers"] | |
40 | FR_area_codes["33"] = ["Gironde"] | |
41 | FR_area_codes["34"] = ["Hérault"] | |
42 | FR_area_codes["35"] = ["Ille-et-Vilaine"] | |
43 | FR_area_codes["36"] = ["Indre"] | |
44 | FR_area_codes["37"] = ["Indre-et-Loire"] | |
45 | FR_area_codes["38"] = ["Isère"] | |
46 | FR_area_codes["39"] = ["Jura"] | |
47 | FR_area_codes["40"] = ["Landes"] | |
48 | FR_area_codes["41"] = ["Loir-et-Cher"] | |
49 | FR_area_codes["42"] = ["Loire"] | |
50 | FR_area_codes["43"] = ["Haute-Loire"] | |
51 | FR_area_codes["44"] = ["Loire-Atlantique"] | |
52 | FR_area_codes["45"] = ["Loiret"] | |
53 | FR_area_codes["46"] = ["Lot"] | |
54 | FR_area_codes["47"] = ["Lot-et-Garonne"] | |
55 | FR_area_codes["48"] = ["Lozère"] | |
56 | FR_area_codes["49"] = ["Maine-et-Loire"] | |
57 | FR_area_codes["50"] = ["Manche"] | |
58 | FR_area_codes["51"] = ["Marne"] | |
59 | FR_area_codes["52"] = ["Haute-Marne"] | |
60 | FR_area_codes["53"] = ["Mayenne"] | |
61 | FR_area_codes["54"] = ["Meurthe-et-Moselle"] | |
62 | FR_area_codes["55"] = ["Meuse"] | |
63 | FR_area_codes["56"] = ["Morbihan"] | |
64 | FR_area_codes["57"] = ["Moselle"] | |
65 | FR_area_codes["58"] = ["Nièvre"] | |
66 | FR_area_codes["59"] = ["Nord"] | |
67 | FR_area_codes["60"] = ["Oise"] | |
68 | FR_area_codes["61"] = ["Orne"] | |
69 | FR_area_codes["62"] = ["Pas-de-Calais"] | |
70 | FR_area_codes["63"] = ["Puy-de-Dôme"] | |
71 | FR_area_codes["64"] = ["Pyrénées-Atlantiques"] | |
72 | FR_area_codes["65"] = ["Hautes-Pyrénées"] | |
73 | FR_area_codes["66"] = ["Pyrénées-Orientales"] | |
74 | FR_area_codes["67"] = ["Bas-Rhin"] | |
75 | FR_area_codes["68"] = ["Haut-Rhin"] | |
76 | FR_area_codes["69"] = ["Rhône"] | |
77 | FR_area_codes["70"] = ["Haute-Saône"] | |
78 | FR_area_codes["71"] = ["Saône-et-Loire"] | |
79 | FR_area_codes["72"] = ["Sarthe"] | |
80 | FR_area_codes["73"] = ["Savoie"] | |
81 | FR_area_codes["74"] = ["Haute-Savoie"] | |
82 | FR_area_codes["75"] = ["Paris"] | |
83 | FR_area_codes["76"] = ["Seine-Maritime"] | |
84 | FR_area_codes["77"] = ["Seine-et-Marne"] | |
85 | FR_area_codes["78"] = ["Yvelines"] | |
86 | FR_area_codes["79"] = ["Deux-Sèvres"] | |
87 | FR_area_codes["80"] = ["Somme"] | |
88 | FR_area_codes["81"] = ["Tarn"] | |
89 | FR_area_codes["82"] = ["Tarn-et-Garonne"] | |
90 | FR_area_codes["83"] = ["Var"] | |
91 | FR_area_codes["84"] = ["Vaucluse"] | |
92 | FR_area_codes["85"] = ["Vendée"] | |
93 | FR_area_codes["86"] = ["Vienne"] | |
94 | FR_area_codes["87"] = ["Haute-Vienne"] | |
95 | FR_area_codes["88"] = ["Vosges"] | |
96 | FR_area_codes["89"] = ["Yonne"] | |
97 | FR_area_codes["90"] = ["Territoire de Belfort"] | |
98 | FR_area_codes["91"] = ["Essonne"] | |
99 | FR_area_codes["92"] = ["Hauts-de-Seine"] | |
100 | FR_area_codes["93"] = ["Seine-Saint-Denis"] | |
101 | FR_area_codes["94"] = ["Val-de-Marne"] | |
102 | FR_area_codes["95"] = ["Val-d’Oise"] | |
103 | FR_area_codes["97"] = ["Collectivités d’outre-mer"] | |
104 | #FR_area_codes["971"] = ["Guadeloupe"] | |
105 | #FR_area_codes["972"] = ["Martinique"] | |
106 | #FR_area_codes["973"] = ["Guyane"] | |
107 | #FR_area_codes["974"] = ["La Réunion"] | |
108 | #FR_area_codes["975"] = ["Saint-Pierre-et-Miquelon"] | |
109 | #FR_area_codes["976"] = ["Mayotte"] | |
110 | #FR_area_codes["977"] = ["Saint-Barthélemy"] | |
111 | #FR_area_codes["978"] = ["Saint-Martin"] | |
112 | FR_area_codes["98"] = ["Collectivités d’outre-mer"] | |
113 | #FR_area_codes["989"] = ["Île de Clipperton"] | |
114 | #FR_area_codes["984"] = ["Terres australes et antarctiques françaises"] | |
115 | #FR_area_codes["986"] = ["Wallis-et-Futuna"] | |
116 | #FR_area_codes["987"] = ["Polynésie française"] | |
117 | #FR_area_codes["988"] = ["Nouvelle-Calédonie"] | |
118 | #FR_area_codes["989"] = ["Île de Clipperton"] | |
119 | ||
120 | ||
121 | class FR_area_Code_Checker < Checker | |
122 | def initialize | |
123 | super | |
124 | @description = "List of French area codes" | |
125 | @areas = {} | |
126 | end | |
127 | ||
128 | def process_word (word, extras = nil) | |
129 | if /(^([0-9]{5})|([0-9]{5})$)/.match(word) | |
130 | #to many matchs with 01234 or 98765 or 11111, etc. | |
131 | if !((($1[0].to_i == $1[1].to_i + 1) and ($1[1].to_i == $1[2].to_i + 1) and | |
132 | ($1[2].to_i == $1[3].to_i + 1) and ($1[3].to_i == $1[4].to_i + 1)) or | |
133 | (($1[0].to_i == $1[1].to_i - 1) and ($1[1].to_i == $1[2].to_i - 1) and | |
134 | ($1[2].to_i == $1[3].to_i - 1) and ($1[3].to_i == $1[4].to_i - 1)) or | |
135 | (($1[0].to_i == $1[1].to_i) and ($1[1].to_i == $1[2].to_i) and | |
136 | ($1[2].to_i == $1[3].to_i) and ($1[3].to_i == $1[4].to_i))) | |
137 | area_code = $1[0,2] | |
138 | if FR_area_codes.has_key?(area_code) | |
139 | if [email protected]_key?(area_code) | |
140 | @areas[area_code] = 1 | |
141 | else | |
142 | @areas[area_code] += 1 | |
143 | end | |
144 | end | |
145 | end | |
146 | end | |
147 | @total_words_processed += 1 | |
148 | end | |
149 | ||
150 | def get_results() | |
151 | ret_str = "Départements français\n" | |
152 | ||
153 | if @areas.length > 0 | |
154 | (@areas.sort do |x,y| (x[1] <=> y[1]) * -1 end).each do |area_code_data| | |
155 | ret_str << "#{area_code_data[0].to_s} #{FR_area_codes[area_code_data[0]][1]} (#{FR_area_codes[area_code_data[0]][0]}) = #{area_code_data[1].to_s} (#{((area_code_data[1].to_f/@total_words_processed) * 100).round(2).to_s}%)\n" | |
156 | end | |
157 | else | |
158 | ret_str = "Aucun trouvé\n" | |
159 | end | |
160 | ||
161 | return ret_str | |
162 | end | |
163 | end | |
164 |
0 | # encoding: utf-8 | |
1 | require_relative "../list_checker.rb" | |
2 | register_checker("FR_Colour_Checker") | |
3 | ||
4 | class FR_Colour_Checker < Checker | |
5 | def initialize | |
6 | super | |
7 | ||
8 | @list = {"noir" => 0, "bleu" => 0, "maron" => 0, "gris" => 0, "vert" => 0, | |
9 | "orange" => 0, "rose" => 0, "rouge" => 0, "blanc" => 0, "jaune" => 0, | |
10 | "violet" => 0, "indigo" => 0, "ocre" => 0, "cyan" => 0, "ocre" => 0} | |
11 | @description = "List of common French colours" | |
12 | end | |
13 | ||
14 | def get_results() | |
15 | return super("Couleurs") | |
16 | end | |
17 | end |
0 | # encoding: utf-8 | |
1 | register_checker("FR_Date_Checker") | |
2 | ||
3 | class FR_Date_Checker < Checker | |
4 | def initialize | |
5 | super | |
6 | @description = "French day, month and year checker" | |
7 | ||
8 | #http://fr.wikipedia.org/wiki/Semaine (3ieres lettres) | |
9 | @days_ab = {'lun' => 0, 'mar' => 0, 'mer' => 0, 'jeu' => 0, 'ven' => 0, 'sam' => 0, 'dim' => 0} | |
10 | #http://fr.wikipedia.org/wiki/Mois#Abr.C3.A9viations | |
11 | @months_ab = {"janv" => 0, "fevr" => 0, "avr" => 0, "juill" => 0, | |
12 | "sept" => 0, "oct" => 0, "nov" => 0, "dec" => 0} | |
13 | ||
14 | @days = {'lundi' => 0, 'mardi' => 0, 'mercredi' => 0, 'jeudi' => 0, 'vendredi' => 0, 'samedi' => 0, 'dimanche' => 0} | |
15 | @months = {"janvier" => 0, "fevrier" => 0, "mars" => 0, "avril" => 0, "mai" => 0, "juin" => 0, | |
16 | "juillet" => 0, "aout" => 0, "septembre" => 0, "octobre" => 0, "novembre" => 0, "decembre" => 0} | |
17 | ||
18 | @years = {} | |
19 | ||
20 | 1975.upto(2020) do |year| | |
21 | @years[year] = 0 | |
22 | end | |
23 | end | |
24 | ||
25 | def process_word (word, extras = nil) | |
26 | @years.each_pair do |year, count| | |
27 | if /#{year}/.match word | |
28 | @years[year] += 1 | |
29 | end | |
30 | end | |
31 | ||
32 | @days_ab.each_pair do |day, count| | |
33 | if /#{day}/i.match word | |
34 | @days_ab[day] += 1 | |
35 | end | |
36 | end | |
37 | ||
38 | @months_ab.each_pair do |month, count| | |
39 | if /#{month}/i.match word | |
40 | @months_ab[month] += 1 | |
41 | end | |
42 | end | |
43 | ||
44 | @days.each_pair do |day, count| | |
45 | if /#{day}/i.match word | |
46 | @days[day] += 1 | |
47 | end | |
48 | end | |
49 | ||
50 | @months.each_pair do |month, count| | |
51 | if /#{month}/i.match word | |
52 | @months[month] += 1 | |
53 | end | |
54 | end | |
55 | @total_words_processed += 1 | |
56 | end | |
57 | ||
58 | def get_results() | |
59 | ret_str = "Dates\n" | |
60 | ||
61 | ret_str << "\nMois\n" | |
62 | disp = false | |
63 | @months.each_pair do |month, count| | |
64 | unless count == 0 | |
65 | disp = true | |
66 | ret_str << "#{month} = #{count.to_s} (#{((count.to_f/@total_words_processed) * 100).round(2).to_s}%)\n" unless count == 0 | |
67 | end | |
68 | end | |
69 | unless disp | |
70 | ret_str = "Aucun trouvé\n" | |
71 | end | |
72 | ||
73 | ret_str << "\nJours\n" | |
74 | disp = false | |
75 | @days.each_pair do |day, count| | |
76 | unless count == 0 | |
77 | disp = true | |
78 | ret_str << "#{day} = #{count.to_s} (#{((count.to_f/@total_words_processed) * 100).round(2).to_s}%)\n" unless count == 0 | |
79 | end | |
80 | end | |
81 | unless disp | |
82 | ret_str << "Aucun trouvé\n" | |
83 | end | |
84 | ||
85 | ret_str << "\nMois (Abréviation)\n" | |
86 | disp = false | |
87 | @months_ab.each_pair do |month, count| | |
88 | unless count == 0 | |
89 | disp = true | |
90 | ret_str << "#{month} = #{count.to_s} (#{((count.to_f/@total_words_processed) * 100).round(2).to_s}%)\n" unless count == 0 | |
91 | end | |
92 | end | |
93 | unless disp | |
94 | ret_str << "Aucun trouvé\n" | |
95 | end | |
96 | ||
97 | ret_str << "\nJours (Abréviation)\n" | |
98 | disp = false | |
99 | @days_ab.each_pair do |day, count| | |
100 | unless count == 0 | |
101 | disp = true | |
102 | ret_str << "#{day} = #{count.to_s} (#{((count.to_f/@total_words_processed) * 100).round(2).to_s} %)\n" unless count == 0 | |
103 | end | |
104 | end | |
105 | unless disp | |
106 | ret_str << "Aucun trouvé\n" | |
107 | end | |
108 | ||
109 | ret_str << "\nAnnées inclues\n" | |
110 | disp = false | |
111 | @years.each_pair do |number, count| | |
112 | unless count == 0 | |
113 | disp = true | |
114 | ret_str << "#{number.to_s} = #{count.to_s} (#{((count.to_f/@total_words_processed) * 100).round(2).to_s}%)\n" unless count == 0 | |
115 | end | |
116 | end | |
117 | unless disp | |
118 | ret_str << "Aucune trouvée\n" | |
119 | end | |
120 | ||
121 | count_ordered = [] | |
122 | @years.each_pair do |year, count| | |
123 | count_ordered << [year, count] unless count == 0 | |
124 | end | |
125 | @years = count_ordered.sort do |x,y| | |
126 | (x[1] <=> y[1]) * -1 | |
127 | end | |
128 | ||
129 | ret_str << "\nAnnées (Top #{@cap_at.to_s})\n" | |
130 | disp = false | |
131 | @years[0, @cap_at].each do |data| | |
132 | disp = true | |
133 | ret_str << "#{data[0].to_s} = #{data[1].to_s} (#{((data[1].to_f/@total_words_processed) * 100).round(2).to_s}%)\n" | |
134 | end | |
135 | unless disp | |
136 | ret_str << "Aucune trouvée\n" | |
137 | end | |
138 | ||
139 | return ret_str | |
140 | end | |
141 | end |
0 | # encoding: utf-8 | |
1 | register_checker("FR_Hashcat_Mask_Generator") | |
2 | ||
3 | class FR_Hashcat_Mask_Generator < Checker | |
4 | ||
5 | def initialize | |
6 | super | |
7 | @description = "Hashcat mask generator (French)" | |
8 | @hashcat_masks = {} | |
9 | end | |
10 | ||
11 | def process_word (word, extras = nil) | |
12 | # This won't work as the special replacement hits all the previous ?'s that have been replaced, | |
13 | # lower at the end would do the same with all the characters so can't use the order to fix this problem | |
14 | # mask_line = line.gsub(/[a-z]/, "?l").gsub(/[A-Z]/,'?u').gsub(/[0-9]/, '?d').gsub(/[\p{Punct}]/, '?s') | |
15 | mask_line = "" | |
16 | word.each_char do |char| | |
17 | case char | |
18 | when /[a-z]/ | |
19 | mask_line << "?l" | |
20 | when /[A-Z]/ | |
21 | mask_line << "?u" | |
22 | when /[0-9]/ | |
23 | mask_line << "?d" | |
24 | else | |
25 | mask_line << "?s" | |
26 | end | |
27 | end | |
28 | ||
29 | if !@hashcat_masks.has_key? mask_line | |
30 | @hashcat_masks[mask_line] = {'count' => 0} | |
31 | end | |
32 | @hashcat_masks[mask_line]['count'] += 1 | |
33 | @total_words_processed += 1 | |
34 | end | |
35 | ||
36 | def get_results() | |
37 | ret_str = "Masques Hashcat (Top #{@cap_at.to_s})\n\n" | |
38 | ||
39 | count_ordered = [] | |
40 | @hashcat_masks.each_pair do |name, data| | |
41 | count_ordered << [name, data] unless data['count'] == 0 | |
42 | end | |
43 | @hashcat_masks = count_ordered.sort do |x,y| | |
44 | (x[1]['count'] <=> y[1]['count']) * -1 | |
45 | end | |
46 | ||
47 | @hashcat_masks[0, @cap_at].each do |name, data| | |
48 | ret_str << "#{name}: #{data['count'].to_s} (#{((data['count'].to_f/@total_words_processed) * 100).round(2).to_s}%)\n" | |
49 | end | |
50 | ||
51 | return ret_str | |
52 | end | |
53 | end |
0 | # encoding: utf-8 | |
1 | register_checker("FR_Windows_Complexity_Checker") | |
2 | ||
3 | class FR_Windows_Complexity_Checker < Checker | |
4 | ||
5 | def initialize | |
6 | super | |
7 | @description = "Check for default Windows complexity (French)" | |
8 | @matches = 0 | |
9 | end | |
10 | ||
11 | def process_word (word, extras = nil) | |
12 | if word =~ /(?=^.{8,255}$)((?=.*\d)(?=.*[A-Z])(?=.*[a-z])|(?=.*\d)(?=.*[^A-Za-z0-9])(?=.*[a-z])|(?=.*[^A-Za-z0-9])(?=.*[A-Z])(?=.*[a-z])|(?=.*\d)(?=.*[A-Z])(?=.*[^A-Za-z0-9]))^.*/ | |
13 | @matches += 1 | |
14 | end | |
15 | @total_words_processed += 1 | |
16 | end | |
17 | ||
18 | def get_results() | |
19 | ret_str = "Complexité par défaut Active Directory\n" | |
20 | ||
21 | ret_str << "Number of matches = #{@matches} (#{((@matches.to_f/@total_words_processed) * 100).round(2).to_s}%)\n" | |
22 | return ret_str | |
23 | end | |
24 | end |
0 | require_relative "../list_checker.rb" | |
1 | ||
2 | register_checker("NL_Colour_Checker") | |
3 | ||
4 | class NL_Colour_Checker < List_Checker | |
5 | def initialize | |
6 | super | |
7 | @description = "List of common dutch colours" | |
8 | @list = {"zwart" => 0, "blauw" => 0, "bruin" => 0, "grijs" => 0, "groen" => 0, "oranje" => 0, "roze" => 0, "paars" => 0, "rood" => 0, "wit" => 0, "geel" => 0, 'violet' => 0, 'indigo' => 0} | |
9 | end | |
10 | ||
11 | def get_results() | |
12 | return super("Dutch Colours") | |
13 | end | |
14 | end |
0 | register_checker("NL_Date_Checker") | |
1 | ||
2 | class NL_Date_Checker < Checker | |
3 | ||
4 | def initialize | |
5 | super | |
6 | ||
7 | @years = {} | |
8 | 1975.upto(2020) do |year| | |
9 | @years[year] = 0 | |
10 | end | |
11 | ||
12 | @days_ab = {'maa' => 0, 'din' => 0, 'woe' => 0, 'don' => 0, 'vrij' => 0, 'zat' => 0, 'zon' => 0} | |
13 | @months_ab = {"jan" => 0, "feb" => 0, "mrt" => 0, "apr" => 0, "mei" => 0, "jun" => 0, "jul" => 0, "aug" => 0, "sep" => 0, "okt" => 0, "nov" => 0, "dec" => 0} | |
14 | ||
15 | @days = {'maandag' => 0, 'dinsdag' => 0, 'woensdag' => 0, 'donderdag' => 0, 'vrijdag' => 0, 'zaterdag' => 0, 'zondag' => 0} | |
16 | @months = {"januari" => 0, "februari" => 0, "maart" => 0, "april" => 0, "mei" => 0, "juni" => 0, "juli" => 0, "augustus" => 0, "september" => 0, "oktober" => 0, "november" => 0, "december" => 0} | |
17 | @description = "Dutch day, month and year checker" | |
18 | end | |
19 | ||
20 | def process_word (word, extras = nil) | |
21 | @years.each_pair do |year, count| | |
22 | if /#{year}/.match word | |
23 | @years[year] += 1 | |
24 | end | |
25 | end | |
26 | ||
27 | @days_ab.each_pair do |day, count| | |
28 | if /#{day}/i.match word | |
29 | @days_ab[day] += 1 | |
30 | end | |
31 | end | |
32 | ||
33 | @months_ab.each_pair do |month, count| | |
34 | if /#{month}/i.match word | |
35 | @months_ab[month] += 1 | |
36 | end | |
37 | end | |
38 | ||
39 | @days.each_pair do |day, count| | |
40 | if /#{day}/i.match word | |
41 | @days[day] += 1 | |
42 | end | |
43 | end | |
44 | ||
45 | @months.each_pair do |month, count| | |
46 | if /#{month}/i.match word | |
47 | @months[month] += 1 | |
48 | end | |
49 | end | |
50 | @total_words_processed += 1 | |
51 | end | |
52 | ||
53 | def get_results() | |
54 | ret_str = "Dutch Dates\n" | |
55 | ||
56 | ret_str << "\nDutch Months\n" | |
57 | disp = false | |
58 | @months.each_pair do |month, count| | |
59 | unless count == 0 | |
60 | disp = true | |
61 | ret_str << "#{month} = #{count.to_s} (#{((count.to_f/@total_words_processed) * 100).round(2).to_s}%)\n" unless count == 0 | |
62 | end | |
63 | end | |
64 | unless disp | |
65 | ret_str = "None found\n" | |
66 | end | |
67 | ||
68 | ret_str << "\nDutch Days\n" | |
69 | disp = false | |
70 | @days.each_pair do |day, count| | |
71 | unless count == 0 | |
72 | disp = true | |
73 | ret_str << "#{day} = #{count.to_s} (#{((count.to_f/@total_words_processed) * 100).round(2).to_s}%)\n" unless count == 0 | |
74 | end | |
75 | end | |
76 | unless disp | |
77 | ret_str << "None found\n" | |
78 | end | |
79 | ||
80 | ret_str << "\nDutch Months (Abreviated)\n" | |
81 | disp = false | |
82 | @months_ab.each_pair do |month, count| | |
83 | unless count == 0 | |
84 | disp = true | |
85 | ret_str << "#{month} = #{count.to_s} (#{((count.to_f/@total_words_processed) * 100).round(2).to_s}%)\n" unless count == 0 | |
86 | end | |
87 | end | |
88 | unless disp | |
89 | ret_str << "None found\n" | |
90 | end | |
91 | ||
92 | ret_str << "\nDutch Days (Abreviated)\n" | |
93 | disp = false | |
94 | @days_ab.each_pair do |day, count| | |
95 | unless count == 0 | |
96 | disp = true | |
97 | ret_str << "#{day} = #{count.to_s} (#{((count.to_f/@total_words_processed) * 100).round(2).to_s} %)\n" unless count == 0 | |
98 | end | |
99 | end | |
100 | unless disp | |
101 | ret_str << "None found\n" | |
102 | end | |
103 | ||
104 | ret_str << "\nIncludes years\n" | |
105 | disp = false | |
106 | @years.each_pair do |number, count| | |
107 | unless count == 0 | |
108 | disp = true | |
109 | ret_str << "#{number.to_s} = #{count.to_s} (#{((count.to_f/@total_words_processed) * 100).round(2).to_s}%)\n" unless count == 0 | |
110 | end | |
111 | end | |
112 | unless disp | |
113 | ret_str << "None found\n" | |
114 | end | |
115 | ||
116 | count_ordered = [] | |
117 | @years.each_pair do |year, count| | |
118 | count_ordered << [year, count] unless count == 0 | |
119 | end | |
120 | @years = count_ordered.sort do |x,y| | |
121 | (x[1] <=> y[1]) * -1 | |
122 | end | |
123 | ||
124 | ret_str << "\nYears (Top #{@cap_at.to_s})\n" | |
125 | disp = false | |
126 | @years[0, @cap_at].each do |data| | |
127 | disp = true | |
128 | ret_str << "#{data[0].to_s} = #{data[1].to_s} (#{((data[1].to_f/@total_words_processed) * 100).round(2).to_s}%)\n" | |
129 | end | |
130 | unless disp | |
131 | ret_str << "None found\n" | |
132 | end | |
133 | ||
134 | return ret_str | |
135 | end | |
136 | end |
0 | require_relative "../list_checker.rb" | |
1 | ||
2 | register_checker("NL_Season_Checker") | |
3 | ||
4 | class NL_Season_Checker < List_Checker | |
5 | def initialize | |
6 | super | |
7 | @description = "List of common Dutch seasons" | |
8 | @list = {"zomer" => 0, "herfst" => 0, "winter" => 0, "lente" => 0} | |
9 | end | |
10 | ||
11 | def get_results() | |
12 | return super("Dutch Seasons") | |
13 | end | |
14 | end |
0 | require_relative "../list_checker.rb" | |
1 | ||
2 | register_checker("Australia_Checker") | |
3 | ||
4 | class Australia_Checker < List_Checker | |
5 | def initialize | |
6 | super | |
7 | @description = "List of Australian places " | |
8 | @list = { | |
9 | "adelaide" => 0, | |
10 | "albany" => 0, | |
11 | "albury-wodonga" => 0, | |
12 | "act" => 0, | |
13 | "ballarat" => 0, | |
14 | "bathurst" => 0, | |
15 | "bendigo" => 0, | |
16 | "bowral-mittagong" => 0, | |
17 | "brisbane" => 0, | |
18 | "bunbury" => 0, | |
19 | "bundaberg" => 0, | |
20 | "busselton" => 0, | |
21 | "cairns" => 0, | |
22 | "canberra" => 0, | |
23 | "canberra-queanbeyan" => 0, | |
24 | "coffs" => 0, | |
25 | "harbour" => 0, | |
26 | "darwin" => 0, | |
27 | "devonport" => 0, | |
28 | "dubbo" => 0, | |
29 | "geelong" => 0, | |
30 | "geraldton" => 0, | |
31 | "gladstone" => 0, | |
32 | "tannum" => 0, | |
33 | "goldcoast" => 0, | |
34 | "gold" => 0, | |
35 | "coast" => 0, | |
36 | "tweedheads" => 0, | |
37 | "herveybay" => 0, | |
38 | "hervey" => 0, | |
39 | "hobart" => 0, | |
40 | "kalgoorlie-boulder" => 0, | |
41 | "launceston" => 0, | |
42 | "mackay" => 0, | |
43 | "melbourne" => 0, | |
44 | "mildura-wentworth" => 0, | |
45 | "newcastle" => 0, | |
46 | "newcastle-maitland" => 0, | |
47 | "newsouthwales" => 0, | |
48 | "northernterritory" => 0, | |
49 | "nowra-bomaderry" => 0, | |
50 | "orange" => 0, | |
51 | "perth" => 0, | |
52 | "portmacquarie" => 0, | |
53 | "macquarie" => 0, | |
54 | "queensland" => 0, | |
55 | "rockhampton" => 0, | |
56 | "shepparton-mooroopna" => 0, | |
57 | "sunshinecoast" => 0, | |
58 | "sunshine" => 0, | |
59 | "sydney" => 0, | |
60 | "tamworth" => 0, | |
61 | "tasmania" => 0, | |
62 | "toowoomba" => 0, | |
63 | "townsville" => 0, | |
64 | "traralgon-morwell" => 0, | |
65 | "victoria" => 0, | |
66 | "wagga" => 0, | |
67 | "warragul-drouin" => 0, | |
68 | "warrnambool" => 0, | |
69 | "western" => 0, | |
70 | "wollongong" => 0, | |
71 | "new" => 0, | |
72 | "south" => 0, | |
73 | "wales" => 0 | |
74 | } | |
75 | ||
76 | end | |
77 | ||
78 | def get_results() | |
79 | return super("Australian Places") | |
80 | end | |
81 | end |
0 | # encoding: utf-8 | |
1 | ||
2 | # Find out what our base path is | |
3 | base_path = File.expand_path(File.dirname(__FILE__)) | |
4 | require File.join(base_path, '../horizbar.rb') | |
5 | register_checker("Basic_Checker") | |
6 | ||
7 | class Basic_Checker < Checker | |
8 | FIRST_CAP_LAST_NUM_RE = /^[A-Z].*[0-9]$/ | |
9 | FIRST_CAP_LAST_SYMBOL_RE = /^[A-Z].*[\p{Punct}]$/ | |
10 | ||
11 | SINGLES_ON_END_RE = /[^0-9]+([0-9]{1})$/ | |
12 | DOUBLES_ON_END_RE = /[^0-9]+([0-9]{2})$/ | |
13 | TRIPLES_ON_END_RE =/[^0-9]+([0-9]{3})$/ | |
14 | ||
15 | def initialize | |
16 | super | |
17 | ||
18 | @words = {} | |
19 | @one_to_six_chars = 0 | |
20 | @one_to_eight_chars = 0 | |
21 | @over_eight_chars = 0 | |
22 | ||
23 | @lengths = [] | |
24 | @max_length = 0 | |
25 | @base_words = {} | |
26 | ||
27 | @first_cap_last_num = 0 | |
28 | @first_cap_last_symbol = 0 | |
29 | ||
30 | # this is the count of words with 1, 2 and 3 numbers on the end | |
31 | @singles_on_end = 0 | |
32 | @doubles_on_end = 0 | |
33 | @triples_on_end = 0 | |
34 | ||
35 | # this is the actual last number on the end, single digit | |
36 | @last_on_end = [] | |
37 | 0.upto(4) do |no_of_digits| | |
38 | @last_on_end[no_of_digits] = {} | |
39 | end | |
40 | ||
41 | # last two and three numbers on the end | |
42 | @last_two_on_end = {} | |
43 | @last_three_on_end = {} | |
44 | ||
45 | @char_stats = { | |
46 | "loweralpha" => {'regex' => /^[a-z]+$/, "count" => 0}, | |
47 | "upperalpha" => {'regex' => /^[A-Z]+$/, "count" => 0}, | |
48 | "numeric" => {'regex' => /^[0-9]+$/, "count" => 0}, | |
49 | "special" => {'regex' => /^[\p{Punct}]+$/, "count" => 0}, | |
50 | ||
51 | "loweralphanum" => {'regex' => /^[a-z0-9]+$/, "count" => 0}, | |
52 | "upperalphanum" => {'regex' => /^[A-Z0-9]+$/, "count" => 0}, | |
53 | "mixedalpha" => {'regex' => /^[a-zA-Z]+$/, "count" => 0}, | |
54 | "loweralphaspecial" => {'regex' => /^[a-z\p{Punct}]+$/, "count" => 0}, | |
55 | "upperalphaspecial" => {'regex' => /^[A-Z\p{Punct}]+$/, "count" => 0}, | |
56 | "specialnum" => {'regex' => /^[\p{Punct}0-9]+$/, "count" => 0}, | |
57 | ||
58 | "mixedalphanum" => {'regex' => /^[a-zA-Z0-9]+$/, "count" => 0}, | |
59 | "loweralphaspecialnum" => {'regex' => /^[a-z\p{Punct}0-9]+$/, "count" => 0}, | |
60 | "mixedalphaspecial" => {'regex' => /^[A-Za-z\p{Punct}]+$/, "count" => 0}, | |
61 | "upperalphaspecialnum" => {'regex' => /^[A-Z\p{Punct}0-9]+$/, "count" => 0}, | |
62 | ||
63 | "mixedalphaspecialnum" => {'regex' => /^[A-Za-z\p{Punct}0-9]+$/, "count" => 0}, | |
64 | } | |
65 | ||
66 | @char_sets_ordering = { | |
67 | "stringdigit" => {"regex" => /^[a-z]+[0-9]+$/, "count" => 0}, | |
68 | "allstring" => {"regex" => /^[a-z]+$/, "count" => 0}, | |
69 | "digitstring" => {"regex" => /^[0-9]+[a-z]+$/, "count" => 0}, | |
70 | "stringdigitstring" => {"regex" => /^[a-z]+[0-9]+[a-z]+$/, "count" => 0}, | |
71 | "alldigit" => {"regex" => /^[0-9]+$/, "count" => 0}, | |
72 | "digitstringdigit" => {"regex" => /^[0-9]+[a-z]+[0-9]+$/, "count" => 0}, | |
73 | "stringspecialdigit" => {"regex" => /^[a-z]+[\p{Punct}]+[0-9]+$/, "count" => 0}, | |
74 | "stringspecialstring" => {"regex" => /^[a-z]+[\p{Punct}]+[a-z]+$/, "count" => 0}, | |
75 | "stringspecial" => {"regex" => /^[a-z]+[\p{Punct}]+$/, "count" => 0}, | |
76 | "specialstring" => {"regex" => /^[\p{Punct}]+[a-z]+$/, "count" => 0}, | |
77 | "specialstringspecial" => {"regex" => /^[\p{Punct}]+[a-z]+[\p{Punct}]+$/, "count" => 0}, | |
78 | "allspecial" => {"regex" => /^[\p{Punct}]+$/, "count" => 0}, | |
79 | "othermask" => {"regex" => /^.*$/, "count" => 0} | |
80 | } | |
81 | ||
82 | ||
83 | @description = "Basic Checks" | |
84 | end | |
85 | ||
86 | def process_word (word, extras = nil) | |
87 | # don't think this is required any more | |
88 | # Doing this so that I can support a wider range of characters, a UK pound sign | |
89 | # breaks the app without it | |
90 | # line.force_encoding("ASCII-8BIT") | |
91 | ||
92 | if [email protected]_key?(word) | |
93 | @words[word] = 0 | |
94 | end | |
95 | @words[word] += 1 | |
96 | ||
97 | lower_word = word.downcase | |
98 | # strip any non-alpha from the start or end, I was going to strip all non-alpha | |
99 | # but then found a list with Unc0rn as a very common base. Stripping all non-alpha | |
100 | # would leave with Uncrn which doesn't really make any sense as without the 133t speak | |
101 | # it is out of context. | |
102 | # | |
103 | # If you want all non-alpha stripped use the following line instead | |
104 | # | |
105 | # word_just_alpha = lower_word.gsub(/[^a-z]*/, "") | |
106 | # | |
107 | word_just_alpha = lower_word.gsub(/^[^a-z]*/, "").gsub(/[^a-z]*$/, '') | |
108 | if word_just_alpha.length > 3 | |
109 | if !@base_words.has_key?(word_just_alpha) | |
110 | @base_words[word_just_alpha] = 0 | |
111 | end | |
112 | @base_words[word_just_alpha] += 1 | |
113 | end | |
114 | ||
115 | if @lengths[word.length].nil? | |
116 | @lengths[word.length] = 0 | |
117 | end | |
118 | @lengths[word.length] += 1 | |
119 | ||
120 | if word.length < 9 | |
121 | @one_to_eight_chars += 1 | |
122 | end | |
123 | ||
124 | if word.length < 7 | |
125 | @one_to_six_chars += 1 | |
126 | end | |
127 | ||
128 | if word.length > 8 | |
129 | @over_eight_chars += 1 | |
130 | end | |
131 | ||
132 | if word =~ FIRST_CAP_LAST_SYMBOL_RE | |
133 | @first_cap_last_symbol += 1 | |
134 | end | |
135 | ||
136 | if word =~ FIRST_CAP_LAST_NUM_RE | |
137 | @first_cap_last_num += 1 | |
138 | end | |
139 | ||
140 | if word =~ SINGLES_ON_END_RE | |
141 | @singles_on_end += 1 | |
142 | end | |
143 | ||
144 | # Can't merge these two as the first is strict, 2 digits on the end, the second | |
145 | # just wants the last two digits regardless | |
146 | if word =~ DOUBLES_ON_END_RE | |
147 | @doubles_on_end += 1 | |
148 | end | |
149 | ||
150 | if word =~ TRIPLES_ON_END_RE | |
151 | @triples_on_end += 1 | |
152 | end | |
153 | ||
154 | 1.upto(5) do |no_of_digits| | |
155 | if /([0-9]{#{no_of_digits}})$/.match word | |
156 | last_numbers = $1 | |
157 | if !@last_on_end[no_of_digits - 1].has_key?(last_numbers) | |
158 | @last_on_end[no_of_digits - 1][last_numbers] = 0 | |
159 | end | |
160 | @last_on_end[no_of_digits - 1][last_numbers] += 1 | |
161 | end | |
162 | ||
163 | end | |
164 | ||
165 | @char_stats.each_pair do |name, data| | |
166 | begin | |
167 | if word =~ data['regex'] | |
168 | @char_stats[name]['count'] += 1 | |
169 | break | |
170 | end | |
171 | rescue Encoding::CompatibilityError | |
172 | puts "Encoding problem found with password: " + word | |
173 | end | |
174 | end | |
175 | ||
176 | @char_sets_ordering.each_pair do |name, data| | |
177 | begin | |
178 | if lower_word =~ data['regex'] | |
179 | @char_sets_ordering[name]['count'] += 1 | |
180 | break | |
181 | end | |
182 | rescue Encoding::CompatibilityError | |
183 | puts "Encoding problem found with password: " + word | |
184 | end | |
185 | end | |
186 | @total_words_processed += 1 | |
187 | end | |
188 | ||
189 | def get_results() | |
190 | ret_str = "Basic Results\n\n" | |
191 | ret_str << "Total entries = #{@total_words_processed.to_s}\n" | |
192 | uniq_words = @words.to_a.uniq | |
193 | ret_str << "Total unique entries = #{uniq_words.length.to_s}\n" | |
194 | uniq_words = Array.new(@words.to_a.uniq) | |
195 | ||
196 | ret_str << "\nTop #{@cap_at.to_s} passwords\n" | |
197 | # The default is to sort lowest to highest, the -1 just inverts that | |
198 | @words.sort{|a,b| (a[1]<=>b[1]) * -1}[0, @cap_at].each { |elem| | |
199 | percentage = (elem[1].to_f / @total_words_processed) * 100 | |
200 | ret_str << "#{elem[0]} = #{elem[1].to_s} (#{percentage.round(2).to_s}%)\n" | |
201 | } | |
202 | ||
203 | ret_str << "\nTop #{@cap_at.to_s} base words\n" | |
204 | @base_words.sort{|a,b| (a[1]<=>b[1]) * -1}[0, @cap_at].each { |elem| | |
205 | percentage = (elem[1].to_f / @total_words_processed) * 100 | |
206 | ret_str << "#{elem[0]} = #{elem[1].to_s} (#{percentage.round(2).to_s}%)\n" | |
207 | } | |
208 | ||
209 | ret_str << "\nPassword length (length ordered)\n" | |
210 | ||
211 | length_ordered = [] | |
212 | 0.upto(@lengths.count - 1) do |len| | |
213 | if @lengths[len].nil? | |
214 | @lengths[len] = 0 | |
215 | end | |
216 | percentage = ((@lengths[len].to_f / @total_words_processed) * 100) | |
217 | ret_str << "#{len.to_s} = #{@lengths[len].to_s} (#{percentage.round(2).to_s}%)\n" if @lengths[len] > 0 | |
218 | ||
219 | pair = [len, @lengths[len], percentage] | |
220 | length_ordered << pair | |
221 | end | |
222 | ||
223 | length_ordered.sort! do |x,y| | |
224 | y[1] <=> x[1] | |
225 | end | |
226 | ||
227 | ret_str << "\nPassword length (count ordered)\n" | |
228 | length_ordered.each do |pair| | |
229 | ret_str << "#{pair[0].to_s} = #{pair[1].to_s} (#{pair[2].round(2).to_s}%)\n" if pair[1] > 0 | |
230 | end | |
231 | ret_str << "\n" | |
232 | ||
233 | horiz = HorizBar.new(@lengths) | |
234 | horiz.generate | |
235 | ret_str << horiz.graph | |
236 | ||
237 | ret_str << "\nOne to six characters = #{@one_to_six_chars.to_s} (#{((@one_to_six_chars.to_f/@total_words_processed) * 100).round(2).to_s}%)\n" | |
238 | ret_str << "One to eight characters = #{@one_to_eight_chars.to_s} (#{((@one_to_eight_chars.to_f/@total_words_processed) * 100).round(2).to_s}'%)\n" | |
239 | ret_str << "More than eight characters = #{@over_eight_chars.to_s} (#{((@over_eight_chars.to_f/@total_words_processed) * 100).round(2).to_s}%)\n" | |
240 | ||
241 | ret_str << "\nOnly lowercase alpha = " + @char_stats['loweralpha']['count'].to_s + ' (' + ((@char_stats['loweralpha']['count'].to_f/@total_words_processed) * 100).round(2).to_s + "%)\n" | |
242 | ret_str << "Only uppercase alpha = " + @char_stats['upperalpha']['count'].to_s + ' (' + ((@char_stats['upperalpha']['count'].to_f/@total_words_processed) * 100).round(2).to_s + "%)\n" | |
243 | ret_str << "Only alpha = " + (@char_stats['upperalpha']['count'] + @char_stats['loweralpha']['count']).to_s + ' (' + (((@char_stats['upperalpha']['count'] + @char_stats['loweralpha']['count']).to_f/@total_words_processed) * 100).round(2).to_s + "%)\n" | |
244 | ||
245 | ret_str << "Only numeric = " + @char_stats['numeric']['count'].to_s + ' (' + ((@char_stats['numeric']['count'].to_f/@total_words_processed) * 100).round(2).to_s + "%)\n" | |
246 | ||
247 | ret_str << "\nFirst capital last symbol = " + @first_cap_last_symbol.to_s + ' (' + ((@first_cap_last_symbol.to_f/@total_words_processed) * 100).round(2).to_s + "%)\n" | |
248 | ret_str << "First capital last number = " + @first_cap_last_num.to_s + ' (' + ((@first_cap_last_num.to_f/@total_words_processed) * 100).round(2).to_s + "%)\n" | |
249 | ||
250 | ret_str << "\nSingle digit on the end = " + @singles_on_end.to_s + ' (' + ((@singles_on_end.to_f/@total_words_processed) * 100).round(2).to_s + "%)\n" | |
251 | ret_str << "Two digits on the end = " + @doubles_on_end.to_s + ' (' + ((@doubles_on_end.to_f/@total_words_processed) * 100).round(2).to_s + "%)\n" | |
252 | ret_str << "Three digits on the end = " + @triples_on_end.to_s + ' (' + ((@triples_on_end.to_f/@total_words_processed) * 100).round(2).to_s + "%)\n" | |
253 | ||
254 | ret_str << "\nLast number\n" | |
255 | disp = false | |
256 | ||
257 | graph_numbers = {0=>0, 1=>0, 2=>0, 3=>0, 4=>0, 5=>0, 6=>0, 7=>0, 8=>0, 9=>0} | |
258 | ||
259 | c = @last_on_end[0].to_a.sort do |x,y| | |
260 | (x[0] <=> y[0]) | |
261 | end | |
262 | ||
263 | c.each do |number, count| | |
264 | unless count == 0 | |
265 | disp = true | |
266 | ret_str << number.to_s + " = " + count.to_s + ' (' + ((count.to_f/@total_words_processed) * 100).round(2).to_s + "%)\n" unless count == 0 | |
267 | end | |
268 | graph_numbers[number.to_i] = count | |
269 | ||
270 | end | |
271 | if disp | |
272 | ret_str << "\n" | |
273 | horiz = HorizBar.new(graph_numbers.values) | |
274 | horiz.generate | |
275 | ret_str << horiz.graph | |
276 | else | |
277 | ret_str << "None found\n" | |
278 | end | |
279 | ||
280 | digit_number = 0 | |
281 | @last_on_end.each do |a| | |
282 | c = a.to_a.sort do |x,y| | |
283 | (x[1] <=> y[1]) * -1 | |
284 | end | |
285 | ||
286 | digit_number += 1 | |
287 | if c.count > 0 | |
288 | if (digit_number == 1) | |
289 | ret_str << "\nLast digit\n" | |
290 | else | |
291 | ret_str << "\nLast " + digit_number.to_s + " digits (Top " + @cap_at.to_s + ")\n" | |
292 | end | |
293 | ||
294 | c[0, @cap_at].each do |d| | |
295 | ret_str << d[0] + " = " + d[1].to_s + ' (' + ((d[1].to_f/@total_words_processed) * 100).round(2).to_s + "%)\n" | |
296 | end | |
297 | end | |
298 | end | |
299 | ||
300 | count_ordered = [] | |
301 | @char_stats.each_pair do |name, data| | |
302 | count_ordered << [name, data] unless data['count'] == 0 | |
303 | end | |
304 | @char_stats = count_ordered.sort do |x,y| | |
305 | (x[1]['count'] <=> y[1]['count']) * -1 | |
306 | end | |
307 | ||
308 | ret_str << "\nCharacter sets\n" | |
309 | @char_stats.each do |name, data| | |
310 | ret_str << name + ": " + data['count'].to_s + " (" + ((data['count'].to_f/@total_words_processed) * 100).round(2).to_s + "%)\n" | |
311 | end | |
312 | ||
313 | count_ordered = [] | |
314 | @char_sets_ordering.each_pair do |name, data| | |
315 | count_ordered << [name, data] unless data['count'] == 0 | |
316 | end | |
317 | @char_sets_ordering = count_ordered.sort do |x,y| | |
318 | (x[1]['count'] <=> y[1]['count']) * -1 | |
319 | end | |
320 | ||
321 | ret_str << "\nCharacter set ordering\n" | |
322 | @char_sets_ordering.each do |name, data| | |
323 | ret_str << name + ": " + data['count'].to_s + " (" + ((data['count'].to_f/@total_words_processed) * 100).round(2).to_s + "%)\n" | |
324 | end | |
325 | ||
326 | return ret_str | |
327 | end | |
328 | end |
0 | require_relative "../list_checker.rb" | |
1 | ||
2 | register_checker("Colour_Checker") | |
3 | ||
4 | class Colour_Checker < List_Checker | |
5 | def initialize | |
6 | super | |
7 | @description = "List of common English colours" | |
8 | @list = {"black" => 0, "blue" => 0, "brown" => 0, "gray" => 0, "green" => 0, "orange" => 0, "pink" => 0, "purple" => 0, "red" => 0, "white" => 0, "yellow" => 0, 'violet' => 0, 'indigo' => 0} | |
9 | end | |
10 | ||
11 | def get_results() | |
12 | return super("Colours") | |
13 | end | |
14 | end |
0 | register_checker("Date_Checker") | |
1 | ||
2 | class Date_Checker < Checker | |
3 | ||
4 | def initialize | |
5 | super | |
6 | ||
7 | @years = {} | |
8 | 1975.upto(2020) do |year| | |
9 | @years[year] = 0 | |
10 | end | |
11 | ||
12 | @days_ab = {'mon' => 0, 'tues' => 0, 'wed' => 0, 'thurs' => 0, 'fri' => 0, 'sat' => 0, 'sun' => 0} | |
13 | @months_ab = {"jan" => 0, "feb" => 0, "mar" => 0, "apr" => 0, "may" => 0, "jun" => 0, "jul" => 0, "aug" => 0, "sept" => 0, "oct" => 0, "nov" => 0, "dec" => 0} | |
14 | ||
15 | @days = {'monday' => 0, 'tuesday' => 0, 'wednesday' => 0, 'thursday' => 0, 'friday' => 0, 'saturday' => 0, 'sunday' => 0} | |
16 | @months = {"january" => 0, "february" => 0, "march" => 0, "april" => 0, "may" => 0, "june" => 0, "july" => 0, "august" => 0, "september" => 0, "october" => 0, "november" => 0, "december" => 0} | |
17 | @description = "Days, months and years" | |
18 | end | |
19 | ||
20 | def process_word (word, extras = nil) | |
21 | @years.each_pair do |year, count| | |
22 | if /#{year}/.match word | |
23 | @years[year] += 1 | |
24 | end | |
25 | end | |
26 | ||
27 | @days_ab.each_pair do |day, count| | |
28 | if /#{day}/i.match word | |
29 | @days_ab[day] += 1 | |
30 | end | |
31 | end | |
32 | ||
33 | @months_ab.each_pair do |month, count| | |
34 | if /#{month}/i.match word | |
35 | @months_ab[month] += 1 | |
36 | end | |
37 | end | |
38 | ||
39 | @days.each_pair do |day, count| | |
40 | if /#{day}/i.match word | |
41 | @days[day] += 1 | |
42 | end | |
43 | end | |
44 | ||
45 | @months.each_pair do |month, count| | |
46 | if /#{month}/i.match word | |
47 | @months[month] += 1 | |
48 | end | |
49 | end | |
50 | @total_words_processed += 1 | |
51 | end | |
52 | ||
53 | def get_results() | |
54 | ret_str = "Dates\n" | |
55 | ||
56 | ret_str << "\nMonths\n" | |
57 | disp = false | |
58 | @months.each_pair do |month, count| | |
59 | unless count == 0 | |
60 | disp = true | |
61 | ret_str << "#{month} = #{count.to_s} (#{((count.to_f/@total_words_processed) * 100).round(2).to_s}%)\n" unless count == 0 | |
62 | end | |
63 | end | |
64 | unless disp | |
65 | ret_str = "None found\n" | |
66 | end | |
67 | ||
68 | ret_str << "\nDays\n" | |
69 | disp = false | |
70 | @days.each_pair do |day, count| | |
71 | unless count == 0 | |
72 | disp = true | |
73 | ret_str << "#{day} = #{count.to_s} (#{((count.to_f/@total_words_processed) * 100).round(2).to_s}%)\n" unless count == 0 | |
74 | end | |
75 | end | |
76 | unless disp | |
77 | ret_str << "None found\n" | |
78 | end | |
79 | ||
80 | ret_str << "\nMonths (Abreviated)\n" | |
81 | disp = false | |
82 | @months_ab.each_pair do |month, count| | |
83 | unless count == 0 | |
84 | disp = true | |
85 | ret_str << "#{month} = #{count.to_s} (#{((count.to_f/@total_words_processed) * 100).round(2).to_s}%)\n" unless count == 0 | |
86 | end | |
87 | end | |
88 | unless disp | |
89 | ret_str << "None found\n" | |
90 | end | |
91 | ||
92 | ret_str << "\nDays (Abreviated)\n" | |
93 | disp = false | |
94 | @days_ab.each_pair do |day, count| | |
95 | unless count == 0 | |
96 | disp = true | |
97 | ret_str << "#{day} = #{count.to_s} (#{((count.to_f/@total_words_processed) * 100).round(2).to_s} %)\n" unless count == 0 | |
98 | end | |
99 | end | |
100 | unless disp | |
101 | ret_str << "None found\n" | |
102 | end | |
103 | ||
104 | ret_str << "\nIncludes years\n" | |
105 | disp = false | |
106 | @years.each_pair do |number, count| | |
107 | unless count == 0 | |
108 | disp = true | |
109 | ret_str << "#{number.to_s} = #{count.to_s} (#{((count.to_f/@total_words_processed) * 100).round(2).to_s}%)\n" unless count == 0 | |
110 | end | |
111 | end | |
112 | unless disp | |
113 | ret_str << "None found\n" | |
114 | end | |
115 | ||
116 | count_ordered = [] | |
117 | @years.each_pair do |year, count| | |
118 | count_ordered << [year, count] unless count == 0 | |
119 | end | |
120 | @years = count_ordered.sort do |x,y| | |
121 | (x[1] <=> y[1]) * -1 | |
122 | end | |
123 | ||
124 | ret_str << "\nYears (Top #{@cap_at.to_s})\n" | |
125 | disp = false | |
126 | @years[0, @cap_at].each do |data| | |
127 | disp = true | |
128 | ret_str << "#{data[0].to_s} = #{data[1].to_s} (#{((data[1].to_f/@total_words_processed) * 100).round(2).to_s}%)\n" | |
129 | end | |
130 | unless disp | |
131 | ret_str << "None found\n" | |
132 | end | |
133 | ||
134 | return ret_str | |
135 | end | |
136 | end |
0 | register_checker("Email_Checker") | |
1 | ||
2 | begin | |
3 | require "levenshtein" | |
4 | rescue LoadError | |
5 | # catch error and prodive feedback on installing gem | |
6 | puts "\nError: levenshtein gem not installed\n" | |
7 | puts "\t use: \"gem install levenshtein-ffi\" to install the required gem\n\n" | |
8 | exit | |
9 | end | |
10 | ||
11 | class Email_Checker < Checker | |
12 | ||
13 | def initialize | |
14 | super | |
15 | @exact_matches_name = [] | |
16 | @exact_matches_email = [] | |
17 | @lev_matches_name = [] | |
18 | @lev_matches_email = [] | |
19 | @lev_total_name = 0 | |
20 | @lev_total_email = 0 | |
21 | @lev_tolerance = 3 | |
22 | ||
23 | @description = "Compare email addresses to passwords. Checks both name and full address." | |
24 | @cli_params = [['--email.lev_tolerance', GetoptLong::REQUIRED_ARGUMENT]] | |
25 | end | |
26 | ||
27 | def parse_params opts | |
28 | opts.each do |opt, arg| | |
29 | case opt | |
30 | when '--email.lev_tolerance' | |
31 | if arg =~ /^[0-9]*$/ | |
32 | @lev_tolerance = arg.to_i | |
33 | if @lev_tolerance <= 0 | |
34 | puts"\nEmail Checker: Please enter a positive distance\n\n" | |
35 | exit 1 | |
36 | end | |
37 | else | |
38 | puts"\nEmail Checker: Invalid Levenshtein tolerance\n\n" | |
39 | exit 1 | |
40 | end | |
41 | end | |
42 | end | |
43 | end | |
44 | ||
45 | def check_it (password, value) | |
46 | puts "Checking #{value} against #{password}" if @verbose | |
47 | if password == value | |
48 | puts "Exact match" if @verbose | |
49 | return {"distance" => 0, "value" => value, "password" => password} | |
50 | else | |
51 | dist = Levenshtein.distance(password, value) | |
52 | puts "Lev distance #{dist}#" if @verbose | |
53 | return {"distance" => dist, "value" => value, "password" => password} | |
54 | end | |
55 | ||
56 | return nil | |
57 | end | |
58 | ||
59 | def process_word (password, extras) | |
60 | if extras.has_key?("email") | |
61 | email = extras['email'] | |
62 | ||
63 | if email =~ /^([^@]*)@(.*)/ | |
64 | name = $1 | |
65 | domain = $2 | |
66 | ||
67 | # Check the whole email address as password | |
68 | res = check_it(password, email) | |
69 | unless res.nil? | |
70 | if res['distance'] == 0 | |
71 | unless @exact_matches_email.include? name | |
72 | @exact_matches_email << {"name" => email, "email" => email} | |
73 | end | |
74 | else | |
75 | @lev_total_email += res["distance"] | |
76 | if res["distance"] <= @lev_tolerance | |
77 | @lev_matches_email << res | |
78 | end | |
79 | end | |
80 | end | |
81 | ||
82 | # Check just the name part of email address. | |
83 | # Could do the domain as well but don't think that | |
84 | # would give many hits | |
85 | res = check_it(password, name) | |
86 | unless res.nil? | |
87 | if res['distance'] == 0 | |
88 | unless @exact_matches_name.include? name | |
89 | @exact_matches_name << {"name" => name, "email" => email} | |
90 | end | |
91 | else | |
92 | @lev_total_name += res["distance"] | |
93 | if res["distance"] <= @lev_tolerance | |
94 | # adding this in so that it can come out in the report | |
95 | res['email'] = email | |
96 | @lev_matches_name << res | |
97 | end | |
98 | end | |
99 | end | |
100 | end | |
101 | end | |
102 | ||
103 | @total_words_processed += 1 | |
104 | end | |
105 | ||
106 | def get_results() | |
107 | ret_str = "Email Checker\n" | |
108 | ret_str << "=============\n\n" | |
109 | ||
110 | ret_str << "Exact Matches\n" | |
111 | ret_str << "-------------\n" | |
112 | ret_str << "Whole Email Address\n" | |
113 | if @exact_matches_email.count > 0 | |
114 | ret_str << "Total: #{@exact_matches_email.count.to_s}\n\n" | |
115 | @exact_matches_email.sort{|a,b| (a['name'] <=> b['name'])}.each do |match| | |
116 | ret_str << "#{match['email']}\n" | |
117 | end | |
118 | else | |
119 | ret_str << "No Exact Matches\n" | |
120 | end | |
121 | ret_str << "\n" | |
122 | ||
123 | ret_str << "Just Name\n" | |
124 | if @exact_matches_name.count > 0 | |
125 | ret_str << "Total: #{@exact_matches_name.count.to_s}\n\n" | |
126 | ||
127 | @exact_matches_name.sort{|a,b| (a['name'] <=> b['name'])}.each do |match| | |
128 | ret_str << "#{match['name']} from #{match['email']}\n" | |
129 | end | |
130 | else | |
131 | ret_str << "No Exact Matches\n" | |
132 | end | |
133 | ||
134 | ret_str << "\nLevenshtein Results\n" | |
135 | ret_str << "-------------------\n" | |
136 | lev_average = (@lev_total_email.to_f / @total_words_processed).round(2) | |
137 | ret_str << "Average distance (email) #{lev_average}\n" | |
138 | lev_average = (@lev_total_name.to_f / @total_words_processed).round(2) | |
139 | ret_str << "Average distance (name) #{lev_average}\n" | |
140 | ||
141 | ret_str << "\nClose Matches\n" | |
142 | ret_str << "-------------\n" | |
143 | ||
144 | ret_str << "Whole Email Address\n" | |
145 | # Need to sort this then have it obey the cap_at value | |
146 | if @lev_matches_email.count > 0 | |
147 | ret_str << "Total: #{@lev_matches_email.count.to_s}\n\n" | |
148 | @lev_matches_email.sort{|a,b| (a['distance'] <=> b['distance'])}[0, @cap_at].each do |user_pass| | |
149 | ret_str << "D: #{user_pass['distance']} U: #{user_pass['value']} P: #{user_pass['password']}\n" | |
150 | end | |
151 | else | |
152 | ret_str << "No matches within supplied tolerance\n" | |
153 | end | |
154 | ||
155 | ret_str << "\nJust Name\n" | |
156 | # Need to sort this then have it obey the cap_at value | |
157 | if @lev_matches_name.count > 0 | |
158 | ret_str << "Total: #{@lev_matches_name.count.to_s}\n\n" | |
159 | @lev_matches_name.sort{|a,b| (a['distance'] <=> b['distance'])}[0, @cap_at].each do |user_pass| | |
160 | ret_str << "D: #{user_pass['distance']} U: #{user_pass['value']} (#{user_pass['email']}) P: #{user_pass['password']}\n" | |
161 | end | |
162 | else | |
163 | ret_str << "No matches within supplied tolerance\n" | |
164 | end | |
165 | ||
166 | return ret_str | |
167 | end | |
168 | end |
0 | register_checker("External_List_Checker") | |
1 | ||
2 | class External_List_Checker < Checker | |
3 | @file_name = nil | |
4 | ||
5 | def initialize | |
6 | super | |
7 | @description = "Check an external file for matches" | |
8 | ||
9 | @external_list = {} | |
10 | @cli_params = [['--ext.file', GetoptLong::REQUIRED_ARGUMENT]] | |
11 | end | |
12 | ||
13 | def usage | |
14 | return "\t--ext.file <filename>: external file" | |
15 | end | |
16 | ||
17 | def parse_params opts | |
18 | opts.each do |opt, arg| | |
19 | case opt | |
20 | when '--ext.file' | |
21 | @file_name = arg | |
22 | load_file | |
23 | end | |
24 | end | |
25 | ||
26 | if @file_name.nil? | |
27 | puts "External File Checker - No file specified, use --ext.file to specify the file to use. Aborting" | |
28 | exit 1 | |
29 | # raise Exception.new(true), "External File Checker - No file specified" | |
30 | end | |
31 | end | |
32 | ||
33 | def load_file | |
34 | if !@file_name.nil? | |
35 | if File.exist?(@file_name) | |
36 | begin | |
37 | File.open(@file_name, 'r').each_line do |word| | |
38 | @external_list[word.force_encoding("ASCII-8BIT").strip] = 0 unless word.force_encoding("ASCII-8BIT").strip == '' | |
39 | end | |
40 | rescue Errno::EACCES => e | |
41 | raise PipalException.new("Unable to open external file") | |
42 | end | |
43 | else | |
44 | raise PipalException.new("Unable to open external file") | |
45 | end | |
46 | end | |
47 | end | |
48 | ||
49 | def process_word (word, extras = nil) | |
50 | @external_list.each_pair do |domain, count| | |
51 | if /#{Regexp.quote(domain)}/i.match word | |
52 | @external_list[domain] += 1 | |
53 | end | |
54 | end | |
55 | ||
56 | @total_words_processed += 1 | |
57 | end | |
58 | ||
59 | def get_results() | |
60 | if @external_list.length > 0 | |
61 | count_ordered = [] | |
62 | @external_list.each_pair do |domain, count| | |
63 | count_ordered << [domain, count] unless count == 0 | |
64 | end | |
65 | @external_list = count_ordered.sort do |x,y| | |
66 | (x[1] <=> y[1]) * -1 | |
67 | end | |
68 | ||
69 | ret_str = "External list (Top #{@cap_at.to_s})\n" | |
70 | disp = false | |
71 | @external_list[0, @cap_at].each do |data| | |
72 | disp = true | |
73 | ret_str << "#{data[0]} = #{data[1].to_s} (#{((data[1].to_f/@total_words_processed) * 100).round(2).to_s}%)\n" | |
74 | end | |
75 | unless disp | |
76 | ret_str << "None found\n" | |
77 | end | |
78 | end | |
79 | ||
80 | return ret_str | |
81 | end | |
82 | end |
0 | # encoding: utf-8 | |
1 | ||
2 | # Find out what our base path is | |
3 | base_path = File.expand_path(File.dirname(__FILE__)) | |
4 | require File.join(base_path, '../horizbar.rb') | |
5 | register_checker("Frequency_Checker") | |
6 | ||
7 | class Frequency_Checker < Checker | |
8 | ||
9 | def initialize | |
10 | super | |
11 | @description = "Frequency Checks" | |
12 | ||
13 | @frequencies = [] | |
14 | @position_count = [] | |
15 | ||
16 | @show_empty = false | |
17 | ||
18 | @cli_params = [['--freq.show_empty', GetoptLong::NO_ARGUMENT]] | |
19 | end | |
20 | ||
21 | def usage | |
22 | return "\t--freq.show_empty: show empty frequencies" | |
23 | end | |
24 | ||
25 | def parse_params opts | |
26 | opts.each do |opt, arg| | |
27 | case opt | |
28 | when '--freq.show_empty' | |
29 | @show_empty = true | |
30 | end | |
31 | end | |
32 | end | |
33 | ||
34 | ||
35 | def setup_new_frequency position | |
36 | @frequencies[position] = {} | |
37 | ||
38 | "a".upto("z") do |a| | |
39 | @frequencies[position][a] = 0 | |
40 | end | |
41 | ||
42 | "A".upto("Z") do |a| | |
43 | @frequencies[position][a] = 0 | |
44 | end | |
45 | ||
46 | "0".upto("9") do |a| | |
47 | @frequencies[position][a] = 0 | |
48 | end | |
49 | ||
50 | punct = "čćžšđČĆŽŠĐ!\"$%^&*()-=_+[]{};':@,.<>" | |
51 | punct.each_char do |a| | |
52 | @frequencies[position][a] = 0 | |
53 | end | |
54 | ||
55 | @frequencies[position]["other"] = 0 | |
56 | end | |
57 | ||
58 | def process_word (word, extras = nil) | |
59 | position = 0 | |
60 | ||
61 | word.each_char do |char| | |
62 | if @frequencies[position].nil? | |
63 | self.setup_new_frequency position | |
64 | end | |
65 | ||
66 | if @frequencies[position].has_key?(char) | |
67 | @frequencies[position][char] += 1 | |
68 | else | |
69 | @frequencies[position]["other"] += 1 | |
70 | end | |
71 | ||
72 | if @position_count[position].nil? | |
73 | @position_count[position] = 0 | |
74 | end | |
75 | @position_count[position] += 1 | |
76 | ||
77 | position += 1 | |
78 | end | |
79 | end | |
80 | ||
81 | def get_results() | |
82 | ret_str = "Frequency Results\n" | |
83 | ret_str << "-----------------\n" | |
84 | ||
85 | position = 0 | |
86 | @frequencies.each do |data| | |
87 | ret_str << "position: #{position} - #{@position_count[position]} character#{(@position_count[position]>1)?'s':''}\n" | |
88 | @frequencies[position].each_pair do |key, count| | |
89 | if (@show_empty or count != 0) | |
90 | ret_str << "#{key}: #{count} (#{(count.to_f/@position_count[position]) * 100}%) " | |
91 | end | |
92 | end | |
93 | # ret_str << @frequencies[position].inspect | |
94 | ret_str << "\n" | |
95 | position += 1 | |
96 | end | |
97 | ret_str << "\n" | |
98 | ||
99 | return ret_str | |
100 | end | |
101 | end |
0 | register_checker("Hashcat_Mask_Generator") | |
1 | ||
2 | class Hashcat_Mask_Generator < Checker | |
3 | @override_cap = false | |
4 | ||
5 | def initialize | |
6 | super | |
7 | @description = "Hashcat mask generator" | |
8 | @hashcat_masks = {} | |
9 | @cli_params = [['--hashcat.all', GetoptLong::NO_ARGUMENT]] | |
10 | end | |
11 | ||
12 | def usage | |
13 | return "\t--hashcat.all: return Hashcat masks for all passwords\n\t\t\tThis overrides --top" | |
14 | end | |
15 | ||
16 | def parse_params opts | |
17 | opts.each do |opt, arg| | |
18 | case opt | |
19 | when '--hashcat.all' | |
20 | @override_cap = true | |
21 | end | |
22 | end | |
23 | end | |
24 | ||
25 | def process_word (word, extras = nil) | |
26 | # This won't work as the special replacement hits all the previous ?'s that have been replaced, | |
27 | # lower at the end would do the same with all the characters so can't use the order to fix this problem | |
28 | # mask_line = line.gsub(/[a-z]/, "?l").gsub(/[A-Z]/,'?u').gsub(/[0-9]/, '?d').gsub(/[\p{Punct}]/, '?s') | |
29 | mask_line = "" | |
30 | word.each_char do |char| | |
31 | case char | |
32 | when /[a-z]/ | |
33 | mask_line << "?l" | |
34 | when /[A-Z]/ | |
35 | mask_line << "?u" | |
36 | when /[0-9]/ | |
37 | mask_line << "?d" | |
38 | else | |
39 | mask_line << "?s" | |
40 | end | |
41 | end | |
42 | ||
43 | if !@hashcat_masks.has_key? mask_line | |
44 | @hashcat_masks[mask_line] = {'count' => 0} | |
45 | end | |
46 | @hashcat_masks[mask_line]['count'] += 1 | |
47 | @total_words_processed += 1 | |
48 | end | |
49 | ||
50 | def get_results() | |
51 | if @override_cap | |
52 | @cap_at = @hashcat_masks.length | |
53 | ret_str = "Hashcat masks\n\n" | |
54 | else | |
55 | ret_str = "Hashcat masks (Top #{@cap_at.to_s})\n\n" | |
56 | end | |
57 | ||
58 | count_ordered = [] | |
59 | @hashcat_masks.each_pair do |name, data| | |
60 | count_ordered << [name, data] unless data['count'] == 0 | |
61 | end | |
62 | @hashcat_masks = count_ordered.sort do |x,y| | |
63 | (x[1]['count'] <=> y[1]['count']) * -1 | |
64 | end | |
65 | ||
66 | @hashcat_masks[0, @cap_at].each do |name, data| | |
67 | ret_str << "#{name}: #{data['count'].to_s} (#{((data['count'].to_f/@total_words_processed) * 100).round(2).to_s}%)\n" | |
68 | end | |
69 | ||
70 | return ret_str | |
71 | end | |
72 | end |
0 | require_relative "../list_checker.rb" | |
1 | ||
2 | register_checker("Russian_Cities_Checker") | |
3 | ||
4 | class Russian_Cities_Checker < List_Checker | |
5 | def initialize | |
6 | super | |
7 | @description = "List of common Russian cities " | |
8 | @list = { | |
9 | "abakan" => 0, | |
10 | "achinsk" => 0, | |
11 | "aleksin" => 0, | |
12 | "alexandrov" => 0, | |
13 | "almetyevsk" => 0, | |
14 | "altaysk" => 0, | |
15 | "amur" => 0, | |
16 | "anapa" => 0, | |
17 | "angarsk" => 0, | |
18 | "anzhero" => 0, | |
19 | "apatity" => 0, | |
20 | "arkhangelsk" => 0, | |
21 | "armavir" => 0, | |
22 | "arsenyev" => 0, | |
23 | "artyom" => 0, | |
24 | "arzamas" => 0, | |
25 | "asbest" => 0, | |
26 | "astrakhan" => 0, | |
27 | "autonomous" => 0, | |
28 | "azov" => 0, | |
29 | "balakhna" => 0, | |
30 | "balakovo" => 0, | |
31 | "balashikha" => 0, | |
32 | "balashov" => 0, | |
33 | "barnaul" => 0, | |
34 | "bashkortostan " => 0, | |
35 | "bataysk" => 0, | |
36 | "belebey" => 0, | |
37 | "belgorod" => 0, | |
38 | "belogorsk" => 0, | |
39 | "belorechensk" => 0, | |
40 | "beloretsk" => 0, | |
41 | "belovo" => 0, | |
42 | "berdsk" => 0, | |
43 | "berezniki" => 0, | |
44 | "beryozovsky" => 0, | |
45 | "birobidzhan" => 0, | |
46 | "biysk" => 0, | |
47 | "blagoveshchensk" => 0, | |
48 | "bor" => 0, | |
49 | "borisoglebsk" => 0, | |
50 | "borovichi" => 0, | |
51 | "bratsk" => 0, | |
52 | "bryansk" => 0, | |
53 | "budyonnovsk" => 0, | |
54 | "bugulma" => 0, | |
55 | "buynaksk" => 0, | |
56 | "buzuluk" => 0, | |
57 | "chapayevsk" => 0, | |
58 | "chaykovsky" => 0, | |
59 | "cheboksary" => 0, | |
60 | "chekhov" => 0, | |
61 | "chelny" => 0, | |
62 | "chelyabinsk" => 0, | |
63 | "chepetsk" => 0, | |
64 | "cheremkhovo" => 0, | |
65 | "cherepovets" => 0, | |
66 | "cherkessk" => 0, | |
67 | "chernogorsk" => 0, | |
68 | "chistopol" => 0, | |
69 | "chita" => 0, | |
70 | "derbent" => 0, | |
71 | "dimitrovgrad" => 0, | |
72 | "dmitrov" => 0, | |
73 | "dolgoprudny" => 0, | |
74 | "domodedovo" => 0, | |
75 | "don" => 0, | |
76 | "donetsk" => 0, | |
77 | "donskoy" => 0, | |
78 | "dubna" => 0, | |
79 | "dzerzhinsk" => 0, | |
80 | "elektrostal" => 0, | |
81 | "elista" => 0, | |
82 | "engels" => 0, | |
83 | "fominsk" => 0, | |
84 | "fryazino" => 0, | |
85 | "gatchina" => 0, | |
86 | "gelendzhik" => 0, | |
87 | "georgiyevsk" => 0, | |
88 | "glazov" => 0, | |
89 | "gorno" => 0, | |
90 | "grozny" => 0, | |
91 | "gubkin" => 0, | |
92 | "gukovo" => 0, | |
93 | "gus" => 0, | |
94 | "ilimsk" => 0, | |
95 | "irkutsk" => 0, | |
96 | "ishim" => 0, | |
97 | "ishimbay" => 0, | |
98 | "iskitim" => 0, | |
99 | "ivanovo" => 0, | |
100 | "ivanteyevka" => 0, | |
101 | "izberbash" => 0, | |
102 | "izhevsk" => 0, | |
103 | "kaliningrad" => 0, | |
104 | "kaluga" => 0, | |
105 | "kamchatsky" => 0, | |
106 | "kamensk" => 0, | |
107 | "kamyshin" => 0, | |
108 | "kansk" => 0, | |
109 | "karelia" => 0, | |
110 | "kaspiysk" => 0, | |
111 | "kazan" => 0, | |
112 | "kemerovo" => 0, | |
113 | "khabarovsk" => 0, | |
114 | "khakassia" => 0, | |
115 | "khanty" => 0, | |
116 | "khasavyurt" => 0, | |
117 | "khimki" => 0, | |
118 | "khrustalny" => 0, | |
119 | "kineshma" => 0, | |
120 | "kirishi" => 0, | |
121 | "kirov" => 0, | |
122 | "kirovo" => 0, | |
123 | "kiselyovsk" => 0, | |
124 | "kislovodsk" => 0, | |
125 | "klimovsk" => 0, | |
126 | "klin" => 0, | |
127 | "klintsy" => 0, | |
128 | "kogalym" => 0, | |
129 | "kolomna" => 0, | |
130 | "komsomolsk" => 0, | |
131 | "kopeysk" => 0, | |
132 | "korolyov" => 0, | |
133 | "kostroma" => 0, | |
134 | "kotlas" => 0, | |
135 | "kovrov" => 0, | |
136 | "krai" => 0, | |
137 | "krasnodar" => 0, | |
138 | "krasnogorsk" => 0, | |
139 | "krasnokamensk" => 0, | |
140 | "krasnokamsk" => 0, | |
141 | "krasnoturyinsk" => 0, | |
142 | "krasnoyarsk" => 0, | |
143 | "kropotkin" => 0, | |
144 | "krymsk" => 0, | |
145 | "kstovo" => 0, | |
146 | "kubani" => 0, | |
147 | "kumertau" => 0, | |
148 | "kungur" => 0, | |
149 | "kurgan" => 0, | |
150 | "kursk" => 0, | |
151 | "kuznetsk" => 0, | |
152 | "kuznetsky" => 0, | |
153 | "kyzyl" => 0, | |
154 | "labinsk" => 0, | |
155 | "leningrad" => 0, | |
156 | "leninogorsk" => 0, | |
157 | "leninsk" => 0, | |
158 | "lesnoy" => 0, | |
159 | "lesosibirsk" => 0, | |
160 | "lipetsk" => 0, | |
161 | "liski" => 0, | |
162 | "livny" => 0, | |
163 | "lobnya" => 0, | |
164 | "luki" => 0, | |
165 | "lysva" => 0, | |
166 | "lytkarino" => 0, | |
167 | "lyubertsy" => 0, | |
168 | "magadan" => 0, | |
169 | "magnitogorsk" => 0, | |
170 | "makhachkala" => 0, | |
171 | "mansi" => 0, | |
172 | "mansiysk" => 0, | |
173 | "maykop" => 0, | |
174 | "meleuz" => 0, | |
175 | "mezhdurechensk" => 0, | |
176 | "miass" => 0, | |
177 | "michurinsk" => 0, | |
178 | "mikhaylovka" => 0, | |
179 | "mikhaylovsk" => 0, | |
180 | "mineralnye" => 0, | |
181 | "minusinsk" => 0, | |
182 | "moscow" => 0, | |
183 | "murmansk" => 0, | |
184 | "murom" => 0, | |
185 | "mytishchi" => 0, | |
186 | "naberezhnye" => 0, | |
187 | "nakhodka" => 0, | |
188 | "nalchik" => 0, | |
189 | "naro" => 0, | |
190 | "nazarovo" => 0, | |
191 | "nazran" => 0, | |
192 | "neftekamsk" => 0, | |
193 | "nefteyugansk" => 0, | |
194 | "neryungri" => 0, | |
195 | "nevinnomyssk" => 0, | |
196 | "nizhnekamsk" => 0, | |
197 | "nizhnevartovsk" => 0, | |
198 | "nizhny" => 0, | |
199 | "noginsk" => 0, | |
200 | "norilsk" => 0, | |
201 | "novgorod" => 0, | |
202 | "novoaltaysk" => 0, | |
203 | "novocheboksarsk" => 0, | |
204 | "novocherkassk" => 0, | |
205 | "novokuybyshevsk" => 0, | |
206 | "novokuznetsk" => 0, | |
207 | "novomoskovsk" => 0, | |
208 | "novorossiysk" => 0, | |
209 | "novoshakhtinsk" => 0, | |
210 | "novosibirsk" => 0, | |
211 | "novotroitsk" => 0, | |
212 | "novouralsk" => 0, | |
213 | "novy" => 0, | |
214 | "noyabrsk" => 0, | |
215 | "nyagan" => 0, | |
216 | "oblast" => 0, | |
217 | "obninsk" => 0, | |
218 | "odintsovo" => 0, | |
219 | "oktyabrsky" => 0, | |
220 | "ola" => 0, | |
221 | "omsk" => 0, | |
222 | "on" => 0, | |
223 | "orekhovo" => 0, | |
224 | "orenburg" => 0, | |
225 | "orsk" => 0, | |
226 | "oryol" => 0, | |
227 | "oskol" => 0, | |
228 | "ozyorsk" => 0, | |
229 | "pavlovsky" => 0, | |
230 | "penza" => 0, | |
231 | "perm" => 0, | |
232 | "pervouralsk" => 0, | |
233 | "petersburg" => 0, | |
234 | "petropavlovsk" => 0, | |
235 | "petrozavodsk" => 0, | |
236 | "podolsk" => 0, | |
237 | "polevskoy" => 0, | |
238 | "posad" => 0, | |
239 | "prokhladny" => 0, | |
240 | "prokopyevsk" => 0, | |
241 | "pskov" => 0, | |
242 | "pushkino" => 0, | |
243 | "pyatigorsk" => 0, | |
244 | "pyshma" => 0, | |
245 | "ramenskoye" => 0, | |
246 | "reutov" => 0, | |
247 | "revda" => 0, | |
248 | "roslavl" => 0, | |
249 | "rossosh" => 0, | |
250 | "rostov" => 0, | |
251 | "rubtsovsk" => 0, | |
252 | "ryazan" => 0, | |
253 | "rybinsk" => 0, | |
254 | "rzhev" => 0, | |
255 | "saint" => 0, | |
256 | "sakhalin" => 0, | |
257 | "sakhalinsk" => 0, | |
258 | "salavat" => 0, | |
259 | "salsk" => 0, | |
260 | "samara" => 0, | |
261 | "saransk" => 0, | |
262 | "sarapul" => 0, | |
263 | "saratov" => 0, | |
264 | "sarov" => 0, | |
265 | "sergiyev" => 0, | |
266 | "serov" => 0, | |
267 | "serpukhov" => 0, | |
268 | "severodvinsk" => 0, | |
269 | "severomorsk" => 0, | |
270 | "seversk" => 0, | |
271 | "shadrinsk" => 0, | |
272 | "shakhtinsky" => 0, | |
273 | "shakhty" => 0, | |
274 | "shchyokino" => 0, | |
275 | "shchyolkovo" => 0, | |
276 | "shuya" => 0, | |
277 | "sibay" => 0, | |
278 | "sibirskoye" => 0, | |
279 | "slavyansk" => 0, | |
280 | "smolensk" => 0, | |
281 | "sochi" => 0, | |
282 | "solikamsk" => 0, | |
283 | "solnechnogorsk" => 0, | |
284 | "sosnovy" => 0, | |
285 | "stary" => 0, | |
286 | "stavropol" => 0, | |
287 | "sterlitamak" => 0, | |
288 | "stupino" => 0, | |
289 | "sudzhensk" => 0, | |
290 | "surgut" => 0, | |
291 | "sverdlovsk" => 0, | |
292 | "svobodny" => 0, | |
293 | "syktyvkar" => 0, | |
294 | "syzran" => 0, | |
295 | "taganrog" => 0, | |
296 | "tagil" => 0, | |
297 | "tambov" => 0, | |
298 | "tatarstan" => 0, | |
299 | "tikhoretsk" => 0, | |
300 | "tikhvin" => 0, | |
301 | "timashyovsk" => 0, | |
302 | "tobolsk" => 0, | |
303 | "tolyatti" => 0, | |
304 | "tomsk" => 0, | |
305 | "troitsk" => 0, | |
306 | "tuapse" => 0, | |
307 | "tula" => 0, | |
308 | "tuymazy" => 0, | |
309 | "tver" => 0, | |
310 | "tyumen" => 0, | |
311 | "ude" => 0, | |
312 | "ufa" => 0, | |
313 | "ukhta" => 0, | |
314 | "ulan" => 0, | |
315 | "ulyanovsk" => 0, | |
316 | "uralsky" => 0, | |
317 | "urengoy" => 0, | |
318 | "usolye" => 0, | |
319 | "ussuriysk" => 0, | |
320 | "ust" => 0, | |
321 | "uzlovaya" => 0, | |
322 | "velikiye" => 0, | |
323 | "veliky" => 0, | |
324 | "verkhnyaya" => 0, | |
325 | "vidnoye" => 0, | |
326 | "vladikavkaz" => 0, | |
327 | "vladimir" => 0, | |
328 | "vladivostok" => 0, | |
329 | "vody" => 0, | |
330 | "volgodonsk" => 0, | |
331 | "volgograd" => 0, | |
332 | "volochyok" => 0, | |
333 | "vologda" => 0, | |
334 | "volsk" => 0, | |
335 | "volzhsk" => 0, | |
336 | "volzhsky" => 0, | |
337 | "vorkuta" => 0, | |
338 | "voronezh" => 0, | |
339 | "voskresensk" => 0, | |
340 | "votkinsk" => 0, | |
341 | "vsevolozhsk" => 0, | |
342 | "vyazma" => 0, | |
343 | "vyborg" => 0, | |
344 | "vyksa" => 0, | |
345 | "vyshny" => 0, | |
346 | "yakutsk" => 0, | |
347 | "yaroslavl" => 0, | |
348 | "yegoryevsk" => 0, | |
349 | "yekaterinburg" => 0, | |
350 | "yelabuga" => 0, | |
351 | "yelets" => 0, | |
352 | "yessentuki" => 0, | |
353 | "yeysk" => 0, | |
354 | "yoshkar" => 0, | |
355 | "yurga" => 0, | |
356 | "yuzhno" => 0, | |
357 | "zarechny" => 0, | |
358 | "zelenodolsk" => 0, | |
359 | "zelenogorsk" => 0, | |
360 | "zheleznodorozhny" => 0, | |
361 | "zheleznogorsk" => 0, | |
362 | "zhigulyovsk" => 0, | |
363 | "zhukovsky" => 0, | |
364 | "zlatoust" => 0, | |
365 | "zuyevo" => 0} | |
366 | ||
367 | end | |
368 | ||
369 | def get_results() | |
370 | return super("Russian Cities") | |
371 | end | |
372 | end |
0 | require_relative "../list_checker.rb" | |
1 | ||
2 | register_checker("Season_Checker") | |
3 | ||
4 | class Season_Checker < List_Checker | |
5 | def initialize | |
6 | super | |
7 | @description = "List of common English seasons" | |
8 | @list = {"summer" => 0, "fall" => 0, "winter" => 0, "spring" => 0} | |
9 | end | |
10 | ||
11 | def get_results() | |
12 | return super("Seasons") | |
13 | end | |
14 | end |
0 | register_checker("US_Area_Code_Checker") | |
1 | ||
2 | US_area_codes = {} | |
3 | ||
4 | US_area_codes[201] = ["NJ","N New Jersey: Jersey City, Hackensack"] | |
5 | US_area_codes[202] = ["DC","Washington, D.C."] | |
6 | US_area_codes[203] = ["CT","Connecticut: Fairfield County and New Haven County; Bridgeport, New Haven"] | |
7 | US_area_codes[204] = ["MB","Canada: Manitoba"] | |
8 | US_area_codes[205] = ["AL","Central Alabama (including Birmingham)"] | |
9 | US_area_codes[206] = ["WA","W Washington state: Seattle and Bainbridge Island"] | |
10 | US_area_codes[207] = ["ME","Maine"] | |
11 | US_area_codes[208] = ["ID","Idaho"] | |
12 | US_area_codes[209] = ["CA","Cent. California: Stockton"] | |
13 | US_area_codes[210] = ["TX","S Texas: San Antonio"] | |
14 | US_area_codes[211] = ["--","Local community info / referral services"] | |
15 | US_area_codes[212] = ["NY","New York City, New York"] | |
16 | US_area_codes[213] = ["CA","S California: Los Angeles"] | |
17 | US_area_codes[214] = ["TX","Texas: Dallas Metro"] | |
18 | US_area_codes[215] = ["PA","SE Pennsylvania: Philadelphia"] | |
19 | US_area_codes[216] = ["OH","Cleveland"] | |
20 | US_area_codes[217] = ["IL","Cent. Illinois: Springfield"] | |
21 | US_area_codes[218] = ["MN","N Minnesota: Duluth"] | |
22 | US_area_codes[219] = ["IN","NW Indiana: Gary"] | |
23 | US_area_codes[224] = ["IL","Northern NE Illinois: Evanston, Waukegan, Northbrook"] | |
24 | US_area_codes[225] = ["LA","Louisiana: Baton Rouge, New Roads, Donaldsonville, Albany, Gonzales, Greensburg, Plaquemine, Vacherie"] | |
25 | US_area_codes[226] = ["ON","Canada: SW Ontario: Windsor"] | |
26 | US_area_codes[228] = ["MS","S Mississippi"] | |
27 | US_area_codes[229] = ["GA","SW Georgia: Albany"] | |
28 | US_area_codes[231] = ["MI","W Michigan: Northwestern portion of lower Peninsula; Traverse City, Muskegon, Cheboygan, Alanson"] | |
29 | US_area_codes[234] = ["OH","NE Ohio: Canton, Akron"] | |
30 | US_area_codes[236] = ["VA","Virginia (region unknown) / Unassigned?"] | |
31 | US_area_codes[239] = ["FL","Florida"] | |
32 | US_area_codes[240] = ["MD","W Maryland: Silver Spring, Frederick, Gaithersburg"] | |
33 | US_area_codes[242] = ["--","Bahamas"] | |
34 | US_area_codes[246] = ["--","Barbados"] | |
35 | US_area_codes[248] = ["MI","Michigan: Oakland County, Pontiac"] | |
36 | US_area_codes[250] = ["BC","Canada: British Columbia"] | |
37 | US_area_codes[251] = ["AL","S Alabama: Mobile and coastal areas, Jackson, Evergreen, Monroeville"] | |
38 | US_area_codes[252] = ["NC","E North Carolina"] | |
39 | US_area_codes[253] = ["WA","Washington: South Tier - Tacoma, Federal Way"] | |
40 | US_area_codes[254] = ["TX","Central Texas"] | |
41 | US_area_codes[256] = ["AL","E and N Alabama"] | |
42 | US_area_codes[260] = ["IN","NE Indiana: Fort Wayne"] | |
43 | US_area_codes[262] = ["WI","SE Wisconsin: counties of Kenosha, Ozaukee, Racine, Walworth, Washington, Waukesha"] | |
44 | US_area_codes[264] = ["--","Anguilla"] | |
45 | US_area_codes[267] = ["PA","SE Pennsylvania: Philadelphia"] | |
46 | US_area_codes[268] = ["--","Antigua and Barbuda"] | |
47 | US_area_codes[269] = ["MI","SW Michigan: Kalamazoo, Saugatuck, Hastings, Battle Creek, Sturgis to Lake Michigan"] | |
48 | US_area_codes[270] = ["KY","W Kentucky: Bowling Green, Paducah"] | |
49 | US_area_codes[276] = ["VA","S and SW Virginia: Bristol, Stuart, Martinsville"] | |
50 | US_area_codes[278] = ["MI","Michigan"] | |
51 | US_area_codes[281] = ["TX","Texas: Houston Metro"] | |
52 | US_area_codes[283] = ["OH","SW Ohio: Cincinnati"] | |
53 | US_area_codes[284] = ["--","British Virgin Islands"] | |
54 | US_area_codes[289] = ["ON","Canada: S Cent. Ontario: Greater Toronto Area -- Durham, Halton, Hamilton-Wentworth, Niagara, Peel, York, and southern Simcoe County"] | |
55 | US_area_codes[301] = ["MD","W Maryland: Silver Spring, Frederick, Camp Springs, Prince George's County"] | |
56 | US_area_codes[302] = ["DE","Delaware"] | |
57 | US_area_codes[303] = ["CO","Central Colorado: Denver"] | |
58 | US_area_codes[304] = ["WV","West Virginia"] | |
59 | US_area_codes[305] = ["FL","SE Florida: Miami, the Keys"] | |
60 | US_area_codes[306] = ["SK","Canada: Saskatchewan"] | |
61 | US_area_codes[307] = ["WY","Wyoming"] | |
62 | US_area_codes[308] = ["NE","W Nebraska: North Platte"] | |
63 | US_area_codes[309] = ["IL","W Cent. Illinois: Peoria"] | |
64 | US_area_codes[310] = ["CA","S California: Beverly Hills, West Hollywood, West Los Angeles"] | |
65 | US_area_codes[311] = ["--","Reserved for special applications"] | |
66 | US_area_codes[312] = ["IL","Illinois: Chicago"] | |
67 | US_area_codes[313] = ["MI","Michigan: Detroit and suburbs"] | |
68 | US_area_codes[314] = ["MO","SE Missouri: St Louis city and parts of the metro area only"] | |
69 | US_area_codes[315] = ["NY","N Cent. New York: Syracuse"] | |
70 | US_area_codes[316] = ["KS","S Kansas: Wichita"] | |
71 | US_area_codes[317] = ["IN","Cent. Indiana: Indianapolis"] | |
72 | US_area_codes[318] = ["LA","N Louisiana: Shreveport, Ruston, Monroe, Alexandria"] | |
73 | US_area_codes[319] = ["IA","E Iowa: Cedar Rapids"] | |
74 | US_area_codes[320] = ["MN","Cent. Minnesota: Saint Cloud"] | |
75 | US_area_codes[321] = ["FL","Florida: Brevard County, Cape Canaveral area; Metro Orlando"] | |
76 | US_area_codes[323] = ["CA","S California: Los Angeles"] | |
77 | US_area_codes[325] = ["TX","Central Texas: Abilene, Sweetwater, Snyder, San Angelo"] | |
78 | US_area_codes[330] = ["OH","NE Ohio: Akron, Canton, Youngstown; Mahoning County, parts of Trumbull/Warren counties"] | |
79 | US_area_codes[331] = ["IL","W NE Illinois, western suburbs of Chicago"] | |
80 | US_area_codes[334] = ["AL","S Alabama: Auburn/Opelika, Montgomery and coastal areas"] | |
81 | US_area_codes[336] = ["NC","Cent. North Carolina: Greensboro, Winston-Salem, High Point"] | |
82 | US_area_codes[337] = ["LA","SW Louisiana: Lake Charles, Lafayette"] | |
83 | US_area_codes[339] = ["MA","Massachusetts: Boston suburbs, to the south and west"] | |
84 | US_area_codes[340] = ["VI","US Virgin Islands"] | |
85 | US_area_codes[341] = ["CA","(overlay on 510; SUSPENDED)"] | |
86 | US_area_codes[345] = ["--","Cayman Islands"] | |
87 | US_area_codes[347] = ["NY","New York"] | |
88 | US_area_codes[351] = ["MA","Massachusetts: north of Boston to NH, 508, and 781"] | |
89 | US_area_codes[352] = ["FL","Florida: Gainesville area, Ocala, Crystal River"] | |
90 | US_area_codes[360] = ["WA","W Washington State: Olympia, Bellingham"] | |
91 | US_area_codes[361] = ["TX","S Texas: Corpus Christi"] | |
92 | US_area_codes[369] = ["CA","Solano County"] | |
93 | US_area_codes[380] = ["OH","Ohio: Columbus"] | |
94 | US_area_codes[385] = ["UT","Utah: Salt Lake City Metro"] | |
95 | US_area_codes[386] = ["FL","N central Florida: Lake City"] | |
96 | US_area_codes[401] = ["RI","Rhode Island"] | |
97 | US_area_codes[402] = ["NE","E Nebraska: Omaha, Lincoln"] | |
98 | US_area_codes[403] = ["AB","Canada: Southern Alberta"] | |
99 | US_area_codes[404] = ["GA","N Georgia: Atlanta and suburbs"] | |
100 | US_area_codes[405] = ["OK","W Oklahoma: Oklahoma City"] | |
101 | US_area_codes[406] = ["MT","Montana"] | |
102 | US_area_codes[407] = ["FL","Central Florida: Metro Orlando"] | |
103 | US_area_codes[408] = ["CA","Cent. Coastal California: San Jose"] | |
104 | US_area_codes[409] = ["TX","SE Texas: Galveston, Port Arthur, Beaumont"] | |
105 | US_area_codes[410] = ["MD","E Maryland: Baltimore, Annapolis, Chesapeake Bay area, Ocean City"] | |
106 | US_area_codes[411] = ["--","Reserved for special applications"] | |
107 | US_area_codes[412] = ["PA","W Pennsylvania: Pittsburgh"] | |
108 | US_area_codes[413] = ["MA","W Massachusetts: Springfield"] | |
109 | US_area_codes[414] = ["WI","SE Wisconsin: Milwaukee County"] | |
110 | US_area_codes[415] = ["CA","California: San Francisco County and Marin County on the north side of the Golden Gate Bridge, extending north to Sonoma County"] | |
111 | US_area_codes[416] = ["ON","Canada: S Cent. Ontario: Toronto"] | |
112 | US_area_codes[417] = ["MO","SW Missouri: Springfield"] | |
113 | US_area_codes[418] = ["QC","Canada: NE Quebec: Quebec"] | |
114 | US_area_codes[419] = ["OH","NW Ohio: Toledo"] | |
115 | US_area_codes[423] = ["TN","E Tennessee, except Knoxville metro area: Chattanooga, Bristol, Johnson City, Kingsport, Greeneville"] | |
116 | US_area_codes[424] = ["CA","S California: Los Angeles"] | |
117 | US_area_codes[425] = ["WA","Washington: North Tier - Everett, Bellevue"] | |
118 | US_area_codes[430] = ["TX","NE Texas: Tyler"] | |
119 | US_area_codes[432] = ["TX","W Texas: Big Spring, Midland, Odessa"] | |
120 | US_area_codes[434] = ["VA","E Virginia: Charlottesville, Lynchburg, Danville, South Boston, and Emporia"] | |
121 | US_area_codes[435] = ["UT","Rural Utah outside Salt Lake City metro"] | |
122 | US_area_codes[438] = ["QC","Canada: SW Quebec: Montreal city"] | |
123 | US_area_codes[440] = ["OH","Ohio: Cleveland metro area, excluding Cleveland"] | |
124 | US_area_codes[441] = ["--","Bermuda"] | |
125 | US_area_codes[442] = ["CA","Far north suburbs of San Diego"] | |
126 | US_area_codes[443] = ["MD","E Maryland: Baltimore, Annapolis, Chesapeake Bay area, Ocean City"] | |
127 | US_area_codes[450] = ["QC","Canada: Southeastern Quebec; suburbs outside metro Montreal"] | |
128 | US_area_codes[456] = ["--","Inbound International"] | |
129 | US_area_codes[464] = ["IL","Illinois: south suburbs of Chicago"] | |
130 | US_area_codes[469] = ["TX","Texas: Dallas Metro"] | |
131 | US_area_codes[470] = ["GA","Georgia: Greater Atlanta Metropolitan Area"] | |
132 | US_area_codes[473] = ["--","Grenada"] | |
133 | US_area_codes[475] = ["CT","Connecticut: New Haven, Greenwich, southwestern"] | |
134 | US_area_codes[478] = ["GA","Central Georgia: Macon"] | |
135 | US_area_codes[479] = ["AR","NW Arkansas: Fort Smith, Fayetteville, Springdale, Bentonville"] | |
136 | US_area_codes[480] = ["AZ","Arizona: East Phoenix"] | |
137 | US_area_codes[484] = ["PA","SE Pennsylvania: Allentown, Bethlehem, Reading, West Chester, Norristown"] | |
138 | US_area_codes[500] = ["--","Personal Communication Service"] | |
139 | US_area_codes[501] = ["AR","Central Arkansas: Little Rock, Hot Springs, Conway"] | |
140 | US_area_codes[502] = ["KY","N Central Kentucky: Louisville"] | |
141 | US_area_codes[503] = ["OR","Oregon"] | |
142 | US_area_codes[504] = ["LA","E Louisiana: New Orleans metro area"] | |
143 | US_area_codes[505] = ["NM","North central and northwestern New Mexico"] | |
144 | US_area_codes[506] = ["NB","Canada: New Brunswick"] | |
145 | US_area_codes[507] = ["MN","S Minnesota: Rochester, Mankato, Worthington"] | |
146 | US_area_codes[508] = ["MA","Cent. Massachusetts: Framingham; Cape Cod"] | |
147 | US_area_codes[509] = ["WA","E and Central Washington state: Spokane, Yakima, Walla Walla, Ellensburg"] | |
148 | US_area_codes[510] = ["CA","California: Oakland, East Bay"] | |
149 | US_area_codes[511] = ["--","Nationwide travel information"] | |
150 | US_area_codes[512] = ["TX","S Texas: Austin"] | |
151 | US_area_codes[513] = ["OH","SW Ohio: Cincinnati"] | |
152 | US_area_codes[514] = ["QC","Canada: SW Quebec: Montreal city"] | |
153 | US_area_codes[515] = ["IA","Cent. Iowa: Des Moines"] | |
154 | US_area_codes[516] = ["NY","New York: Nassau County, Long Island; Hempstead"] | |
155 | US_area_codes[517] = ["MI","Cent. Michigan: Lansing"] | |
156 | US_area_codes[518] = ["NY","NE New York: Albany"] | |
157 | US_area_codes[519] = ["ON","Canada: SW Ontario: Windsor"] | |
158 | US_area_codes[520] = ["AZ","SE Arizona: Tucson area"] | |
159 | US_area_codes[530] = ["CA","NE California: Eldorado County area, excluding Eldorado Hills itself: incl cities of Auburn, Chico, Redding, So. Lake Tahoe, Marysville, Nevada City/Grass Valley"] | |
160 | US_area_codes[539] = ["OK","E Oklahoma: Tulsa area"] | |
161 | US_area_codes[540] = ["VA","Western and Southwest Virginia: Shenandoah and Roanoke valleys: Fredericksburg, Harrisonburg, Roanoke, Salem, Lexington and nearby areas"] | |
162 | US_area_codes[541] = ["OR","Oregon: Eugene, Medford"] | |
163 | US_area_codes[551] = ["NJ","N New Jersey: Jersey City, Hackensack"] | |
164 | US_area_codes[555] = ["--","Reserved for directory assistance applications"] | |
165 | US_area_codes[557] = ["MO","SE Missouri: St Louis metro area only"] | |
166 | US_area_codes[559] = ["CA","Central California: Fresno"] | |
167 | US_area_codes[561] = ["FL","S. Central Florida: Palm Beach County"] | |
168 | US_area_codes[562] = ["CA","California: Long Beach"] | |
169 | US_area_codes[563] = ["IA","E Iowa: Davenport, Dubuque"] | |
170 | US_area_codes[564] = ["WA","W Washington State: Olympia, Bellingham"] | |
171 | US_area_codes[567] = ["OH","NW Ohio: Toledo"] | |
172 | US_area_codes[570] = ["PA","NE and N Central Pennsylvania: Wilkes-Barre, Scranton"] | |
173 | US_area_codes[571] = ["VA","Northern Virginia: Arlington, McLean, Tysons Corner"] | |
174 | US_area_codes[573] = ["MO","SE Missouri: excluding St Louis metro area, includes Central/East Missouri, area between St. Louis and Kansas City"] | |
175 | US_area_codes[574] = ["IN","N Indiana: Elkhart, South Bend"] | |
176 | US_area_codes[575] = ["NM","New Mexico"] | |
177 | US_area_codes[580] = ["OK","W Oklahoma"] | |
178 | US_area_codes[585] = ["NY","NW New York: Rochester"] | |
179 | US_area_codes[586] = ["MI","Michigan: Macomb County"] | |
180 | US_area_codes[600] = ["--","Canadian Services"] | |
181 | US_area_codes[601] = ["MS","Mississippi: Meridian, Jackson area"] | |
182 | US_area_codes[602] = ["AZ","Arizona: Phoenix"] | |
183 | US_area_codes[603] = ["NH","New Hampshire"] | |
184 | US_area_codes[604] = ["BC","Canada: British Columbia: Greater Vancouver"] | |
185 | US_area_codes[605] = ["SD","South Dakota"] | |
186 | US_area_codes[606] = ["KY","E Kentucky: area east of Frankfort: Ashland"] | |
187 | US_area_codes[607] = ["NY","S Cent. New York: Ithaca, Binghamton; Catskills"] | |
188 | US_area_codes[608] = ["WI","SW Wisconsin: Madison"] | |
189 | US_area_codes[609] = ["NJ","S New Jersey: Trenton"] | |
190 | US_area_codes[610] = ["PA","SE Pennsylvania: Allentown, Bethlehem, Reading, West Chester, Norristown"] | |
191 | US_area_codes[611] = ["--","Reserved for special applications"] | |
192 | US_area_codes[612] = ["MN","Cent. Minnesota: Minneapolis"] | |
193 | US_area_codes[613] = ["ON","Canada: SE Ontario: Ottawa"] | |
194 | US_area_codes[614] = ["OH","SE Ohio: Columbus"] | |
195 | US_area_codes[615] = ["TN","Northern Middle Tennessee: Nashville metro area"] | |
196 | US_area_codes[616] = ["MI","W Michigan: Holland, Grand Haven, Greenville, Grand Rapids, Ionia"] | |
197 | US_area_codes[617] = ["MA","Massachusetts: greater Boston"] | |
198 | US_area_codes[618] = ["IL","S Illinois: Centralia"] | |
199 | US_area_codes[619] = ["CA","S California: San Diego"] | |
200 | US_area_codes[620] = ["KS","S Kansas: Wichita"] | |
201 | US_area_codes[623] = ["AZ","Arizona: West Phoenix"] | |
202 | US_area_codes[626] = ["CA","E S California: Pasadena"] | |
203 | US_area_codes[627] = ["CA","No longer in use [was Napa, Sonoma counties"] | |
204 | US_area_codes[628] = ["CA","(Region unknown; perm 10/21/00)21/00)00)"] | |
205 | US_area_codes[630] = ["IL","W NE Illinois, western suburbs of Chicago"] | |
206 | US_area_codes[631] = ["NY","New York: Suffolk County, Long Island; Huntington, Riverhead"] | |
207 | US_area_codes[636] = ["MO","Missouri: W St. Louis metro area of St. Louis county, St. Charles County, Jefferson County area south"] | |
208 | US_area_codes[641] = ["IA","Iowa: Mason City, Marshalltown, Creston, Ottumwa"] | |
209 | US_area_codes[646] = ["NY","New York"] | |
210 | US_area_codes[647] = ["ON","Canada: S Cent. Ontario: Toronto"] | |
211 | US_area_codes[649] = ["--","Turks & Caicos Islands"] | |
212 | US_area_codes[650] = ["CA","California: Peninsula south of San Francisco -- San Mateo County, parts of Santa Clara County"] | |
213 | US_area_codes[651] = ["MN","Cent. Minnesota: St. Paul"] | |
214 | US_area_codes[660] = ["MO","N Missouri"] | |
215 | US_area_codes[661] = ["CA","California: N Los Angeles, Mckittrick, Mojave, Newhall, Oildale, Palmdale, Taft, Tehachapi, Bakersfield, Earlimart, Lancaster"] | |
216 | US_area_codes[662] = ["MS","N Mississippi: Tupelo, Grenada"] | |
217 | US_area_codes[664] = ["--","Montserrat"] | |
218 | US_area_codes[669] = ["CA","Cent. Coastal California: San Jose"] | |
219 | US_area_codes[670] = ["MP","Commonwealth of the Northern Mariana Islands (CNMI, US Commonwealth)"] | |
220 | US_area_codes[671] = ["GU","Guam"] | |
221 | US_area_codes[678] = ["GA","N Georgia: metropolitan Atlanta"] | |
222 | US_area_codes[679] = ["MI","Michigan: Dearborn area"] | |
223 | US_area_codes[682] = ["TX","Texas: Fort Worth areas"] | |
224 | US_area_codes[684] = ["--","American Samoa"] | |
225 | US_area_codes[689] = ["FL","Central Florida: Metro Orlando"] | |
226 | US_area_codes[700] = ["--","Interexchange Carrier Services"] | |
227 | US_area_codes[701] = ["ND","North Dakota"] | |
228 | US_area_codes[702] = ["NV","S. Nevada: Clark County, incl Las Vegas"] | |
229 | US_area_codes[703] = ["VA","Northern Virginia: Arlington, McLean, Tysons Corner"] | |
230 | US_area_codes[704] = ["NC","W North Carolina: Charlotte"] | |
231 | US_area_codes[705] = ["ON","Canada: NE Ontario: Sault Ste. Marie/N Ontario: N Bay, Sudbury"] | |
232 | US_area_codes[706] = ["GA","N Georgia: Columbus, Augusta"] | |
233 | US_area_codes[707] = ["CA","NW California: Santa Rosa, Napa, Vallejo, American Canyon, Fairfield"] | |
234 | US_area_codes[708] = ["IL","Illinois: southern and western suburbs of Chicago"] | |
235 | US_area_codes[709] = ["NL","Canada: Newfoundland and Labrador"] | |
236 | US_area_codes[710] = ["--","US Government"] | |
237 | US_area_codes[711] = ["--","Telecommunications Relay Services"] | |
238 | US_area_codes[712] = ["IA","W Iowa: Council Bluffs"] | |
239 | US_area_codes[713] = ["TX","Mid SE Texas: central Houston"] | |
240 | US_area_codes[714] = ["CA","North and Central Orange County"] | |
241 | US_area_codes[715] = ["WI","N Wisconsin: Eau Claire, Wausau, Superior"] | |
242 | US_area_codes[716] = ["NY","NW New York: Buffalo"] | |
243 | US_area_codes[717] = ["PA","E Pennsylvania: Harrisburg"] | |
244 | US_area_codes[718] = ["NY","New York City, New York"] | |
245 | US_area_codes[719] = ["CO","SE Colorado: Pueblo, Colorado Springs"] | |
246 | US_area_codes[720] = ["CO","Central Colorado: Denver"] | |
247 | US_area_codes[724] = ["PA","SW Pennsylvania"] | |
248 | US_area_codes[727] = ["FL","Florida Tampa Metro: Saint Petersburg, Clearwater"] | |
249 | US_area_codes[731] = ["TN","W Tennessee: outside Memphis metro area"] | |
250 | US_area_codes[732] = ["NJ","Cent. New Jersey: Toms River, New Brunswick, Bound Brook"] | |
251 | US_area_codes[734] = ["MI","SE Michigan: west and south of Detroit -- Ann Arbor, Monroe"] | |
252 | US_area_codes[737] = ["TX","S Texas: Austin"] | |
253 | US_area_codes[740] = ["OH","SE Ohio"] | |
254 | US_area_codes[747] = ["CA","S California: Los Angeles, Agoura Hills, Calabasas, Hidden Hills, and Westlake Village"] | |
255 | US_area_codes[754] = ["FL","Florida: Broward County area, incl Ft. Lauderdale"] | |
256 | US_area_codes[757] = ["VA","E Virginia: Tidewater / Hampton Roads area -- Norfolk, Virginia Beach, Chesapeake, Portsmouth, Hampton, Newport News, Suffolk"] | |
257 | US_area_codes[758] = ["--","St. Lucia"] | |
258 | US_area_codes[760] = ["CA","California: San Diego North County to Sierra Nevada"] | |
259 | US_area_codes[762] = ["GA","N Georgia: Columbus, Augusta"] | |
260 | US_area_codes[763] = ["MN","Minnesota: Minneapolis NW"] | |
261 | US_area_codes[764] = ["CA","SUSPENDED"] | |
262 | US_area_codes[765] = ["IN","Indiana: outside Indianapolis"] | |
263 | US_area_codes[767] = ["--","Dominica"] | |
264 | US_area_codes[769] = ["MS","Mississippi: Meridian, Jackson area"] | |
265 | US_area_codes[770] = ["GA","Georgia: Atlanta suburbs: outside of I-285 ring road"] | |
266 | US_area_codes[772] = ["FL","S. Central Florida: St. Lucie, Martin, and Indian River counties"] | |
267 | US_area_codes[773] = ["IL","Illinois: city of Chicago, outside the loop"] | |
268 | US_area_codes[774] = ["MA","Cent. Massachusetts: Framingham; Cape Cod"] | |
269 | US_area_codes[775] = ["NV","N. Nevada: Reno"] | |
270 | US_area_codes[778] = ["BC","Canada: British Columbia: Greater Vancouver"] | |
271 | US_area_codes[779] = ["IL","NW Illinois: Rockford, Kankakee"] | |
272 | US_area_codes[780] = ["AB","Canada: Northern Alberta, north of Lacombe"] | |
273 | US_area_codes[781] = ["MA","Massachusetts: Boston surburbs, to the north and west"] | |
274 | US_area_codes[784] = ["--","St. Vincent & Grenadines"] | |
275 | US_area_codes[785] = ["KS","N & W Kansas: Topeka"] | |
276 | US_area_codes[786] = ["FL","SE Florida, Monroe County"] | |
277 | US_area_codes[787] = ["PR","Puerto Rico"] | |
278 | US_area_codes[800] = ["--","US/Canada toll free"] | |
279 | US_area_codes[801] = ["UT","Utah: Salt Lake City Metro"] | |
280 | US_area_codes[802] = ["VT","Vermont"] | |
281 | US_area_codes[803] = ["SC","South Carolina: Columbia, Aiken, Sumter"] | |
282 | US_area_codes[804] = ["VA","E Virginia: Richmond"] | |
283 | US_area_codes[805] = ["CA","S Cent. and Cent. Coastal California: Ventura County, Santa Barbara County: San Luis Obispo, Thousand Oaks, Carpinteria, Santa Barbara, Santa Maria, Lompoc, Santa Ynez Valley / Solvang"] | |
284 | US_area_codes[806] = ["TX","Panhandle Texas: Amarillo, Lubbock"] | |
285 | US_area_codes[807] = ["ON","Canada: W Ontario: Thunder Bay region to Manitoba border"] | |
286 | US_area_codes[808] = ["HI","Hawaii"] | |
287 | US_area_codes[809] = ["--","Dominican Republic"] | |
288 | US_area_codes[810] = ["MI","E Michigan: Flint, Pontiac"] | |
289 | US_area_codes[811] = ["--","Reserved for special applications"] | |
290 | US_area_codes[812] = ["IN","S Indiana: Evansville, Cincinnati outskirts in IN, Columbus, Bloomington"] | |
291 | US_area_codes[813] = ["FL","SW Florida: Tampa Metro"] | |
292 | US_area_codes[814] = ["PA","Cent. Pennsylvania: Erie"] | |
293 | US_area_codes[815] = ["IL","NW Illinois: Rockford, Kankakee"] | |
294 | US_area_codes[816] = ["MO","N Missouri: Kansas City"] | |
295 | US_area_codes[817] = ["TX","N Cent. Texas: Fort Worth area"] | |
296 | US_area_codes[818] = ["CA","S California: Los Angeles: San Fernando Valley"] | |
297 | US_area_codes[819] = ["QC","NW Quebec: Trois Rivieres, Sherbrooke, Outaouais"] | |
298 | US_area_codes[822] = ["--","US/Canada toll free"] | |
299 | US_area_codes[828] = ["NC","W North Carolina: Asheville"] | |
300 | US_area_codes[829] = ["--","Dominican Republic"] | |
301 | US_area_codes[830] = ["TX","Texas: region surrounding San Antonio"] | |
302 | US_area_codes[831] = ["CA","California: central coast area from Santa Cruz through Monterey County"] | |
303 | US_area_codes[832] = ["TX","Texas: Houston"] | |
304 | US_area_codes[833] = ["--","US/Canada toll free"] | |
305 | US_area_codes[835] = ["PA","SE Pennsylvania: Allentown, Bethlehem, Reading, West Chester, Norristown"] | |
306 | US_area_codes[843] = ["SC","South Carolina, coastal area: Charleston, Beaufort, Myrtle Beach"] | |
307 | US_area_codes[844] = ["--","US/Canada toll free"] | |
308 | US_area_codes[845] = ["NY","New York: Poughkeepsie; Nyack, Nanuet, Valley Cottage, New City, Putnam, Dutchess, Rockland, Orange, Ulster and parts of Sullivan counties in New York's lower Hudson Valley and Delaware County in the Catskills"] | |
309 | US_area_codes[847] = ["IL","Northern NE Illinois: northwestern suburbs of chicago"] | |
310 | US_area_codes[848] = ["NJ","Cent. New Jersey: Toms River, New Brunswick, Bound Brook"] | |
311 | US_area_codes[850] = ["FL","Florida panhandle, from east of Tallahassee to Pensacola"] | |
312 | US_area_codes[855] = ["--","US/Canada toll free"] | |
313 | US_area_codes[856] = ["NJ","SW New Jersey: greater Camden area, Mt Laurel"] | |
314 | US_area_codes[857] = ["MA","Massachusetts: greater Boston"] | |
315 | US_area_codes[858] = ["CA","S California: San Diego"] | |
316 | US_area_codes[859] = ["KY","N and Central Kentucky: Lexington; suburban KY counties of Cincinnati OH metro area; Covington, Newport, Ft. Thomas, Ft. Wright, Florence"] | |
317 | US_area_codes[860] = ["CT","Connecticut: areas outside of Fairfield and New Haven Counties"] | |
318 | US_area_codes[862] = ["NJ","N New Jersey: Newark Paterson Morristown"] | |
319 | US_area_codes[863] = ["FL","Florida: Lakeland, Polk County"] | |
320 | US_area_codes[864] = ["SC","South Carolina, upstate area: Greenville, Spartanburg"] | |
321 | US_area_codes[865] = ["TN","E Tennessee: Knoxville, Knox and adjacent counties"] | |
322 | US_area_codes[866] = ["--","US/Canada toll free"] | |
323 | US_area_codes[867] = ["YT","Canada: Yukon, Northwest Territories, Nunavut"] | |
324 | US_area_codes[868] = ["--","Trinidad and Tobago"] | |
325 | US_area_codes[869] = ["--","St. Kitts & Nevis"] | |
326 | US_area_codes[870] = ["AR","Arkansas: areas outside of west/central AR: Jonesboro, etc"] | |
327 | US_area_codes[872] = ["IL","Illinois: Chicago"] | |
328 | US_area_codes[876] = ["--","Jamaica"] | |
329 | US_area_codes[877] = ["--","US/Canada toll free"] | |
330 | US_area_codes[878] = ["PA","Pittsburgh, New Castle"] | |
331 | US_area_codes[880] = ["--","Paid Toll-Free Service"] | |
332 | US_area_codes[881] = ["--","Paid Toll-Free Service"] | |
333 | US_area_codes[882] = ["--","Paid Toll-Free Service"] | |
334 | US_area_codes[888] = ["--","US/Canada toll free"] | |
335 | US_area_codes[898] = ["--","VoIP service"] | |
336 | US_area_codes[900] = ["--","US toll calls -- prices vary with the number called"] | |
337 | US_area_codes[901] = ["TN","W Tennessee: Memphis metro area"] | |
338 | US_area_codes[902] = ["NS","Canada: Nova Scotia, Prince Edward Island"] | |
339 | US_area_codes[903] = ["TX","NE Texas: Tyler"] | |
340 | US_area_codes[904] = ["FL","N Florida: Jacksonville"] | |
341 | US_area_codes[905] = ["ON","Canada: S Cent. Ontario: Greater Toronto Area -- Durham, Halton, Hamilton-Wentworth, Niagara, Peel, York, and southern Simcoe County"] | |
342 | US_area_codes[906] = ["MI","Upper Peninsula Michigan: Sault Ste. Marie, Escanaba, Marquette"] | |
343 | US_area_codes[907] = ["AK","Alaska"] | |
344 | US_area_codes[908] = ["NJ","Cent. New Jersey: Elizabeth, Basking Ridge, Somerville, Bridgewater, Bound Brook"] | |
345 | US_area_codes[909] = ["CA","California: Inland empire: San Bernardino"] | |
346 | US_area_codes[910] = ["NC","S Cent. North Carolina: Fayetteville, Wilmington"] | |
347 | US_area_codes[911] = ["--","Emergency"] | |
348 | US_area_codes[912] = ["GA","SE Georgia: Savannah"] | |
349 | US_area_codes[913] = ["KS","Kansas: Kansas City area"] | |
350 | US_area_codes[914] = ["NY","S New York: Westchester County"] | |
351 | US_area_codes[915] = ["TX","W Texas: El Paso"] | |
352 | US_area_codes[916] = ["CA","NE California: Sacramento, Walnut Grove, Lincoln, Newcastle and El Dorado Hills"] | |
353 | US_area_codes[917] = ["NY","New York: New York City"] | |
354 | US_area_codes[918] = ["OK","E Oklahoma: Tulsa"] | |
355 | US_area_codes[919] = ["NC","E North Carolina: Raleigh"] | |
356 | US_area_codes[920] = ["WI","NE Wisconsin: Appleton, Green Bay, Sheboygan, Fond du Lac"] | |
357 | US_area_codes[925] = ["CA","California: Contra Costa area: Antioch, Concord, Pleasanton, Walnut Creek"] | |
358 | US_area_codes[927] = ["FL","Florida: Cellular coverage in Orlando area"] | |
359 | US_area_codes[928] = ["AZ","Central and Northern Arizona: Prescott, Flagstaff, Yuma"] | |
360 | US_area_codes[931] = ["TN","Middle Tennessee: semi-circular ring around Nashville"] | |
361 | US_area_codes[935] = ["CA","S California: San Diego"] | |
362 | US_area_codes[936] = ["TX","SE Texas: Conroe, Lufkin, Nacogdoches, Crockett"] | |
363 | US_area_codes[937] = ["OH","SW Ohio: Dayton"] | |
364 | US_area_codes[939] = ["PR","Puerto Rico"] | |
365 | US_area_codes[940] = ["TX","N Cent. Texas: Denton, Wichita Falls"] | |
366 | US_area_codes[941] = ["FL","SW Florida: Sarasota and Manatee counties"] | |
367 | US_area_codes[947] = ["MI","Michigan: Oakland County"] | |
368 | US_area_codes[949] = ["CA","California: S Coastal Orange County"] | |
369 | US_area_codes[951] = ["CA","California: W Riverside County"] | |
370 | US_area_codes[952] = ["MN","Minnesota: Minneapolis SW, Bloomington"] | |
371 | US_area_codes[954] = ["FL","Florida: Broward County area, incl Ft. Lauderdale"] | |
372 | US_area_codes[956] = ["TX","Texas: Valley of Texas area; Harlingen, Laredo"] | |
373 | US_area_codes[957] = ["NM","New Mexico"] | |
374 | US_area_codes[959] = ["CT","Connecticut: Hartford, New London"] | |
375 | US_area_codes[970] = ["CO","N and W Colorado"] | |
376 | US_area_codes[971] = ["OR","Oregon: Metropolitan Portland, Salem/Keizer area, incl Cricket Wireless"] | |
377 | US_area_codes[972] = ["TX","Texas: Dallas Metro"] | |
378 | US_area_codes[973] = ["NJ","N New Jersey: Newark, Paterson, Morristown"] | |
379 | US_area_codes[975] = ["MO","N Missouri: Kansas City"] | |
380 | US_area_codes[976] = ["--","Unassigned"] | |
381 | US_area_codes[978] = ["MA","Massachusetts: north of Boston to NH"] | |
382 | US_area_codes[979] = ["TX","SE Texas: Bryan, College Station, Bay City"] | |
383 | US_area_codes[980] = ["NC","North Carolina:"] | |
384 | US_area_codes[984] = ["NC","E North Carolina: Raleigh"] | |
385 | US_area_codes[985] = ["LA","E Louisiana: SE/N shore of Lake Pontchartrain: Hammond, Slidell, Covington, Amite, Kentwood, area SW of New Orleans, Houma, Thibodaux, Morgan City"] | |
386 | US_area_codes[989] = ["MI","Upper central Michigan: Mt Pleasant, Saginaw"] | |
387 | US_area_codes[999] = ["--","Often used by carriers to indicate that the area code information is unavailable for CNID, even though the rest of the number is present"] | |
388 | ||
389 | class US_Area_Code_Checker < Checker | |
390 | ||
391 | def initialize | |
392 | super | |
393 | @description = "List of US area codes" | |
394 | @areas = {} | |
395 | end | |
396 | ||
397 | def process_word (word, extras = nil) | |
398 | if /([0-9]{3})$/.match(word) | |
399 | area_code = $1.to_i | |
400 | if US_area_codes.has_key?(area_code) | |
401 | if [email protected]_key?(area_code) | |
402 | @areas[area_code] = 1 | |
403 | else | |
404 | @areas[area_code] += 1 | |
405 | end | |
406 | end | |
407 | end | |
408 | @total_words_processed += 1 | |
409 | end | |
410 | ||
411 | def get_results() | |
412 | ret_str = "US Area Codes\n" | |
413 | ||
414 | if @areas.length > 0 | |
415 | # The sort changes the hash: | |
416 | # { [200] => 3, [201] => 4} | |
417 | # | |
418 | # into an array of pairs: | |
419 | # [ [201, 4], [200, 3] ] | |
420 | # | |
421 | # the -1 in the sort makes it to sort highest first | |
422 | (@areas.sort do |x,y| (x[1] <=> y[1]) * -1 end).each do |area_code_data| | |
423 | ret_str << "#{area_code_data[0].to_s} #{US_area_codes[area_code_data[0]][1]} (#{US_area_codes[area_code_data[0]][0]}) = #{area_code_data[1].to_s} (#{((area_code_data[1].to_f/@total_words_processed) * 100).round(2).to_s}%)\n" | |
424 | end | |
425 | else | |
426 | ret_str << "None found\n" | |
427 | end | |
428 | ||
429 | return ret_str | |
430 | end | |
431 | end | |
432 |
0 | register_checker("US_Zip_Code_Checker") | |
1 | ||
2 | class US_Zip_Code_Checker < Checker | |
3 | # Place your google API key here | |
4 | # For more info on getting a key see here | |
5 | # https://developers.google.com/maps/documentation/javascript/tutorial#api_key | |
6 | # | |
7 | # If you want to leave this blank and pass the key on the command line you can use the --gkey option | |
8 | # From experiments it looks like you don't actually need a valid key but better to have one just in case | |
9 | API_KEY='' | |
10 | ||
11 | def initialize | |
12 | super | |
13 | @description = "List of US zip codes" | |
14 | @zip_codes = {} | |
15 | end | |
16 | ||
17 | def lookup_by_zipcode(zip) | |
18 | geocoder = "http://maps.google.com/maps/geo?q=" | |
19 | apikey = "&key=" + API_KEY | |
20 | ||
21 | # Since the zipcode goes directly into the URL request it needs to be cleaned up. | |
22 | request = "#{geocoder}#{URI::encode(zip.to_s)}, USA#{apikey}" | |
23 | resp = Net::HTTP.get_response(URI.parse(request)) | |
24 | ||
25 | data = JSON.parse(resp.body) | |
26 | ||
27 | if data.has_key?('Status') | |
28 | # puts "status: " + data['Status']['code'].to_s | |
29 | ||
30 | if (data.has_key?('Placemark') and data['Placemark'].length > 0) | |
31 | #puts data['Placemark'][0].inspect | |
32 | # puts "location: " + data['Placemark'][0]['address'] | |
33 | ||
34 | if data['Placemark'][0].has_key? 'AddressDetails' and | |
35 | data['Placemark'][0]['AddressDetails'].has_key? 'Country' and | |
36 | data['Placemark'][0]['AddressDetails']['Country'].has_key? 'AdministrativeArea' and | |
37 | data['Placemark'][0]['AddressDetails']['Country']['AdministrativeArea'].has_key? 'Locality' and | |
38 | data['Placemark'][0]['AddressDetails']['Country']['AdministrativeArea']['Locality'].has_key? 'PostalCode' and | |
39 | data['Placemark'][0]['AddressDetails']['Country']['AdministrativeArea']['Locality']['PostalCode'].has_key? 'PostalCodeNumber' and | |
40 | data['Placemark'][0]['AddressDetails']['Country'].has_key? 'CountryName' | |
41 | ||
42 | # puts "Location: " + data['Placemark'][0]['AddressDetails']['Country']['CountryName'] | |
43 | # puts "Location: " + data['Placemark'][0]['AddressDetails']['Country']['AdministrativeArea']['Locality']['PostalCode']['PostalCodeNumber'] | |
44 | if data['Placemark'][0]['AddressDetails']['Country']['CountryName'] == 'USA' and data['Placemark'][0]['AddressDetails']['Country']['AdministrativeArea']['Locality']['PostalCode']['PostalCodeNumber'] == zip | |
45 | return data['Placemark'][0]['address'] | |
46 | end | |
47 | end | |
48 | ||
49 | # return data['Placemark'][0]['address'] | |
50 | end | |
51 | end | |
52 | ||
53 | return nil | |
54 | end | |
55 | ||
56 | def process_word (word, extras = nil) | |
57 | if @API_KEY != "" | |
58 | if /([0-9]{5})$/.match(word) | |
59 | zip_code = $1.to_i | |
60 | if !@zip_codes.has_key?(zip_code) | |
61 | @zip_codes[zip_code] = 1 | |
62 | else | |
63 | @zip_codes[zip_code] += 1 | |
64 | end | |
65 | end | |
66 | end | |
67 | @total_words_processed += 1 | |
68 | end | |
69 | ||
70 | def get_results() | |
71 | if API_KEY != "" | |
72 | areas = {} | |
73 | @zip_codes.each do |zip| | |
74 | area = lookup_by_zipcode zip | |
75 | unless area.nil? | |
76 | areas[zip] = area | |
77 | end | |
78 | end | |
79 | if areas.length > 0 | |
80 | ret_str = "US Zip Codes\n" | |
81 | areas.each_pair do |zip, area| | |
82 | ret_str << "#{zip} = #{area}\n" | |
83 | end | |
84 | ret_str << "\n" | |
85 | end | |
86 | else | |
87 | ret_str = "US Zip Codes\n" | |
88 | ret_str << "\nNo Google API key specified\n" | |
89 | end | |
90 | ||
91 | return ret_str | |
92 | end | |
93 | end |
0 | register_checker("Username_Checker") | |
1 | ||
2 | begin | |
3 | require "levenshtein" | |
4 | rescue LoadError | |
5 | # catch error and prodive feedback on installing gem | |
6 | puts "\nError: levenshtein gem not installed\n" | |
7 | puts "\t use: \"gem install levenshtein-ffi\" to install the required gem\n\n" | |
8 | exit | |
9 | end | |
10 | ||
11 | class Username_Checker < Checker | |
12 | ||
13 | def initialize | |
14 | super | |
15 | @exact_matches_name = [] | |
16 | @lev_matches_name = [] | |
17 | @lev_total_name = 0 | |
18 | @lev_tolerance = 3 | |
19 | @ignore_cap = false | |
20 | ||
21 | @description = "Compare usernames to passwords." | |
22 | @cli_params = [ | |
23 | ['--username.lev_tolerance', GetoptLong::REQUIRED_ARGUMENT], | |
24 | ['--username.ignore_cap', GetoptLong::NO_ARGUMENT] | |
25 | ] | |
26 | end | |
27 | ||
28 | def parse_params opts | |
29 | opts.each do |opt, arg| | |
30 | case opt | |
31 | when '--username.ignore_cap' | |
32 | @ignore_cap = true | |
33 | when '--username.lev_tolerance' | |
34 | if arg =~ /^[0-9]*$/ | |
35 | @lev_tolerance = arg.to_i | |
36 | if @lev_tolerance <= 0 | |
37 | puts"\nUsername Checker: Please enter a positive distance\n\n" | |
38 | exit 1 | |
39 | end | |
40 | else | |
41 | puts"\nUsername Checker: Invalid Levenshtein tolerance\n\n" | |
42 | exit 1 | |
43 | end | |
44 | end | |
45 | end | |
46 | end | |
47 | ||
48 | def check_it (password, value) | |
49 | puts "Checking #{value} against #{password}" if @verbose | |
50 | if password == value | |
51 | puts "Exact match" if @verbose | |
52 | return {"distance" => 0, "value" => value, "password" => password} | |
53 | else | |
54 | dist = Levenshtein.distance(password, value) | |
55 | puts "Lev distance #{dist}#" if @verbose | |
56 | return {"distance" => dist, "value" => value, "password" => password} | |
57 | end | |
58 | ||
59 | return nil | |
60 | end | |
61 | ||
62 | def process_word (password, extras) | |
63 | if extras.has_key?("username") | |
64 | username = extras['username'] | |
65 | ||
66 | res = check_it(password, username) | |
67 | unless res.nil? | |
68 | if res['distance'] == 0 | |
69 | data = {"name" => username} | |
70 | unless @exact_matches_name.include? data | |
71 | @exact_matches_name << data | |
72 | end | |
73 | else | |
74 | @lev_total_name += res["distance"] | |
75 | if res["distance"] <= @lev_tolerance and not (@lev_matches_name.include? res) | |
76 | @lev_matches_name << res | |
77 | end | |
78 | end | |
79 | end | |
80 | end | |
81 | ||
82 | @total_words_processed += 1 | |
83 | end | |
84 | ||
85 | def get_results() | |
86 | ret_str = "Username Checker\n" | |
87 | ret_str << "================\n\n" | |
88 | ||
89 | ret_str << "Exact Matches\n" | |
90 | ret_str << "-------------\n" | |
91 | if @exact_matches_name.count > 0 | |
92 | ret_str << "Total: #{@exact_matches_name.count.to_s} Unique\n\n" | |
93 | ||
94 | # Need to sort this then have it obey the cap_at value (if not ignored) | |
95 | if @ignore_cap | |
96 | @cap_at = @exact_matches_name.count | |
97 | end | |
98 | @exact_matches_name.sort{|a,b| (a['name'] <=> b['name'])}[0, @cap_at].each do |match| | |
99 | ret_str << "#{match['name']}\n" | |
100 | end | |
101 | else | |
102 | ret_str << "No Exact Matches\n" | |
103 | end | |
104 | ||
105 | ret_str << "\nLevenshtein Results\n" | |
106 | ret_str << "-------------------\n" | |
107 | lev_average = (@lev_total_name.to_f / @total_words_processed).round(2) | |
108 | ret_str << "Average distance #{lev_average}\n" | |
109 | ||
110 | ret_str << "\nClose Matches\n" | |
111 | ret_str << "-------------\n" | |
112 | ||
113 | if @ignore_cap | |
114 | @cap_at = @lev_matches_name.count | |
115 | end | |
116 | if @lev_matches_name.count > 0 | |
117 | ret_str << "Total: #{@lev_matches_name.count.to_s} Unique\n\n" | |
118 | @lev_matches_name.sort{|a,b| (a['distance'] <=> b['distance'])}[0, @cap_at].each do |user_pass| | |
119 | ret_str << "D: #{user_pass['distance']} U: #{user_pass['value']} P: #{user_pass['password']}\n" | |
120 | end | |
121 | else | |
122 | ret_str << "No matches within supplied tolerance\n" | |
123 | end | |
124 | ||
125 | return ret_str | |
126 | end | |
127 | end |
0 | register_checker("Windows_Complexity_Checker") | |
1 | ||
2 | class Windows_Complexity_Checker < Checker | |
3 | ||
4 | def initialize | |
5 | super | |
6 | @description = "Check for default Windows complexity" | |
7 | @matches = 0 | |
8 | end | |
9 | ||
10 | def process_word (word, extras = nil) | |
11 | ||
12 | if word =~ /(?=^.{8,255}$)((?=.*\d)(?=.*[A-Z])(?=.*[a-z])|(?=.*\d)(?=.*[^A-Za-z0-9])(?=.*[a-z])|(?=.*[^A-Za-z0-9])(?=.*[A-Z])(?=.*[a-z])|(?=.*\d)(?=.*[A-Z])(?=.*[^A-Za-z0-9]))^.*/ | |
13 | @matches += 1 | |
14 | end | |
15 | @total_words_processed += 1 | |
16 | end | |
17 | ||
18 | def get_results() | |
19 | ret_str = "Windows AD Default Complexity\n" | |
20 | ||
21 | ret_str << "Number of matches = #{@matches} (#{((@matches.to_f/@total_words_processed) * 100).round(2).to_s}%)\n" | |
22 | return ret_str | |
23 | end | |
24 | end |
0 | # Ignore everything in this directory | |
1 | * | |
2 | # Except this file | |
3 | !.gitignore | |
4 | !README | |
5 | !01basic.rb |
0 | ../checkers_available/basic.rb⏎ |
0 | This directory contains the checkers you want to enable. | |
1 | ||
2 | The way I see this working is the same as Apache does with modules and sites, | |
3 | keep the checkers in the checkers_available directory but then symlink the | |
4 | ones you want to use into here. |
4 | 4 | WIDTH = 72 |
5 | 5 | HEIGHT = 16 |
6 | 6 | attr :output_file, true |
7 | attr_reader :graph | |
7 | 8 | |
8 | 9 | def initialize(array) |
9 | 10 | @values = array |
10 | 11 | @output_file = STDOUT |
12 | @graph = nil | |
11 | 13 | end |
12 | 14 | |
13 | 15 | def draw |
16 | if @graph.nil? | |
17 | self.generate | |
18 | end | |
19 | @output_file.puts @graph | |
20 | end | |
21 | ||
22 | def generate | |
23 | @graph = "" | |
24 | ||
14 | 25 | #Adjust X axis when there are more than WIDTH cols |
15 | 26 | if @values.length > WIDTH then |
16 | 27 | old_values = @values; |
39 | 50 | num= f*HEIGHT/max |
40 | 51 | (HEIGHT - 1).downto(HEIGHT - 1 - num){|j| display[j][i] = '|'} |
41 | 52 | end |
42 | display.each{|ar| ar.each{|e| @output_file.putc e}; @output_file.puts "\n"} #now print | |
53 | display.each{|ar| ar.each{|e| @graph << e}; @graph << "\n"} #now print | |
43 | 54 | |
44 | 55 | no_of_digits = (@values.length - 1).to_s.length |
45 | 0.upto(no_of_digits) do |digit_number| | |
56 | ||
57 | 0.upto(no_of_digits - 1) do |digit_number| | |
46 | 58 | 0.upto(@values.length - 1) do |x| |
47 | @output_file.print sprintf("%0#{no_of_digits}d", x)[digit_number] | |
59 | @graph << sprintf("%0#{no_of_digits}d", x)[digit_number] | |
48 | 60 | end |
49 | @output_file.puts | |
61 | @graph << "\n" | |
50 | 62 | end |
51 | 63 | end |
52 | 64 | end |
0 | # encoding: utf-8 | |
1 | # A description of the file, used in verbose mode | |
2 | $layout_description = "French keyboard layout" | |
3 | ||
4 | $layout = { | |
5 | "²" => { 1 => "1&"}, | |
6 | "1" => { 0 => "&",1 => "a2é~"}, | |
7 | "2" => { 0 => "é~", 1 => "1&az3\"#"}, | |
8 | "3" => { 0 => "\"#", 1 => "2é~4'{ze€"}, | |
9 | "4" => { 0 => "'{", 1 => "3\"#er5(["}, | |
10 | "5" => { 0 => "([", 1 => "4'{6-|rt"}, | |
11 | "6" => { 0 => "-|", 1 => "5([7è`ty"}, | |
12 | "7" => { 0 => "è`", 1 => "6-|8_\\yu"}, | |
13 | "8" => { 0 => "_\\", 1 => "7è`9ç^ui"}, | |
14 | "9" => { 0 => "ç^", 1 => "8_\\0à@io"}, | |
15 | "0" => { 0 => "à@", 1 => "9ç^°)]op"}, | |
16 | "°" => { 0 => ")]", 1 => "0à@+=}p^"}, | |
17 | "+" => { 0 => "=}", 1 => "°)]$£ø"}, | |
18 | "&" => { 0 => "&",1 => "a2é~"}, | |
19 | "é" => { 0 => "2~", 1 => "1&az3\"#"}, | |
20 | "\"" => { 0 => "3#", 1 => "2é~4'{ze€"}, | |
21 | "'" => { 0 => "4{", 1 => "3\"#er5(["}, | |
22 | "(" => { 0 => "5[", 1 => "4'{6-|rt"}, | |
23 | "-" => { 0 => "6|", 1 => "5([7è`ty"}, | |
24 | "è" => { 0 => "7`", 1 => "6-|8_\\yu"}, | |
25 | "_" => { 0 => "8\\", 1 => "7è`9ç^ui"}, | |
26 | "ç" => { 0 => "9^", 1 => "8_\\0à@io"}, | |
27 | "à" => { 0 => "0@", 1 => "9ç^°)]op"}, | |
28 | ")" => { 0 => "°]", 1 => "0à@+=}^p"}, | |
29 | "=" => { 0 => "+}", 1 => "°)]$£ø"}, | |
30 | "~" => { 0 => "é2", 1 => "1&az3\"#"}, | |
31 | "#" => { 0 => "\"3", 1 => "2é~4'{ze€"}, | |
32 | "{" => { 0 => "'4", 1 => "3\"#er5(["}, | |
33 | "[" => { 0 => "(5", 1 => "4'{6-|rt"}, | |
34 | "|" => { 0 => "-6", 1 => "5([7è`ty"}, | |
35 | "`" => { 0 => "è7", 1 => "6-|8_\\yu"}, | |
36 | "\\" => { 0 => "_8", 1 => "7è`9ç^ui"}, | |
37 | "^" => { 0 => "ç9", 1 => "8_\\0à@io"}, | |
38 | "@" => { 0 => "à0", 1 => "9ç^°)]op"}, | |
39 | "]" => { 0 => ")°", 1 => "0à@+=}p"}, | |
40 | "}" => { 0 => "=+", 1 => "°)]$£ø"}, | |
41 | "a" => { 1 => "1&2éqz"}, | |
42 | "z" => { 1 => "aqse€2é~3\"#"}, | |
43 | "e" => { 0 => "€", 1 => "zsdr3\"#4'{"}, | |
44 | "€" => { 0 => "e", 1 => "zsdr3\"#4'{"}, | |
45 | "r" => { 1 => "e€dft4'{5(["}, | |
46 | "t" => { 1 => "rfgy5([6-|"}, | |
47 | "y" => { 1 => "tghu6-|7è`"}, | |
48 | "u" => { 1 => "yhji7è`8_\\"}, | |
49 | "i" => { 1 => "ujko8_\\9ç^"}, | |
50 | "o" => { 1 => "iklp9ç^0à@"}, | |
51 | "p" => { 1 => "olm0à@°)]"}, | |
52 | "$" => { 0 => "£ø", 1 => "ù%*µ+=}"}, | |
53 | "£" => { 0 => "$ø", 1 => "ù%*µ+=}"}, | |
54 | "ø" => { 0 => "£$", 1 => "ù%*µ+=}"}, | |
55 | "q" => { 1 => "azsw<>"}, | |
56 | "s" => { 1 => "ze€dxwq"}, | |
57 | "d" => { 1 => "e€rfcxs"}, | |
58 | "f" => { 1 => "rtgvcd"}, | |
59 | "g" => { 1 => "tyhbvf"}, | |
60 | "h" => { 1 => "yujnbg"}, | |
61 | "j" => { 1 => "uik,?nh"}, | |
62 | "k" => { 1 => "iol;.,?j"}, | |
63 | "l" => { 1 => "opm:/;.k"}, | |
64 | "m" => { 1 => "pù%!§:/l"}, | |
65 | "ù" => { 0 => "%", 1 => "$£ø*µ!§m"}, | |
66 | "%" => { 0 => "ù", 1 => "$£ø*µ!§m"}, | |
67 | "*" => { 0 => "µ", 1 => "$£øù%"}, | |
68 | "µ" => { 0 => "*", 1 => "$£øù%"}, | |
69 | "<" => { 1 => "qw"}, | |
70 | ">" => { 1 => "qw"}, | |
71 | "w" => { 1 => "<>qsx"}, | |
72 | "x" => { 1 => "wsdc"}, | |
73 | "c" => { 1 => "xdfv"}, | |
74 | "v" => { 1 => "cfgb"}, | |
75 | "b" => { 1 => "vghn"}, | |
76 | "n" => { 1 => "bhj,?"}, | |
77 | "," => { 0 => "?", 1 => "njk;."}, | |
78 | "?" => { 0 => ",", 1 => "njk;."}, | |
79 | ";" => { 0 => ".", 1 => ",?kl:/"}, | |
80 | "." => { 0 => ";", 1 => ",?kl:/"}, | |
81 | ":" => { 0 => "/", 1 => ";.lm!§"}, | |
82 | "/" => { 0 => ":", 1 => ";.lm!§"}, | |
83 | "!" => { 0 => "§", 1 => ":/mù%"}, | |
84 | "§" => { 0 => "!", 1 => ":/mù%"}, | |
85 | } | |
86 | ||
87 | # This is the furthest distance we are looking for as a jump + 1 | |
88 | # This could be calculated by the app when it starts up but that | |
89 | # seems like unnecessary work as you already know it when creating | |
90 | # this file. | |
91 | # | |
92 | # You could also chose to penalise keys further away more by giving | |
93 | # them a higher score. | |
94 | MAX_SCORE = 2 |
0 | $layout_description = "Numeric Keypad" | |
1 | ||
2 | $layout = { | |
3 | "0" => { 1 => "12"}, | |
4 | "1" => { 1 => "4520"}, | |
5 | "2" => { 1 => "014563"}, | |
6 | "3" => { 1 => "256"}, | |
7 | "4" => { 1 => "78521"}, | |
8 | "5" => { 1 => "12346789"}, | |
9 | "6" => { 1 => "98523"}, | |
10 | "7" => { 1 => "458"}, | |
11 | "8" => { 1 => "74569"}, | |
12 | "9" => { 1 => "856"}, | |
13 | } | |
14 | ||
15 | # This is the furthest distance we are looking for as a jump + 1 | |
16 | MAX_SCORE = 2 |
0 | # the UK pound sign breaks some editors so just specifying it | |
1 | # as a char code rather than the symbol | |
2 | gbp = 163.chr | |
3 | ||
4 | $layout_description = "Macbook Pro keyboard layout" | |
5 | ||
6 | $layout = { | |
7 | "!" => { 0 => "1", 1 => "2@q"}, | |
8 | "1" => { 0 => "!", 1 => "2@q"}, | |
9 | "q" => { 1 => "1!2@wa"}, | |
10 | "a" => { 1 => "qwsxz\\"}, | |
11 | "z" => { 1 => "asx\\"}, | |
12 | "2" => { 0 => '@', 1 => "1!qw3#"}, | |
13 | '@' => { 0 => '2', 1 => "1!qw3#"}, | |
14 | "w" => { 1 => "2@3#esaq"}, | |
15 | "s" => { 1 => "wedxza"}, | |
16 | "x" => { 1 => "zsdc"}, | |
17 | "3" => { 0 => "#", 1 => "2we4"}, | |
18 | "#" => { 0 => "3", 1 => "2we4"}, | |
19 | "e" => { 1 => "3#4$rdsw"}, | |
20 | "d" => { 1 => "erfcxs"}, | |
21 | "c" => { 1 => "xdfv"}, | |
22 | "4" => { 0 => "$", 1 => "3#er5%"}, | |
23 | "$" => { 0 => "4", 1 => "3#er5%"}, | |
24 | "r" => { 1 => "4$5%tfde"}, | |
25 | "f" => { 1 => "rtdgcv"}, | |
26 | "v" => { 1 => "cfgb"}, | |
27 | "5" => { 0 => "%", 1 => "4$6^rt"}, | |
28 | "%" => { 0 => "5", 1 => "4$6^rt"}, | |
29 | "t" => { 1 => "5%6^ygr"}, | |
30 | "g" => { 1 => "vbhfty"}, | |
31 | "b" => { 1 => "vghn"}, | |
32 | "6" => { 0 => "^", 1 => "5%ty7&"}, | |
33 | "^" => { 0 => "6", 1 => "5%ty7&"}, | |
34 | "y" => { 1 => "67^&uhgt" }, | |
35 | "h" => { 1 => "yujnbg" }, | |
36 | "n" => { 1 => "bhjm" }, | |
37 | "7" => { 0 => "&", 1 => "6^yu8*"}, | |
38 | "&" => { 0 => "7", 1 => "6^yu8*"}, | |
39 | "u" => { 1 => "78&*ijhy"}, | |
40 | "j" => { 1 => "uikmnh"}, | |
41 | "m" => { 1 => "njk,<"}, | |
42 | "8" => { 0 => "*", 1 => "7ui9&("}, | |
43 | "*" => { 0 => "8", 1 => "7ui9&("}, | |
44 | "i" => { 1 => "89*(okju"}, | |
45 | "k" => { 1 => "iol,mj"}, | |
46 | "," => { 0 => "<", 1 => "mkl.>"}, | |
47 | "9" => { 0 => "(", 1 => "80*)io"}, | |
48 | "(" => { 0 => "9", 1 => "80*)io"}, | |
49 | "o" => { 1 => "90()plki"}, | |
50 | "l" => { 1 => "op;:.>,<k"}, | |
51 | "." => { 0 => ">", 1 => ",<l;:/?"}, | |
52 | ">" => { 0 => ".", 1 => ",<l;:/?"}, | |
53 | "0" => { 0 => ")", 1 => "9(op-_"}, | |
54 | ")" => { 0 => "9", 1 => "9(op-_"}, | |
55 | "p" => { 1 => "0)-_[{;:lo"}, | |
56 | ";" => { 0 => ":", 1 => "p[{'@/?.>l"}, | |
57 | ":" => { 0 => ";", 1 => "p[{'@/?.>l"}, | |
58 | "/" => { 0 => "?", 1 => ".>;:'\""}, | |
59 | "?" => { 0 => "/", 1 => ".>;:'\""}, | |
60 | "-" => { 0 => "_", 1 => "0)p[{=+"}, | |
61 | "_" => { 0 => "-", 1 => "0)p[{=+"}, | |
62 | "[" => { 0 => "{", 1 => "-_=+]}'\";:p"}, | |
63 | "{" => { 0 => "[", 1 => "-_=+]}'\";:p"}, | |
64 | "'" => { 0 => "@", 1 => "/?;:[{]}"}, | |
65 | "\"" => { 0 => "'", 1 => "/?;:[{]}"}, | |
66 | "=" => { 0 => "+", 1 => "-_[{]}"}, | |
67 | "+" => { 0 => "=", 1 => "-_[{]}"}, | |
68 | "]" => { 0 => "}", 1 => "=+[{'\"\\|"}, | |
69 | "}" => { 0 => "]", 1 => "=+[{'\"\\|"}, | |
70 | "~" => { 0 => "`", 1 => "1!"}, | |
71 | "`" => { 0 => "~", 1 => "1!"}, | |
72 | "|" => { 0 => "\\", 1 => "]}"}, | |
73 | "\\" => { 0 => "|", 1 => "]}"}, | |
74 | } | |
75 | ||
76 | # This is the furthest distance we are looking for as a jump + 1 | |
77 | MAX_SCORE = 2 |
0 | # the UK pound sign breaks some editors so just specifying it | |
1 | # as a char code rather than the symbol | |
2 | gbp = 163.chr | |
3 | ||
4 | # A description of the file, used in verbose mode | |
5 | $layout_description = "UK keyboard layout" | |
6 | ||
7 | $layout = { | |
8 | "!" => { # The character ! | |
9 | 0 => "1", # is on the same key as 1 | |
10 | 1 => "2\"q" # and is just one key away from 2, " and q | |
11 | # 2 => "3wa" + gbp # If you wanted to add keys two characters away you could with this line | |
12 | }, | |
13 | "1" => { 0 => "!", 1 => "2\"q"}, | |
14 | "q" => { 1 => "1!2\"wa"}, | |
15 | "a" => { 1 => "qwsxz\\"}, | |
16 | "z" => { 1 => "asx\\"}, | |
17 | "|" => { 0 => "\\", 1 => "az"}, | |
18 | "\\" => { 0 => "|", 1 => "az"}, | |
19 | "2" => { 0 => '"', 1 => "1!qw3"+ gbp}, | |
20 | '"' => { 0 => '2', 1 => "1!qw3"+ gbp}, | |
21 | "w" => { 1 => "2\"3edsaq"+ gbp}, | |
22 | "s" => { 1 => "qwedcxza"}, | |
23 | "x" => { 1 => "zasdc"}, | |
24 | "3" => { 0 => "" + gbp, 1 => "2wer4\""}, | |
25 | gbp => { 0 => "3", 1 => "2wer4\""}, | |
26 | "e" => { 1 => "w34rfds"+ gbp}, | |
27 | "d" => { 1 => "werfvcxs"}, | |
28 | "c" => { 1 => "xsdfv"}, | |
29 | "4" => { 0 => "$", 1 => "%3er5"+ gbp}, | |
30 | "$" => { 0 => "4", 1 => "%3er5"+ gbp}, | |
31 | "r" => { 1 => "4$5%tgfde"}, | |
32 | "f" => { 1 => "ertgvcd"}, | |
33 | "v" => { 1 => "cfgb"}, | |
34 | "5" => { 0 => "%", 1 => "4$rt6^"}, | |
35 | "%" => { 0 => "%", 5 => "4$rt6^"}, | |
36 | "t" => { 1 => "5%6^ygr"}, | |
37 | "g" => { 1 => "vbhfty"}, | |
38 | "b" => { 1 => "vghn"}, | |
39 | "6" => { 0 => "^", 1 => "5%ty7&"}, | |
40 | "^" => { 0 => "6", 1 => "5%ty7&"}, | |
41 | "y" => { 1 => "67^&uhgt" }, | |
42 | "h" => { 1 => "yujnbg" }, | |
43 | "n" => { 1 => "bhjm" }, | |
44 | "7" => { 0 => "&", 1 => "6^yu8*"}, | |
45 | "&" => { 0 => "7", 1 => "6^yu8*"}, | |
46 | "u" => { 1 => "78&*ijhy"}, | |
47 | "j" => { 1 => "uikmnh"}, | |
48 | "m" => { 1 => "njk,<"}, | |
49 | "8" => { 0 => "*", 1 => "7ui9&("}, | |
50 | "*" => { 0 => "8", 1 => "7ui9&("}, | |
51 | "i" => { 1 => "89*(okju"}, | |
52 | "k" => { 1 => "iol,mj"}, | |
53 | "," => { 0 => "<", 1 => "mkl.>"}, | |
54 | "9" => { 0 => "(", 1 => "80*)io"}, | |
55 | "(" => { 0 => "9", 1 => "80*)io"}, | |
56 | "o" => { 1 => "90()plki"}, | |
57 | "l" => { 1 => "op;:.>,<k"}, | |
58 | "." => { 0 => ">", 1 => ",<l;:/?"}, | |
59 | ">" => { 0 => ".", 1 => ",<l;:/?"}, | |
60 | "0" => { 0 => ")", 1 => "9(op-_"}, | |
61 | ")" => { 0 => "9", 1 => "9(op-_"}, | |
62 | "p" => { 1 => "0)-_[{;:lo"}, | |
63 | ";" => { 0 => ":", 1 => "p[{'@/?.>l"}, | |
64 | ":" => { 0 => ";", 1 => "p[{'@/?.>l"}, | |
65 | "/" => { 0 => "?", 1 => ".>;:'@"}, | |
66 | "?" => { 0 => "/", 1 => ".>;:'@"}, | |
67 | "-" => { 0 => "_", 1 => "0)p[{=+"}, | |
68 | "_" => { 0 => "-", 1 => "0)p[{=+"}, | |
69 | "[" => { 0 => "{", 1 => "-_=+]}'@;:p"}, | |
70 | "{" => { 0 => "[", 1 => "-_=+]}'@;:p"}, | |
71 | "'" => { 0 => "@", 1 => "[{]}#~/?;:"}, | |
72 | "@" => { 0 => "'", 1 => "[{]}#~/?;:"}, | |
73 | "=" => { 0 => "+", 1 => "-_[{]}"}, | |
74 | "+" => { 0 => "=", 1 => "-_[{]}"}, | |
75 | "]" => { 0 => "}", 1 => "=+[{'@#~"}, | |
76 | "}" => { 0 => "}", 1 => "=+[{'@#~"}, | |
77 | "#" => { 0 => "~", 1 => "]}'@"}, | |
78 | "~" => { 0 => "#", 1 => "]}'@"}, | |
79 | } | |
80 | ||
81 | # This is the furthest distance we are looking for as a jump + 1 | |
82 | # This could be calculated by the app when it starts up but that | |
83 | # seems like unnecessary work as you already know it when creating | |
84 | # this file. | |
85 | # | |
86 | # You could also chose to penalise keys further away more by giving | |
87 | # them a higher score. | |
88 | MAX_SCORE = 2 |
0 | class List_Checker < Checker | |
1 | @list = {} | |
2 | ||
3 | def initialize | |
4 | super | |
5 | end | |
6 | ||
7 | def process_word (word, extras = nil) | |
8 | @list.each_pair do |colour, count| | |
9 | if /#{colour}/i.match word | |
10 | @list[colour] += 1 | |
11 | end | |
12 | end | |
13 | @total_words_processed += 1 | |
14 | end | |
15 | ||
16 | def get_results(title) | |
17 | ret_str = "#{title}\n" | |
18 | disp = false | |
19 | ||
20 | (@list.sort do |x,y| (x[1] <=> y[1]) * -1 end).each do |colour_data| | |
21 | unless colour_data[1] == 0 | |
22 | disp = true | |
23 | ret_str << "#{colour_data[0]} = #{colour_data[1].to_s} (#{((colour_data[1].to_f/@total_words_processed) * 100).round(2).to_s}%)\n" | |
24 | end | |
25 | end | |
26 | unless disp | |
27 | ret_str << "None found\n" | |
28 | end | |
29 | ||
30 | return ret_str | |
31 | end | |
32 | end |
0 | module OS | |
1 | def OS.windows? | |
2 | (/cygwin|mswin|mingw|bccwin|wince|emx/ =~ RUBY_PLATFORM) != nil | |
3 | end | |
4 | ||
5 | def OS.mac? | |
6 | (/darwin/ =~ RUBY_PLATFORM) != nil | |
7 | end | |
8 | ||
9 | def OS.unix? | |
10 | !OS.windows? | |
11 | end | |
12 | ||
13 | def OS.linux? | |
14 | OS.unix? and not OS.mac? | |
15 | end | |
16 | end |
0 | #!/usr/bin/env ruby | |
1 | # encoding: utf-8 | |
2 | ||
3 | # | |
4 | # Author:: Robin Wood ([email protected]) | |
5 | # Copyright:: Copyright (c) Robin Wood 2013 | |
6 | # Licence:: Creative Commons Attribution-Share Alike 2.0 | |
7 | # | |
8 | ||
9 | require 'getoptlong' | |
10 | ||
11 | def usage | |
12 | puts"passpat 1.0 Robin Wood ([email protected]) (http://digi.ninja) | |
13 | ||
14 | Usage: passpat.rb [OPTIONS] ... PASSWORD_FILE | |
15 | --layout x, -l x: use the layout file specified. No default is set so this | |
16 | must be specified | |
17 | --list-layouts: show the available layout files | |
18 | --help, -h: show help | |
19 | --verbose, -v: verbose messages | |
20 | ||
21 | PASSWORD_FILE: the list of passwords to check | |
22 | ||
23 | The results are scored from 0 to upwards. A score of 0 means that a the | |
24 | password didn't move from a single key, a score of 1 means that each key entered | |
25 | was adjacent to the previous. The higher the score above 1, the lower the | |
26 | grouping of the keys. | |
27 | ||
28 | Based on this, the closer to 1 the score is, the more likely the password is | |
29 | to be a keyboard pattern. | |
30 | ||
31 | Note though, this will not pick up a pattern such as \"qpalzm\" as the system isn't | |
32 | that smart (yet). | |
33 | ||
34 | This project is sponsored by the BruCON 5x5 scheme. | |
35 | ||
36 | " | |
37 | end | |
38 | ||
39 | def list_layouts | |
40 | puts"passpat 1.0 Robin Wood ([email protected]) (http://digi.ninja)" | |
41 | puts | |
42 | puts "Available layouts:" | |
43 | puts | |
44 | ||
45 | # This gives the directory that passpat is running from | |
46 | script_directory = File.dirname(__FILE__) | |
47 | ||
48 | layouts = Dir[script_directory + '/layouts/*'].reject do |fn| File.directory?(fn) end | |
49 | layouts.each do |layout| | |
50 | layout_name = layout.match(/#{script_directory + '/layouts/'}(.*)\.rb$/) | |
51 | if !layout_name.nil? | |
52 | puts layout_name[1] | |
53 | end | |
54 | end | |
55 | puts | |
56 | end | |
57 | ||
58 | opts = GetoptLong.new( | |
59 | [ '--help', '-h', "-?", GetoptLong::NO_ARGUMENT ], | |
60 | [ '--layout', "-l" , GetoptLong::REQUIRED_ARGUMENT ], | |
61 | [ '--list-layouts', GetoptLong::NO_ARGUMENT ], | |
62 | [ "--verbose", "-v" , GetoptLong::NO_ARGUMENT ] | |
63 | ) | |
64 | ||
65 | verbose = false | |
66 | ||
67 | begin | |
68 | opts.each do |opt, arg| | |
69 | case opt | |
70 | when '--verbose' | |
71 | verbose = true | |
72 | when '--help' | |
73 | usage | |
74 | exit 0 | |
75 | when "--list-layouts" | |
76 | list_layouts | |
77 | exit 0 | |
78 | when "--layout" | |
79 | # This gives the directory that passpat is running from | |
80 | script_directory = File.dirname(__FILE__) | |
81 | ||
82 | puts script_directory + "/layouts/" + arg + ".rb" | |
83 | # Yes, directory traversal is here but don't care | |
84 | if File.exist?(script_directory + "/layouts/" + arg + ".rb") | |
85 | require_relative "layouts/" + arg + ".rb" | |
86 | else | |
87 | puts"passpat 1.0 Robin Wood ([email protected]) (http://digi.ninja) | |
88 | ||
89 | Layout file not found | |
90 | ||
91 | " | |
92 | exit 1 | |
93 | end | |
94 | end | |
95 | end | |
96 | rescue GetoptLong::InvalidOption => e | |
97 | puts | |
98 | usage | |
99 | exit | |
100 | rescue => e | |
101 | puts "Something went wrong, please report it to [email protected] along with these messages:" | |
102 | puts | |
103 | puts e.message | |
104 | puts | |
105 | puts e.class.to_s | |
106 | puts | |
107 | puts "Backtrace:" | |
108 | puts e.backtrace | |
109 | puts | |
110 | usage | |
111 | exit 1 | |
112 | end | |
113 | ||
114 | if $layout.nil? | |
115 | puts"passpat 1.0 Robin Wood ([email protected]) (http://digi.ninja) | |
116 | ||
117 | No layout file specified | |
118 | ||
119 | " | |
120 | exit 1 | |
121 | end | |
122 | ||
123 | keyboard = $layout | |
124 | ||
125 | if verbose | |
126 | puts "Using layout file: " + $layout_description | |
127 | puts | |
128 | end | |
129 | ||
130 | if ARGV.count < 1 | |
131 | puts"passpat 1.0 Robin Wood ([email protected]) (http://digi.ninja) | |
132 | ||
133 | No password file specified | |
134 | ||
135 | " | |
136 | exit 1 | |
137 | end | |
138 | ||
139 | filename = ARGV.shift | |
140 | ||
141 | if filename.nil? or !File.exist? filename | |
142 | puts"passpat 1.0 Robin Wood ([email protected]) (http://digi.ninja) | |
143 | ||
144 | Can't find the password file | |
145 | ||
146 | " | |
147 | exit 1 | |
148 | end | |
149 | ||
150 | total_lines = 0 | |
151 | total_score = 0 | |
152 | total_zeros = 0 | |
153 | total_ones = 0 | |
154 | ||
155 | catch :ctrl_c do | |
156 | begin | |
157 | File.open(filename, "r").each_line do |line| | |
158 | begin | |
159 | # because the password processed in the loop is lower case | |
160 | # and has the first character stripped off it | |
161 | original_password = line.strip | |
162 | ||
163 | if original_password == "" | |
164 | next | |
165 | end | |
166 | ||
167 | # Don't care about case | |
168 | pass = original_password.downcase | |
169 | ||
170 | if verbose | |
171 | puts "Checking password: #{pass}" | |
172 | puts | |
173 | end | |
174 | ||
175 | score = 0 | |
176 | # take the first character and store it | |
177 | last_char = pass[0] | |
178 | ||
179 | # remove the first character | |
180 | pass = pass[1 .. -1] | |
181 | ||
182 | pass.each_char do |c| | |
183 | if c == last_char | |
184 | # just to indicate what is actually happening | |
185 | # the characters are the same so the score | |
186 | # stays the same | |
187 | score += 0 | |
188 | else | |
189 | if keyboard.has_key?(c) | |
190 | found = false | |
191 | puts "Moving from #{last_char} to #{c}" if verbose | |
192 | ||
193 | keyboard[c].each do | diff, chars| | |
194 | puts "\tCharacters #{diff} keys away: #{chars}" if verbose | |
195 | if chars.count(last_char) > 0 | |
196 | # The character is next to the last one | |
197 | score += diff | |
198 | puts "\tCharacter found at score #{diff}" if verbose | |
199 | found = true | |
200 | break | |
201 | end | |
202 | end | |
203 | if !found | |
204 | puts "\tNext key not found so using default score #{MAX_SCORE}" if verbose | |
205 | score += MAX_SCORE | |
206 | end | |
207 | else | |
208 | puts "Character not found in mapping: #{c} so scoring default #{MAX_SCORE}" if verbose | |
209 | score += MAX_SCORE | |
210 | end | |
211 | end | |
212 | last_char = c | |
213 | puts "Current total score #{score}" if verbose | |
214 | end | |
215 | ||
216 | puts "Password: #{original_password}" | |
217 | puts "Total score = #{score.to_s}" | |
218 | puts "Number of moves = #{pass.length.to_s}" | |
219 | # stops divide by zero problems | |
220 | if pass.length == 0 | |
221 | puts "Pattern score = 0 out of " + MAX_SCORE.to_s | |
222 | total_zeros += 1 | |
223 | else | |
224 | avg_score = (score.to_f / pass.length) | |
225 | puts "Pattern score = #{avg_score.to_s} out of " + MAX_SCORE.to_s | |
226 | total_score += avg_score | |
227 | if avg_score == 0 | |
228 | total_zeros += 1 | |
229 | elsif avg_score == 1 | |
230 | total_ones += 1 | |
231 | end | |
232 | end | |
233 | puts | |
234 | ||
235 | total_lines += 1 | |
236 | rescue ArgumentError => e | |
237 | puts "Encoding problem processing word: " + line | |
238 | rescue => e | |
239 | puts "Something went wrong, please report it to [email protected] along with these messages:" | |
240 | puts | |
241 | puts e.message | |
242 | puts | |
243 | puts e.class.to_s | |
244 | puts | |
245 | puts "Backtrace:" | |
246 | puts e.backtrace | |
247 | puts | |
248 | usage | |
249 | exit 1 | |
250 | end | |
251 | end | |
252 | puts "Total passwords processed: #{total_lines.to_s}" | |
253 | if total_lines > 0 | |
254 | puts "Overall pattern score #{(total_score.to_f / total_lines).to_s} out of #{MAX_SCORE}" | |
255 | end | |
256 | puts "Total length zeros found: #{total_zeros.to_s}" | |
257 | puts "Total length ones found: #{total_ones.to_s}" | |
258 | rescue Errno::EACCES => e | |
259 | puts"passpat 1.0 Robin Wood ([email protected]) (http://digi.ninja) | |
260 | ||
261 | Unable to open the password file | |
262 | ||
263 | " | |
264 | exit 1 | |
265 | rescue => e | |
266 | puts "Something went wrong, please report it to [email protected] along with these messages:" | |
267 | puts | |
268 | puts e.message | |
269 | puts | |
270 | puts e.class.to_s | |
271 | puts | |
272 | puts "Backtrace:" | |
273 | puts e.backtrace | |
274 | puts | |
275 | usage | |
276 | exit 1 | |
277 | end | |
278 | end |
0 | 0 | #!/usr/bin/env ruby |
1 | # encoding: utf-8 | |
1 | 2 | |
2 | 3 | # == Pipal: Statistical analysis on password dumps |
3 | 4 | # |
7 | 8 | # --help, -h: show help |
8 | 9 | # --top, -t X: show the top X results (default 10) |
9 | 10 | # --output, -o <filename>: output to file |
10 | # --external, -e <filename>: external file to compare words against | |
11 | 11 | # --gkey <Google Maps API key>: to allow zip code lookups (optional) |
12 | 12 | # |
13 | 13 | # FILENAME: The file to count |
14 | 14 | # |
15 | # Author:: Robin Wood ([email protected]) | |
16 | # Copyright:: Copyright (c) Robin Wood 2011 | |
15 | # Author:: Robin Wood ([email protected]) | |
16 | # Copyright:: Copyright (c) Robin Wood 2013 | |
17 | 17 | # Licence:: Creative Commons Attribution-Share Alike 2.0 |
18 | 18 | # Speedbumped by Stefan Venken ([email protected]) |
19 | 19 | # |
20 | 20 | |
21 | 21 | require 'benchmark' |
22 | require 'getoptlong' | |
23 | 22 | require'net/http' |
24 | 23 | require'uri' |
25 | 24 | require'json' |
26 | require_relative './horizbar' | |
27 | require_relative './progressbar' | |
28 | require_relative './us_area_codes.rb' | |
29 | ||
30 | # Place your google API key here | |
31 | # For more info on getting a key see here https://developers.google.com/maps/documentation/javascript/tutorial#api_key | |
32 | # If you want to leave this blank and pass the key on the command line you can use the --gkey option | |
33 | # From experiments it looks like you don't actually need a valid key but better to have one just in case | |
34 | GOOGLE_API_KEY='' | |
25 | require "pathname" | |
26 | ||
27 | VERSION = "3.1" | |
28 | ||
29 | # Find out what our base path is | |
30 | base_path = File.expand_path(File.dirname(__FILE__)) | |
31 | require File.join(base_path, 'base_checker.rb') | |
32 | require File.join(base_path, 'progressbar.rb') | |
33 | require File.join(base_path, 'pipal_getoptlong.rb') | |
34 | require File.join(base_path, 'os.rb') | |
35 | 35 | |
36 | 36 | if RUBY_VERSION =~ /1\.8/ |
37 | puts "Sorry, Pipal only works correctly on Ruby 1.9.x." | |
37 | puts "Sorry, Pipal only works correctly on Ruby >= 1.9.x." | |
38 | 38 | puts |
39 | 39 | exit |
40 | 40 | end |
41 | 41 | |
42 | class PipalException < Exception | |
43 | end | |
44 | ||
45 | @checkers = [] | |
46 | ||
47 | def register_checker (class_name) | |
48 | @checkers << class_name | |
49 | end | |
50 | ||
42 | 51 | trap("SIGINT") { throw :ctrl_c } |
43 | 52 | |
44 | time = Benchmark.measure do | |
45 | ||
46 | days_ab = {'mon' => 0, 'tues' => 0, 'wed' => 0, 'thurs' => 0, 'fri' => 0, 'sat' => 0, 'sun' => 0} | |
47 | months_ab = {"jan" => 0, "feb" => 0, "mar" => 0, "apr" => 0, "may" => 0, "jun" => 0, "jul" => 0, "aug" => 0, "sept" => 0, "oct" => 0, "nov" => 0, "dec" => 0} | |
48 | ||
49 | colours = {"black" => 0, "blue" => 0, "brown" => 0, "gray" => 0, "green" => 0, "orange" => 0, "pink" => 0, "purple" => 0, "red" => 0, "white" => 0, "yellow" => 0, 'violet' => 0, 'indigo' => 0} | |
50 | days = {'monday' => 0, 'tuesday' => 0, 'wednesday' => 0, 'thursday' => 0, 'friday' => 0, 'saturday' => 0, 'sunday' => 0} | |
51 | months = {"january" => 0, "february" => 0, "march" => 0, "april" => 0, "may" => 0, "june" => 0, "july" => 0, "august" => 0, "september" => 0, "october" => 0, "november" => 0, "december" => 0} | |
52 | ||
53 | char_stats = { | |
54 | "loweralpha" => {'regex' => /^[a-z]+$/, "count" => 0}, | |
55 | "upperalpha" => {'regex' => /^[A-Z]+$/, "count" => 0}, | |
56 | "numeric" => {'regex' => /^[0-9]+$/, "count" => 0}, | |
57 | "special" => {'regex' => /^[\p{Punct}]+$/, "count" => 0}, | |
58 | ||
59 | "loweralphanum" => {'regex' => /^[a-z0-9]+$/, "count" => 0}, | |
60 | "upperalphanum" => {'regex' => /^[A-Z0-9]+$/, "count" => 0}, | |
61 | "mixedalpha" => {'regex' => /^[a-zA-Z]+$/, "count" => 0}, | |
62 | "loweralphaspecial" => {'regex' => /^[a-z\p{Punct}]+$/, "count" => 0}, | |
63 | "upperalphaspecial" => {'regex' => /^[A-Z\p{Punct}]+$/, "count" => 0}, | |
64 | "specialnum" => {'regex' => /^[\p{Punct}0-9]+$/, "count" => 0}, | |
65 | ||
66 | "mixedalphanum" => {'regex' => /^[a-zA-Z0-9]+$/, "count" => 0}, | |
67 | "loweralphaspecialnum" => {'regex' => /^[a-z\p{Punct}0-9]+$/, "count" => 0}, | |
68 | "mixedalphaspecial" => {'regex' => /^[A-Za-z\p{Punct}]+$/, "count" => 0}, | |
69 | "upperalphaspecialnum" => {'regex' => /^[A-Z\p{Punct}0-9]+$/, "count" => 0}, | |
70 | ||
71 | "mixedalphaspecialnum" => {'regex' => /^[A-Za-z\p{Punct}0-9]+$/, "count" => 0}, | |
72 | } | |
73 | ||
74 | char_sets_ordering = { | |
75 | "stringdigit" => {"regex" => /^[a-z]+[0-9]+$/, "count" => 0}, | |
76 | "allstring" => {"regex" => /^[a-z]+$/, "count" => 0}, | |
77 | "digitstring" => {"regex" => /^[0-9]+[a-z]+$/, "count" => 0}, | |
78 | "stringdigitstring" => {"regex" => /^[a-z]+[0-9]+[a-z]+$/, "count" => 0}, | |
79 | "alldigit" => {"regex" => /^[0-9]+$/, "count" => 0}, | |
80 | "digitstringdigit" => {"regex" => /^[0-9]+[a-z]+[0-9]+$/, "count" => 0}, | |
81 | "stringspecialdigit" => {"regex" => /^[a-z]+[\p{Punct}]+[0-9]+$/, "count" => 0}, | |
82 | "stringspecialstring" => {"regex" => /^[a-z]+[\p{Punct}]+[a-z]+$/, "count" => 0}, | |
83 | "stringspecial" => {"regex" => /^[a-z]+[\p{Punct}]+$/, "count" => 0}, | |
84 | "specialstring" => {"regex" => /^[\p{Punct}]+[a-z]+$/, "count" => 0}, | |
85 | "specialstringspecial" => {"regex" => /^[\p{Punct}]+[a-z]+[\p{Punct}]+$/, "count" => 0}, | |
86 | "allspecial" => {"regex" => /^[\p{Punct}]+$/, "count" => 0}, | |
87 | "othermask" => {"regex" => /^.*$/, "count" => 0} | |
88 | } | |
89 | ||
90 | hashcat_masks = {} | |
91 | ||
92 | words = {} | |
93 | total_lines = 0 | |
94 | ||
95 | one_to_six_chars = 0 | |
96 | one_to_eight_chars = 0 | |
97 | over_eight_chars = 0 | |
98 | #only_lower_alpha_chars = 0 | |
99 | #only_upper_alpha_chars = 0 | |
100 | #only_numeric_chars = 0 | |
101 | ||
102 | first_cap_last_num = 0 | |
103 | first_cap_last_num_re = /^[A-Z].*[0-9]$/ | |
104 | first_cap_last_symbol = 0 | |
105 | first_cap_last_symbol_re = /^[A-Z].*[\p{Punct}]$/ | |
106 | ||
107 | years = {} | |
108 | ||
109 | 1975.upto(2020) do |year| | |
110 | years[year] = 0 | |
111 | end | |
112 | ||
113 | # this is the count of words with 1, 2 and 3 numbers on the end | |
114 | #strict_last_on_end = [0,0,0,0,0] | |
115 | singles_on_end_re = /[^0-9]+([0-9]{1})$/ | |
116 | singles_on_end = 0 | |
117 | doubles_on_end_re = /[^0-9]+([0-9]{2})$/ | |
118 | doubles_on_end = 0 | |
119 | triples_on_end_re =/[^0-9]+([0-9]{3})$/ | |
120 | triples_on_end = 0 | |
121 | ||
122 | # this is the actual last number on the end, single digit | |
123 | last_on_end = [] | |
124 | 0.upto(4) do |no_of_digits| | |
125 | last_on_end[no_of_digits] = {} | |
126 | end | |
127 | ||
128 | # last two and three numbers on the end | |
129 | last_two_on_end = {} | |
130 | last_three_on_end = {} | |
131 | ||
132 | def lookup_by_zipcode(zip, key) | |
133 | geocoder = "http://maps.google.com/maps/geo?q=" | |
134 | apikey = "&key=" + key | |
135 | ||
136 | # Since the zipcode goes directly into the URL request it needs to be cleaned up. | |
137 | request = geocoder + URI::encode(zip + ', USA') + apikey | |
138 | resp = Net::HTTP.get_response(URI.parse(request)) | |
139 | ||
140 | data = JSON.parse(resp.body) | |
141 | ||
142 | if data.has_key?('Status') | |
143 | # puts "status: " + data['Status']['code'].to_s | |
144 | ||
145 | if (data.has_key?('Placemark') and data['Placemark'].length > 0) | |
146 | #puts data['Placemark'][0].inspect | |
147 | # puts "location: " + data['Placemark'][0]['address'] | |
148 | ||
149 | if data['Placemark'][0].has_key? 'AddressDetails' and | |
150 | data['Placemark'][0]['AddressDetails'].has_key? 'Country' and | |
151 | data['Placemark'][0]['AddressDetails']['Country'].has_key? 'AdministrativeArea' and | |
152 | data['Placemark'][0]['AddressDetails']['Country']['AdministrativeArea'].has_key? 'Locality' and | |
153 | data['Placemark'][0]['AddressDetails']['Country']['AdministrativeArea']['Locality'].has_key? 'PostalCode' and | |
154 | data['Placemark'][0]['AddressDetails']['Country']['AdministrativeArea']['Locality']['PostalCode'].has_key? 'PostalCodeNumber' and | |
155 | data['Placemark'][0]['AddressDetails']['Country'].has_key? 'CountryName' | |
156 | ||
157 | # puts "Location: " + data['Placemark'][0]['AddressDetails']['Country']['CountryName'] | |
158 | # puts "Location: " + data['Placemark'][0]['AddressDetails']['Country']['AdministrativeArea']['Locality']['PostalCode']['PostalCodeNumber'] | |
159 | if data['Placemark'][0]['AddressDetails']['Country']['CountryName'] == 'USA' and data['Placemark'][0]['AddressDetails']['Country']['AdministrativeArea']['Locality']['PostalCode']['PostalCodeNumber'] == zip | |
160 | return data['Placemark'][0]['address'] | |
161 | end | |
162 | end | |
163 | ||
164 | # return data['Placemark'][0]['address'] | |
165 | end | |
166 | end | |
167 | ||
168 | return nil | |
169 | end | |
53 | # uncomment this and its pair towards the end to benchmark the app | |
54 | #time = Benchmark.measure do | |
170 | 55 | |
171 | 56 | class String |
172 | 57 | def is_numeric? |
174 | 59 | end |
175 | 60 | end |
176 | 61 | |
177 | def is_numeric val | |
178 | return val.to_s =~ /^[0-9]+$/ | |
179 | end | |
180 | ||
181 | opts = GetoptLong.new( | |
62 | def puts_msg_with_header (msg) | |
63 | puts"pipal #{VERSION} Robin Wood ([email protected]) (http://digi.ninja)\n" | |
64 | puts msg | |
65 | puts "\n" | |
66 | end | |
67 | ||
68 | # Display the usage | |
69 | def usage | |
70 | puts"pipal #{VERSION} Robin Wood ([email protected]) (http://digi.ninja) | |
71 | ||
72 | Usage: pipal [OPTION] ... FILENAME | |
73 | --help, -h, -?: show help | |
74 | --top, -t X: show the top X results (default 10) | |
75 | --output, -o <filename>: output to file | |
76 | --gkey <Google Maps API key>: to allow zip code lookups (optional) | |
77 | --list-checkers: Show the available checkers and which are enabled | |
78 | --verbose, -v: Verbose | |
79 | " | |
80 | ||
81 | @checkers.each do |class_name| | |
82 | mod = Object::const_get(class_name).new | |
83 | ||
84 | # Check if each Checker has any usage to add and if so add it | |
85 | use = mod.usage | |
86 | if !use.nil? | |
87 | puts use | |
88 | end | |
89 | end | |
90 | ||
91 | puts " | |
92 | ||
93 | FILENAME: The file to count | |
94 | ||
95 | " | |
96 | exit | |
97 | end | |
98 | ||
99 | def list_checkers | |
100 | all_checkers = {} | |
101 | ||
102 | # Find out what our base path is | |
103 | base_path = File.expand_path(File.dirname(__FILE__)) | |
104 | ||
105 | # doing it like this so that the files can be symlinked in | |
106 | # in numeric order | |
107 | checker_names = [] | |
108 | Dir.glob(base_path + '/checkers_enabled/*rb').select do |fn| | |
109 | if !File.directory? fn | |
110 | checker_names << fn | |
111 | end | |
112 | end | |
113 | checker_names.sort.each do |name| | |
114 | # Ruby doesn't seem to like doing a require | |
115 | # on a symlink so this finds the ultimate target | |
116 | # of the link (i.e. will travel multiple links) | |
117 | # and require that instead | |
118 | require Pathname.new(name).realpath | |
119 | end | |
120 | ||
121 | @checkers.each do |class_name| | |
122 | mod = Object::const_get(class_name).new | |
123 | all_checkers[class_name] = {'description' => mod.description, 'enabled' => true} | |
124 | end | |
125 | ||
126 | @checkers = [] | |
127 | Dir.glob(base_path + '/checkers_available/*rb').select do |fn| | |
128 | if !File.directory? fn | |
129 | # Ruby doesn't seem to like doing a require | |
130 | # on a symlink so this finds the ultimate target | |
131 | # of the link (i.e. will travel multiple links) | |
132 | # and require that instead | |
133 | require Pathname.new(fn).realpath | |
134 | end | |
135 | end | |
136 | ||
137 | @checkers.each do |class_name| | |
138 | mod = Object::const_get(class_name).new | |
139 | all_checkers[class_name] = {'description' => mod.description, 'enabled' => false} | |
140 | end | |
141 | ||
142 | puts "pipal #{VERSION} Robin Wood ([email protected]) (http://digi.ninja)" | |
143 | puts | |
144 | puts "You have the following Checkers on your system" | |
145 | puts "==============================================" | |
146 | ||
147 | all_checkers.sort.each do |check| | |
148 | puts "#{check[0]} - #{check[1]['description']}" + (check[1]['enabled']?" - Enabled":"") | |
149 | end | |
150 | ||
151 | puts | |
152 | ||
153 | exit | |
154 | end | |
155 | ||
156 | # Defaults | |
157 | verbose = false | |
158 | cap_at = 10 | |
159 | output_file = STDOUT | |
160 | custom_word_splitter = nil | |
161 | ||
162 | # If there is a customer Splitter sylinked in then require it in | |
163 | # and it will automatically be used | |
164 | ||
165 | if File.exists?(File.join(base_path, "custom_splitter.rb")) | |
166 | require Pathname.new(File.join(base_path, "custom_splitter.rb")).realpath | |
167 | custom_word_splitter = Custom_word_splitter | |
168 | end | |
169 | ||
170 | # Loop thorugh all the Checkers which have been enabled and | |
171 | # require them in | |
172 | require_list = [] | |
173 | Dir.glob(base_path + '/checkers_enabled/*rb').select do |f| | |
174 | if !File.directory? f | |
175 | require_list << f | |
176 | end | |
177 | end | |
178 | require_list.sort.each do |fn| | |
179 | # Ruby doesn't seem to like doing a require | |
180 | # on a symlink so this finds the ultimate target | |
181 | # of the link (i.e. will travel multiple links) | |
182 | # and require that instead | |
183 | require Pathname.new(fn).realpath | |
184 | end | |
185 | ||
186 | if @checkers.count == 0 | |
187 | puts_msg_with_header("No Checkers enabled, please read README_modular for more information") | |
188 | exit 1 | |
189 | end | |
190 | ||
191 | modules = [] | |
192 | ||
193 | opts = PipalGetoptLong.new( | |
182 | 194 | [ '--help', '-h', "-?", GetoptLong::NO_ARGUMENT ], |
183 | 195 | [ '--top', "-t" , GetoptLong::REQUIRED_ARGUMENT ], |
184 | 196 | [ '--output', "-o" , GetoptLong::REQUIRED_ARGUMENT ], |
185 | [ '--external', "-e" , GetoptLong::REQUIRED_ARGUMENT ], | |
186 | 197 | [ '--gkey', GetoptLong::REQUIRED_ARGUMENT ], |
187 | [ "-v" , GetoptLong::NO_ARGUMENT ] | |
198 | [ "--verbose", "-v" , GetoptLong::NO_ARGUMENT ], | |
199 | [ "--list-checkers" , GetoptLong::NO_ARGUMENT ], | |
188 | 200 | ) |
189 | 201 | |
190 | # Display the usage | |
191 | def usage | |
192 | puts"pipal 2.0 Robin Wood ([email protected]) (www.digininja.org) | |
193 | ||
194 | Usage: pipal [OPTION] ... FILENAME | |
195 | --help, -h: show help | |
196 | --top, -t X: show the top X results (default 10) | |
197 | --output, -o <filename>: output to file | |
198 | --external, -e <filename>: external file to compare words against | |
199 | --gkey <Google Maps API key>: to allow zip code lookups (optional) | |
200 | ||
201 | FILENAME: The file to count | |
202 | ||
203 | " | |
204 | exit | |
205 | end | |
206 | ||
207 | cap_at = 10 | |
208 | output_file = STDOUT | |
209 | external_list = {} | |
210 | google_maps_api_key = GOOGLE_API_KEY | |
202 | @checkers.each do |class_name| | |
203 | mod = Object::const_get(class_name).new | |
204 | modules << mod | |
205 | ||
206 | # If the module has any parameters then they | |
207 | # will be in the cli_params attribute as an array | |
208 | # so go through it and add them all to the main options list | |
209 | if !mod.cli_params.nil? | |
210 | mod.cli_params.each do |param| | |
211 | opts.add_option(param) | |
212 | end | |
213 | end | |
214 | end | |
211 | 215 | |
212 | 216 | begin |
217 | # Having to store them as once you've parsed through opts once you can't do it | |
218 | # again as far as I can tell, all the values disappear. | |
219 | stored_opts = {} | |
220 | ||
213 | 221 | opts.each do |opt, arg| |
222 | stored_opts[opt] = arg | |
214 | 223 | case opt |
215 | 224 | when '--help' |
216 | 225 | usage |
226 | when "--list-checkers" | |
227 | list_checkers | |
228 | exit | |
217 | 229 | when "--top" |
218 | 230 | if arg.is_numeric? |
219 | 231 | cap_at = arg.to_i |
220 | 232 | if cap_at <= 0 |
221 | puts"pipal 2.0 Robin Wood ([email protected]) (www.digininja.org) | |
222 | ||
223 | Please enter a positive number of lines | |
224 | ||
225 | " | |
233 | puts_msg_with_header("Please enter a positive number of lines") | |
226 | 234 | exit 1 |
227 | 235 | end |
228 | 236 | else |
229 | puts"pipal 2.0 Robin Wood ([email protected]) (www.digininja.org) | |
230 | ||
231 | Invalid number of lines | |
232 | ||
233 | " | |
237 | puts_msg_with_header("Invalid number of lines") | |
234 | 238 | exit 1 |
235 | 239 | end |
236 | 240 | when "--gkey" |
237 | 241 | google_maps_api_key = arg |
238 | when "--external" | |
239 | if File.exist?(arg) | |
240 | begin | |
241 | File.open(arg, 'r').each_line do |word| | |
242 | external_list[word.force_encoding("ASCII-8BIT").strip] = 0 unless word.force_encoding("ASCII-8BIT").strip == '' | |
243 | end | |
244 | rescue Errno::EACCES => e | |
245 | puts"pipal 2.0 Robin Wood ([email protected]) (www.digininja.org) | |
246 | ||
247 | Unable to open external file | |
248 | ||
249 | " | |
250 | exit 1 | |
251 | end | |
252 | else | |
253 | puts"pipal 2.0 Robin Wood ([email protected]) (www.digininja.org) | |
254 | ||
255 | Unable to find external file | |
256 | ||
257 | " | |
258 | exit 1 | |
259 | end | |
260 | 242 | when "--output" |
261 | 243 | begin |
262 | 244 | output_file = File.new(arg, "w") |
263 | 245 | rescue Errno::EACCES => e |
264 | puts"pipal 2.0 Robin Wood ([email protected]) (www.digininja.org) | |
265 | ||
266 | Unable to open output file | |
267 | ||
268 | " | |
246 | puts_msg_with_header("Unable to open output file") | |
269 | 247 | exit 1 |
270 | 248 | end |
271 | end | |
249 | when "--verbose" | |
250 | verbose = true | |
251 | end | |
252 | end | |
253 | ||
254 | # allow each of the modules to pull out the CLI params they require | |
255 | # and pass through any global values | |
256 | modules.each do |mod| | |
257 | mod.verbose = verbose | |
258 | mod.cap_at = cap_at | |
259 | mod.parse_params stored_opts | |
272 | 260 | end |
273 | 261 | rescue GetoptLong::InvalidOption => e |
274 | 262 | puts |
275 | 263 | usage |
276 | 264 | exit |
277 | 265 | rescue => e |
278 | puts "Something went wrong, please report it to [email protected] along with these messages:" | |
266 | puts "Something went wrong, please report it to [email protected] along with these messages:" | |
279 | 267 | puts |
280 | 268 | puts e.message |
281 | 269 | puts |
289 | 277 | end |
290 | 278 | |
291 | 279 | if ARGV.length != 1 |
292 | puts"pipal 2.0 Robin Wood ([email protected]) (www.digininja.org) | |
293 | ||
294 | Please specify the file to count | |
295 | ||
296 | " | |
280 | puts_msg_with_header("Please specify the file to analyse") | |
297 | 281 | exit 1 |
298 | 282 | end |
299 | 283 | |
300 | 284 | filename = ARGV.shift |
301 | 285 | |
302 | 286 | if !File.exist? filename |
303 | puts"pipal 2.0 Robin Wood ([email protected]) (www.digininja.org) | |
304 | ||
305 | Can't find the password file | |
306 | ||
307 | " | |
287 | puts_msg_with_header("Can't find the password file") | |
308 | 288 | exit 2 |
309 | 289 | end |
310 | ||
311 | lengths = [] | |
312 | max_length = 0 | |
313 | base_words = {} | |
314 | 290 | |
315 | 291 | puts "Generating stats, hit CTRL-C to finish early and dump stats on words already processed." |
316 | 292 | puts "Please wait..." |
317 | 293 | |
318 | if %x{wc -l '#{filename}'}.match(/\s*([0-9]+).*/) | |
294 | if (not OS.windows?) and %x{wc -l '#{filename}'}.match(/\s*([0-9]+).*/) | |
319 | 295 | file_line_count = $1.to_i |
320 | 296 | else |
321 | 297 | filesize = File.stat(filename).size |
334 | 310 | pbar.inc |
335 | 311 | next |
336 | 312 | end |
337 | # Doing this so that I can support a wider range of characters, a UK pound sign | |
338 | # breaks the app without it | |
339 | line.force_encoding("ASCII-8BIT") | |
340 | lower_line = line.downcase | |
341 | ||
342 | if !words.has_key?(line) | |
343 | words[line] = 0 | |
344 | end | |
345 | words[line] += 1 | |
346 | ||
347 | # strip any non-alpha from the start or end, I was going to strip all non-alpha | |
348 | # but then found a list with Unc0rn as a very common base. Stripping all non-alpha | |
349 | # would leave with Uncrn which doesn't really make any sense as without the 133t speak | |
350 | # it is out of context. | |
351 | # | |
352 | # If you want all non-alpha stripped use the following line instead | |
353 | # | |
354 | # word_just_alpha = lower_line.gsub(/[^a-z]*/, "") | |
355 | # | |
356 | word_just_alpha = lower_line.gsub(/^[^a-z]*/, "").gsub(/[^a-z]*$/, '') | |
357 | if word_just_alpha.length > 3 | |
358 | if !base_words.has_key?(word_just_alpha) | |
359 | base_words[word_just_alpha] = 0 | |
313 | ||
314 | if !custom_word_splitter.nil? | |
315 | word, extras = Custom_word_splitter::split(line) | |
316 | else | |
317 | word = line | |
318 | extras = {} | |
319 | end | |
320 | ||
321 | modules.each do |mod| | |
322 | # allow the custom splitter to pass back nil | |
323 | # which indicates that the line isn't to be parsed | |
324 | if !word.nil? | |
325 | mod.process_word(word, extras) | |
360 | 326 | end |
361 | base_words[word_just_alpha] += 1 | |
362 | end | |
363 | ||
364 | if lengths[line.length].nil? | |
365 | lengths[line.length] = 0 | |
366 | end | |
367 | lengths[line.length] += 1 | |
368 | ||
369 | # if line.length > max_length | |
370 | # max_length = line.length | |
371 | # end | |
372 | ||
373 | if line.length < 9 | |
374 | one_to_eight_chars += 1 | |
375 | end | |
376 | ||
377 | if line.length < 7 | |
378 | one_to_six_chars += 1 | |
379 | end | |
380 | ||
381 | if line.length > 8 | |
382 | over_eight_chars += 1 | |
383 | end | |
384 | ||
385 | # Replaced with character set upperalpha | |
386 | # if line. =~ /^[A-Z]*$/ | |
387 | # only_upper_alpha_chars += 1 | |
388 | # end | |
389 | ||
390 | # Replaced with character set loweralpha | |
391 | # if line. =~ /^[a-z]*$/ | |
392 | # only_lower_alpha_chars += 1 | |
393 | # end | |
394 | ||
395 | # Replaced with character set alldigit | |
396 | # if line. =~ /^[0-9]*$/ | |
397 | # only_numeric_chars += 1 | |
398 | # end | |
399 | ||
400 | if line =~ first_cap_last_symbol_re | |
401 | first_cap_last_symbol += 1 | |
402 | end | |
403 | ||
404 | if line =~ first_cap_last_num_re | |
405 | first_cap_last_num += 1 | |
406 | end | |
407 | ||
408 | years.each_pair do |year, count| | |
409 | if /#{year}/.match line | |
410 | years[year] += 1 | |
411 | end | |
412 | end | |
413 | ||
414 | days_ab.each_pair do |day, count| | |
415 | if /#{day}/i.match line | |
416 | days_ab[day] += 1 | |
417 | end | |
418 | end | |
419 | ||
420 | months_ab.each_pair do |month, count| | |
421 | if /#{month}/i.match line | |
422 | months_ab[month] += 1 | |
423 | end | |
424 | end | |
425 | ||
426 | colours.each_pair do |colour, count| | |
427 | if /#{colour}/i.match line | |
428 | colours[colour] += 1 | |
429 | end | |
430 | end | |
431 | ||
432 | days.each_pair do |day, count| | |
433 | if /#{day}/i.match line | |
434 | days[day] += 1 | |
435 | end | |
436 | end | |
437 | ||
438 | months.each_pair do |month, count| | |
439 | if /#{month}/i.match line | |
440 | months[month] += 1 | |
441 | end | |
442 | end | |
443 | ||
444 | external_list.each_pair do |domain, count| | |
445 | if /#{Regexp.quote(domain)}/i.match line | |
446 | external_list[domain] += 1 | |
447 | end | |
448 | end | |
449 | ||
450 | #if line =~ /[^0-9]+([0-9]{1})$/ | |
451 | # if /[^0-9]+([0-9]{1})$/.match line | |
452 | if singles_on_end_re.match line | |
453 | singles_on_end += 1 | |
454 | end | |
455 | ||
456 | # Can't merge these two as the first is strict, 2 digits on the end, the second | |
457 | # just wants the last two digits regardless | |
458 | # if /[^0-9]+([0-9]{2})$/.match line | |
459 | if doubles_on_end_re.match line | |
460 | # if line =~ /[^0-9]+([0-9]{2})$/ | |
461 | doubles_on_end += 1 | |
462 | end | |
463 | ||
464 | # if /[^0-9]+([0-9]{3})$/.match line | |
465 | if triples_on_end_re.match line | |
466 | #if line =~ /[^0-9]+([0-9]{3})$/ | |
467 | triples_on_end += 1 | |
468 | end | |
469 | ||
470 | 1.upto(5) do |no_of_digits| | |
471 | if /([0-9]{#{no_of_digits}})$/.match line | |
472 | last_numbers = $1 | |
473 | if !last_on_end[no_of_digits - 1].has_key?(last_numbers) | |
474 | last_on_end[no_of_digits - 1][last_numbers] = 0 | |
475 | end | |
476 | last_on_end[no_of_digits - 1][last_numbers] += 1 | |
477 | end | |
478 | # if /[^0-9]+([0-9]{#{no_of_digits}})$/.match line | |
479 | # strict_last_on_end[no_of_digits - 1] += 1 | |
480 | # end | |
481 | ||
482 | end | |
483 | ||
484 | # numbers_on_end.each_pair do |number, count| | |
485 | # if /[^0-9]*#{number}$/.match line | |
486 | # numbers_on_end[number] += 1 | |
487 | # end | |
488 | # end | |
489 | ||
490 | char_stats.each_pair do |name, data| | |
491 | begin | |
492 | if line =~ data['regex'] | |
493 | char_stats[name]['count'] += 1 | |
494 | break | |
495 | end | |
496 | rescue Encoding::CompatibilityError | |
497 | puts "Encoding problem found with password: " + line | |
498 | end | |
499 | end | |
500 | ||
501 | char_sets_ordering.each_pair do |name, data| | |
502 | begin | |
503 | if lower_line =~ data['regex'] | |
504 | char_sets_ordering[name]['count'] += 1 | |
505 | break | |
506 | end | |
507 | rescue Encoding::CompatibilityError | |
508 | puts "Encoding problem found with password: " + line | |
509 | end | |
510 | end | |
511 | ||
512 | # This won't work as the special replacement hits all the previous ?'s that have been replaced, | |
513 | # lower at the end would do the same with all the characters so can't use the order to fix this problem | |
514 | # mask_line = line.gsub(/[a-z]/, "?l").gsub(/[A-Z]/,'?u').gsub(/[0-9]/, '?d').gsub(/[\p{Punct}]/, '?s') | |
515 | mask_line = "" | |
516 | line.each_char do |char| | |
517 | case char | |
518 | when /[a-z]/ | |
519 | mask_line << "?l" | |
520 | when /[A-Z]/ | |
521 | mask_line << "?u" | |
522 | when /[0-9]/ | |
523 | mask_line << "?d" | |
524 | else | |
525 | mask_line << "?s" | |
526 | end | |
527 | end | |
528 | ||
529 | if !hashcat_masks.has_key? mask_line | |
530 | hashcat_masks[mask_line] = {'count' => 0} | |
531 | end | |
532 | hashcat_masks[mask_line]['count'] += 1 | |
327 | end | |
533 | 328 | |
534 | 329 | pbar.inc |
535 | ||
536 | total_lines += 1 | |
537 | 330 | rescue ArgumentError => e |
538 | 331 | puts "Encoding problem processing word: " + line |
332 | # puts e.inspect | |
333 | # puts e.backtrace | |
334 | # exit | |
539 | 335 | pbar.inc |
540 | 336 | rescue => e |
541 | puts "Something went wrong, please report it to [email protected] along with these messages:" | |
337 | puts "Something went wrong, please report it to [email protected] along with these messages:" | |
542 | 338 | puts |
543 | 339 | puts e.message |
544 | 340 | puts |
547 | 343 | puts "Backtrace:" |
548 | 344 | puts e.backtrace |
549 | 345 | puts |
550 | usage | |
551 | 346 | exit 1 |
552 | 347 | end |
553 | 348 | end |
554 | 349 | rescue Errno::EACCES => e |
555 | puts"pipal 2.0 Robin Wood ([email protected]) (www.digininja.org) | |
556 | ||
557 | Unable to open the password file | |
558 | ||
559 | " | |
350 | puts_msg_with_header("Unable to open the password file") | |
560 | 351 | exit 1 |
561 | 352 | rescue => e |
562 | puts "Something went wrong, please report it to [email protected] along with these messages:" | |
353 | puts "Something went wrong, please report it to [email protected] along with these messages:" | |
563 | 354 | puts |
564 | 355 | puts e.message |
565 | 356 | puts |
579 | 370 | puts |
580 | 371 | puts |
581 | 372 | |
582 | output_file.puts "Total entries = " + total_lines.to_s | |
583 | uniq_words = words.to_a.uniq | |
584 | output_file.puts "Total unique entries = " + uniq_words.length.to_s | |
585 | uniq_words = Array.new(words.to_a.uniq) | |
373 | modules.each do |mod| | |
374 | output_file.puts mod.get_results | |
375 | output_file.puts | |
376 | end | |
586 | 377 | |
587 | 378 | output_file.puts |
588 | output_file.puts "Top " + cap_at.to_s + " passwords" | |
589 | # The default is to sort lowest to highest, the -1 just inverts that | |
590 | words.sort{|a,b| (a[1]<=>b[1]) * -1}[0, cap_at].each { |elem| | |
591 | percentage = (elem[1].to_f / total_lines) * 100 | |
592 | output_file.puts elem[0] + " = " + elem[1].to_s + " (" + percentage.round(2).to_s + "%)" | |
593 | } | |
594 | ||
595 | output_file.puts | |
596 | output_file.puts "Top " + cap_at.to_s + " base words" | |
597 | base_words.sort{|a,b| (a[1]<=>b[1]) * -1}[0, cap_at].each { |elem| | |
598 | percentage = (elem[1].to_f / total_lines) * 100 | |
599 | output_file.puts elem[0] + " = " + elem[1].to_s + " (" + percentage.round(2).to_s + "%)" | |
600 | } | |
601 | ||
602 | output_file.puts | |
603 | output_file.puts "Password length (length ordered)" | |
604 | ||
605 | length_ordered = [] | |
606 | 0.upto(lengths.count) do |len| | |
607 | if lengths[len].nil? | |
608 | lengths[len] = 0 | |
609 | end | |
610 | percentage = ((lengths[len].to_f / total_lines) * 100) | |
611 | output_file.puts len.to_s + ' = ' + lengths[len].to_s + " (" + percentage.round(2).to_s + "%)" if lengths[len] > 0 | |
612 | ||
613 | pair = [len, lengths[len], percentage] | |
614 | length_ordered << pair | |
615 | end | |
616 | ||
617 | length_ordered.sort! do |x,y| | |
618 | y[1] <=> x[1] | |
619 | end | |
620 | ||
621 | output_file.puts | |
622 | output_file.puts "Password length (count ordered)" | |
623 | length_ordered.each do |pair| | |
624 | output_file.puts pair[0].to_s + " = " + pair[1].to_s + " (" + pair[2].round(2).to_s + "%)" if pair[1] > 0 | |
625 | end | |
626 | ||
627 | output_file.puts | |
628 | ||
629 | horiz = HorizBar.new(lengths) | |
630 | horiz.output_file = output_file | |
631 | horiz.draw | |
632 | ||
633 | output_file.puts "One to six characters = " + one_to_six_chars.to_s + ' (' + ((one_to_six_chars.to_f/total_lines) * 100).round(2).to_s + '%)' | |
634 | output_file.puts "One to eight characters = " + one_to_eight_chars.to_s + ' (' + ((one_to_eight_chars.to_f/total_lines) * 100).round(2).to_s + '%)' | |
635 | output_file.puts "More than eight characters = " + over_eight_chars.to_s + ' (' + ((over_eight_chars.to_f/total_lines) * 100).round(2).to_s + '%)' | |
636 | ||
637 | output_file.puts | |
638 | ||
639 | output_file.puts "Only lowercase alpha = " + char_stats['loweralpha']['count'].to_s + ' (' + ((char_stats['loweralpha']['count'].to_f/total_lines) * 100).round(2).to_s + '%)' | |
640 | output_file.puts "Only uppercase alpha = " + char_stats['upperalpha']['count'].to_s + ' (' + ((char_stats['upperalpha']['count'].to_f/total_lines) * 100).round(2).to_s + '%)' | |
641 | output_file.puts "Only alpha = " + (char_stats['upperalpha']['count'] + char_stats['loweralpha']['count']).to_s + ' (' + (((char_stats['upperalpha']['count'] + char_stats['loweralpha']['count']).to_f/total_lines) * 100).round(2).to_s + '%)' | |
642 | ||
643 | output_file.puts "Only numeric = " + char_stats['numeric']['count'].to_s + ' (' + ((char_stats['numeric']['count'].to_f/total_lines) * 100).round(2).to_s + '%)' | |
644 | ||
645 | output_file.puts | |
646 | output_file.puts "First capital last symbol = " + first_cap_last_symbol.to_s + ' (' + ((first_cap_last_symbol.to_f/total_lines) * 100).round(2).to_s + '%)' | |
647 | output_file.puts "First capital last number = " + first_cap_last_num.to_s + ' (' + ((first_cap_last_num.to_f/total_lines) * 100).round(2).to_s + '%)' | |
648 | ||
649 | if external_list.length > 0 | |
650 | count_ordered = [] | |
651 | external_list.each_pair do |domain, count| | |
652 | count_ordered << [domain, count] unless count == 0 | |
653 | end | |
654 | external_list = count_ordered.sort do |x,y| | |
655 | (x[1] <=> y[1]) * -1 | |
656 | end | |
657 | ||
658 | output_file.puts | |
659 | output_file.puts "External list (Top " + cap_at.to_s + ")" | |
660 | disp = false | |
661 | external_list[0, cap_at].each do |data| | |
662 | disp = true | |
663 | output_file.puts data[0] + " = " + data[1].to_s + ' (' + ((data[1].to_f/total_lines) * 100).round(2).to_s + '%)' | |
664 | end | |
665 | unless disp | |
666 | output_file.puts "None found" | |
667 | end | |
668 | end | |
669 | ||
670 | output_file.puts | |
671 | output_file.puts "Months" | |
672 | disp = false | |
673 | months.each_pair do |month, count| | |
674 | unless count == 0 | |
675 | disp = true | |
676 | output_file.puts month + " = " + count.to_s + ' (' + ((count.to_f/total_lines) * 100).round(2).to_s + '%)'unless count == 0 | |
677 | end | |
678 | end | |
679 | unless disp | |
680 | output_file.puts "None found" | |
681 | end | |
682 | ||
683 | output_file.puts | |
684 | output_file.puts "Days" | |
685 | disp = false | |
686 | days.each_pair do |day, count| | |
687 | unless count == 0 | |
688 | disp = true | |
689 | output_file.puts day + " = " + count.to_s + ' (' + ((count.to_f/total_lines) * 100).round(2).to_s + '%)' unless count == 0 | |
690 | end | |
691 | end | |
692 | unless disp | |
693 | output_file.puts "None found" | |
694 | end | |
695 | ||
696 | output_file.puts | |
697 | output_file.puts "Months (Abreviated)" | |
698 | disp = false | |
699 | months_ab.each_pair do |month, count| | |
700 | unless count == 0 | |
701 | disp = true | |
702 | output_file.puts month + " = " + count.to_s + ' (' + ((count.to_f/total_lines) * 100).round(2).to_s + '%)' unless count == 0 | |
703 | end | |
704 | end | |
705 | unless disp | |
706 | output_file.puts "None found" | |
707 | end | |
708 | ||
709 | output_file.puts | |
710 | output_file.puts "Days (Abreviated)" | |
711 | disp = false | |
712 | days_ab.each_pair do |day, count| | |
713 | unless count == 0 | |
714 | disp = true | |
715 | output_file.puts day + " = " + count.to_s + ' (' + ((count.to_f/total_lines) * 100).round(2).to_s + '%)' unless count == 0 | |
716 | end | |
717 | end | |
718 | unless disp | |
719 | output_file.puts "None found" | |
720 | end | |
721 | ||
722 | output_file.puts | |
723 | output_file.puts "Includes years" | |
724 | disp = false | |
725 | years.each_pair do |number, count| | |
726 | unless count == 0 | |
727 | disp = true | |
728 | output_file.puts number.to_s + " = " + count.to_s + ' (' + ((count.to_f/total_lines) * 100).round(2).to_s + '%)'unless count == 0 | |
729 | end | |
730 | end | |
731 | unless disp | |
732 | output_file.puts "None found" | |
733 | end | |
734 | ||
735 | count_ordered = [] | |
736 | years.each_pair do |year, count| | |
737 | count_ordered << [year, count] unless count == 0 | |
738 | end | |
739 | years = count_ordered.sort do |x,y| | |
740 | (x[1] <=> y[1]) * -1 | |
741 | end | |
742 | ||
743 | output_file.puts | |
744 | output_file.puts "Years (Top " + cap_at.to_s + ")" | |
745 | disp = false | |
746 | years[0, cap_at].each do |data| | |
747 | disp = true | |
748 | output_file.puts data[0].to_s + " = " + data[1].to_s + ' (' + ((data[1].to_f/total_lines) * 100).round(2).to_s + '%)' | |
749 | end | |
750 | unless disp | |
751 | output_file.puts "None found" | |
752 | end | |
753 | ||
754 | output_file.puts | |
755 | output_file.puts "Colours" | |
756 | disp = false | |
757 | colours.each_pair do |colour, count| | |
758 | unless count == 0 | |
759 | disp = true | |
760 | output_file.puts colour + " = " + count.to_s + ' (' + ((count.to_f/total_lines) * 100).round(2).to_s + '%)' unless count == 0 | |
761 | end | |
762 | end | |
763 | unless disp | |
764 | output_file.puts "None found" | |
765 | end | |
766 | ||
767 | ||
768 | output_file.puts | |
769 | ||
770 | #output_file.puts "Single digit on the end = " + strict_last_on_end[2].count.to_s + ' (' + ((strict_last_on_end[0].count.to_f/total_lines) * 100).round(2).to_s + '%)' | |
771 | #output_file.puts "Two digits on the end = " + strict_last_on_end[2].count.to_s + ' (' + ((strict_last_on_end[1].count.to_f/total_lines) * 100).round(2).to_s + '%)' | |
772 | #output_file.puts "Three digits on the end = " + strict_last_on_end[2].count.to_s + ' (' + ((strict_last_on_end[2].count.to_f/total_lines) * 100).round(2).to_s + '%)' | |
773 | ||
774 | output_file.puts "Single digit on the end = " + singles_on_end.to_s + ' (' + ((singles_on_end.to_f/total_lines) * 100).round(2).to_s + '%)' | |
775 | output_file.puts "Two digits on the end = " + doubles_on_end.to_s + ' (' + ((doubles_on_end.to_f/total_lines) * 100).round(2).to_s + '%)' | |
776 | output_file.puts "Three digits on the end = " + triples_on_end.to_s + ' (' + ((triples_on_end.to_f/total_lines) * 100).round(2).to_s + '%)' | |
777 | ||
778 | output_file.puts | |
779 | output_file.puts "Last number" | |
780 | disp = false | |
781 | ||
782 | graph_numbers = {0=>0, 1=>0, 2=>0, 3=>0, 4=>0, 5=>0, 6=>0, 7=>0, 8=>0, 9=>0} | |
783 | ||
784 | c = last_on_end[0].to_a.sort do |x,y| | |
785 | (x[0] <=> y[0]) | |
786 | end | |
787 | ||
788 | c.each do |number, count| | |
789 | unless count == 0 | |
790 | disp = true | |
791 | output_file.puts number.to_s + " = " + count.to_s + ' (' + ((count.to_f/total_lines) * 100).round(2).to_s + '%)' unless count == 0 | |
792 | end | |
793 | graph_numbers[number.to_i] = count | |
794 | end | |
795 | unless disp | |
796 | output_file.puts "None found" | |
797 | end | |
798 | ||
799 | output_file.puts | |
800 | horiz = HorizBar.new(graph_numbers.values) | |
801 | horiz.output_file = output_file | |
802 | horiz.draw | |
803 | ||
804 | area_codes = [] | |
805 | zip_codes = [] | |
806 | ||
807 | digit_number = 0 | |
808 | last_on_end.each do |a| | |
809 | c = a.to_a.sort do |x,y| | |
810 | (x[1] <=> y[1]) * -1 | |
811 | end | |
812 | ||
813 | digit_number += 1 | |
814 | if c.count > 0 | |
815 | if (digit_number == 1) | |
816 | output_file.puts "Last digit" | |
817 | else | |
818 | output_file.puts "Last " + digit_number.to_s + " digits (Top " + cap_at.to_s + ")" | |
819 | end | |
820 | ||
821 | c[0, cap_at].each do |d| | |
822 | output_file.puts d[0] + " = " + d[1].to_s + ' (' + ((d[1].to_f/total_lines) * 100).round(2).to_s + '%)' | |
823 | ||
824 | if digit_number == 3 | |
825 | area_codes << d[0] | |
826 | end | |
827 | if digit_number == 5 | |
828 | zip_codes << d[0] | |
829 | end | |
830 | end | |
831 | output_file.puts | |
832 | end | |
833 | end | |
834 | ||
835 | count_ordered = [] | |
836 | char_stats.each_pair do |name, data| | |
837 | count_ordered << [name, data] unless data['count'] == 0 | |
838 | end | |
839 | char_stats = count_ordered.sort do |x,y| | |
840 | (x[1]['count'] <=> y[1]['count']) * -1 | |
841 | end | |
842 | ||
843 | areas = {} | |
844 | area_codes.each do |code| | |
845 | code = code.to_s | |
846 | if US_area_codes.has_key? code | |
847 | area = US_area_codes[code] | |
848 | areas[code] = area | |
849 | end | |
850 | end | |
851 | if areas.length > 0 | |
852 | output_file.puts "US Area Codes" | |
853 | areas.each_pair do |code, area| | |
854 | output_file.puts code + ' = ' + area[1] + " (" + area[0] + ")" | |
855 | end | |
856 | output_file.puts | |
857 | end | |
858 | ||
859 | if google_maps_api_key != "" | |
860 | areas = {} | |
861 | zip_codes.each do |zip| | |
862 | area = lookup_by_zipcode zip.to_s, google_maps_api_key | |
863 | unless area.nil? | |
864 | areas[zip] = area | |
865 | end | |
866 | end | |
867 | if areas.length > 0 | |
868 | output_file.puts "US Zip Codes" | |
869 | areas.each_pair do |zip, area| | |
870 | output_file.puts zip + ' = ' + area | |
871 | end | |
872 | output_file.puts | |
873 | end | |
874 | end | |
875 | ||
876 | output_file.puts "Character sets" | |
877 | char_stats.each do |name, data| | |
878 | output_file.puts name + ": " + data['count'].to_s + " (" + ((data['count'].to_f/total_lines) * 100).round(2).to_s + "%)" | |
879 | end | |
880 | ||
881 | count_ordered = [] | |
882 | char_sets_ordering.each_pair do |name, data| | |
883 | count_ordered << [name, data] unless data['count'] == 0 | |
884 | end | |
885 | char_sets_ordering = count_ordered.sort do |x,y| | |
886 | (x[1]['count'] <=> y[1]['count']) * -1 | |
887 | end | |
888 | ||
889 | output_file.puts | |
890 | output_file.puts "Character set ordering" | |
891 | char_sets_ordering.each do |name, data| | |
892 | output_file.puts name + ": " + data['count'].to_s + " (" + ((data['count'].to_f/total_lines) * 100).round(2).to_s + "%)" | |
893 | end | |
894 | ||
895 | count_ordered = [] | |
896 | hashcat_masks.each_pair do |name, data| | |
897 | count_ordered << [name, data] unless data['count'] == 0 | |
898 | end | |
899 | hashcat_masks = count_ordered.sort do |x,y| | |
900 | (x[1]['count'] <=> y[1]['count']) * -1 | |
901 | end | |
902 | ||
903 | output_file.puts | |
904 | output_file.puts "Hashcat masks (Top " + cap_at.to_s + ")" | |
905 | hashcat_masks[0, cap_at].each do |name, data| | |
906 | output_file.puts name + ": " + data['count'].to_s + " (" + ((data['count'].to_f/total_lines) * 100).round(2).to_s + "%)" | |
907 | end | |
908 | ||
909 | end | |
910 | puts time if false | |
379 | ||
380 | # Companion to the commented out benchmark at the top | |
381 | #end | |
382 | #puts time |
0 | # Class to extend getoptlong to add the ability to add | |
1 | # an option to an existing list. | |
2 | # | |
3 | # Basically the code from set_options with the loop removed | |
4 | # so it only parses the argument passed and without clearing | |
5 | # down the structures first. | |
6 | ||
7 | require "getoptlong" | |
8 | ||
9 | class PipalGetoptLong < GetoptLong | |
10 | def add_option (arg) | |
11 | # | |
12 | # The method is failed if option processing has already started. | |
13 | # | |
14 | if @status != STATUS_YET | |
15 | raise RuntimeError, | |
16 | "invoke set_options, but option processing has already started" | |
17 | end | |
18 | ||
19 | if !arg.is_a?(Array) | |
20 | raise ArgumentError, "the option list contains non-Array argument" | |
21 | end | |
22 | ||
23 | # | |
24 | # Find an argument flag and it set to `argument_flag'. | |
25 | # | |
26 | argument_flag = nil | |
27 | arg.each do |i| | |
28 | if ARGUMENT_FLAGS.include?(i) | |
29 | if argument_flag != nil | |
30 | raise ArgumentError, "too many argument-flags" | |
31 | end | |
32 | argument_flag = i | |
33 | end | |
34 | end | |
35 | ||
36 | raise ArgumentError, "no argument-flag" if argument_flag == nil | |
37 | ||
38 | canonical_name = nil | |
39 | arg.each do |i| | |
40 | # | |
41 | # Check an option name. | |
42 | # | |
43 | next if i == argument_flag | |
44 | begin | |
45 | if !i.is_a?(String) || i !~ /^-([^-]|-.+)$/ | |
46 | raise ArgumentError, "an invalid option `#{i}'" | |
47 | end | |
48 | if (@canonical_names.include?(i)) | |
49 | raise ArgumentError, "option redefined `#{i}'" | |
50 | end | |
51 | rescue | |
52 | @canonical_names.clear | |
53 | @argument_flags.clear | |
54 | raise | |
55 | end | |
56 | ||
57 | # | |
58 | # Register the option (`i') to the `@canonical_names' and | |
59 | # `@canonical_names' Hashes. | |
60 | # | |
61 | if canonical_name == nil | |
62 | canonical_name = i | |
63 | end | |
64 | @canonical_names[i] = canonical_name | |
65 | @argument_flags[i] = argument_flag | |
66 | end | |
67 | raise ArgumentError, "no option name" if canonical_name == nil | |
68 | ||
69 | ||
70 | end | |
71 | end |
0 | # Split the line on a pipe with the format | |
1 | # password|username | |
2 | # | |
3 | # To use this script sym link it to | |
4 | # custom_splitter.rb in the main Pipal directory | |
5 | ||
6 | class Custom_word_splitter | |
7 | def self.split (line) | |
8 | begin | |
9 | ||
10 | # 2014-07-31 15:37:17+0100 [SSHService ssh-userauth on HoneyPotTransport,1,2.123.133.112] login attempt [root/root] failed | |
11 | if line =~ /^.*login attempt \[([^\]]*)\].*$/ | |
12 | creds = $1 | |
13 | # Treat everything up to the first / as username and | |
14 | # everything after as password. | |
15 | # A username could have a / in it but unlikely | |
16 | if creds =~ /^([^\/]*)\/(.*)$/ | |
17 | username = $1 | |
18 | password = $2 | |
19 | return [password, {"username" => username}] | |
20 | end | |
21 | end | |
22 | ||
23 | return [nil, {}] | |
24 | rescue | |
25 | return [nil, {}] | |
26 | end | |
27 | end | |
28 | end |
0 | # Split the line on a pipe with the format | |
1 | # password|username | |
2 | # | |
3 | # To use this script sym link it to | |
4 | # custom_splitter.rb in the main Pipal directory | |
5 | ||
6 | class Custom_word_splitter | |
7 | def self.split (line) | |
8 | if line =~ /^([^|]*)\|(.*)$/ | |
9 | word = $1 | |
10 | username = $2 | |
11 | ||
12 | return [word, {"username" => username}] | |
13 | end | |
14 | return [line, {}] | |
15 | end | |
16 | end |
0 | US_area_codes = {} | |
1 | ||
2 | US_area_codes["201"] = ["NJ","N New Jersey: Jersey City, Hackensack"] | |
3 | US_area_codes["202"] = ["DC","Washington, D.C."] | |
4 | US_area_codes["203"] = ["CT","Connecticut: Fairfield County and New Haven County; Bridgeport, New Haven"] | |
5 | US_area_codes["204"] = ["MB","Canada: Manitoba"] | |
6 | US_area_codes["205"] = ["AL","Central Alabama (including Birmingham)"] | |
7 | US_area_codes["206"] = ["WA","W Washington state: Seattle and Bainbridge Island"] | |
8 | US_area_codes["207"] = ["ME","Maine"] | |
9 | US_area_codes["208"] = ["ID","Idaho"] | |
10 | US_area_codes["209"] = ["CA","Cent. California: Stockton"] | |
11 | US_area_codes["210"] = ["TX","S Texas: San Antonio"] | |
12 | US_area_codes["211"] = ["--","Local community info / referral services"] | |
13 | US_area_codes["212"] = ["NY","New York City, New York"] | |
14 | US_area_codes["213"] = ["CA","S California: Los Angeles"] | |
15 | US_area_codes["214"] = ["TX","Texas: Dallas Metro"] | |
16 | US_area_codes["215"] = ["PA","SE Pennsylvania: Philadelphia"] | |
17 | US_area_codes["216"] = ["OH","Cleveland"] | |
18 | US_area_codes["217"] = ["IL","Cent. Illinois: Springfield"] | |
19 | US_area_codes["218"] = ["MN","N Minnesota: Duluth"] | |
20 | US_area_codes["219"] = ["IN","NW Indiana: Gary"] | |
21 | US_area_codes["224"] = ["IL","Northern NE Illinois: Evanston, Waukegan, Northbrook"] | |
22 | US_area_codes["225"] = ["LA","Louisiana: Baton Rouge, New Roads, Donaldsonville, Albany, Gonzales, Greensburg, Plaquemine, Vacherie"] | |
23 | US_area_codes["226"] = ["ON","Canada: SW Ontario: Windsor"] | |
24 | US_area_codes["228"] = ["MS","S Mississippi"] | |
25 | US_area_codes["229"] = ["GA","SW Georgia: Albany"] | |
26 | US_area_codes["231"] = ["MI","W Michigan: Northwestern portion of lower Peninsula; Traverse City, Muskegon, Cheboygan, Alanson"] | |
27 | US_area_codes["234"] = ["OH","NE Ohio: Canton, Akron"] | |
28 | US_area_codes["236"] = ["VA","Virginia (region unknown) / Unassigned?"] | |
29 | US_area_codes["239"] = ["FL","Florida"] | |
30 | US_area_codes["240"] = ["MD","W Maryland: Silver Spring, Frederick, Gaithersburg"] | |
31 | US_area_codes["242"] = ["--","Bahamas"] | |
32 | US_area_codes["246"] = ["--","Barbados"] | |
33 | US_area_codes["248"] = ["MI","Michigan: Oakland County, Pontiac"] | |
34 | US_area_codes["250"] = ["BC","Canada: British Columbia"] | |
35 | US_area_codes["251"] = ["AL","S Alabama: Mobile and coastal areas, Jackson, Evergreen, Monroeville"] | |
36 | US_area_codes["252"] = ["NC","E North Carolina"] | |
37 | US_area_codes["253"] = ["WA","Washington: South Tier - Tacoma, Federal Way"] | |
38 | US_area_codes["254"] = ["TX","Central Texas"] | |
39 | US_area_codes["256"] = ["AL","E and N Alabama"] | |
40 | US_area_codes["260"] = ["IN","NE Indiana: Fort Wayne"] | |
41 | US_area_codes["262"] = ["WI","SE Wisconsin: counties of Kenosha, Ozaukee, Racine, Walworth, Washington, Waukesha"] | |
42 | US_area_codes["264"] = ["--","Anguilla"] | |
43 | US_area_codes["267"] = ["PA","SE Pennsylvania: Philadelphia"] | |
44 | US_area_codes["268"] = ["--","Antigua and Barbuda"] | |
45 | US_area_codes["269"] = ["MI","SW Michigan: Kalamazoo, Saugatuck, Hastings, Battle Creek, Sturgis to Lake Michigan"] | |
46 | US_area_codes["270"] = ["KY","W Kentucky: Bowling Green, Paducah"] | |
47 | US_area_codes["276"] = ["VA","S and SW Virginia: Bristol, Stuart, Martinsville"] | |
48 | US_area_codes["278"] = ["MI","Michigan"] | |
49 | US_area_codes["281"] = ["TX","Texas: Houston Metro"] | |
50 | US_area_codes["283"] = ["OH","SW Ohio: Cincinnati"] | |
51 | US_area_codes["284"] = ["--","British Virgin Islands"] | |
52 | US_area_codes["289"] = ["ON","Canada: S Cent. Ontario: Greater Toronto Area -- Durham, Halton, Hamilton-Wentworth, Niagara, Peel, York, and southern Simcoe County"] | |
53 | US_area_codes["301"] = ["MD","W Maryland: Silver Spring, Frederick, Camp Springs, Prince George's County"] | |
54 | US_area_codes["302"] = ["DE","Delaware"] | |
55 | US_area_codes["303"] = ["CO","Central Colorado: Denver"] | |
56 | US_area_codes["304"] = ["WV","West Virginia"] | |
57 | US_area_codes["305"] = ["FL","SE Florida: Miami, the Keys"] | |
58 | US_area_codes["306"] = ["SK","Canada: Saskatchewan"] | |
59 | US_area_codes["307"] = ["WY","Wyoming"] | |
60 | US_area_codes["308"] = ["NE","W Nebraska: North Platte"] | |
61 | US_area_codes["309"] = ["IL","W Cent. Illinois: Peoria"] | |
62 | US_area_codes["310"] = ["CA","S California: Beverly Hills, West Hollywood, West Los Angeles"] | |
63 | US_area_codes["311"] = ["--","Reserved for special applications"] | |
64 | US_area_codes["312"] = ["IL","Illinois: Chicago"] | |
65 | US_area_codes["313"] = ["MI","Michigan: Detroit and suburbs"] | |
66 | US_area_codes["314"] = ["MO","SE Missouri: St Louis city and parts of the metro area only"] | |
67 | US_area_codes["315"] = ["NY","N Cent. New York: Syracuse"] | |
68 | US_area_codes["316"] = ["KS","S Kansas: Wichita"] | |
69 | US_area_codes["317"] = ["IN","Cent. Indiana: Indianapolis"] | |
70 | US_area_codes["318"] = ["LA","N Louisiana: Shreveport, Ruston, Monroe, Alexandria"] | |
71 | US_area_codes["319"] = ["IA","E Iowa: Cedar Rapids"] | |
72 | US_area_codes["320"] = ["MN","Cent. Minnesota: Saint Cloud"] | |
73 | US_area_codes["321"] = ["FL","Florida: Brevard County, Cape Canaveral area; Metro Orlando"] | |
74 | US_area_codes["323"] = ["CA","S California: Los Angeles"] | |
75 | US_area_codes["325"] = ["TX","Central Texas: Abilene, Sweetwater, Snyder, San Angelo"] | |
76 | US_area_codes["330"] = ["OH","NE Ohio: Akron, Canton, Youngstown; Mahoning County, parts of Trumbull/Warren counties"] | |
77 | US_area_codes["331"] = ["IL","W NE Illinois, western suburbs of Chicago"] | |
78 | US_area_codes["334"] = ["AL","S Alabama: Auburn/Opelika, Montgomery and coastal areas"] | |
79 | US_area_codes["336"] = ["NC","Cent. North Carolina: Greensboro, Winston-Salem, High Point"] | |
80 | US_area_codes["337"] = ["LA","SW Louisiana: Lake Charles, Lafayette"] | |
81 | US_area_codes["339"] = ["MA","Massachusetts: Boston suburbs, to the south and west"] | |
82 | US_area_codes["340"] = ["VI","US Virgin Islands"] | |
83 | US_area_codes["341"] = ["CA","(overlay on 510; SUSPENDED)"] | |
84 | US_area_codes["345"] = ["--","Cayman Islands"] | |
85 | US_area_codes["347"] = ["NY","New York"] | |
86 | US_area_codes["351"] = ["MA","Massachusetts: north of Boston to NH, 508, and 781"] | |
87 | US_area_codes["352"] = ["FL","Florida: Gainesville area, Ocala, Crystal River"] | |
88 | US_area_codes["360"] = ["WA","W Washington State: Olympia, Bellingham"] | |
89 | US_area_codes["361"] = ["TX","S Texas: Corpus Christi"] | |
90 | US_area_codes["369"] = ["CA","Solano County"] | |
91 | US_area_codes["380"] = ["OH","Ohio: Columbus"] | |
92 | US_area_codes["385"] = ["UT","Utah: Salt Lake City Metro"] | |
93 | US_area_codes["386"] = ["FL","N central Florida: Lake City"] | |
94 | US_area_codes["401"] = ["RI","Rhode Island"] | |
95 | US_area_codes["402"] = ["NE","E Nebraska: Omaha, Lincoln"] | |
96 | US_area_codes["403"] = ["AB","Canada: Southern Alberta"] | |
97 | US_area_codes["404"] = ["GA","N Georgia: Atlanta and suburbs"] | |
98 | US_area_codes["405"] = ["OK","W Oklahoma: Oklahoma City"] | |
99 | US_area_codes["406"] = ["MT","Montana"] | |
100 | US_area_codes["407"] = ["FL","Central Florida: Metro Orlando"] | |
101 | US_area_codes["408"] = ["CA","Cent. Coastal California: San Jose"] | |
102 | US_area_codes["409"] = ["TX","SE Texas: Galveston, Port Arthur, Beaumont"] | |
103 | US_area_codes["410"] = ["MD","E Maryland: Baltimore, Annapolis, Chesapeake Bay area, Ocean City"] | |
104 | US_area_codes["411"] = ["--","Reserved for special applications"] | |
105 | US_area_codes["412"] = ["PA","W Pennsylvania: Pittsburgh"] | |
106 | US_area_codes["413"] = ["MA","W Massachusetts: Springfield"] | |
107 | US_area_codes["414"] = ["WI","SE Wisconsin: Milwaukee County"] | |
108 | US_area_codes["415"] = ["CA","California: San Francisco County and Marin County on the north side of the Golden Gate Bridge, extending north to Sonoma County"] | |
109 | US_area_codes["416"] = ["ON","Canada: S Cent. Ontario: Toronto"] | |
110 | US_area_codes["417"] = ["MO","SW Missouri: Springfield"] | |
111 | US_area_codes["418"] = ["QC","Canada: NE Quebec: Quebec"] | |
112 | US_area_codes["419"] = ["OH","NW Ohio: Toledo"] | |
113 | US_area_codes["423"] = ["TN","E Tennessee, except Knoxville metro area: Chattanooga, Bristol, Johnson City, Kingsport, Greeneville"] | |
114 | US_area_codes["424"] = ["CA","S California: Los Angeles"] | |
115 | US_area_codes["425"] = ["WA","Washington: North Tier - Everett, Bellevue"] | |
116 | US_area_codes["430"] = ["TX","NE Texas: Tyler"] | |
117 | US_area_codes["432"] = ["TX","W Texas: Big Spring, Midland, Odessa"] | |
118 | US_area_codes["434"] = ["VA","E Virginia: Charlottesville, Lynchburg, Danville, South Boston, and Emporia"] | |
119 | US_area_codes["435"] = ["UT","Rural Utah outside Salt Lake City metro"] | |
120 | US_area_codes["438"] = ["QC","Canada: SW Quebec: Montreal city"] | |
121 | US_area_codes["440"] = ["OH","Ohio: Cleveland metro area, excluding Cleveland"] | |
122 | US_area_codes["441"] = ["--","Bermuda"] | |
123 | US_area_codes["442"] = ["CA","Far north suburbs of San Diego"] | |
124 | US_area_codes["443"] = ["MD","E Maryland: Baltimore, Annapolis, Chesapeake Bay area, Ocean City"] | |
125 | US_area_codes["450"] = ["QC","Canada: Southeastern Quebec; suburbs outside metro Montreal"] | |
126 | US_area_codes["456"] = ["--","Inbound International"] | |
127 | US_area_codes["464"] = ["IL","Illinois: south suburbs of Chicago"] | |
128 | US_area_codes["469"] = ["TX","Texas: Dallas Metro"] | |
129 | US_area_codes["470"] = ["GA","Georgia: Greater Atlanta Metropolitan Area"] | |
130 | US_area_codes["473"] = ["--","Grenada"] | |
131 | US_area_codes["475"] = ["CT","Connecticut: New Haven, Greenwich, southwestern"] | |
132 | US_area_codes["478"] = ["GA","Central Georgia: Macon"] | |
133 | US_area_codes["479"] = ["AR","NW Arkansas: Fort Smith, Fayetteville, Springdale, Bentonville"] | |
134 | US_area_codes["480"] = ["AZ","Arizona: East Phoenix"] | |
135 | US_area_codes["484"] = ["PA","SE Pennsylvania: Allentown, Bethlehem, Reading, West Chester, Norristown"] | |
136 | US_area_codes["500"] = ["--","Personal Communication Service"] | |
137 | US_area_codes["501"] = ["AR","Central Arkansas: Little Rock, Hot Springs, Conway"] | |
138 | US_area_codes["502"] = ["KY","N Central Kentucky: Louisville"] | |
139 | US_area_codes["503"] = ["OR","Oregon"] | |
140 | US_area_codes["504"] = ["LA","E Louisiana: New Orleans metro area"] | |
141 | US_area_codes["505"] = ["NM","North central and northwestern New Mexico"] | |
142 | US_area_codes["506"] = ["NB","Canada: New Brunswick"] | |
143 | US_area_codes["507"] = ["MN","S Minnesota: Rochester, Mankato, Worthington"] | |
144 | US_area_codes["508"] = ["MA","Cent. Massachusetts: Framingham; Cape Cod"] | |
145 | US_area_codes["509"] = ["WA","E and Central Washington state: Spokane, Yakima, Walla Walla, Ellensburg"] | |
146 | US_area_codes["510"] = ["CA","California: Oakland, East Bay"] | |
147 | US_area_codes["511"] = ["--","Nationwide travel information"] | |
148 | US_area_codes["512"] = ["TX","S Texas: Austin"] | |
149 | US_area_codes["513"] = ["OH","SW Ohio: Cincinnati"] | |
150 | US_area_codes["514"] = ["QC","Canada: SW Quebec: Montreal city"] | |
151 | US_area_codes["515"] = ["IA","Cent. Iowa: Des Moines"] | |
152 | US_area_codes["516"] = ["NY","New York: Nassau County, Long Island; Hempstead"] | |
153 | US_area_codes["517"] = ["MI","Cent. Michigan: Lansing"] | |
154 | US_area_codes["518"] = ["NY","NE New York: Albany"] | |
155 | US_area_codes["519"] = ["ON","Canada: SW Ontario: Windsor"] | |
156 | US_area_codes["520"] = ["AZ","SE Arizona: Tucson area"] | |
157 | US_area_codes["530"] = ["CA","NE California: Eldorado County area, excluding Eldorado Hills itself: incl cities of Auburn, Chico, Redding, So. Lake Tahoe, Marysville, Nevada City/Grass Valley"] | |
158 | US_area_codes["539"] = ["OK","E Oklahoma: Tulsa area"] | |
159 | US_area_codes["540"] = ["VA","Western and Southwest Virginia: Shenandoah and Roanoke valleys: Fredericksburg, Harrisonburg, Roanoke, Salem, Lexington and nearby areas"] | |
160 | US_area_codes["541"] = ["OR","Oregon: Eugene, Medford"] | |
161 | US_area_codes["551"] = ["NJ","N New Jersey: Jersey City, Hackensack"] | |
162 | US_area_codes["555"] = ["--","Reserved for directory assistance applications"] | |
163 | US_area_codes["557"] = ["MO","SE Missouri: St Louis metro area only"] | |
164 | US_area_codes["559"] = ["CA","Central California: Fresno"] | |
165 | US_area_codes["561"] = ["FL","S. Central Florida: Palm Beach County"] | |
166 | US_area_codes["562"] = ["CA","California: Long Beach"] | |
167 | US_area_codes["563"] = ["IA","E Iowa: Davenport, Dubuque"] | |
168 | US_area_codes["564"] = ["WA","W Washington State: Olympia, Bellingham"] | |
169 | US_area_codes["567"] = ["OH","NW Ohio: Toledo"] | |
170 | US_area_codes["570"] = ["PA","NE and N Central Pennsylvania: Wilkes-Barre, Scranton"] | |
171 | US_area_codes["571"] = ["VA","Northern Virginia: Arlington, McLean, Tysons Corner"] | |
172 | US_area_codes["573"] = ["MO","SE Missouri: excluding St Louis metro area, includes Central/East Missouri, area between St. Louis and Kansas City"] | |
173 | US_area_codes["574"] = ["IN","N Indiana: Elkhart, South Bend"] | |
174 | US_area_codes["575"] = ["NM","New Mexico"] | |
175 | US_area_codes["580"] = ["OK","W Oklahoma"] | |
176 | US_area_codes["585"] = ["NY","NW New York: Rochester"] | |
177 | US_area_codes["586"] = ["MI","Michigan: Macomb County"] | |
178 | US_area_codes["600"] = ["--","Canadian Services"] | |
179 | US_area_codes["601"] = ["MS","Mississippi: Meridian, Jackson area"] | |
180 | US_area_codes["602"] = ["AZ","Arizona: Phoenix"] | |
181 | US_area_codes["603"] = ["NH","New Hampshire"] | |
182 | US_area_codes["604"] = ["BC","Canada: British Columbia: Greater Vancouver"] | |
183 | US_area_codes["605"] = ["SD","South Dakota"] | |
184 | US_area_codes["606"] = ["KY","E Kentucky: area east of Frankfort: Ashland"] | |
185 | US_area_codes["607"] = ["NY","S Cent. New York: Ithaca, Binghamton; Catskills"] | |
186 | US_area_codes["608"] = ["WI","SW Wisconsin: Madison"] | |
187 | US_area_codes["609"] = ["NJ","S New Jersey: Trenton"] | |
188 | US_area_codes["610"] = ["PA","SE Pennsylvania: Allentown, Bethlehem, Reading, West Chester, Norristown"] | |
189 | US_area_codes["611"] = ["--","Reserved for special applications"] | |
190 | US_area_codes["612"] = ["MN","Cent. Minnesota: Minneapolis"] | |
191 | US_area_codes["613"] = ["ON","Canada: SE Ontario: Ottawa"] | |
192 | US_area_codes["614"] = ["OH","SE Ohio: Columbus"] | |
193 | US_area_codes["615"] = ["TN","Northern Middle Tennessee: Nashville metro area"] | |
194 | US_area_codes["616"] = ["MI","W Michigan: Holland, Grand Haven, Greenville, Grand Rapids, Ionia"] | |
195 | US_area_codes["617"] = ["MA","Massachusetts: greater Boston"] | |
196 | US_area_codes["618"] = ["IL","S Illinois: Centralia"] | |
197 | US_area_codes["619"] = ["CA","S California: San Diego"] | |
198 | US_area_codes["620"] = ["KS","S Kansas: Wichita"] | |
199 | US_area_codes["623"] = ["AZ","Arizona: West Phoenix"] | |
200 | US_area_codes["626"] = ["CA","E S California: Pasadena"] | |
201 | US_area_codes["627"] = ["CA","No longer in use [was Napa, Sonoma counties"] | |
202 | US_area_codes["628"] = ["CA","(Region unknown; perm 10/21/00)21/00)00)"] | |
203 | US_area_codes["630"] = ["IL","W NE Illinois, western suburbs of Chicago"] | |
204 | US_area_codes["631"] = ["NY","New York: Suffolk County, Long Island; Huntington, Riverhead"] | |
205 | US_area_codes["636"] = ["MO","Missouri: W St. Louis metro area of St. Louis county, St. Charles County, Jefferson County area south"] | |
206 | US_area_codes["641"] = ["IA","Iowa: Mason City, Marshalltown, Creston, Ottumwa"] | |
207 | US_area_codes["646"] = ["NY","New York"] | |
208 | US_area_codes["647"] = ["ON","Canada: S Cent. Ontario: Toronto"] | |
209 | US_area_codes["649"] = ["--","Turks & Caicos Islands"] | |
210 | US_area_codes["650"] = ["CA","California: Peninsula south of San Francisco -- San Mateo County, parts of Santa Clara County"] | |
211 | US_area_codes["651"] = ["MN","Cent. Minnesota: St. Paul"] | |
212 | US_area_codes["660"] = ["MO","N Missouri"] | |
213 | US_area_codes["661"] = ["CA","California: N Los Angeles, Mckittrick, Mojave, Newhall, Oildale, Palmdale, Taft, Tehachapi, Bakersfield, Earlimart, Lancaster"] | |
214 | US_area_codes["662"] = ["MS","N Mississippi: Tupelo, Grenada"] | |
215 | US_area_codes["664"] = ["--","Montserrat"] | |
216 | US_area_codes["669"] = ["CA","Cent. Coastal California: San Jose"] | |
217 | US_area_codes["670"] = ["MP","Commonwealth of the Northern Mariana Islands (CNMI, US Commonwealth)"] | |
218 | US_area_codes["671"] = ["GU","Guam"] | |
219 | US_area_codes["678"] = ["GA","N Georgia: metropolitan Atlanta"] | |
220 | US_area_codes["679"] = ["MI","Michigan: Dearborn area"] | |
221 | US_area_codes["682"] = ["TX","Texas: Fort Worth areas"] | |
222 | US_area_codes["684"] = ["--","American Samoa"] | |
223 | US_area_codes["689"] = ["FL","Central Florida: Metro Orlando"] | |
224 | US_area_codes["700"] = ["--","Interexchange Carrier Services"] | |
225 | US_area_codes["701"] = ["ND","North Dakota"] | |
226 | US_area_codes["702"] = ["NV","S. Nevada: Clark County, incl Las Vegas"] | |
227 | US_area_codes["703"] = ["VA","Northern Virginia: Arlington, McLean, Tysons Corner"] | |
228 | US_area_codes["704"] = ["NC","W North Carolina: Charlotte"] | |
229 | US_area_codes["705"] = ["ON","Canada: NE Ontario: Sault Ste. Marie/N Ontario: N Bay, Sudbury"] | |
230 | US_area_codes["706"] = ["GA","N Georgia: Columbus, Augusta"] | |
231 | US_area_codes["707"] = ["CA","NW California: Santa Rosa, Napa, Vallejo, American Canyon, Fairfield"] | |
232 | US_area_codes["708"] = ["IL","Illinois: southern and western suburbs of Chicago"] | |
233 | US_area_codes["709"] = ["NL","Canada: Newfoundland and Labrador"] | |
234 | US_area_codes["710"] = ["--","US Government"] | |
235 | US_area_codes["711"] = ["--","Telecommunications Relay Services"] | |
236 | US_area_codes["712"] = ["IA","W Iowa: Council Bluffs"] | |
237 | US_area_codes["713"] = ["TX","Mid SE Texas: central Houston"] | |
238 | US_area_codes["714"] = ["CA","North and Central Orange County"] | |
239 | US_area_codes["715"] = ["WI","N Wisconsin: Eau Claire, Wausau, Superior"] | |
240 | US_area_codes["716"] = ["NY","NW New York: Buffalo"] | |
241 | US_area_codes["717"] = ["PA","E Pennsylvania: Harrisburg"] | |
242 | US_area_codes["718"] = ["NY","New York City, New York"] | |
243 | US_area_codes["719"] = ["CO","SE Colorado: Pueblo, Colorado Springs"] | |
244 | US_area_codes["720"] = ["CO","Central Colorado: Denver"] | |
245 | US_area_codes["724"] = ["PA","SW Pennsylvania"] | |
246 | US_area_codes["727"] = ["FL","Florida Tampa Metro: Saint Petersburg, Clearwater"] | |
247 | US_area_codes["731"] = ["TN","W Tennessee: outside Memphis metro area"] | |
248 | US_area_codes["732"] = ["NJ","Cent. New Jersey: Toms River, New Brunswick, Bound Brook"] | |
249 | US_area_codes["734"] = ["MI","SE Michigan: west and south of Detroit -- Ann Arbor, Monroe"] | |
250 | US_area_codes["737"] = ["TX","S Texas: Austin"] | |
251 | US_area_codes["740"] = ["OH","SE Ohio"] | |
252 | US_area_codes["747"] = ["CA","S California: Los Angeles, Agoura Hills, Calabasas, Hidden Hills, and Westlake Village"] | |
253 | US_area_codes["754"] = ["FL","Florida: Broward County area, incl Ft. Lauderdale"] | |
254 | US_area_codes["757"] = ["VA","E Virginia: Tidewater / Hampton Roads area -- Norfolk, Virginia Beach, Chesapeake, Portsmouth, Hampton, Newport News, Suffolk"] | |
255 | US_area_codes["758"] = ["--","St. Lucia"] | |
256 | US_area_codes["760"] = ["CA","California: San Diego North County to Sierra Nevada"] | |
257 | US_area_codes["762"] = ["GA","N Georgia: Columbus, Augusta"] | |
258 | US_area_codes["763"] = ["MN","Minnesota: Minneapolis NW"] | |
259 | US_area_codes["764"] = ["CA","SUSPENDED"] | |
260 | US_area_codes["765"] = ["IN","Indiana: outside Indianapolis"] | |
261 | US_area_codes["767"] = ["--","Dominica"] | |
262 | US_area_codes["769"] = ["MS","Mississippi: Meridian, Jackson area"] | |
263 | US_area_codes["770"] = ["GA","Georgia: Atlanta suburbs: outside of I-285 ring road"] | |
264 | US_area_codes["772"] = ["FL","S. Central Florida: St. Lucie, Martin, and Indian River counties"] | |
265 | US_area_codes["773"] = ["IL","Illinois: city of Chicago, outside the loop"] | |
266 | US_area_codes["774"] = ["MA","Cent. Massachusetts: Framingham; Cape Cod"] | |
267 | US_area_codes["775"] = ["NV","N. Nevada: Reno"] | |
268 | US_area_codes["778"] = ["BC","Canada: British Columbia: Greater Vancouver"] | |
269 | US_area_codes["779"] = ["IL","NW Illinois: Rockford, Kankakee"] | |
270 | US_area_codes["780"] = ["AB","Canada: Northern Alberta, north of Lacombe"] | |
271 | US_area_codes["781"] = ["MA","Massachusetts: Boston surburbs, to the north and west"] | |
272 | US_area_codes["784"] = ["--","St. Vincent & Grenadines"] | |
273 | US_area_codes["785"] = ["KS","N & W Kansas: Topeka"] | |
274 | US_area_codes["786"] = ["FL","SE Florida, Monroe County"] | |
275 | US_area_codes["787"] = ["PR","Puerto Rico"] | |
276 | US_area_codes["800"] = ["--","US/Canada toll free"] | |
277 | US_area_codes["801"] = ["UT","Utah: Salt Lake City Metro"] | |
278 | US_area_codes["802"] = ["VT","Vermont"] | |
279 | US_area_codes["803"] = ["SC","South Carolina: Columbia, Aiken, Sumter"] | |
280 | US_area_codes["804"] = ["VA","E Virginia: Richmond"] | |
281 | US_area_codes["805"] = ["CA","S Cent. and Cent. Coastal California: Ventura County, Santa Barbara County: San Luis Obispo, Thousand Oaks, Carpinteria, Santa Barbara, Santa Maria, Lompoc, Santa Ynez Valley / Solvang"] | |
282 | US_area_codes["806"] = ["TX","Panhandle Texas: Amarillo, Lubbock"] | |
283 | US_area_codes["807"] = ["ON","Canada: W Ontario: Thunder Bay region to Manitoba border"] | |
284 | US_area_codes["808"] = ["HI","Hawaii"] | |
285 | US_area_codes["809"] = ["--","Dominican Republic"] | |
286 | US_area_codes["810"] = ["MI","E Michigan: Flint, Pontiac"] | |
287 | US_area_codes["811"] = ["--","Reserved for special applications"] | |
288 | US_area_codes["812"] = ["IN","S Indiana: Evansville, Cincinnati outskirts in IN, Columbus, Bloomington"] | |
289 | US_area_codes["813"] = ["FL","SW Florida: Tampa Metro"] | |
290 | US_area_codes["814"] = ["PA","Cent. Pennsylvania: Erie"] | |
291 | US_area_codes["815"] = ["IL","NW Illinois: Rockford, Kankakee"] | |
292 | US_area_codes["816"] = ["MO","N Missouri: Kansas City"] | |
293 | US_area_codes["817"] = ["TX","N Cent. Texas: Fort Worth area"] | |
294 | US_area_codes["818"] = ["CA","S California: Los Angeles: San Fernando Valley"] | |
295 | US_area_codes["819"] = ["QC","NW Quebec: Trois Rivieres, Sherbrooke, Outaouais"] | |
296 | US_area_codes["822"] = ["--","US/Canada toll free"] | |
297 | US_area_codes["828"] = ["NC","W North Carolina: Asheville"] | |
298 | US_area_codes["829"] = ["--","Dominican Republic"] | |
299 | US_area_codes["830"] = ["TX","Texas: region surrounding San Antonio"] | |
300 | US_area_codes["831"] = ["CA","California: central coast area from Santa Cruz through Monterey County"] | |
301 | US_area_codes["832"] = ["TX","Texas: Houston"] | |
302 | US_area_codes["833"] = ["--","US/Canada toll free"] | |
303 | US_area_codes["835"] = ["PA","SE Pennsylvania: Allentown, Bethlehem, Reading, West Chester, Norristown"] | |
304 | US_area_codes["843"] = ["SC","South Carolina, coastal area: Charleston, Beaufort, Myrtle Beach"] | |
305 | US_area_codes["844"] = ["--","US/Canada toll free"] | |
306 | US_area_codes["845"] = ["NY","New York: Poughkeepsie; Nyack, Nanuet, Valley Cottage, New City, Putnam, Dutchess, Rockland, Orange, Ulster and parts of Sullivan counties in New York's lower Hudson Valley and Delaware County in the Catskills"] | |
307 | US_area_codes["847"] = ["IL","Northern NE Illinois: northwestern suburbs of chicago"] | |
308 | US_area_codes["848"] = ["NJ","Cent. New Jersey: Toms River, New Brunswick, Bound Brook"] | |
309 | US_area_codes["850"] = ["FL","Florida panhandle, from east of Tallahassee to Pensacola"] | |
310 | US_area_codes["855"] = ["--","US/Canada toll free"] | |
311 | US_area_codes["856"] = ["NJ","SW New Jersey: greater Camden area, Mt Laurel"] | |
312 | US_area_codes["857"] = ["MA","Massachusetts: greater Boston"] | |
313 | US_area_codes["858"] = ["CA","S California: San Diego"] | |
314 | US_area_codes["859"] = ["KY","N and Central Kentucky: Lexington; suburban KY counties of Cincinnati OH metro area; Covington, Newport, Ft. Thomas, Ft. Wright, Florence"] | |
315 | US_area_codes["860"] = ["CT","Connecticut: areas outside of Fairfield and New Haven Counties"] | |
316 | US_area_codes["862"] = ["NJ","N New Jersey: Newark Paterson Morristown"] | |
317 | US_area_codes["863"] = ["FL","Florida: Lakeland, Polk County"] | |
318 | US_area_codes["864"] = ["SC","South Carolina, upstate area: Greenville, Spartanburg"] | |
319 | US_area_codes["865"] = ["TN","E Tennessee: Knoxville, Knox and adjacent counties"] | |
320 | US_area_codes["866"] = ["--","US/Canada toll free"] | |
321 | US_area_codes["867"] = ["YT","Canada: Yukon, Northwest Territories, Nunavut"] | |
322 | US_area_codes["868"] = ["--","Trinidad and Tobago"] | |
323 | US_area_codes["869"] = ["--","St. Kitts & Nevis"] | |
324 | US_area_codes["870"] = ["AR","Arkansas: areas outside of west/central AR: Jonesboro, etc"] | |
325 | US_area_codes["872"] = ["IL","Illinois: Chicago"] | |
326 | US_area_codes["876"] = ["--","Jamaica"] | |
327 | US_area_codes["877"] = ["--","US/Canada toll free"] | |
328 | US_area_codes["878"] = ["PA","Pittsburgh, New Castle"] | |
329 | US_area_codes["880"] = ["--","Paid Toll-Free Service"] | |
330 | US_area_codes["881"] = ["--","Paid Toll-Free Service"] | |
331 | US_area_codes["882"] = ["--","Paid Toll-Free Service"] | |
332 | US_area_codes["888"] = ["--","US/Canada toll free"] | |
333 | US_area_codes["898"] = ["--","VoIP service"] | |
334 | US_area_codes["900"] = ["--","US toll calls -- prices vary with the number called"] | |
335 | US_area_codes["901"] = ["TN","W Tennessee: Memphis metro area"] | |
336 | US_area_codes["902"] = ["NS","Canada: Nova Scotia, Prince Edward Island"] | |
337 | US_area_codes["903"] = ["TX","NE Texas: Tyler"] | |
338 | US_area_codes["904"] = ["FL","N Florida: Jacksonville"] | |
339 | US_area_codes["905"] = ["ON","Canada: S Cent. Ontario: Greater Toronto Area -- Durham, Halton, Hamilton-Wentworth, Niagara, Peel, York, and southern Simcoe County"] | |
340 | US_area_codes["906"] = ["MI","Upper Peninsula Michigan: Sault Ste. Marie, Escanaba, Marquette"] | |
341 | US_area_codes["907"] = ["AK","Alaska"] | |
342 | US_area_codes["908"] = ["NJ","Cent. New Jersey: Elizabeth, Basking Ridge, Somerville, Bridgewater, Bound Brook"] | |
343 | US_area_codes["909"] = ["CA","California: Inland empire: San Bernardino"] | |
344 | US_area_codes["910"] = ["NC","S Cent. North Carolina: Fayetteville, Wilmington"] | |
345 | US_area_codes["911"] = ["--","Emergency"] | |
346 | US_area_codes["912"] = ["GA","SE Georgia: Savannah"] | |
347 | US_area_codes["913"] = ["KS","Kansas: Kansas City area"] | |
348 | US_area_codes["914"] = ["NY","S New York: Westchester County"] | |
349 | US_area_codes["915"] = ["TX","W Texas: El Paso"] | |
350 | US_area_codes["916"] = ["CA","NE California: Sacramento, Walnut Grove, Lincoln, Newcastle and El Dorado Hills"] | |
351 | US_area_codes["917"] = ["NY","New York: New York City"] | |
352 | US_area_codes["918"] = ["OK","E Oklahoma: Tulsa"] | |
353 | US_area_codes["919"] = ["NC","E North Carolina: Raleigh"] | |
354 | US_area_codes["920"] = ["WI","NE Wisconsin: Appleton, Green Bay, Sheboygan, Fond du Lac"] | |
355 | US_area_codes["925"] = ["CA","California: Contra Costa area: Antioch, Concord, Pleasanton, Walnut Creek"] | |
356 | US_area_codes["927"] = ["FL","Florida: Cellular coverage in Orlando area"] | |
357 | US_area_codes["928"] = ["AZ","Central and Northern Arizona: Prescott, Flagstaff, Yuma"] | |
358 | US_area_codes["931"] = ["TN","Middle Tennessee: semi-circular ring around Nashville"] | |
359 | US_area_codes["935"] = ["CA","S California: San Diego"] | |
360 | US_area_codes["936"] = ["TX","SE Texas: Conroe, Lufkin, Nacogdoches, Crockett"] | |
361 | US_area_codes["937"] = ["OH","SW Ohio: Dayton"] | |
362 | US_area_codes["939"] = ["PR","Puerto Rico"] | |
363 | US_area_codes["940"] = ["TX","N Cent. Texas: Denton, Wichita Falls"] | |
364 | US_area_codes["941"] = ["FL","SW Florida: Sarasota and Manatee counties"] | |
365 | US_area_codes["947"] = ["MI","Michigan: Oakland County"] | |
366 | US_area_codes["949"] = ["CA","California: S Coastal Orange County"] | |
367 | US_area_codes["951"] = ["CA","California: W Riverside County"] | |
368 | US_area_codes["952"] = ["MN","Minnesota: Minneapolis SW, Bloomington"] | |
369 | US_area_codes["954"] = ["FL","Florida: Broward County area, incl Ft. Lauderdale"] | |
370 | US_area_codes["956"] = ["TX","Texas: Valley of Texas area; Harlingen, Laredo"] | |
371 | US_area_codes["957"] = ["NM","New Mexico"] | |
372 | US_area_codes["959"] = ["CT","Connecticut: Hartford, New London"] | |
373 | US_area_codes["970"] = ["CO","N and W Colorado"] | |
374 | US_area_codes["971"] = ["OR","Oregon: Metropolitan Portland, Salem/Keizer area, incl Cricket Wireless"] | |
375 | US_area_codes["972"] = ["TX","Texas: Dallas Metro"] | |
376 | US_area_codes["973"] = ["NJ","N New Jersey: Newark, Paterson, Morristown"] | |
377 | US_area_codes["975"] = ["MO","N Missouri: Kansas City"] | |
378 | US_area_codes["976"] = ["--","Unassigned"] | |
379 | US_area_codes["978"] = ["MA","Massachusetts: north of Boston to NH"] | |
380 | US_area_codes["979"] = ["TX","SE Texas: Bryan, College Station, Bay City"] | |
381 | US_area_codes["980"] = ["NC","North Carolina:"] | |
382 | US_area_codes["984"] = ["NC","E North Carolina: Raleigh"] | |
383 | US_area_codes["985"] = ["LA","E Louisiana: SE/N shore of Lake Pontchartrain: Hammond, Slidell, Covington, Amite, Kentwood, area SW of New Orleans, Houma, Thibodaux, Morgan City"] | |
384 | US_area_codes["989"] = ["MI","Upper central Michigan: Mt Pleasant, Saginaw"] | |
385 | US_area_codes["999"] = ["--","Often used by carriers to indicate that the area code information is unavailable for CNID, even though the rest of the number is present"] |