Advertisement
Guest User

Untitled

a guest
Mar 18th, 2010
196
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Ruby 2.44 KB | None | 0 0
  1. =begin
  2.  
  3.     Given:
  4.         1. a hash
  5.         2. a hashing algorithm
  6.         3. the length of the original message
  7.         4. the alphabet of the original message
  8.  
  9.     Bruteforce the original message by randomly iterating through the search space.
  10.     To take advantage of a multicore CPU, execute this script using JRuby.
  11.  
  12.     As an example, this script searches for a randomly generated password.
  13.  
  14. =end
  15.  
  16. # perform an in-place Fisher-Yates shuffle
  17. class Array
  18.     def shuffle!
  19.         j = length
  20.         i = 0
  21.         while j > 1
  22.             r = i + rand(j)
  23.             self[i], self[r] = self[r], self[i]
  24.             i += 1
  25.             j -= 1
  26.         end
  27.         self
  28.     end
  29. end
  30.  
  31. # map an integer to a string
  32. def dec2base(int)
  33.     ret = ""
  34.     while int > 0
  35.         ret = "#{ALPHABET[int % ALPHA_SIZE]}#{ret}"
  36.         int /= ALPHA_SIZE
  37.     end
  38.     ret.rjust(PW_LEN, ALPHABET[0])
  39. end
  40.  
  41. # example hash function
  42. def hash(str)
  43.     str.crypt("..")
  44. end
  45.  
  46. # check if a string maps to the target hash
  47. def check(int)
  48.     str = dec2base(int)
  49.     if hash(str) == $target
  50.         puts "match:   #{str}  =>  #{hash(str)}"
  51.         $found = true
  52.         exit
  53.     end
  54. end
  55.  
  56. # partition a range into an array of N equal-sized ranges
  57. def partition(range, n)
  58.     ranges = []
  59.     first = range.first
  60.     last = range.last
  61.     length = last - first + 1
  62.     step = length / n # integer division
  63.     ((first + step - 1)..last).step(step) { |i|
  64.         ranges << (first..i)
  65.         first = i + 1
  66.     }
  67.     # append any extra onto the last element
  68.     ranges[-1] = (ranges[-1].first)..last if last > step * ranges.length
  69.     ranges
  70. end
  71.  
  72. # recursively search a range
  73. def search(range)
  74.     if range.last - range.first < BLOCK_SIZE
  75.         # range is small enough to check
  76.         a = range.to_a
  77.         a.shuffle!
  78.         a.each { |i| check(i) }
  79.     else
  80.         # range is too large; subdivide it
  81.         a = partition(range, NUM_PARTS)
  82.         a.shuffle!
  83.         a.each { |r| search(r) }
  84.     end
  85. end
  86.  
  87. # options
  88. Thread.abort_on_exception = true
  89. NUM_THREADS = 8
  90. PW_LEN = 4
  91.  
  92. # constants
  93. ALPHABET = ("0".."9").to_a + ("a".."z").to_a
  94. ALPHA_SIZE = ALPHABET.length
  95. BLOCK_SIZE = 2 ** 16
  96. NUM_PARTS = 4
  97. COMPLEXITY = ALPHA_SIZE ** PW_LEN
  98.  
  99. # variables
  100. pw = Array.new(PW_LEN) { ALPHABET[rand(ALPHA_SIZE)] }.join
  101. $target = hash(pw)
  102. $found = false
  103. puts "target:  #{pw}  =>  #{$target}"
  104. puts "search:  #{COMPLEXITY} keys"
  105.  
  106. # partition and assign each search space to a thread
  107. threads = []
  108. partition(0..(COMPLEXITY-1), NUM_THREADS).each { |r| threads << Thread.new { search(r) } }
  109.  
  110. # wait until a match is found, or all threads are dead
  111. sleep(5) until $found || threads.all? { |t| !t.alive? }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement