-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathBURP.rb
executable file
·191 lines (162 loc) · 5.77 KB
/
BURP.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
#!/usr/bin/env ruby
# encoding: utf-8
require 'rubygems'
require 'openssl'
require 'base64'
require 'digest/sha2'
require 'thor'
BURP_VERSION = '0.0.7'
DEFAULT_WORDLIST = %w{
abode abyss air angle apple arm army arrow artist author avenue
baby bandit banker banner bard baron barrel beast belfry bird
blood board body book bosom boss bottle boy brain breeze bronze
cabin candy cane car cash cat cell cellar chair chasm chief child
chin cigar circle city claw clock coast coffee coin colony comedy
cord core corn corner corpse cotton cradle crime damsel dawn dirt
doctor doll dollar door dove drama dream dress dust earth engine
errand fabric feline flag flask flesh flower fork form fowl fox
friend frog fur galaxy garden garret geese girl goblet gold gore
grass green hall hamlet hammer harp health hoof hotel hound house
hurdle icebox infant ink insect iron jail judge jury keg kettle
king kiss lad lark lawn lemon letter lice limb lime link lip
locker lord lump maiden mantle mast master meadow mirage money
monk month morgue moss mother mucus murder nail nephew noose nun
nymph oats odour opium owner oxygen palace peach pelt pepper
piano pipe piston plain plank poet poetry pole poster prayer
priest prison pupil python queen rattle reflex revolt ritual
river robber rock rod rosin rubble salad salary salute sauce sea
season seat serf ship shock shriek singer skin skull sky slush
snake sonata speech spire spray stain star stone street string
stub suds sugar sultan sunset swamp table tank temple thief thorn
ticket tidbit toast tomb tool tower tree troops truck vacuum
vapour vessel vest victim vision volume warmth water weapon
wench whale wheat wife wigwam window wine woman woods world yacht
}
class BURP < Thor
include Thor::Actions
default_task :generate
BURP_CIPHER = 'AES-256-CFB'
NIL_SHA256 = "\343\260\304B\230\374\034\024\232\373\364\310\231o\271$'\256A\344d\233\223L\244\225\231\exR\270U"
desc 'generate', 'Generates a new password (Default task)'
method_option :wordlist, type: :string, aliases: '-W'
method_option :words, type: :numeric, aliases: '-w', default: 4
method_option :separator, type: :string, aliases: '-s', default: '-'
method_option :alphanumeric, type: :boolean
def generate
sha256 = Digest::SHA256.new
key = sha256.digest(ask 'Enter your unique key: ')
if key == NIL_SHA256
say 'Error: key must not be nil', :red
exit
end
system 'stty -echo' # don't echo our passphrase back to the terminal
passphrase = sha256.digest(ask 'Enter your secret passphrase: ')
puts # new line
system 'stty echo'
if passphrase == NIL_SHA256
say 'Error: passphrase must not be nil', :red
exit
end
if options[:wordlist].nil?
wordlist = DEFAULT_WORDLIST
elsif options[:wordlist].match(/\.aes$/)
e_wordlist = self.read_file(options[:wordlist])
cipher = OpenSSL::Cipher.new(BURP_CIPHER)
cipher.decrypt
cipher.key = passphrase
cipher.iv = e_wordlist.slice(0, 16)
d_wordlist = cipher.update(Base64.decode64(e_wordlist)) + cipher.final
d_wordlist.gsub!(/^.{16}/ , '') # remove iv prefix
e_wordlist = nil
wordlist = []
d_wordlist.scan(/^.*\n/).each { |w| wordlist.push w.chomp }
d_wordlist = nil
if wordlist.length < 256
say 'Error: Invalid wordlist', :red
exit
end
else
wordlist = self.wordlist_from_file(options[:wordlist])
end
hash = sha256.hexdigest("#{key}#{passphrase}")
chunk_size = hash.length / options[:words]
chunks = hash.scan(/.{#{chunk_size}}/)
words = []
if options[:alphanumeric]
nums = []
end
(0..(options[:words] - 1)).each do |i|
c = chunks[i]
n = c.to_i(36).modulo(wordlist.length)
words.push wordlist[n]
if options[:alphanumeric]
r = c.to_i(36).remainder(wordlist.length)
nums.push r
end
end
password = words.join(options[:separator])
if options[:alphanumeric]
password << options[:separator]
nums.each do |n|
z = 0
n.to_s.scan(/.{1}/).each { |x| z = z + x.to_i }
password << z.to_s[0]
end
end
say "Your password is: #{password}"
end
desc 'encrypt FILE', "Encrypt a file using #{BURP_CIPHER} and your passphrase"
def encrypt(file)
contents = self.read_file(file)
sha256 = Digest::SHA256.new
system 'stty -echo'
passphrase = sha256.digest(ask 'Enter your secret passphrase: ')
puts
system 'stty echo'
if passphrase == NIL_SHA256
say 'Error: passphrase must not be nil', :red
exit
end
cipher = OpenSSL::Cipher.new(BURP_CIPHER)
cipher.encrypt
cipher.key = passphrase
cipher.iv = initialization_vector = cipher.random_iv
e_contents = cipher.update(contents) + cipher.final
self.write_file("#{file}.aes", Base64.encode64(initialization_vector + e_contents))
end
desc 'version', 'BURP version number'
def version
puts "BURP: v#{BURP_VERSION} (https://github.com/jwmarshall/BURP)"
end
no_tasks do
def wordlist_from_file(file)
wordlist = []
file = "#{Dir.pwd}/#{file}" if ! file.match(/^\//)
File.open(file, 'r') do |f|
f.each_line { |line| wordlist.push line.chomp }
end
if wordlist.length < 256
say 'Error: word list must have at least 256 words', :red
exit
end
return wordlist
end
def read_file(file)
file = "#{Dir.pwd}/#{file}" if ! file.match(/^\//)
File.open(file, 'r') do |f|
return f.read
end
end
def write_file(file, content)
file = "#{Dir.pwd}/#{file}" if ! file.match(/^\//)
if File.exists?(file)
say 'File exists!'
exit
end
File.open(file, 'w+') do |f|
f.puts content
end
end
end
end
BURP.start