ruby_hashcat 0.1.2 → 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 0ec228aef049a3ad95a48ec1469fd4776485adb5
4
- data.tar.gz: 7f0feb43dffdf57ea6ac483454adfad3f88b1778
3
+ metadata.gz: 1c7c6e7d06815bcc3d0c9599c9bff96f7cf7c65c
4
+ data.tar.gz: a59f83883b5ce173f358dd514e3e9b73528984fd
5
5
  SHA512:
6
- metadata.gz: d0dda83de1f4ae91c18f25b73c9f9e3841290b24a005e69dbde75f9de260c10dc382a662ad69f6d711c711ed80998d6852f64608410605cbbb0cbc74b8a52b4a
7
- data.tar.gz: 98b68cdfbfd925293ee7264bb8cbe963598db13ddd39bed4ff8174c68d30c087fbcfef96ebb867600215540b14571dac7fff5eeec8e576e8f47248c5e125ef42
6
+ metadata.gz: a859e87170241e660147e70276322a6f1c3d33ce09d9ff906381bd40ffbf66801ffc9fd2f1cbfbaeae6efceb0d08fd285ede9620137955ae677c47120ad1f082
7
+ data.tar.gz: 7bb9dac6700d925f8b188798b1655a4cd99a6388e1d6da1d01ec8ad1b734968e5c688cc5ee52a91427d2246913bfa4affa5258e05a2f0c60e56537e0ec37b949
data/.gitignore CHANGED
@@ -12,9 +12,7 @@ lib/bundler/man
12
12
  pkg
13
13
  rdoc
14
14
  spec/reports
15
- test/tmp
16
15
  test/version_tmp
17
- tmp
18
16
  *.bundle
19
17
  *.so
20
18
  *.o
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # RubyHashcat
2
2
 
3
- TODO: Write a gem description
3
+ Ruby wrapper created to run oclHashcat cracking jobs from inside of ruby. Initially created to integrate with a Rest API.
4
4
 
5
5
  ## Installation
6
6
 
@@ -18,11 +18,11 @@ Or install it yourself as:
18
18
 
19
19
  ## Usage
20
20
 
21
- TODO: Write usage instructions here
21
+ Check out the test folder to see some examples of running a crack job.
22
22
 
23
23
  ## Contributing
24
24
 
25
- 1. Fork it ( https://github.com/[my-github-username]/ruby_hashcat/fork )
25
+ 1. Fork it ( https://github.com/coleton/ruby_hashcat/fork )
26
26
  2. Create your feature branch (`git checkout -b my-new-feature`)
27
27
  3. Commit your changes (`git commit -am 'Add some feature'`)
28
28
  4. Push to the branch (`git push origin my-new-feature`)
@@ -1,3 +1,23 @@
1
+ require 'ruby_hashcat/objects/init'
2
+ require 'ruby_hashcat/api'
3
+ require 'ruby_hashcat/parse'
1
4
  require 'ruby_hashcat/program'
2
5
  require 'ruby_hashcat/task'
6
+ require 'ruby_hashcat/tools'
7
+ require 'ruby_hashcat/validation'
3
8
  require 'ruby_hashcat/version'
9
+
10
+ module RubyHashcat
11
+ # Hashcat Rest API
12
+ def self.start_api(hashcat_location, debug=false)
13
+ RubyHashcat::API.set :ocl_location, hashcat_location
14
+ RubyHashcat::API.set :debug, debug
15
+ RubyHashcat::API.run!
16
+ end
17
+ end
18
+
19
+ if __FILE__ == $0
20
+ path = File.dirname(__FILE__)
21
+ puts File.exists?("#{path}/../../cudaHashcat-1.30/cudaHashcat64.bin")
22
+ RubyHashcat.start_api("#{path}/../../cudaHashcat-1.30/cudaHashcat64.bin", true)
23
+ end
@@ -0,0 +1,22 @@
1
+ require 'sinatra/base'
2
+ require 'thin'
3
+ require 'sucker_punch'
4
+ require 'json'
5
+ require 'pp'
6
+
7
+ ###########################################################################
8
+ # Author: Coleton Pierson #
9
+ # Company: Praetorian #
10
+ # Date: August 20, 2014 #
11
+ # Project: Ruby Hashcat #
12
+ # Description: Main API class. Loads routes and sinatra methods. #
13
+ ###########################################################################
14
+
15
+ module RubyHashcat
16
+
17
+ class API < Sinatra::Application
18
+ path = File.dirname(__FILE__)
19
+ require "#{path}/routes/init"
20
+ end
21
+
22
+ end
@@ -0,0 +1,419 @@
1
+ require 'sucker_punch'
2
+
3
+ ###########################################################################
4
+ # Author: Coleton Pierson #
5
+ # Company: Praetorian #
6
+ # Date: August 20, 2014 #
7
+ # Project: Ruby Hashcat #
8
+ # Description: Main hash class. Interfaces with cli wrapper #
9
+ # and processes async tasks. #
10
+ ###########################################################################
11
+
12
+ module RubyHashcat
13
+ module Objects
14
+ class Hash
15
+
16
+ ###########################################################################
17
+ # @method initialize(id, path) #
18
+ # @param id: [Integer] Hash ID #
19
+ # @param path: [String] oclHashcat Path #
20
+ # @description Initialize a new hash. #
21
+ ###########################################################################
22
+ def initialize(id, path)
23
+ raise RubyHashcat::Objects::Hash::InvalidHashId unless id.is_a? Integer
24
+ raise RubyHashcat::Objects::Hash::InvalidHashCatLocation unless Dir.exists?(File.dirname(path))
25
+ @id = id
26
+ @path = File.dirname(path)
27
+ @ocl = path
28
+ end
29
+
30
+ ###########################################################################
31
+ # @method crack(async) #
32
+ # @param async: [Boolean] Crack Async #
33
+ # @description Crack the hash with the current settings. #
34
+ ###########################################################################
35
+ def crack(async=false)
36
+
37
+ # Check if async
38
+ if async
39
+ # SuckerPunch the crack method
40
+ RubyHashcat::Objects::Hash::Async.new.async.crack(self)
41
+ else
42
+ path = File.dirname(__FILE__)
43
+
44
+ # Write standard output to a file without redirecting it.
45
+ tee_out = TeeIO.new($stdout, File.new("#{path}/../tmp/#{@id}_output.txt", 'w'))
46
+ $stdout = tee_out
47
+
48
+ # Write standard error to a file without redirecting it.
49
+ tee_err = TeeIO.new($stderr, File.new("#{path}/../tmp/#{@id}_errors.txt", 'w'))
50
+ $stderr = tee_err
51
+
52
+ # Create PID file for this hash ID
53
+ File.touch("#{path}/../tmp/.hashcat_#{@id}_pid")
54
+
55
+ # oclHashcat Object
56
+ worker = RubyHashcat::Program.new(@ocl)
57
+
58
+ # Start cracking with wrapper
59
+ worker.crack do |crack|
60
+
61
+ # Hash Type
62
+ crack.hash_type = @type
63
+ # Output
64
+ crack.outfile = "#{path}/../tmp/#{@id}.crack"
65
+ crack.outfile_format = 5
66
+ # Status Output
67
+ crack.status = true
68
+ crack.status_timer = 15
69
+
70
+ # Disable Restore and Pot File (not needed)
71
+ crack.disable_restore = true
72
+ crack.disable_potfile = true
73
+
74
+ # Rules
75
+ crack.rules = @rule if @rule
76
+
77
+ # Runtime limit
78
+ crack.runtime = @runtime if @runtime
79
+
80
+ # Contains Username
81
+ crack.username = true if @username
82
+
83
+ # Combination Rules
84
+ if @attack == 1
85
+ crack.rule_left = @left_rule if @left_rule
86
+ crack.rule_right = @right_rule if @right_rule
87
+ end
88
+
89
+ # Attack Mode
90
+ crack.attack_mode = @attack
91
+
92
+ # Hash
93
+ crack.hash = @hash
94
+
95
+ # Attack mode config
96
+ case @attack
97
+ when 0
98
+ # Dictionary Attack
99
+ crack.wordlist = @word_list
100
+ when 1
101
+ # Combination Attack
102
+ raise RubyHashcat::Objects::Hash::InvalidCombinationAttack unless @word_list.count == 2
103
+ crack.wordlist = @word_list
104
+ when 3
105
+ # Bruteforce/Mask Attack
106
+ raise RubyHashcat::Objects::Hash::InvalidMaskAttack unless @charset
107
+ crack.charset = @charset
108
+ when 6
109
+ # Hybrid Dict + Mask Attack
110
+ raise RubyHashcat::Objects::Hash::InvalidHybridAttack unless @word_list and @charset
111
+ crack.wordlist = @word_list
112
+ crack.charset = @charset
113
+ when 7
114
+ # Hybrid Mask + Dict Attack
115
+ raise RubyHashcat::Objects::Hash::InvalidHybridAttack unless @word_list and @charset
116
+ crack.charset = @charset
117
+ crack.wordlist = @word_list
118
+ else
119
+ raise RubyHashcat::Objects::Hash::InvalidAttack
120
+ end
121
+
122
+ end
123
+
124
+ # Delete PID
125
+ File.delete("#{path}/../tmp/.hashcat_#{@id}_pid") if File.exists?("#{path}/../tmp/.hashcat_#{@id}_pid")
126
+ end
127
+ end
128
+
129
+ ###########################################################################
130
+ # @method clean #
131
+ # @description Deletes all files created by cracking. #
132
+ ###########################################################################
133
+ def clean
134
+ path = File.dirname(__FILE__)
135
+ File.delete("#{path}/../tmp/.hashcat_#{@id}_pid") if File.exists?("#{path}/../tmp/.hashcat_#{@id}_pid")
136
+ File.delete("#{path}/../tmp/#{@id}_output.txt") if File.exists?("#{path}/../tmp/#{@id}_output.txt")
137
+ File.delete("#{path}/../tmp/#{@id}_errors.txt") if File.exists?("#{path}/../tmp/#{@id}_errors.txt")
138
+ File.delete("#{path}/../tmp/#{@id}.crack") if File.exists?("#{path}/../tmp/#{@id}.crack")
139
+ end
140
+
141
+ ###########################################################################
142
+ # @method status #
143
+ # @description Reads oclHashcat output and parses the status. #
144
+ # @return [Hash] Hash with status and errors #
145
+ ###########################################################################
146
+ def status
147
+ path = File.dirname(__FILE__)
148
+ if File.exists?("#{path}/../tmp/#{@id}_output.txt") and File.exists?("#{path}/../tmp/#{@id}_errors.txt")
149
+ arr = RubyHashcat::Parse.stdout("#{path}/../tmp/#{@id}_output.txt")
150
+ if arr.is_a? Array
151
+ arr_dat = arr[-1]
152
+ end
153
+ err = File.read("#{path}/../tmp/#{@id}_errors.txt").chomp.strip
154
+ {:data => arr_dat, :errors => err}
155
+ else
156
+ return false
157
+ end
158
+ end
159
+
160
+ ###########################################################################
161
+ # @method running? #
162
+ # @description Checks pid file to see if oclhashcat is running. #
163
+ # @return [Boolean] oclHashcat Running #
164
+ ###########################################################################
165
+ def running?
166
+ path = File.dirname(__FILE__)
167
+ File.exists?("#{path}/../tmp/.hashcat_#{@id}_pid")
168
+ end
169
+
170
+ ###########################################################################
171
+ # @method exists? #
172
+ # @description Checks to see if the object has initiated cracking. #
173
+ # @return [Boolean] #
174
+ ###########################################################################
175
+ def exists?
176
+ path = File.dirname(__FILE__)
177
+ File.exists?("#{path}/../tmp/#{@id}_output.txt")
178
+ end
179
+
180
+ ###########################################################################
181
+ # @method status #
182
+ # @description Reads oclHashcat pot file and parses the cracked hashes. #
183
+ # @return [Hash] Returns cracked hashes and their plaintext passwords. #
184
+ ###########################################################################
185
+ def results
186
+ path = File.dirname(__FILE__)
187
+ RubyHashcat::Parse.pot_file("#{path}/../tmp/#{@id}.crack")
188
+ end
189
+
190
+ ####################
191
+ # Modifier Methods #
192
+ ####################
193
+
194
+ ###########################################################################
195
+ # @method word_list=(value) #
196
+ # @param value: [Array] Word List Paths #
197
+ # [String] Word List Path #
198
+ # @description Set word list(s). #
199
+ ###########################################################################
200
+ def word_list=(value)
201
+ @word_list = []
202
+ if value.is_a? Array
203
+ value.each do |x|
204
+ raise RubyHashcat::Objects::Hash::InvalidHashFile unless File.exists?(x)
205
+ @word_list << x
206
+ end
207
+ else
208
+ raise RubyHashcat::Objects::Hash::InvalidHashFile unless File.exists?(value)
209
+ @word_list << value
210
+ end
211
+ end
212
+
213
+ ###########################################################################
214
+ # @method hash=(value) #
215
+ # @param value: [String] Hash File Path #
216
+ # @description Set hash. #
217
+ ###########################################################################
218
+ def hash=(value)
219
+ raise RubyHashcat::Objects::Hash::InvalidHashFile unless File.exists?(value)
220
+ @hash = value
221
+ end
222
+
223
+ ###########################################################################
224
+ # @method type=(value) #
225
+ # @param value: [Integer] Hash Type #
226
+ # @description Set hash type. #
227
+ ###########################################################################
228
+ def type=(value)
229
+ raise RubyHashcat::Objects::Hash::InvalidHashId unless value.is_a? Integer
230
+ @type = value
231
+ end
232
+
233
+ ###########################################################################
234
+ # @method attack=(value) #
235
+ # @param value: [Integer] Attack Type #
236
+ # @description Set attack type. #
237
+ ###########################################################################
238
+ def attack=(value)
239
+ raise RubyHashcat::Objects::Hash::InvalidAttack unless value.is_a? Integer and [0, 1, 3, 6, 7].include?(value)
240
+ @attack = value
241
+ end
242
+
243
+ ###########################################################################
244
+ # @method char_word=(value) #
245
+ # @param value: [Boolean] Charset first in Hybrid attack order #
246
+ # @description Set attack order for hybrid attack to (charset #
247
+ # + word list) instead of (word list + charset). #
248
+ ###########################################################################
249
+ def char_word=(value)
250
+ @char_word = !!value
251
+ end
252
+
253
+ ###########################################################################
254
+ # @method rules=(value) #
255
+ # @param value: [Array] Rule File Names #
256
+ # [String] Rule File Name #
257
+ # @description Set rules for word lists. Verifies rules #
258
+ # are in the ocl rule folder (/ocl/rules). #
259
+ ###########################################################################
260
+ def rules=(value)
261
+ list = Dir.entries("#{@path}/rules/")
262
+ @rule = []
263
+ if value.is_a? Array
264
+ raise RubyHashcat::Objects::Hash::InvalidRuleFile unless (value - list).empty?
265
+ value.each do |x|
266
+ @rule << "#{@path}/rules/#{x}"
267
+ end
268
+ else
269
+ raise RubyHashcat::Objects::Hash::InvalidRuleFile unless list.include?(value)
270
+ @rule << "#{@path}/rules/#{value}"
271
+ end
272
+ end
273
+
274
+ ###########################################################################
275
+ # @method max_runtime=(value) #
276
+ # @param value: [Integer] Seconds #
277
+ # @description Set max time for cracking to last. #
278
+ ###########################################################################
279
+ def max_runtime=(value)
280
+ raise RubyHashcat::Objects::Hash::InvalidRuntime unless value.is_a? Integer and value >= 300
281
+ @runtime = value
282
+ end
283
+
284
+ ###########################################################################
285
+ # @method username=(value) #
286
+ # @param value: [Boolean] Username #
287
+ # @description Set true if hash file contains user names. #
288
+ ###########################################################################
289
+ def username=(value)
290
+ @username = !!value
291
+ end
292
+
293
+ ###########################################################################
294
+ # @method charset=(value) #
295
+ # @param value: [String] Charset #
296
+ # @description Set charset for brute forcing or hybrid attack. #
297
+ # Must follow oclHashcat's charset pattern: #
298
+ # ?l - lowercase #
299
+ # ?u - uppercase #
300
+ # ?d - digit #
301
+ # ?s - special #
302
+ # ?a - all #
303
+ ###########################################################################
304
+ def charset=(value)
305
+ raise RubyHashcat::Objects::Hash::InvalidCharset unless value.match(/(\?[lasdu]{1})+/)
306
+ @charset = value
307
+ end
308
+
309
+ ###########################################################################
310
+ # @method left_rule=(value) #
311
+ # @param value: [String] Charset #
312
+ # @description Set rules for left dict on hybrid attack. #
313
+ ###########################################################################
314
+ def left_rule=(value)
315
+ raise RubyHashcat::Objects::Hash::InvalidRule unless value.match(/([:lucCtrdfq\{\}\[\]]{1})||(T[0-9]+)||(p[0-9]+)||(\$[0-9]+)||(\^[0-9]+)||(D[0-9]+)||(x[0-9]{2,})||(i[0-9]{2,})||(o[0-9]{2,})||('[0-9]+)||(s[0-9]{2,})||(@[0-9]+)||(z[0-9]+)||(Z[0-9]+)/) and value != ''
316
+ @left_rule = value
317
+ end
318
+
319
+ ###########################################################################
320
+ # @method right_rule=(value) #
321
+ # @param value: [String] Charset #
322
+ # @description Set rules for right dict on hybrid attack. #
323
+ ###########################################################################
324
+ def right_rule=(value)
325
+ raise RubyHashcat::Objects::Hash::InvalidRule unless value.match(/([:lucCtrdfq\{\}\[\]]{1})||(T[0-9]+)||(p[0-9]+)||(\$[0-9]+)||(\^[0-9]+)||(D[0-9]+)||(x[0-9]{2,})||(i[0-9]{2,})||(o[0-9]{2,})||('[0-9]+)||(s[0-9]{2,})||(@[0-9]+)||(z[0-9]+)||(Z[0-9]+)/) and value != ''
326
+ @right_rule = value
327
+ end
328
+
329
+ ####################
330
+ # Class Exceptions #
331
+ ####################
332
+ class RubyHashcatError < StandardError
333
+ end
334
+ class InvalidHashType < RubyHashcatError
335
+ def message
336
+ 'Invalid Hash Type. Hash type must be an integer.'
337
+ end
338
+ end
339
+ class InvalidHashFile < RubyHashcatError
340
+ def message
341
+ 'Invalid Hash File. Check your hash file.'
342
+ end
343
+ end
344
+ class InvalidHashWordList < RubyHashcatError
345
+ def message
346
+ 'Invalid Word List File. Please check your post request'
347
+ end
348
+ end
349
+ class InvalidRuleFile < RubyHashcatError
350
+ def message
351
+ 'Invalid Rule File. To view the default rule files packaged with hashcat, please check the documentation or GET /rules.json'
352
+ end
353
+ end
354
+ class InvalidCharset < RubyHashcatError
355
+ def message
356
+ 'Invalid Charset String. To view a list of valid charsets, please check the documentation.'
357
+ end
358
+ end
359
+ class InvalidRule < RubyHashcatError
360
+ def message
361
+ 'Invalid Rule. To view a list of valid rules, please check the documentation.'
362
+ end
363
+ end
364
+ class InvalidAttack < RubyHashcatError
365
+ def message
366
+ 'Invalid Attack. To view a list of attacks, please check the documentation.'
367
+ end
368
+ end
369
+ class InvalidHashId < RubyHashcatError
370
+ def message
371
+ 'Invalid Hash ID. Hash ID must be an integer.'
372
+ end
373
+ end
374
+ class InvalidHashCatLocation < RubyHashcatError
375
+ def message
376
+ 'Invalid HashCat path. HashCat path must exist.'
377
+ end
378
+ end
379
+ class InvalidRuntime < RubyHashcatError
380
+ def message
381
+ 'Invalid HashCat runtime. Runtime must be an integer and greater or equal to 300.'
382
+ end
383
+ end
384
+ class InvalidMaskAttack < RubyHashcatError
385
+ def message
386
+ 'Invalid HashCat mask attack. You must specify a valid charset.'
387
+ end
388
+ end
389
+ class InvalidHybridAttack < RubyHashcatError
390
+ def message
391
+ 'Invalid HashCat hybrid attack. You must specify a valid charset and word list.'
392
+ end
393
+ end
394
+ class InvalidCombinationAttack < RubyHashcatError
395
+ def message
396
+ 'Invalid HashCat combination attack. You must specify an array of 2 word lists.'
397
+ end
398
+ end
399
+ class HashIDAlreadyExists < RubyHashcatError
400
+ def message
401
+ 'The ID you chose for this hash already exists. Please choose another.'
402
+ end
403
+ end
404
+
405
+ #########################
406
+ # Sucker Punch Subclass #
407
+ #########################
408
+ class Async
409
+ include ::SuckerPunch::Job
410
+ workers 3
411
+
412
+ def crack(obj)
413
+ obj.crack
414
+ end
415
+
416
+ end
417
+ end
418
+ end
419
+ end