ptj 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,26 @@
1
+ module PTJ
2
+ module Parser
3
+ # FileParser class which allows you to parse a file line by line.
4
+ #
5
+ class PassThreeColons < FileParser
6
+
7
+ # Expecting the following format:
8
+ # something ::: pass ::: something
9
+ # something ::: pass ::: something
10
+ # something ::: pass ::: something
11
+ #
12
+ # @param line
13
+ # Individual line from a text file
14
+ #
15
+ # @return Hash Password, Password Hash
16
+ def parse_line(line)
17
+ if line =~ /\s*\S*\s*:::\s*(\S+)\s*:::/
18
+ pass = $~[1]
19
+ hash = nil
20
+ end
21
+ {:mypass => pass, :myhash => hash}
22
+ end
23
+
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,120 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{ptj}
8
+ s.version = "0.1.0"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Josh Grunzweig"]
12
+ s.date = %q{2011-08-29}
13
+ s.description = %q{An easy way to collect and analyze data about password
14
+ databases.}
15
+ s.email = %q{jgrunzweig@gmail.com}
16
+ s.extra_rdoc_files = [
17
+ "LICENSE.txt",
18
+ "README.rdoc"
19
+ ]
20
+ s.files = [
21
+ ".document",
22
+ "Gemfile",
23
+ "Gemfile.lock",
24
+ "LICENSE.txt",
25
+ "README.rdoc",
26
+ "Rakefile",
27
+ "VERSION",
28
+ "etc/config.yml",
29
+ "lib/ptj.rb",
30
+ "lib/ptj/default_setup.rb",
31
+ "lib/ptj/environment.rb",
32
+ "lib/ptj/ext.rb",
33
+ "lib/ptj/ext/datamapper_collection.rb",
34
+ "lib/ptj/model.rb",
35
+ "lib/ptj/model/password.rb",
36
+ "lib/ptj/model/tag.rb",
37
+ "lib/ptj/model/tasks.rb",
38
+ "lib/ptj/parser.rb",
39
+ "lib/ptj/parser/fileparser.rb",
40
+ "lib/ptj/parser/fileparser/countpassonly.rb",
41
+ "lib/ptj/parser/fileparser/hashpassonlycolon.rb",
42
+ "lib/ptj/parser/fileparser/passhashonly.rb",
43
+ "lib/ptj/parser/fileparser/passonly.rb",
44
+ "lib/ptj/parser/fileparser/passthreecolons.rb",
45
+ "ptj.gemspec",
46
+ "scripts/analyze.rb",
47
+ "scripts/generate_wordlist.rb",
48
+ "scripts/import.rb",
49
+ "scripts/ptj_libpath.rb",
50
+ "spec/.helper.rb.swp",
51
+ "spec/.test_ptj.rb.swp",
52
+ "spec/model/password_spec.rb",
53
+ "spec/model/shared_behaviors.rb",
54
+ "spec/model/tag_spec.rb",
55
+ "spec/spec_helper.rb",
56
+ "spec/spec_ptj.rb",
57
+ "tasks/db.rake",
58
+ "tasks/irb.rake"
59
+ ]
60
+ s.homepage = %q{http://github.com/jgrunzweig/ptj}
61
+ s.licenses = ["MIT"]
62
+ s.require_paths = ["lib"]
63
+ s.rubygems_version = %q{1.6.2}
64
+ s.summary = %q{Password analysis and collection database.}
65
+
66
+ if s.respond_to? :specification_version then
67
+ s.specification_version = 3
68
+
69
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
70
+ s.add_development_dependency(%q<shoulda>, [">= 0"])
71
+ s.add_development_dependency(%q<bundler>, ["~> 1.0.0"])
72
+ s.add_development_dependency(%q<jeweler>, ["~> 1.6.2"])
73
+ s.add_development_dependency(%q<rcov>, [">= 0"])
74
+ s.add_development_dependency(%q<rspec>, ["~> 2.3.0"])
75
+ s.add_development_dependency(%q<dm-core>, [">= 0"])
76
+ s.add_development_dependency(%q<dm-migrations>, [">= 0"])
77
+ s.add_development_dependency(%q<dm-types>, [">= 0"])
78
+ s.add_development_dependency(%q<dm-transactions>, [">= 0"])
79
+ s.add_development_dependency(%q<dm-aggregates>, [">= 0"])
80
+ s.add_development_dependency(%q<dm-validations>, [">= 0"])
81
+ s.add_development_dependency(%q<dm-serializer>, [">= 0"])
82
+ s.add_development_dependency(%q<dm-timestamps>, [">= 0"])
83
+ s.add_development_dependency(%q<dm-sqlite-adapter>, [">= 0"])
84
+ s.add_development_dependency(%q<dm-postgres-adapter>, [">= 0"])
85
+ else
86
+ s.add_dependency(%q<shoulda>, [">= 0"])
87
+ s.add_dependency(%q<bundler>, ["~> 1.0.0"])
88
+ s.add_dependency(%q<jeweler>, ["~> 1.6.2"])
89
+ s.add_dependency(%q<rcov>, [">= 0"])
90
+ s.add_dependency(%q<rspec>, ["~> 2.3.0"])
91
+ s.add_dependency(%q<dm-core>, [">= 0"])
92
+ s.add_dependency(%q<dm-migrations>, [">= 0"])
93
+ s.add_dependency(%q<dm-types>, [">= 0"])
94
+ s.add_dependency(%q<dm-transactions>, [">= 0"])
95
+ s.add_dependency(%q<dm-aggregates>, [">= 0"])
96
+ s.add_dependency(%q<dm-validations>, [">= 0"])
97
+ s.add_dependency(%q<dm-serializer>, [">= 0"])
98
+ s.add_dependency(%q<dm-timestamps>, [">= 0"])
99
+ s.add_dependency(%q<dm-sqlite-adapter>, [">= 0"])
100
+ s.add_dependency(%q<dm-postgres-adapter>, [">= 0"])
101
+ end
102
+ else
103
+ s.add_dependency(%q<shoulda>, [">= 0"])
104
+ s.add_dependency(%q<bundler>, ["~> 1.0.0"])
105
+ s.add_dependency(%q<jeweler>, ["~> 1.6.2"])
106
+ s.add_dependency(%q<rcov>, [">= 0"])
107
+ s.add_dependency(%q<rspec>, ["~> 2.3.0"])
108
+ s.add_dependency(%q<dm-core>, [">= 0"])
109
+ s.add_dependency(%q<dm-migrations>, [">= 0"])
110
+ s.add_dependency(%q<dm-types>, [">= 0"])
111
+ s.add_dependency(%q<dm-transactions>, [">= 0"])
112
+ s.add_dependency(%q<dm-aggregates>, [">= 0"])
113
+ s.add_dependency(%q<dm-validations>, [">= 0"])
114
+ s.add_dependency(%q<dm-serializer>, [">= 0"])
115
+ s.add_dependency(%q<dm-timestamps>, [">= 0"])
116
+ s.add_dependency(%q<dm-sqlite-adapter>, [">= 0"])
117
+ s.add_dependency(%q<dm-postgres-adapter>, [">= 0"])
118
+ end
119
+ end
120
+
@@ -0,0 +1,129 @@
1
+ #!/usr/bin/env ruby
2
+ require 'pp'
3
+ require 'optparse'
4
+
5
+ require_relative('ptj_libpath')
6
+ require 'ptj/default_setup'
7
+
8
+ DataMapper::Model.raise_on_save_failure = true if $DEBUG
9
+
10
+ include PTJ
11
+
12
+ #FILTER = {:fields => [:id, :password, :upper, :lower, :special, :number, :size]}
13
+ FILTER = {}
14
+ CFG = {
15
+ :tags => [],
16
+ :file => nil,
17
+ :includecount => false
18
+ }
19
+
20
+ opts = OptionParser.new do |o|
21
+ o.banner = "Usage: #{File.basename $0} [opts]"
22
+
23
+ o.on_tail("-h", "--help", "Show this message") do
24
+ puts o
25
+ exit 1
26
+ end
27
+
28
+ o.on("-t", "--tags TAGS", "Tags to be used to when querying passwords (separated by a comma)") do |t|
29
+ t = t.split(",").each{|x| x.strip!}
30
+ t=[t] unless t.is_a?(Array)
31
+ t.each do |tag|
32
+ CFG[:tags] << tag
33
+ end
34
+ end
35
+
36
+ o.on("--max-size SIZE", Integer, "Maximum size of the resulting passords") do |f|
37
+ FILTER[:size.lt] = f
38
+ end
39
+
40
+ o.on("--min-size SIZE", Integer, "Minimum size of the resulting passwords") do |f|
41
+ FILTER[:size.gt] = f
42
+ end
43
+
44
+ o.on("--[no-]upper", "Query based on upper-case letters") do |f|
45
+ FILTER[:upper] = f
46
+ end
47
+
48
+ o.on("--[no-]lower", "Query based on lower-case letters") do |f|
49
+ FILTER[:lower] = f
50
+ end
51
+
52
+ o.on("--[no-]special", "Query based on special charaters") do |f|
53
+ FILTER[:special] = f
54
+ end
55
+
56
+ o.on("--[no-]number", "Query based on numbers") do |f|
57
+ FILTER[:number] = f
58
+ end
59
+
60
+ end.parse!(ARGV)
61
+
62
+ def top5_pass(object, my_hash)
63
+ my_hash.delete(:fields) if my_hash[:fields]
64
+ my_hash.delete(:order) if my_hash[:order]
65
+ return object.aggregate(:password, :password.count, my_hash).sort {|x,y| y[1] <=> x[1]}.first(5)
66
+ end
67
+
68
+ def size_count(object, my_hash)
69
+ my_hash.delete(:fields) if my_hash[:fields]
70
+ my_hash.delete(:order) if my_hash[:order]
71
+ return object.aggregate(:size, :size.count, my_hash).sort {|x,y| x[0] <=> y[0]}
72
+ end
73
+
74
+ def cat_result(object, my_hash)
75
+ my_hash.delete(:fields) if my_hash[:fields]
76
+ my_hash.delete(:order) if my_hash[:order]
77
+ return_hash = {}
78
+ return_hash["Lower"] = object.all(my_hash).count(:upper => false, :special => false, :lower => true, :number => false)
79
+ return_hash["Upper"] = object.all(my_hash).count(:upper => true, :special => false, :lower => false, :number => false)
80
+ return_hash["Number"] = object.all(my_hash).count(:upper => false, :special => false, :lower => false, :number => true)
81
+ return_hash["Special"] = object.all(my_hash).count(:upper => false, :special => true, :lower => false, :number => false)
82
+ return_hash["Lower/Upper"] = object.all(my_hash).count(:upper => true, :special => false, :lower => true, :number => false)
83
+ return_hash["Lower/Number"] = object.all(my_hash).count(:upper => false, :special => false, :lower => true, :number => true)
84
+ return_hash["Upper/Number"] = object.all(my_hash).count(:upper => true, :special => false, :lower => false, :number => true)
85
+ return_hash["Lower/Special"] = object.all(my_hash).count(:upper => false, :special => true, :lower => true, :number => false)
86
+ return_hash["Upper/Special"] = object.all(my_hash).count(:upper => true, :special => true, :lower => false, :number => false)
87
+ return_hash["Number/Special"] = object.all(my_hash).count(:upper => false, :special => true, :lower => false, :number =>true)
88
+ return_hash["Lower/Upper/Number"] = object.all(my_hash).count(:upper => true, :special => false, :lower => true, :number => true)
89
+ return_hash["Lower/Upper/Special"] = object.all(my_hash).count(:upper => true, :special => true, :lower => true, :number => false)
90
+ return_hash["Lower/Number/Special"] = object.all(my_hash).count(:upper => false, :special => true, :lower => true, :number => true)
91
+ return_hash["Upper/Number/Special"] = object.all(my_hash).count(:upper => true, :special => true, :lower => false, :number =>true)
92
+ return_hash["Lower/Upper/Number/Special"] = object.all(my_hash).count(:upper => true, :special => true, :lower => true, :number => true)
93
+ return_hash
94
+ end
95
+
96
+ time_now = Time.now
97
+ if CFG[:tags]
98
+ top5 = top5_pass(PTJ::Tag.all(:tag => CFG[:tags]).passwords, FILTER)
99
+ my_count = size_count(PTJ::Tag.all(:tag => CFG[:tags]).passwords, FILTER)
100
+ split_up = cat_result(PTJ::Tag.all(:tag => CFG[:tags]).passwords, FILTER)
101
+ else
102
+ top5 = top5_pass(PTJ::Passwords.all, FILTER)
103
+ my_count = size_count(PTJ::Passwords.all, FILTER)
104
+ split_up = cat_result(PTJ::Passwords.all, FILTER)
105
+ end
106
+
107
+
108
+ puts "-=-=-=-=-=- Top 5 Passwords -=-=-=-=-=-"
109
+ top5.each do |pass, count|
110
+ printf("%-30s : %d", pass, count)
111
+ puts ""
112
+ end
113
+
114
+ total_size = 0
115
+ my_count.each{|result| total_size += result[1] }
116
+ puts "\n-=-=-=-=-=- Password Length -=-=-=-=-=-"
117
+ my_count.each do |result|
118
+ percent = "%.2f" % ((result[1].to_f/total_size.to_f)*100).to_f
119
+ printf("%-30s %s", ("Password Length: #{result[0]}"), ("Count: #{result[1]} (#{percent}%)") )
120
+ puts ""
121
+ end
122
+ puts "Total: #{total_size}"
123
+
124
+ puts "\n-=-=-=-=-=- Password Type -=-=-=-=-=-"
125
+ split_up.sort_by{|k,v| k.length}.each do |result|
126
+ printf("Type: %-30s %s", result[0], ("Result: #{result[1]}"))
127
+ puts ""
128
+ end
129
+ p "Time taken: #{Time.now - time_now}"
@@ -0,0 +1,121 @@
1
+ #!/usr/bin/env ruby
2
+ require 'pp'
3
+ require 'optparse'
4
+
5
+ require_relative('ptj_libpath')
6
+ require 'ptj/default_setup'
7
+
8
+ DataMapper::Model.raise_on_save_failure = true if $DEBUG
9
+
10
+ include PTJ
11
+
12
+ FILTER = {:fields => [:password, :id]}
13
+
14
+ CFG = {
15
+ :tags => [],
16
+ :file => nil,
17
+ :includecount => false
18
+ }
19
+
20
+ opts = OptionParser.new do |o|
21
+ o.banner = "Usage: #{File.basename $0} [opts]"
22
+
23
+ o.on_tail("-h", "--help", "Show this message") do
24
+ puts o
25
+ exit 1
26
+ end
27
+
28
+ o.on("-t", "--tags TAGS", "Tags to be used to when querying passwords (separated by a comma)") do |t|
29
+ t = t.split(",").each{|x| x.strip!}
30
+ t=[t] unless t.is_a?(Array)
31
+ t.each do |tag|
32
+ CFG[:tags] << tag
33
+ end
34
+ end
35
+
36
+ o.on("-o", "--output FILENAME", String, "Where to output results (Default outputs to screen)") do |f|
37
+ CFG[:file] = f
38
+ end
39
+
40
+ o.on("--max-size SIZE", Integer, "Maximum size of the resulting passords") do |f|
41
+ FILTER[:size.lt] = f
42
+ end
43
+
44
+ o.on("--min-size SIZE", Integer, "Minimum size of the resulting passwords") do |f|
45
+ FILTER[:size.gt] = f
46
+ end
47
+
48
+ o.on("--max-results SIZE", Integer, "Maximum number of results to return") do |f|
49
+ CFG[:max_results] = f
50
+ end
51
+
52
+ o.on("--include-count", "Include the counts of passwords identified") do |f|
53
+ CFG[:includecount] = f
54
+ end
55
+
56
+ o.on("--[no-]upper", "Query based on upper-case letters") do |f|
57
+ FILTER[:upper] = f
58
+ end
59
+
60
+ o.on("--[no-]lower", "Query based on lower-case letters") do |f|
61
+ FILTER[:lower] = f
62
+ end
63
+
64
+ o.on("--[no-]special", "Query based on special charaters") do |f|
65
+ FILTER[:special] = f
66
+ end
67
+
68
+ o.on("--[no-]number", "Query based on numbers") do |f|
69
+ FILTER[:number] = f
70
+ end
71
+
72
+
73
+ end.parse!(ARGV)
74
+
75
+ time_now = Time.now
76
+
77
+ #raise(OptionParser::MissingArgument, "Must specify file with -f or password with -p") if (CFG[:file].nil? and CFG[:password].nil?)
78
+ def top_pass(object, my_hash)
79
+ my_hash.delete(:fields) if my_hash[:fields]
80
+ my_hash.delete(:order) if my_hash[:order]
81
+ return object.aggregate(:password, :password.count, my_hash).sort {|x,y| y[1] <=> x[1]}
82
+ end
83
+
84
+ if CFG[:tags]
85
+ if CFG[:max_results]
86
+ o_pass = top_pass(PTJ::Tag.all(:tag => CFG[:tags]).passwords, FILTER).first(CFG[:max_results])
87
+ else
88
+ o_pass = top_pass(PTJ::Tag.all(:tag => CFG[:tags]).passwords, FILTER)
89
+ end
90
+ else
91
+ if CFG[:max_results]
92
+ o_pass = top_pass(PTJ::Passwords.all, FILTER).first(CFG[:max_results])
93
+ else
94
+ o_pass = top_pass(PTJ::Passwords.all, FILTER)
95
+ end
96
+ end
97
+
98
+
99
+ if CFG[:file]
100
+ File.open(CFG[:file], "w+") do |file_handle|
101
+ o_pass.each do |tiny_array|
102
+ if CFG[:includecount]
103
+ file_handle.puts "#{tiny_array[0]}, #{tiny_array[1]}"
104
+ else
105
+ file_handle.puts "#{tiny_array[0]}"
106
+ end
107
+ end
108
+ end
109
+ else
110
+ o_pass.each do |tiny_array|
111
+ if CFG[:includecount]
112
+ puts "#{tiny_array[0]}, #{tiny_array[1]}"
113
+ else
114
+ puts "#{tiny_array[0]}"
115
+ end
116
+ end
117
+ end
118
+ puts "Time Taken: #{Time.now - time_now}"
119
+ exit
120
+
121
+
@@ -0,0 +1,111 @@
1
+ #!/usr/bin/env ruby
2
+ require 'pp'
3
+ require 'optparse'
4
+
5
+ require_relative('ptj_libpath')
6
+ require 'ptj/default_setup'
7
+
8
+ DataMapper::Model.raise_on_save_failure = true if $DEBUG
9
+
10
+ include PTJ
11
+
12
+ FILTER = {}
13
+
14
+ CFG = {
15
+ :password => nil,
16
+ :pw_hash => "",
17
+ :tags => [],
18
+ :basename => true,
19
+ :file => nil
20
+ }
21
+
22
+ opts = OptionParser.new do |o|
23
+ o.banner = "Usage: #{File.basename $0} [opts] -f file|-p password"
24
+
25
+ o.on_tail("-h", "--help", "Show this message.") do
26
+ puts o
27
+ exit 1
28
+ end
29
+
30
+ o.on("-t", "--tag TAGS", "Tags to be used to identify imported passwords (separated by a comma)") do |t|
31
+ t = t.split(",").each{|x| x.strip!}
32
+ t=[t] unless t.is_a?(Array)
33
+ t.each do |tag|
34
+ mytag=(Tag.get(tag) || Tag.create(:tag => tag.to_s))
35
+ CFG[:tags] << mytag
36
+ end
37
+ end
38
+
39
+ o.on("--[no-]strict", "Enable/Disable Strict Mode") do |s|
40
+ DataMapper::Model.raise_on_save_failure = s
41
+ end
42
+
43
+ o.on("-f", "--file FILENAME", String, "File to import.") do |f|
44
+ CFG[:file] = f
45
+ end
46
+
47
+ o.on("-r", "--parser NUMBER", Integer, "File parser to use:", "1 - Password Only", "2 - Hash:Password", "3 - Count, Password", "4 - Something ::: Password ::: Something") do |f|
48
+ case f
49
+ when 1
50
+ CFG[:parser] = Parser::PassOnly.new
51
+ when 2
52
+ CFG[:parser] = Parser::HashPassOnlyColon.new
53
+ when 3
54
+ CFG[:parser] = Parser::CountPassOnly.new
55
+ when 4
56
+ CFG[:parser] = Parser::PassThreeColons.new
57
+ else
58
+ raise(OptionParser::InvalidOption, "Incorrect parsing number specified.")
59
+ end
60
+ end
61
+
62
+ o.on("-p", "--password PASSWORD", String, "Password to import.") do |f|
63
+ CFG[:file] = f
64
+ end
65
+
66
+ o.on("-a", "--hash HASH", String, "Hash to import (Use in conjunction with -p).") do |f|
67
+ CFG[:file] = f
68
+ end
69
+
70
+ end.parse!(ARGV)
71
+
72
+ raise(OptionParser::MissingArgument, "Must specify file with -f or password with -p") if (CFG[:file].nil? and CFG[:password].nil?)
73
+
74
+ #o_pass_count = Password.all(:fields => [:id]).size
75
+
76
+
77
+ def import_file
78
+ file = Pathname.new(CFG[:file])
79
+ parser = CFG[:parser]
80
+ tags = CFG[:tags]
81
+ file = File.open(CFG[:file], "r")
82
+ lines = file.readlines
83
+ lines.each do |line|
84
+ begin
85
+ line = line.force_encoding("BINARY")
86
+ parsed = parser.parse_line(line)
87
+ mypass = parsed[:mypass]
88
+ myhash = parsed[:myhash]
89
+ next if mypass.to_s.empty?
90
+ if parsed[:count]
91
+ parsed[:count].to_i.times do
92
+ pass = Password.add_single(mypass, myhash)
93
+ tags.each{|tag| pass.tags << tag}
94
+ pass.save
95
+ #puts "Adding #{mypass}"
96
+ end
97
+ else
98
+ pass = Password.add_single(mypass, myhash)
99
+ tags.each{|tag| pass.tags << tag}
100
+ pass.save
101
+ #puts "Adding #{mypass}"
102
+ end
103
+ rescue
104
+ next
105
+ end
106
+ end
107
+ end
108
+
109
+ import_file
110
+
111
+