ruby_hashcat 0.1.2 → 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,2 @@
1
+ path = File.dirname(__FILE__)
2
+ require "#{path}/hash"
@@ -0,0 +1,245 @@
1
+ path = File.dirname(__FILE__)
2
+ require "#{path}/tools"
3
+
4
+ ###########################################################################
5
+ # Author: Coleton Pierson #
6
+ # Company: Praetorian #
7
+ # Date: August 20, 2014 #
8
+ # Project: Ruby Hashcat #
9
+ # Description: Main parser class. Parses ocl stdout and pot file. #
10
+ ###########################################################################
11
+
12
+ module RubyHashcat
13
+ module Parse
14
+
15
+ ###########################################################################
16
+ # @method RubyHashcat::Parse.stdout(file) #
17
+ # @param file: [String] Path to oclHashcat stdout file #
18
+ # @description Parses the oclHashcat stdout file into hashes. #
19
+ # @return [Array][Hash] Array of Hashes with oclHashcat status. #
20
+ ###########################################################################
21
+ def self.stdout(file)
22
+ array = []
23
+ return array unless File.exists?(file)
24
+ placement = -1
25
+ string = []
26
+ File.open(file).each_line do |x|
27
+ string << x
28
+ end
29
+ string.each do |line|
30
+ if line.include?('Session.Name.')
31
+ placement += 1
32
+ array[placement] = {}
33
+ elsif placement < 0
34
+ next
35
+ elsif line.include?('Status.')
36
+ tmp = line.split(':')
37
+ array[placement][:status] = tmp[-1].chomp.strip
38
+ elsif line.include?('Rules.Type.')
39
+ tmp = line.split(':')
40
+ array[placement][:rules] = tmp[-1].chomp.strip
41
+ elsif line.include?('Input.Mode.')
42
+ tmp = line.split(':')
43
+ array[placement][:input] = tmp[-1].chomp.strip
44
+ elsif line.include?('Input.Base.')
45
+ # Label only used in combination attack
46
+ tmp = line.split(':')
47
+ array[placement][:input_base] = tmp[-1].chomp.strip
48
+ elsif line.include?('Input.Mod.')
49
+ # Label only used in combination attack
50
+ tmp = line.split(':')
51
+ array[placement][:input_mod] = tmp[-1].chomp.strip
52
+ elsif line.include?('Hash.Target.')
53
+ tmp = line.split(':')
54
+ array[placement][:target] = tmp[-1].chomp.strip
55
+ elsif line.include?('Hash.Type.')
56
+ tmp = line.split(':')
57
+ array[placement][:type] = tmp[-1].chomp.strip
58
+ elsif line.include?('Time.Started.')
59
+ tmp = line.split(':')
60
+ tmp.delete_at(0)
61
+ tmp = tmp.join(':')
62
+ array[placement][:started] = tmp.chomp.strip
63
+ elsif line.include?('Time.Estimated.')
64
+ tmp = line.split(':')
65
+ tmp.delete_at(0)
66
+ tmp = tmp.join(':')
67
+ array[placement][:estimated] = tmp.chomp.strip
68
+ elsif line.include?('Speed.GPU.')
69
+ # Must account for x amount of GPUs
70
+ tmp = line.split(':')
71
+ tmp[0].gsub!('Speed.GPU.', '')
72
+ tmp[0].gsub!('.', '')
73
+ tmp[0].gsub!('#', '')
74
+ num = tmp[0].to_i
75
+ if num == 1
76
+ array[placement][:speed] = []
77
+ end
78
+ array[placement][:speed][num-1] = tmp[-1].chomp.strip
79
+ elsif line.include?('Recovered.')
80
+ tmp = line.split(':')
81
+ array[placement][:recovered] = tmp[-1].chomp.strip
82
+ elsif line.include?('Progress.')
83
+ tmp = line.split(':')
84
+ array[placement][:progress] = tmp[-1].chomp.strip
85
+ elsif line.include?('Rejected.')
86
+ tmp = line.split(':')
87
+ array[placement][:rejected] = tmp[-1].chomp.strip
88
+ elsif line.include?('HWMon.GPU.')
89
+ # Must account for x amount of GPUs
90
+ tmp = line.split(':')
91
+ tmp[0].gsub!('HWMon.GPU.', '')
92
+ tmp[0].gsub!('.', '')
93
+ tmp[0].gsub!('#', '')
94
+ num = tmp[0].to_i
95
+ if num == 1
96
+ array[placement][:hwmon] = []
97
+ end
98
+ array[placement][:hwmon][num-1] = tmp[-1].chomp.strip
99
+ end
100
+ end
101
+ array
102
+ end
103
+
104
+
105
+ ###########################################################################
106
+ # @method RubyHashcat::Parse.status_automat(file) #
107
+ # @param file: [String] Path to oclHashcat stdout file #
108
+ # @description Parses the oclHashcat status-automat stdout format. #
109
+ # @return [Array][Hash] Array of Hashes with oclHashcat status. #
110
+ ###########################################################################
111
+ def self.status_automat(file)
112
+ array = []
113
+ return array unless File.exists?(file)
114
+ string = []
115
+ File.open(file).each_line do |x|
116
+ string << x
117
+ end
118
+ string.each do |line|
119
+ line = line.chomp
120
+ line = line.strip
121
+ line = line.gsub(' ', ' ')
122
+ unless line.include?('STATUS')
123
+ next
124
+ end
125
+ split = line.split(' ')
126
+ stat = {}
127
+ i = 0
128
+ if split[i] == 'STATUS'
129
+ stat[:status] = split[i+1].chomp.strip
130
+ i += 2
131
+ end
132
+ if split[i] == 'SPEED'
133
+ i += 1
134
+ speed = 0
135
+ si = 0
136
+ while split[i] != 'CURKU'
137
+ calc = split[i].to_f
138
+ duration = split[i+1].to_f
139
+ if calc == 0.0 and duration == 0.0
140
+ stat["speed_gpu_#{si+1}".to_sym] = 0
141
+ else
142
+ stat["speed_gpu_#{si+1}".to_sym] = (calc/duration).round
143
+ speed += (calc/duration).round
144
+ end
145
+ si += 1
146
+ i += 2
147
+ end
148
+ stat[:total_speed] = speed
149
+ end
150
+ if split[i] == 'CURKU'
151
+ stat[:checkpoint] = split[i+1]
152
+ i += 2
153
+ end
154
+ if split[i] == 'PROGRESS'
155
+ current_prog = split[i+1].to_f
156
+ total_prog = split[i+2].to_f
157
+ stat[:progress] = ((((current_prog + 0.0)/(total_prog + 0.0)) * 10000).round)/10000.0
158
+ i += 3
159
+ end
160
+ if split[i] == 'RECHASH'
161
+ rec_count = split[i+1].to_f.to_i
162
+ rec_total = split[i+2].to_f.to_i
163
+ stat[:rec_hash] = "#{rec_count}/#{rec_total}"
164
+ i += 3
165
+ end
166
+ if split[i] == 'RECSALT'
167
+ rec_count = split[i+1].to_f.to_i
168
+ rec_total = split[i+2].to_f.to_i
169
+ stat[:rec_salt] = "#{rec_count}/#{rec_total}"
170
+ i += 3
171
+ end
172
+ if split[i] == 'TEMP'
173
+ i += 1
174
+ si = 0
175
+ while i < split.count
176
+ stat["temp_gpu_#{si+1}".to_sym] = split[i].to_i
177
+ si += 1
178
+ i += 1
179
+ end
180
+ end
181
+ array << stat
182
+ end
183
+ array
184
+ end
185
+
186
+ ###########################################################################
187
+ # @method RubyHashcat::Parse.pot_file(file) #
188
+ # @param file: [String] Path to oclHashcat cracked passwords #
189
+ # @description Parses the cracked passwords into a hash. #
190
+ # @return [Array][Hash] Array of Hashes with cracked passwords. #
191
+ ###########################################################################
192
+ def self.pot_file(file)
193
+ arr = []
194
+ return arr unless File.exists?(file)
195
+ File.open(file).each_line do |x|
196
+ split = x.split(':')
197
+ plain = self.hex_to_bin(split[-1])
198
+ split.delete_at(-1)
199
+ hash = split.join(':')
200
+ arr << {:hash => hash, :plain => plain}
201
+ end
202
+ arr
203
+ end
204
+
205
+ ###########################################################################
206
+ # @method RubyHashcat::Parse.hash(hash) #
207
+ # @param hash: [Hash] Original Hash with strings as keys. #
208
+ # @description Parses a hash with strings as keys and converts them #
209
+ # to symbols. #
210
+ # @return [Hash] Hash with all keys as symbols. #
211
+ ###########################################################################
212
+ def self.hash(obj)
213
+ return obj.reduce({}) do |memo, (k, v)|
214
+ memo.tap { |m| m[k.to_sym] = hash(v) }
215
+ end if obj.is_a? Hash
216
+
217
+ return obj.reduce([]) do |memo, v|
218
+ memo << hash(v); memo
219
+ end if obj.is_a? Array
220
+
221
+ obj
222
+ end
223
+
224
+ ###########################################################################
225
+ # @method RubyHashcat::Parse.bin_to_hex(s) #
226
+ # @param s: [String] Normal String #
227
+ # @description Converts a string to hex #
228
+ # @return [String] Hexed String #
229
+ ###########################################################################
230
+ def self.bin_to_hex(s)
231
+ s.each_byte.map { |b| b.to_s(16) }.join
232
+ end
233
+
234
+ ###########################################################################
235
+ # @method RubyHashcat::Parse.hex_to_bin(s) #
236
+ # @param s: [String] Hexed String #
237
+ # @description Converts hex to a string #
238
+ # @return [String] Normal String #
239
+ ###########################################################################
240
+ def self.hex_to_bin(s)
241
+ s.scan(/../).map { |x| x.hex.chr }.join
242
+ end
243
+
244
+ end
245
+ end
@@ -1,16 +1,25 @@
1
1
  require 'rprogram/program'
2
2
 
3
+ ###########################################################################
4
+ # Author: Coleton Pierson #
5
+ # Company: Praetorian #
6
+ # Date: June 28, 2014 #
7
+ # Project: Ruby Hashcat #
8
+ # Description: Main program wrapper class. Holds the main method #
9
+ # for initializing a cli session. #
10
+ ###########################################################################
11
+
3
12
  module RubyHashcat
4
13
  class Program < RProgram::Program
5
14
 
6
15
  # Add a top-level method which finds and runs the program.
7
16
  def self.crack(options={}, &block)
8
- self.find.crack(options,&block)
17
+ self.find.crack(options, &block)
9
18
  end
10
19
 
11
20
  # Add a method which runs the program with hashcat_task
12
- def crack(options={},&block)
13
- run_task(HashcatTask.new(options,&block))
21
+ def crack(options={}, &block)
22
+ run_task(HashcatTask.new(options, &block))
14
23
  end
15
24
 
16
25
  end
@@ -0,0 +1,23 @@
1
+ module RubyHashcat
2
+ class API < Sinatra::Application
3
+ post '/clean.json' do
4
+ content_type :json
5
+
6
+ if settings.debug
7
+ pp params
8
+ end
9
+
10
+ begin
11
+ hc = RubyHashcat::Objects::Hash.new(params[:id].to_i, settings.ocl_location)
12
+ if hc.exists?
13
+ hc.clean
14
+ return {:status => 'success'}.to_json
15
+ else
16
+ return {:status => 'error', :message => 'Invalid ID.'}.to_json
17
+ end
18
+ rescue => e
19
+ return {:status => 'error'}.to_json
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,85 @@
1
+ module RubyHashcat
2
+ class API < Sinatra::Application
3
+ post '/crack.json' do
4
+ content_type :json
5
+
6
+ if settings.debug
7
+ pp params
8
+ end
9
+
10
+ path = File.dirname(__FILE__)
11
+
12
+ tmp = params.clone
13
+ params = RubyHashcat::Parse.hash(tmp)
14
+
15
+ # Validate required parameters
16
+ unless params[:id] and params[:type] and params[:attack] and params[:hash]
17
+ return {error: 'Invalid Parameters. Please check the documentation.'}.to_json
18
+ end
19
+
20
+ begin
21
+ hc = RubyHashcat::Objects::Hash.new(params[:id].to_i, settings.ocl_location)
22
+ if hc.exists? and not hc.running?
23
+ hc.clean
24
+ end
25
+ id = params[:id].to_i
26
+ attack = params[:attack].to_i
27
+ type = params[:type].to_i
28
+ hash = "#{path}/../tmp/#{id}.hash"
29
+
30
+ hc.attack = attack
31
+
32
+ case attack
33
+ when 1
34
+ raise RubyHashcat::Objects::Hash::InvalidCombinationAttack unless File.exists?(params[:word_list][:tempfile]) and File.exists?(params[:word_list_2][:tempfile])
35
+ word_list = "#{path}/../tmp/#{id}.dict"
36
+ word_list_2 = "#{path}/../tmp/#{id}.dict2"
37
+ tmp = []
38
+ tmp << word_list.clone
39
+ tmp << word_list_2.clone
40
+ File.rename(params[:word_list][:tempfile], word_list)
41
+ File.rename(params[:word_list_2][:tempfile], word_list_2)
42
+ word_list = tmp
43
+ else
44
+ if params[:word_list]
45
+ if params[:word_list][:tempfile]
46
+ if File.exists?(params[:word_list][:tempfile])
47
+ word_list = "#{path}/../tmp/#{id}.dict"
48
+ File.rename(params[:word_list][:tempfile], word_list)
49
+ end
50
+ end
51
+ end
52
+ end
53
+
54
+ if params[:rule_sets]
55
+ hc.rules = params[:rule_sets]
56
+ end
57
+ if params[:username]
58
+ hc.username = true
59
+ end
60
+ if params[:charset]
61
+ hc.charset = params[:charset]
62
+ end
63
+
64
+ File.rename(params[:hash][:tempfile], hash)
65
+
66
+ hc.hash = hash
67
+
68
+ if word_list
69
+ hc.word_list = word_list
70
+ end
71
+
72
+ hc.type = type
73
+
74
+ hc.crack(true)
75
+
76
+ return {:status => 'success'}.to_json
77
+ rescue RubyHashcat::Objects::Hash::RubyHashcatError => e
78
+ return {:error => e.message}.to_json
79
+ rescue => e
80
+ return {:error => e.message}.to_json
81
+ end
82
+
83
+ end
84
+ end
85
+ end
@@ -0,0 +1,7 @@
1
+ path = File.dirname(__FILE__)
2
+
3
+ require "#{path}/clean"
4
+ require "#{path}/crack"
5
+ require "#{path}/results"
6
+ require "#{path}/settings"
7
+ require "#{path}/status"
@@ -0,0 +1,25 @@
1
+ module RubyHashcat
2
+ class API < Sinatra::Application
3
+ get '/results.json' do
4
+ content_type :json
5
+
6
+ if settings.debug
7
+ pp params
8
+ end
9
+
10
+ begin
11
+ hc = RubyHashcat::Objects::Hash.new(params[:id].to_i, settings.ocl_location)
12
+ unless hc.exists?
13
+ return {:status => 'error', :message => 'Invalid ID.'}.to_json
14
+ end
15
+ if hc.running?
16
+ return {:status => 'running'}.to_json
17
+ else
18
+ return {:results => hc.results}.to_json
19
+ end
20
+ rescue => e
21
+ return {:status => 'error', :message => e.message}.to_json
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,26 @@
1
+ module RubyHashcat
2
+ class API < Sinatra::Application
3
+ get '/location.json' do
4
+ content_type :json
5
+
6
+ if settings.debug
7
+ pp params
8
+ end
9
+
10
+ {:location => settings.ocl_location}.to_json
11
+ end
12
+
13
+ get '/rules.json' do
14
+ content_type :json
15
+
16
+ if settings.debug
17
+ pp params
18
+ end
19
+
20
+ list = Dir.entries("#{settings.ocl_location}/rules/")
21
+ list.delete('.')
22
+ list.delete('..')
23
+ {:rules => list}.to_json
24
+ end
25
+ end
26
+ end