Codebase list pipal / upstream/latest
Imported Upstream version 3.1 Devon Kearns 9 years ago
42 changed file(s) with 3849 addition(s) and 1272 deletion(s). Raw diff Collapse all Expand all
+0
-128
README less more
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.
44 WIDTH = 72
55 HEIGHT = 16
66 attr :output_file, true
7 attr_reader :graph
78
89 def initialize(array)
910 @values = array
1011 @output_file = STDOUT
12 @graph = nil
1113 end
1214
1315 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
1425 #Adjust X axis when there are more than WIDTH cols
1526 if @values.length > WIDTH then
1627 old_values = @values;
3950 num= f*HEIGHT/max
4051 (HEIGHT - 1).downto(HEIGHT - 1 - num){|j| display[j][i] = '|'}
4152 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
4354
4455 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|
4658 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]
4860 end
49 @output_file.puts
61 @graph << "\n"
5062 end
5163 end
5264 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
+226
-754
pipal.rb less more
00 #!/usr/bin/env ruby
1 # encoding: utf-8
12
23 # == Pipal: Statistical analysis on password dumps
34 #
78 # --help, -h: show help
89 # --top, -t X: show the top X results (default 10)
910 # --output, -o <filename>: output to file
10 # --external, -e <filename>: external file to compare words against
1111 # --gkey <Google Maps API key>: to allow zip code lookups (optional)
1212 #
1313 # FILENAME: The file to count
1414 #
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
1717 # Licence:: Creative Commons Attribution-Share Alike 2.0
1818 # Speedbumped by Stefan Venken ([email protected])
1919 #
2020
2121 require 'benchmark'
22 require 'getoptlong'
2322 require'net/http'
2423 require'uri'
2524 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')
3535
3636 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."
3838 puts
3939 exit
4040 end
4141
42 class PipalException < Exception
43 end
44
45 @checkers = []
46
47 def register_checker (class_name)
48 @checkers << class_name
49 end
50
4251 trap("SIGINT") { throw :ctrl_c }
4352
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
17055
17156 class String
17257 def is_numeric?
17459 end
17560 end
17661
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(
182194 [ '--help', '-h', "-?", GetoptLong::NO_ARGUMENT ],
183195 [ '--top', "-t" , GetoptLong::REQUIRED_ARGUMENT ],
184196 [ '--output', "-o" , GetoptLong::REQUIRED_ARGUMENT ],
185 [ '--external', "-e" , GetoptLong::REQUIRED_ARGUMENT ],
186197 [ '--gkey', GetoptLong::REQUIRED_ARGUMENT ],
187 [ "-v" , GetoptLong::NO_ARGUMENT ]
198 [ "--verbose", "-v" , GetoptLong::NO_ARGUMENT ],
199 [ "--list-checkers" , GetoptLong::NO_ARGUMENT ],
188200 )
189201
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
211215
212216 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
213221 opts.each do |opt, arg|
222 stored_opts[opt] = arg
214223 case opt
215224 when '--help'
216225 usage
226 when "--list-checkers"
227 list_checkers
228 exit
217229 when "--top"
218230 if arg.is_numeric?
219231 cap_at = arg.to_i
220232 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")
226234 exit 1
227235 end
228236 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")
234238 exit 1
235239 end
236240 when "--gkey"
237241 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
260242 when "--output"
261243 begin
262244 output_file = File.new(arg, "w")
263245 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")
269247 exit 1
270248 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
272260 end
273261 rescue GetoptLong::InvalidOption => e
274262 puts
275263 usage
276264 exit
277265 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:"
279267 puts
280268 puts e.message
281269 puts
289277 end
290278
291279 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")
297281 exit 1
298282 end
299283
300284 filename = ARGV.shift
301285
302286 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")
308288 exit 2
309289 end
310
311 lengths = []
312 max_length = 0
313 base_words = {}
314290
315291 puts "Generating stats, hit CTRL-C to finish early and dump stats on words already processed."
316292 puts "Please wait..."
317293
318 if %x{wc -l '#{filename}'}.match(/\s*([0-9]+).*/)
294 if (not OS.windows?) and %x{wc -l '#{filename}'}.match(/\s*([0-9]+).*/)
319295 file_line_count = $1.to_i
320296 else
321297 filesize = File.stat(filename).size
334310 pbar.inc
335311 next
336312 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)
360326 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
533328
534329 pbar.inc
535
536 total_lines += 1
537330 rescue ArgumentError => e
538331 puts "Encoding problem processing word: " + line
332 # puts e.inspect
333 # puts e.backtrace
334 # exit
539335 pbar.inc
540336 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:"
542338 puts
543339 puts e.message
544340 puts
547343 puts "Backtrace:"
548344 puts e.backtrace
549345 puts
550 usage
551346 exit 1
552347 end
553348 end
554349 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")
560351 exit 1
561352 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:"
563354 puts
564355 puts e.message
565356 puts
579370 puts
580371 puts
581372
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
586377
587378 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
-386
us_area_codes.rb less more
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"]