From b0eb679c56464ebbe178f9c456dc38635bb19a17 Mon Sep 17 00:00:00 2001 From: Simon Wistow Date: Mon, 7 Nov 2011 12:27:58 -0800 Subject: [PATCH] Add ability to try this with multiple different hashes --- README.md | 10 ++++++++-- bozocrack.rb | 49 ++++++++++++++++++++++++++++++++++++++++++------- 2 files changed, 50 insertions(+), 9 deletions(-) mode change 100644 => 100755 bozocrack.rb diff --git a/README.md b/README.md index b47c3fc..b22ad2b 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ # BozoCrack -BozoCrack is a depressingly effective MD5 password hash cracker with almost zero CPU/GPU load. Instead of rainbow tables, dictionaries, or brute force, BozoCrack simply *finds* the plaintext password. Specifically, it googles the MD5 hash and hopes the plaintext appears somewhere on the first page of results. +BozoCrack is a depressingly effective password hash cracker with almost zero CPU/GPU load. Instead of rainbow tables, dictionaries, or brute force, BozoCrack simply *finds* the plaintext password. Specifically, it googles the hash and hopes the plaintext appears somewhere on the first page of results. It works way better than it ever should. @@ -9,7 +9,13 @@ Basic usage: $ ruby bozocrack.rb my_md5_hashes.txt -The input file has no specified format. BozoCrack automatically picks up strings that look like MD5 hashes. A single line shouldn't contain more than one hash. +The input file has no specified format. BozoCrack automatically picks up strings that look like hashes. A single line shouldn't contain more than one hash. + +Advanced usage: + + $ ruby bozocrack.rb --hash sha1 my_sha1_hashes.txt + +hash can be passed md5 (default), sha1 or sha2 Example with output: diff --git a/bozocrack.rb b/bozocrack.rb old mode 100644 new mode 100755 index 5a4bd6f..2f0f9e2 --- a/bozocrack.rb +++ b/bozocrack.rb @@ -1,14 +1,38 @@ +#!/usr/bin/env ruby + require 'digest/md5' require 'net/http' +HASHES = { + :md5 => { + :require => 'digest/md5', + :size => 32, + :class => Digest::MD5 + }, + :sha1 => { + :require => 'digest/sha1', + :size => 40, + :class => Digest::SHA1 + }, + :sha2 => { + :require => 'digest/sha2', + :size => 64, + :class => Digest::SHA2 + }, +} + class BozoCrack - def initialize(filename) + def initialize(filename, hash=:md5) @hashes = Array.new @cache = Hash.new + @hash = HASHES[hash] + raise "Unknown hash function #{hash} - try one of #{HASHES.keys.join(', ')}\n" unless @hash + require @hash[:require] + @hash_regex = "\\b([a-fA-F0-9]{#{@hash[:size]}})\\b" File.new(filename).each_line do |line| - if m = line.chomp.match(/\b([a-fA-F0-9]{32})\b/) + if m = line.chomp.match(/#{@hash_regex}/) @hashes << m[1] end end @@ -45,7 +69,7 @@ def crack_single_hash(hash) def dictionary_attack(hash, wordlist) wordlist.each do |word| - if Digest::MD5.hexdigest(word) == hash.downcase + if @hash[:class].hexdigest(word) == hash.downcase return word end end @@ -55,7 +79,7 @@ def dictionary_attack(hash, wordlist) def load_cache(filename = "cache") if File.file? filename File.new(filename).each_line do |line| - if m = line.chomp.match(/^([a-fA-F0-9]{32}):(.*)$/) + if m = line.chomp.match(/^(#{@hash_regex}):(.*)$/) @cache[m[1]] = m[2] end end @@ -70,8 +94,19 @@ def append_to_cache(hash, plaintext, filename = "cache") end +hash = :md5 +while ARGV[0] =~ /^--/ do + opt = ARGV.shift + if opt == "--hash" + raise "#{opt} needs a parameter" if ARGV.empty? + hash = ARGV.shift.to_sym + else + raise "Unknown option #{opt}" + end +end + if ARGV.size == 1 - BozoCrack.new(ARGV[0]).crack + BozoCrack.new(ARGV.shift, hash).crack else - puts "Usage example: ruby bozocrack.rb file_with_md5_hashes.txt" -end \ No newline at end of file + puts "Usage example: ruby #{File.basename($0)} [arg[s]] file_with_md5_hashes.txt" +end