pwn 0.4.476 → 0.4.479
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Gemfile +4 -4
- data/README.md +2 -2
- data/bin/pwn_perimeter_recon +2 -2
- data/bin/pwn_serial_msr206 +37 -81
- data/bin/pwn_shodan_search +1 -1
- data/lib/pwn/plugins/msr206.rb +491 -95
- data/lib/pwn/plugins/serial.rb +2 -2
- data/lib/pwn/version.rb +1 -1
- metadata +10 -10
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5ca99e7a8fee7afaa96d59d48264cf78faaf50b54d9d355b2efa1064f50bc618
|
4
|
+
data.tar.gz: 416841cc29f3d57207d6b61b783636af8d9b93e29af36b901132492b70066405
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 78eee723d46b98c17f833e10086a34d95e9aaaac55180cce18cb1106b45821d0739613ca53e99d1f72ef311dad108617bf9e2ee178ac0e67cc9daa2582921d58
|
7
|
+
data.tar.gz: 45661044936bbc8a6bdac18a61c0daaa9fd0a28565f3a50fde1dcbf903ede702e7e07f69806e4f7097ba754ca032fa4a1897888fcd5a0314ae986eecb5b451e6
|
data/Gemfile
CHANGED
@@ -33,12 +33,12 @@ gem 'ipaddress', '0.8.3'
|
|
33
33
|
gem 'js-beautify', '0.1.8'
|
34
34
|
gem 'json', '2.6.2'
|
35
35
|
gem 'jsonpath', '1.1.2'
|
36
|
-
gem 'jwt', '2.
|
36
|
+
gem 'jwt', '2.4.0'
|
37
37
|
gem 'luhn', '1.0.2'
|
38
38
|
gem 'mail', '2.7.1'
|
39
39
|
gem 'mongo', '2.17.1'
|
40
40
|
gem 'msfrpc-client', '1.1.2'
|
41
|
-
gem 'net-ldap', '0.17.
|
41
|
+
gem 'net-ldap', '0.17.1'
|
42
42
|
gem 'net-openvpn', '0.8.7'
|
43
43
|
gem 'net-smtp', '0.3.1'
|
44
44
|
gem 'nexpose', '7.3.0'
|
@@ -59,7 +59,7 @@ gem 'rex', '2.0.13'
|
|
59
59
|
gem 'rmagick', '4.2.5'
|
60
60
|
gem 'rspec', '3.11.0'
|
61
61
|
gem 'rtesseract', '3.1.2'
|
62
|
-
gem 'rubocop', '1.30.
|
62
|
+
gem 'rubocop', '1.30.1'
|
63
63
|
gem 'rubocop-rake', '0.6.0'
|
64
64
|
gem 'rubocop-rspec', '2.11.1'
|
65
65
|
gem 'ruby-audio', '1.6.1'
|
@@ -70,7 +70,7 @@ gem 'savon', '2.12.1'
|
|
70
70
|
gem 'selenium-devtools', '0.102.0'
|
71
71
|
gem 'serialport', '1.3.2'
|
72
72
|
gem 'sinatra', '2.2.0'
|
73
|
-
gem 'slack-ruby-client', '1.
|
73
|
+
gem 'slack-ruby-client', '1.1.0'
|
74
74
|
gem 'socksify', '1.7.1'
|
75
75
|
gem 'spreadsheet', '1.3.0'
|
76
76
|
gem 'sqlite3', '1.4.2'
|
data/README.md
CHANGED
@@ -37,7 +37,7 @@ $ rvm use ruby-3.1.2@pwn
|
|
37
37
|
$ rvm list gemsets
|
38
38
|
$ gem install --verbose pwn
|
39
39
|
$ pwn
|
40
|
-
pwn[v0.4.
|
40
|
+
pwn[v0.4.479]:001 >>> PWN.help
|
41
41
|
```
|
42
42
|
|
43
43
|
[](https://youtu.be/G7iLUY4FzsI)
|
@@ -52,7 +52,7 @@ $ rvm use ruby-3.1.2@pwn
|
|
52
52
|
$ gem uninstall --all --executables pwn
|
53
53
|
$ gem install --verbose pwn
|
54
54
|
$ pwn
|
55
|
-
pwn[v0.4.
|
55
|
+
pwn[v0.4.479]:001 >>> PWN.help
|
56
56
|
```
|
57
57
|
|
58
58
|
|
data/bin/pwn_perimeter_recon
CHANGED
@@ -130,7 +130,7 @@ def invoke_burp(opts = {})
|
|
130
130
|
)
|
131
131
|
|
132
132
|
File.open(json_results, 'w') do |f|
|
133
|
-
f.puts scan_issues_hash
|
133
|
+
f.puts JSON.pretty_generate(scan_issues_hash)
|
134
134
|
end
|
135
135
|
puts "#{@green}complete.#{@end_of_color}\n\n\n"
|
136
136
|
|
@@ -190,7 +190,7 @@ unless ipinfo.nil?
|
|
190
190
|
|
191
191
|
ipinfo_struc = PWN::Plugins::IPInfo.get(ip_or_host: ipinfo_target)
|
192
192
|
File.open(ipinfo_json_results, 'w') do |f|
|
193
|
-
f.puts ipinfo_struc
|
193
|
+
f.puts JSON.pretty_generate(ipinfo_struc)
|
194
194
|
end
|
195
195
|
end
|
196
196
|
end
|
data/bin/pwn_serial_msr206
CHANGED
@@ -15,7 +15,7 @@ OptionParser.new do |options|
|
|
15
15
|
opts[:block_dev] = d
|
16
16
|
end
|
17
17
|
|
18
|
-
options.on('-bBAUD', '--baud=BAUD', '<Optional - (defaults to
|
18
|
+
options.on('-bBAUD', '--baud=BAUD', '<Optional - (defaults to 9_600)>') do |b|
|
19
19
|
opts[:baud] = b
|
20
20
|
end
|
21
21
|
|
@@ -31,7 +31,7 @@ OptionParser.new do |options|
|
|
31
31
|
opts[:parity] = p
|
32
32
|
end
|
33
33
|
|
34
|
-
options.on('-fFLOWCTRL', '--flow-control=FLOWCTRL', '<Optional - none||hard||soft (defaults to
|
34
|
+
options.on('-fFLOWCTRL', '--flow-control=FLOWCTRL', '<Optional - none||hard||soft (defaults to soft)>') do |f|
|
35
35
|
opts[:flow_control] = f
|
36
36
|
end
|
37
37
|
end.parse!
|
@@ -68,26 +68,17 @@ begin
|
|
68
68
|
cmd: :simulate_power_cycle_warm_reset
|
69
69
|
)
|
70
70
|
|
71
|
-
#
|
72
|
-
#
|
73
|
-
#
|
74
|
-
#
|
75
|
-
#
|
76
|
-
#
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
# 2 |Track 3 Read not present |Track 3 Read present
|
81
|
-
# 3 |not used – should be 0 |not used
|
82
|
-
# 4 |Track 3 Write not present|Track 3 Write present
|
83
|
-
# 5 |Track 2 Write not present|Track 2 Write present
|
84
|
-
# 6 |Track 1 Write not present|Track 1 Write present
|
85
|
-
# 7 |parity bit** |parity bit**
|
86
|
-
exec_resp = PWN::Plugins::MSR206.exec(
|
87
|
-
msr206_obj: msr206_obj,
|
88
|
-
cmd: :configuration_request
|
71
|
+
# Unsure if this switches the protocol from USI0 to USI1
|
72
|
+
# exec_resp = PWN::Plugins::MSR206.exec(
|
73
|
+
# msr206_obj: msr206_obj,
|
74
|
+
# cmd: :proto_usi1
|
75
|
+
# )
|
76
|
+
# puts exec_resp.inspect
|
77
|
+
|
78
|
+
config_hash = PWN::Plugins::MSR206.get_config(
|
79
|
+
msr206_obj: msr206_obj
|
89
80
|
)
|
90
|
-
puts "Configuration
|
81
|
+
puts "Configuration: #{config_hash.inspect}"
|
91
82
|
|
92
83
|
exec_resp = PWN::Plugins::MSR206.exec(
|
93
84
|
msr206_obj: msr206_obj,
|
@@ -107,9 +98,10 @@ begin
|
|
107
98
|
|
108
99
|
puts "\n>> MAIN MENU OPTIONS:"
|
109
100
|
puts '[(R)ead Card]'
|
101
|
+
puts '[(B)ackup Card]'
|
110
102
|
puts '[(C)opy Card]'
|
103
|
+
puts '[(L)oad Card from File]'
|
111
104
|
puts '[(E)dit Card]'
|
112
|
-
puts '[(B)ackup Card]'
|
113
105
|
puts '[(W)arm Reset]'
|
114
106
|
puts '[(Q)uit]'
|
115
107
|
puts menu_msg
|
@@ -119,77 +111,41 @@ begin
|
|
119
111
|
|
120
112
|
case option
|
121
113
|
when :R
|
122
|
-
menu_msg = '
|
114
|
+
menu_msg = 'READ CARD'
|
123
115
|
# Read Card
|
124
|
-
track_data = PWN::Plugins::MSR206.
|
125
|
-
msr206_obj: msr206_obj
|
126
|
-
|
116
|
+
track_data = PWN::Plugins::MSR206.read_card(
|
117
|
+
msr206_obj: msr206_obj
|
118
|
+
)
|
119
|
+
when :B
|
120
|
+
menu_msg = 'BACKUP CARD TO FILE'
|
121
|
+
# Read Card to Backup
|
122
|
+
track_data = PWN::Plugins::MSR206.backup_card(
|
123
|
+
msr206_obj: msr206_obj
|
127
124
|
)
|
128
125
|
when :C
|
129
|
-
menu_msg = '
|
130
|
-
#
|
131
|
-
track_data = PWN::Plugins::MSR206.
|
132
|
-
msr206_obj: msr206_obj
|
133
|
-
|
126
|
+
menu_msg = 'COPY CARD'
|
127
|
+
# Copy Card
|
128
|
+
track_data = PWN::Plugins::MSR206.copy_card(
|
129
|
+
msr206_obj: msr206_obj
|
130
|
+
)
|
131
|
+
when :L
|
132
|
+
menu_msg = 'LOAD FROM FILE'
|
133
|
+
# Read Card to Backup
|
134
|
+
track_data = PWN::Plugins::MSR206.load_card_from_file(
|
135
|
+
msr206_obj: msr206_obj
|
134
136
|
)
|
135
|
-
|
136
|
-
# TODO: Save Original Card Contents
|
137
|
-
# arm_to_write card to clone
|
138
|
-
# read cloned card to verify successful write
|
139
137
|
when :E
|
140
|
-
menu_msg = '
|
138
|
+
menu_msg = 'EDIT'
|
141
139
|
# Read Target Card
|
142
|
-
track_data = PWN::Plugins::MSR206.
|
143
|
-
msr206_obj: msr206_obj
|
144
|
-
type: :arm_to_read
|
140
|
+
track_data = PWN::Plugins::MSR206.edit_card(
|
141
|
+
msr206_obj: msr206_obj
|
145
142
|
)
|
146
143
|
|
147
144
|
# TODO: Save Original Card Contents
|
148
145
|
# arm_to_write card to edit
|
149
146
|
# read edited card to verify successful write
|
150
|
-
when :B
|
151
|
-
menu_msg = 'READY TO BACKUP - PLEASE SWIPE CARD'
|
152
|
-
# Read Card
|
153
|
-
track_data = PWN::Plugins::MSR206.wait_for_swipe(
|
154
|
-
msr206_obj: msr206_obj,
|
155
|
-
type: :arm_to_read
|
156
|
-
)
|
157
|
-
|
158
|
-
file = ''
|
159
|
-
backup_msg = ''
|
160
|
-
loop do
|
161
|
-
if backup_msg.empty?
|
162
|
-
exec_resp = PWN::Plugins::MSR206.exec(
|
163
|
-
msr206_obj: msr206_obj,
|
164
|
-
cmd: :green_flash
|
165
|
-
)
|
166
|
-
end
|
167
|
-
|
168
|
-
print 'Enter File Name to Save Backup: '
|
169
|
-
file = gets.scrub.chomp.strip
|
170
|
-
file_dir = File.dirname(file)
|
171
|
-
break if Dir.exist?(file_dir)
|
172
|
-
|
173
|
-
backup_msg = "\n****** ERROR: Directory #{file_dir} for #{file} does not exist ******"
|
174
|
-
puts backup_msg
|
175
|
-
exec_resp = PWN::Plugins::MSR206.exec(
|
176
|
-
msr206_obj: msr206_obj,
|
177
|
-
cmd: :green_off
|
178
|
-
)
|
179
|
-
exec_resp = PWN::Plugins::MSR206.exec(
|
180
|
-
msr206_obj: msr206_obj,
|
181
|
-
cmd: :yellow_flash
|
182
|
-
)
|
183
|
-
end
|
184
|
-
|
185
|
-
File.write(file, "#{track_data.to_json}\n")
|
186
|
-
exec_resp = PWN::Plugins::MSR206.exec(
|
187
|
-
msr206_obj: msr206_obj,
|
188
|
-
cmd: :yellow_off
|
189
|
-
)
|
190
|
-
|
191
|
-
puts 'complete.'
|
192
147
|
when :W
|
148
|
+
menu_msg = 'WARM RESET'
|
193
149
|
exec_resp = PWN::Plugins::MSR206.exec(
|
194
150
|
msr206_obj: msr206_obj,
|
195
151
|
cmd: :simulate_power_cycle_warm_reset
|
data/bin/pwn_shodan_search
CHANGED
data/lib/pwn/plugins/msr206.rb
CHANGED
@@ -12,7 +12,7 @@ module PWN
|
|
12
12
|
# data_bits: 'optional - (defaults to 8)',
|
13
13
|
# stop_bits: 'optional - (defaults to 1)',
|
14
14
|
# parity: 'optional - :even|:mark|:odd|:space|:none (defaults to :none),'
|
15
|
-
# flow_control: 'optional - :none
|
15
|
+
# flow_control: 'optional - :none|:hard|:soft (defaults to :soft)'
|
16
16
|
# )
|
17
17
|
|
18
18
|
public_class_method def self.connect(opts = {})
|
@@ -22,7 +22,7 @@ module PWN
|
|
22
22
|
opts[:data_bits] = 8 unless opts[:data_bits]
|
23
23
|
opts[:stop_bits] = 1 unless opts[:stop_bits]
|
24
24
|
opts[:parity] = :none unless opts[:parity]
|
25
|
-
opts[:flow_control] = :
|
25
|
+
opts[:flow_control] = :soft unless opts[:flow_control]
|
26
26
|
msr206_obj = PWN::Plugins::Serial.connect(opts)
|
27
27
|
rescue StandardError => e
|
28
28
|
disconnect(msr206_obj: msr206_obj) unless msr206_obj.nil?
|
@@ -34,6 +34,8 @@ module PWN
|
|
34
34
|
public_class_method def self.list_cmds
|
35
35
|
# Returns an Array of Symbols
|
36
36
|
cmds = %i[
|
37
|
+
proto_usi0
|
38
|
+
proto_usi1
|
37
39
|
version_report
|
38
40
|
simulate_power_cycle_warm_reset
|
39
41
|
configuration_request
|
@@ -104,6 +106,7 @@ module PWN
|
|
104
106
|
decoded_data_str = ''
|
105
107
|
if raw_byte_arr
|
106
108
|
raw_byte_arr.first.split.each do |byte_str|
|
109
|
+
# TODO: Different case statements for each parity
|
107
110
|
case byte_str
|
108
111
|
when '1B'
|
109
112
|
decoded_data_str += ''
|
@@ -319,7 +322,7 @@ module PWN
|
|
319
322
|
binary_byte_arr = []
|
320
323
|
if raw_byte_arr
|
321
324
|
raw_byte_arr.first.split.each do |byte_str|
|
322
|
-
binary_byte_arr.push([byte_str].pack('H*').unpack1('B*')
|
325
|
+
binary_byte_arr.push([byte_str].pack('H*').unpack1('B*'))
|
323
326
|
end
|
324
327
|
end
|
325
328
|
|
@@ -336,6 +339,7 @@ module PWN
|
|
336
339
|
private_class_method def self.parse_responses(opts = {})
|
337
340
|
msr206_obj = opts[:msr206_obj]
|
338
341
|
cmd = opts[:cmd]
|
342
|
+
cmd_bytes = opts[:cmd_bytes]
|
339
343
|
|
340
344
|
keep_parsing_responses = true
|
341
345
|
next_response_detected = false
|
@@ -343,22 +347,28 @@ module PWN
|
|
343
347
|
response[:cmd] = cmd
|
344
348
|
response[:cmd] ||= :na
|
345
349
|
|
350
|
+
if cmd_bytes.instance_of?(Array)
|
351
|
+
response[:cmd_bytes] = opts[:cmd_bytes].map do |base10_int|
|
352
|
+
"0x#{base10_int.to_s(16).rjust(2, '0')}"
|
353
|
+
end
|
354
|
+
end
|
355
|
+
response[:cmd_bytes] ||= :na
|
356
|
+
|
346
357
|
raw_byte_arr = []
|
347
|
-
|
348
|
-
|
358
|
+
raw_byte_arr_len = 0
|
359
|
+
last_raw_byte_arr_len = 0
|
349
360
|
|
350
361
|
parsed_cmd_resp_arr = []
|
351
|
-
bytes_in_cmd_resp = 0
|
352
362
|
cmd_resp = ''
|
353
363
|
|
354
364
|
while keep_parsing_responses
|
355
365
|
until next_response_detected
|
366
|
+
last_raw_byte_arr_len = raw_byte_arr_len
|
356
367
|
raw_byte_arr = PWN::Plugins::Serial.response(serial_obj: msr206_obj)
|
357
368
|
cmd_resp = raw_byte_arr.last
|
358
|
-
|
359
|
-
a_cmd_r_len = raw_byte_arr.length
|
369
|
+
raw_byte_arr_len = raw_byte_arr.length
|
360
370
|
|
361
|
-
next_response_detected = true if
|
371
|
+
next_response_detected = true if raw_byte_arr_len > last_raw_byte_arr_len
|
362
372
|
end
|
363
373
|
|
364
374
|
case cmd_resp
|
@@ -393,15 +403,15 @@ module PWN
|
|
393
403
|
when '7E'
|
394
404
|
response[:msg] = :command_not_supported_by_hardware
|
395
405
|
else
|
396
|
-
response[:msg] = :
|
406
|
+
response[:msg] = :response
|
397
407
|
end
|
398
408
|
|
399
409
|
next_response_detected = false
|
400
|
-
|
410
|
+
last_raw_byte_arr_len = raw_byte_arr_len
|
401
411
|
keep_parsing_responses = false
|
402
412
|
end
|
403
413
|
|
404
|
-
response[:
|
414
|
+
response[:hex] = raw_byte_arr
|
405
415
|
response[:binary] = binary(raw_byte_arr: raw_byte_arr)
|
406
416
|
response[:decoded] = decode(raw_byte_arr: raw_byte_arr)
|
407
417
|
response
|
@@ -421,10 +431,15 @@ module PWN
|
|
421
431
|
public_class_method def self.exec(opts = {})
|
422
432
|
msr206_obj = opts[:msr206_obj]
|
423
433
|
cmd = opts[:cmd].to_s.scrub.strip.chomp
|
424
|
-
params = opts[:params]
|
434
|
+
params = opts[:params]
|
435
|
+
raise 'ERROR: params argument must be a byte array (e.g. [0x41]).' if params && !params.instance_of?(Array)
|
425
436
|
|
426
437
|
params_bytes = []
|
427
438
|
case cmd.to_sym
|
439
|
+
when :proto_usi0
|
440
|
+
cmd_bytes = [0x55, 0x53, 0x49, 0x30]
|
441
|
+
when :proto_usi1
|
442
|
+
cmd_bytes = [0x55, 0x53, 0x49, 0x31]
|
428
443
|
when :resume_transmission_to_host
|
429
444
|
cmd_bytes = [0x11]
|
430
445
|
when :pause_transmission_to_host
|
@@ -459,11 +474,11 @@ module PWN
|
|
459
474
|
cmd_bytes = [0x42]
|
460
475
|
when :load_iso_std_data_for_writing_track3
|
461
476
|
cmd_bytes = [0x43]
|
462
|
-
when :
|
477
|
+
when :load_custom_data_for_writing_track1
|
463
478
|
cmd_bytes = [0x45]
|
464
|
-
when :
|
479
|
+
when :load_custom_data_for_writing_track2
|
465
480
|
cmd_bytes = [0x46]
|
466
|
-
when :
|
481
|
+
when :load_custom_data_for_writing_track3
|
467
482
|
cmd_bytes = [0x47]
|
468
483
|
when :tx_error_data
|
469
484
|
cmd_bytes = [0x49]
|
@@ -485,6 +500,12 @@ module PWN
|
|
485
500
|
cmd_bytes = [0x52]
|
486
501
|
when :tx_iso_std_data_track3
|
487
502
|
cmd_bytes = [0x53]
|
503
|
+
when :tx_custom_data_forward_track1
|
504
|
+
cmd_bytes = [0x55]
|
505
|
+
when :tx_custom_data_forward_track2
|
506
|
+
cmd_bytes = [0x56]
|
507
|
+
when :tx_custom_data_forward_track3
|
508
|
+
cmd_bytes = [0x57]
|
488
509
|
when :tx_passbook_data
|
489
510
|
cmd_bytes = [0x58]
|
490
511
|
when :arm_to_write_no_raw
|
@@ -532,7 +553,7 @@ module PWN
|
|
532
553
|
end
|
533
554
|
|
534
555
|
# If parameters to a command are set, append them.
|
535
|
-
cmd_bytes +=
|
556
|
+
cmd_bytes += params if params
|
536
557
|
# Execute the command.
|
537
558
|
PWN::Plugins::Serial.request(
|
538
559
|
serial_obj: msr206_obj,
|
@@ -543,7 +564,8 @@ module PWN
|
|
543
564
|
# Return an array of hashes.
|
544
565
|
parse_responses(
|
545
566
|
msr206_obj: msr206_obj,
|
546
|
-
cmd: cmd.to_sym
|
567
|
+
cmd: cmd.to_sym,
|
568
|
+
cmd_bytes: cmd_bytes
|
547
569
|
)
|
548
570
|
rescue StandardError => e
|
549
571
|
raise e
|
@@ -553,25 +575,18 @@ module PWN
|
|
553
575
|
end
|
554
576
|
|
555
577
|
# Supported Method Parameters::
|
556
|
-
#
|
578
|
+
# MSR206.wait_for_swipe(
|
557
579
|
# msr206_obj: 'required - msr206_obj returned from #connect method'
|
558
|
-
# type: 'required - swipe type'
|
580
|
+
# type: 'required - swipe type :arm_to_read || :arm_to_read_w_speed_prompts || :arm_to_write_no_raw || :arm_to_write_with_raw || :arm_to_write_with_raw_speed_prompts',
|
581
|
+
# encoding: 'required - :iso || :iso_alt || :raw',
|
582
|
+
# track_data: 'optional - track_data to write'
|
559
583
|
# )
|
560
584
|
|
561
|
-
|
585
|
+
private_class_method def self.wait_for_swipe(opts = {})
|
562
586
|
msr206_obj = opts[:msr206_obj]
|
563
587
|
type = opts[:type].to_s.scrub.strip.chomp.to_sym
|
564
|
-
|
565
|
-
|
566
|
-
arm_to_read_w_speed_prompts
|
567
|
-
arm_to_write_no_raw
|
568
|
-
arm_to_write_with_raw
|
569
|
-
arm_to_write_with_raw_speed_prompts
|
570
|
-
]
|
571
|
-
|
572
|
-
raise "ERROR Unsupported type in #wait_for_swipe - #{type}. Valid types:\n#{types_arr}" unless types_arr.include?(type)
|
573
|
-
|
574
|
-
track_data = {}
|
588
|
+
encoding = opts[:encoding].to_s.scrub.strip.chomp.to_sym
|
589
|
+
track_data = opts[:track_data]
|
575
590
|
|
576
591
|
exec_resp = exec(
|
577
592
|
msr206_obj: msr206_obj,
|
@@ -583,96 +598,477 @@ module PWN
|
|
583
598
|
cmd: :yellow_off
|
584
599
|
)
|
585
600
|
|
586
|
-
exec_resp =
|
601
|
+
exec_resp = exec(
|
587
602
|
msr206_obj: msr206_obj,
|
588
|
-
cmd:
|
603
|
+
cmd: :green_on
|
589
604
|
)
|
590
605
|
|
606
|
+
track_data_arr = []
|
607
|
+
|
608
|
+
case type
|
609
|
+
when :arm_to_read,
|
610
|
+
:arm_to_read_w_speed_prompts
|
611
|
+
|
612
|
+
exec_resp = PWN::Plugins::MSR206.exec(
|
613
|
+
msr206_obj: msr206_obj,
|
614
|
+
cmd: type
|
615
|
+
)
|
616
|
+
|
617
|
+
print 'Ready to Read. Please Swipe Card Now:'
|
618
|
+
loop do
|
619
|
+
exec_resp = parse_responses(
|
620
|
+
msr206_obj: msr206_obj,
|
621
|
+
cmd: type
|
622
|
+
)
|
623
|
+
|
624
|
+
break if exec_resp[:msg] == :ack_command_completed
|
625
|
+
end
|
626
|
+
|
627
|
+
if encoding == :iso
|
628
|
+
cmds_arr = %i[
|
629
|
+
tx_iso_std_data_track1
|
630
|
+
tx_iso_std_data_track2
|
631
|
+
tx_iso_std_data_track3
|
632
|
+
]
|
633
|
+
cmds_arr.each do |cmd|
|
634
|
+
puts "\n*** #{cmd.to_s.gsub('_', ' ').upcase} #{'*' * 17}"
|
635
|
+
exec_resp = exec(
|
636
|
+
msr206_obj: msr206_obj,
|
637
|
+
cmd: cmd
|
638
|
+
)
|
639
|
+
exec_resp[:encoding] = encoding
|
640
|
+
puts exec_resp[:decoded]
|
641
|
+
puts exec_resp.inspect
|
642
|
+
track_data_arr.push(exec_resp)
|
643
|
+
end
|
644
|
+
end
|
645
|
+
|
646
|
+
if encoding == :iso_alt
|
647
|
+
cmds_arr = %i[
|
648
|
+
alt_tx_iso_std_data_track1
|
649
|
+
alt_tx_iso_std_data_track2
|
650
|
+
alt_tx_iso_std_data_track3
|
651
|
+
]
|
652
|
+
|
653
|
+
cmds_arr.each do |cmd|
|
654
|
+
params_arr = [0x31, 0x32, 0x33]
|
655
|
+
params_arr.each do |param|
|
656
|
+
puts "\n*** #{cmd.to_s.gsub('_', ' ').upcase} #{'*' * 17}"
|
657
|
+
exec_resp = exec(
|
658
|
+
msr206_obj: msr206_obj,
|
659
|
+
cmd: cmd,
|
660
|
+
params: [param]
|
661
|
+
)
|
662
|
+
exec_resp[:encoding] = encoding
|
663
|
+
puts exec_resp[:decoded]
|
664
|
+
puts exec_resp.inspect
|
665
|
+
track_data_arr.push(exec_resp)
|
666
|
+
end
|
667
|
+
end
|
668
|
+
end
|
669
|
+
|
670
|
+
if encoding == :raw
|
671
|
+
cmds_arr = %i[
|
672
|
+
tx_custom_data_forward_track1
|
673
|
+
tx_custom_data_forward_track2
|
674
|
+
tx_custom_data_forward_track3
|
675
|
+
]
|
676
|
+
|
677
|
+
cmds_arr.each do |cmd|
|
678
|
+
params_arr = [0x33, 0x34, 0x35, 0x36, 0x37]
|
679
|
+
params_arr.each do |param|
|
680
|
+
puts "\n*** #{cmd.to_s.gsub('_', ' ').upcase} #{'*' * 17}"
|
681
|
+
# 2 byte command
|
682
|
+
exec_resp = exec(
|
683
|
+
msr206_obj: msr206_obj,
|
684
|
+
cmd: cmd,
|
685
|
+
params: [param]
|
686
|
+
)
|
687
|
+
exec_resp[:encoding] = encoding
|
688
|
+
puts exec_resp[:decoded]
|
689
|
+
puts exec_resp.inspect
|
690
|
+
track_data_arr.push(exec_resp)
|
691
|
+
|
692
|
+
# 3 byte command
|
693
|
+
exec_resp = exec(
|
694
|
+
msr206_obj: msr206_obj,
|
695
|
+
cmd: cmd,
|
696
|
+
params: [0x5f] + [param]
|
697
|
+
)
|
698
|
+
exec_resp[:encoding] = encoding
|
699
|
+
puts exec_resp[:decoded]
|
700
|
+
puts exec_resp.inspect
|
701
|
+
track_data_arr.push(exec_resp)
|
702
|
+
end
|
703
|
+
end
|
704
|
+
end
|
705
|
+
when :arm_to_write_no_raw,
|
706
|
+
:arm_to_write_with_raw,
|
707
|
+
:arm_to_write_with_raw_speed_prompts
|
708
|
+
|
709
|
+
if encoding == :iso
|
710
|
+
cmds_arr = %i[
|
711
|
+
load_iso_std_data_for_writing_track1
|
712
|
+
load_iso_std_data_for_writing_track2
|
713
|
+
load_iso_std_data_for_writing_track3
|
714
|
+
]
|
715
|
+
|
716
|
+
cmds_arr.each_with_index do |cmd, track|
|
717
|
+
puts "\n*** #{cmd.to_s.gsub('_', ' ').upcase} #{'*' * 17}"
|
718
|
+
this_track = track_data[track][:decoded].chars.map do |c|
|
719
|
+
c.unpack1('H*').to_i(16)
|
720
|
+
end
|
721
|
+
this_track_w_eot = this_track + [0x04]
|
722
|
+
puts this_track_w_eot.inspect
|
723
|
+
exec_resp = exec(
|
724
|
+
msr206_obj: msr206_obj,
|
725
|
+
cmd: cmd,
|
726
|
+
params: this_track_w_eot
|
727
|
+
)
|
728
|
+
exec_resp[:encoding] = encoding
|
729
|
+
puts exec_resp[:decoded]
|
730
|
+
puts exec_resp.inspect
|
731
|
+
track_data_arr.push(exec_resp)
|
732
|
+
end
|
733
|
+
end
|
734
|
+
|
735
|
+
# if encoding == :iso_alt
|
736
|
+
# cmds_arr = %i[
|
737
|
+
# alt_load_iso_std_data_for_writing_track1
|
738
|
+
# alt_load_iso_std_data_for_writing_track2
|
739
|
+
# alt_load_iso_std_data_for_writing_track3
|
740
|
+
# ]
|
741
|
+
|
742
|
+
# cmds_arr.each do |cmd|
|
743
|
+
# puts "\n*** #{cmd.to_s.gsub('_', ' ').upcase} #{'*' * 17}"
|
744
|
+
# exec_resp = exec(
|
745
|
+
# msr206_obj: msr206_obj,
|
746
|
+
# cmd: cmd
|
747
|
+
# )
|
748
|
+
# exec_resp[:encoding] = encoding
|
749
|
+
# puts exec_resp[:decoded]
|
750
|
+
# puts exec_resp.inspect
|
751
|
+
# track_data_arr.push(exec_resp)
|
752
|
+
# end
|
753
|
+
# end
|
754
|
+
|
755
|
+
# if encoding == :raw
|
756
|
+
# cmds_arr = %i[
|
757
|
+
# load_custom_data_for_writing_track1
|
758
|
+
# load_custom_data_for_writing_track2
|
759
|
+
# load_custom_data_for_writing_track3
|
760
|
+
# ]
|
761
|
+
|
762
|
+
# cmds_arr.each do |cmd|
|
763
|
+
# puts "\n*** #{cmd.to_s.gsub('_', ' ').upcase} #{'*' * 17}"
|
764
|
+
# exec_resp = exec(
|
765
|
+
# msr206_obj: msr206_obj,
|
766
|
+
# cmd: cmd
|
767
|
+
# )
|
768
|
+
# exec_resp[:encoding] = encoding
|
769
|
+
# puts exec_resp[:decoded]
|
770
|
+
# puts exec_resp.inspect
|
771
|
+
# track_data_arr.push(exec_resp)
|
772
|
+
# end
|
773
|
+
# end
|
774
|
+
|
775
|
+
exec_resp = PWN::Plugins::MSR206.exec(
|
776
|
+
msr206_obj: msr206_obj,
|
777
|
+
cmd: type
|
778
|
+
)
|
779
|
+
|
780
|
+
print 'Ready to Write. Please Swipe Card Now:'
|
781
|
+
loop do
|
782
|
+
exec_resp = parse_responses(
|
783
|
+
msr206_obj: msr206_obj,
|
784
|
+
cmd: type
|
785
|
+
)
|
786
|
+
|
787
|
+
break if exec_resp[:msg] == :ack_command_completed
|
788
|
+
end
|
789
|
+
else
|
790
|
+
raise "ERROR Unsupported type in #wait_for_swipe - #{type}"
|
791
|
+
end
|
792
|
+
|
793
|
+
track_data_arr
|
794
|
+
rescue StandardError => e
|
795
|
+
raise e
|
796
|
+
ensure
|
591
797
|
exec_resp = exec(
|
592
798
|
msr206_obj: msr206_obj,
|
593
|
-
cmd: :
|
799
|
+
cmd: :green_off
|
594
800
|
)
|
801
|
+
end
|
595
802
|
|
596
|
-
|
803
|
+
# Supported Method Parameters::
|
804
|
+
# PWN::Plugins::MSR206.read_card(
|
805
|
+
# msr206_obj: 'required - msr206_obj returned from #connect method'
|
806
|
+
# )
|
807
|
+
|
808
|
+
public_class_method def self.read_card(opts = {})
|
809
|
+
msr206_obj = opts[:msr206_obj]
|
810
|
+
type = opts[:type].to_s.scrub.strip.chomp.to_sym
|
811
|
+
|
812
|
+
encoding = :waiting_for_selection
|
813
|
+
loop do
|
814
|
+
puts "\nENCODING OPTIONS:"
|
815
|
+
puts '[(I)SO Standard]'
|
816
|
+
puts '[(A)LT ISO Standard]'
|
817
|
+
puts '[(R)aw]'
|
818
|
+
print 'ENCODING TYPE >>> '
|
819
|
+
encoding_choice = gets.scrub.chomp.strip.upcase.to_sym
|
820
|
+
|
821
|
+
case encoding_choice
|
822
|
+
when :I
|
823
|
+
encoding = :iso
|
824
|
+
break
|
825
|
+
when :A
|
826
|
+
encoding = :iso_alt
|
827
|
+
break
|
828
|
+
when :R
|
829
|
+
encoding = :raw
|
830
|
+
break
|
831
|
+
end
|
832
|
+
end
|
833
|
+
|
834
|
+
wait_for_swipe(
|
597
835
|
msr206_obj: msr206_obj,
|
598
|
-
|
836
|
+
type: :arm_to_read,
|
837
|
+
encoding: encoding
|
838
|
+
)
|
839
|
+
rescue StandardError => e
|
840
|
+
raise e
|
841
|
+
end
|
842
|
+
|
843
|
+
# Supported Method Parameters::
|
844
|
+
# PWN::Plugins::MSR206.backup_card(
|
845
|
+
# msr206_obj: 'required - msr206_obj returned from #connect method'
|
846
|
+
# )
|
847
|
+
|
848
|
+
public_class_method def self.backup_card(opts = {})
|
849
|
+
msr206_obj = opts[:msr206_obj]
|
850
|
+
type = opts[:type].to_s.scrub.strip.chomp.to_sym
|
851
|
+
|
852
|
+
# Read Card to Backup
|
853
|
+
track_data = read_card(
|
854
|
+
msr206_obj: msr206_obj
|
599
855
|
)
|
600
856
|
|
601
|
-
|
857
|
+
file = ''
|
858
|
+
backup_msg = ''
|
602
859
|
loop do
|
603
|
-
|
860
|
+
if backup_msg.empty?
|
861
|
+
exec_resp = exec(
|
862
|
+
msr206_obj: msr206_obj,
|
863
|
+
cmd: :green_flash
|
864
|
+
)
|
865
|
+
end
|
866
|
+
|
867
|
+
print 'Enter File Name to Save Backup: '
|
868
|
+
file = gets.scrub.chomp.strip
|
869
|
+
file_dir = File.dirname(file)
|
870
|
+
break if Dir.exist?(file_dir)
|
871
|
+
|
872
|
+
backup_msg = "\n****** ERROR: Directory #{file_dir} for #{file} does not exist ******"
|
873
|
+
puts backup_msg
|
874
|
+
exec_resp = exec(
|
604
875
|
msr206_obj: msr206_obj,
|
605
|
-
cmd: :
|
876
|
+
cmd: :green_off
|
877
|
+
)
|
878
|
+
exec_resp = exec(
|
879
|
+
msr206_obj: msr206_obj,
|
880
|
+
cmd: :yellow_flash
|
606
881
|
)
|
607
|
-
|
608
|
-
break if exec_resp[:msg] == :ack_command_completed
|
609
882
|
end
|
610
883
|
|
611
|
-
|
612
|
-
print 'TRACK 1 >>> '
|
884
|
+
File.write(file, "#{JSON.pretty_generate(track_data)}\n")
|
613
885
|
exec_resp = exec(
|
614
886
|
msr206_obj: msr206_obj,
|
615
|
-
cmd: :
|
887
|
+
cmd: :yellow_off
|
616
888
|
)
|
617
|
-
|
618
|
-
puts
|
619
|
-
|
620
|
-
|
621
|
-
|
622
|
-
|
623
|
-
|
624
|
-
|
625
|
-
|
626
|
-
|
627
|
-
|
628
|
-
|
629
|
-
|
630
|
-
|
631
|
-
|
632
|
-
|
889
|
+
|
890
|
+
puts 'complete.'
|
891
|
+
|
892
|
+
track_data
|
893
|
+
rescue StandardError => e
|
894
|
+
raise e
|
895
|
+
end
|
896
|
+
|
897
|
+
# Supported Method Parameters::
|
898
|
+
# PWN::Plugins::MSR206.copy_card(
|
899
|
+
# msr206_obj: 'required - msr206_obj returned from #connect method'
|
900
|
+
# )
|
901
|
+
|
902
|
+
public_class_method def self.copy_card(opts = {})
|
903
|
+
msr206_obj = opts[:msr206_obj]
|
904
|
+
|
905
|
+
# Read Card to Backup
|
906
|
+
track_data = backup_card(
|
907
|
+
msr206_obj: msr206_obj
|
908
|
+
)
|
909
|
+
|
910
|
+
encoding = track_data.first[:encoding] if track_data.length == 3
|
911
|
+
# TODO: Save Original Card Contents
|
912
|
+
track_data = wait_for_swipe(
|
633
913
|
msr206_obj: msr206_obj,
|
634
|
-
|
914
|
+
type: :arm_to_write_no_raw,
|
915
|
+
encoding: encoding,
|
916
|
+
track_data: track_data
|
635
917
|
)
|
636
|
-
|
637
|
-
puts
|
638
|
-
|
639
|
-
|
640
|
-
|
641
|
-
|
642
|
-
|
643
|
-
|
644
|
-
|
645
|
-
|
646
|
-
|
647
|
-
|
648
|
-
|
649
|
-
|
650
|
-
|
918
|
+
|
919
|
+
puts 'complete.'
|
920
|
+
|
921
|
+
track_data
|
922
|
+
rescue StandardError => e
|
923
|
+
raise e
|
924
|
+
end
|
925
|
+
|
926
|
+
# Supported Method Parameters::
|
927
|
+
# PWN::Plugins::MSR206.load_card_from_file(
|
928
|
+
# msr206_obj: 'required - msr206_obj returned from #connect method'
|
929
|
+
# )
|
930
|
+
|
931
|
+
public_class_method def self.load_card_from_file(opts = {})
|
932
|
+
msr206_obj = opts[:msr206_obj]
|
933
|
+
|
934
|
+
file = ''
|
935
|
+
restore_msg = ''
|
936
|
+
loop do
|
937
|
+
if restore_msg.empty?
|
938
|
+
exec_resp = exec(
|
939
|
+
msr206_obj: msr206_obj,
|
940
|
+
cmd: :green_flash
|
941
|
+
)
|
942
|
+
end
|
943
|
+
|
944
|
+
print 'Enter File Name to Restore to Card: '
|
945
|
+
file = gets.scrub.chomp.strip
|
946
|
+
break if File.exist?(file)
|
947
|
+
|
948
|
+
restore_msg = "\n****** ERROR: #{file} does not exist ******"
|
949
|
+
puts restore_msg
|
950
|
+
exec_resp = exec(
|
951
|
+
msr206_obj: msr206_obj,
|
952
|
+
cmd: :green_off
|
953
|
+
)
|
954
|
+
exec_resp = exec(
|
955
|
+
msr206_obj: msr206_obj,
|
956
|
+
cmd: :yellow_flash
|
957
|
+
)
|
958
|
+
end
|
959
|
+
|
960
|
+
track_data = JSON.parse(
|
961
|
+
File.read(file),
|
962
|
+
symbolize_names: true
|
963
|
+
)
|
964
|
+
|
651
965
|
exec_resp = exec(
|
652
966
|
msr206_obj: msr206_obj,
|
653
|
-
cmd: :
|
967
|
+
cmd: :yellow_off
|
968
|
+
)
|
969
|
+
|
970
|
+
# Read Card from Backup
|
971
|
+
encoding = track_data.first[:encoding] if track_data.length == 3
|
972
|
+
|
973
|
+
# TODO: Save Original Card Contents
|
974
|
+
track_data = wait_for_swipe(
|
975
|
+
msr206_obj: msr206_obj,
|
976
|
+
type: :arm_to_write_no_raw,
|
977
|
+
encoding: encoding,
|
978
|
+
track_data: track_data
|
654
979
|
)
|
655
|
-
|
656
|
-
puts
|
657
|
-
|
658
|
-
|
659
|
-
# (1..3).each do |n|
|
660
|
-
# print ">> Track 3 (ALT DATA) ISO Track Format: #{n}\n"
|
661
|
-
# exec_resp = exec(
|
662
|
-
# msr206_obj: msr206_obj,
|
663
|
-
# cmd: :alt_tx_iso_std_data_track3,
|
664
|
-
# params: [n.to_s]
|
665
|
-
# )
|
666
|
-
# puts exec_resp.inspect
|
667
|
-
# end
|
980
|
+
|
981
|
+
puts 'complete.'
|
982
|
+
|
668
983
|
track_data
|
669
984
|
rescue StandardError => e
|
670
985
|
raise e
|
671
|
-
|
672
|
-
|
986
|
+
end
|
987
|
+
|
988
|
+
# Supported Method Parameters::
|
989
|
+
# PWN::Plugins::MSR206.edit_card(
|
990
|
+
# msr206_obj: 'required - msr206_obj returned from #connect method'
|
991
|
+
# )
|
992
|
+
|
993
|
+
public_class_method def self.edit_card(opts = {})
|
994
|
+
msr206_obj = opts[:msr206_obj]
|
995
|
+
|
996
|
+
# Read Card to Backup
|
997
|
+
track_data = backup_card(
|
998
|
+
msr206_obj: msr206_obj
|
999
|
+
)
|
1000
|
+
|
1001
|
+
# TODO: Inline Editing
|
1002
|
+
|
1003
|
+
encoding = track_data.first[:encoding] if track_data.length == 3
|
1004
|
+
# TODO: Save Original Card Contents
|
1005
|
+
track_data = wait_for_swipe(
|
673
1006
|
msr206_obj: msr206_obj,
|
674
|
-
|
1007
|
+
type: :arm_to_write_no_raw,
|
1008
|
+
encoding: encoding
|
1009
|
+
)
|
1010
|
+
|
1011
|
+
puts 'complete.'
|
1012
|
+
|
1013
|
+
track_data
|
1014
|
+
rescue StandardError => e
|
1015
|
+
raise e
|
1016
|
+
end
|
1017
|
+
|
1018
|
+
# Supported Method Parameters::
|
1019
|
+
# PWN::Plugins::MSR206.get_config(
|
1020
|
+
# msr206_obj: 'required - msr206_obj returned from #connect method'
|
1021
|
+
# )
|
1022
|
+
|
1023
|
+
public_class_method def self.get_config(opts = {})
|
1024
|
+
msr206_obj = opts[:msr206_obj]
|
1025
|
+
|
1026
|
+
# --------------------------------------------------
|
1027
|
+
# Bit|Bit = 0 |Bit = 1
|
1028
|
+
# --------------------------------------------------
|
1029
|
+
# 0 |Track 1 Read not present |Track 1 Read present
|
1030
|
+
# 1 |Track 2 Read not present |Track 2 Read present
|
1031
|
+
# 2 |Track 3 Read not present |Track 3 Read present
|
1032
|
+
# 3 |not used – should be 0 |not used
|
1033
|
+
# 4 |Track 3 Write not present|Track 3 Write present
|
1034
|
+
# 5 |Track 2 Write not present|Track 2 Write present
|
1035
|
+
# 6 |Track 1 Write not present|Track 1 Write present
|
1036
|
+
# 7 |parity bit** |parity bit**
|
1037
|
+
exec_resp = PWN::Plugins::MSR206.exec(
|
1038
|
+
msr206_obj: msr206_obj,
|
1039
|
+
cmd: :configuration_request
|
675
1040
|
)
|
1041
|
+
|
1042
|
+
config_arr = exec_resp[:binary].first.reverse.chars
|
1043
|
+
config_hash = {}
|
1044
|
+
config_arr.each_with_index do |bit_str, i|
|
1045
|
+
bit = bit_str.to_i
|
1046
|
+
config_hash[:track1_read] = false if bit.zero? && i.zero?
|
1047
|
+
config_hash[:track1_read] = true if bit == 1 && i.zero?
|
1048
|
+
|
1049
|
+
config_hash[:track2_read] = false if bit.zero? && i == 1
|
1050
|
+
config_hash[:track2_read] = true if bit == 1 && i == 1
|
1051
|
+
|
1052
|
+
config_hash[:track3_read] = false if bit.zero? && i == 2
|
1053
|
+
config_hash[:track3_read] = true if bit == 1 && i == 2
|
1054
|
+
|
1055
|
+
config_hash[:not_used] if i == 3
|
1056
|
+
|
1057
|
+
config_hash[:track1_write] = false if bit.zero? && i == 4
|
1058
|
+
config_hash[:track1_write] = true if bit == 1 && i == 4
|
1059
|
+
|
1060
|
+
config_hash[:track2_write] = false if bit.zero? && i == 5
|
1061
|
+
config_hash[:track2_write] = true if bit == 1 && i == 5
|
1062
|
+
|
1063
|
+
config_hash[:track3_write] = false if bit.zero? && i == 6
|
1064
|
+
config_hash[:track3_write] = true if bit == 1 && i == 6
|
1065
|
+
|
1066
|
+
config_hash[:parity] = true if bit == 1 && i == 7
|
1067
|
+
end
|
1068
|
+
|
1069
|
+
config_hash
|
1070
|
+
rescue StandardError => e
|
1071
|
+
raise e
|
676
1072
|
end
|
677
1073
|
|
678
1074
|
# Supported Method Parameters::
|
@@ -706,7 +1102,7 @@ module PWN
|
|
706
1102
|
data_bits: 'optional (defaults to 8)',
|
707
1103
|
stop_bits: 'optional (defaults to 1)',
|
708
1104
|
parity: 'optional - :even|:mark|:odd|:space|:none (defaults to :none),'
|
709
|
-
flow_control: 'optional - :none
|
1105
|
+
flow_control: 'optional - :none|:hard|:soft (defaults to :none)'
|
710
1106
|
)
|
711
1107
|
|
712
1108
|
cmds = #{self}.list_cmds
|
data/lib/pwn/plugins/serial.rb
CHANGED
@@ -44,7 +44,7 @@ module PWN
|
|
44
44
|
opts[:stop_bits].to_i
|
45
45
|
end
|
46
46
|
|
47
|
-
case opts[:parity]
|
47
|
+
case opts[:parity].to_s.to_sym
|
48
48
|
when :even
|
49
49
|
parity = SerialPort::EVEN
|
50
50
|
when :mark
|
@@ -57,7 +57,7 @@ module PWN
|
|
57
57
|
parity = SerialPort::NONE
|
58
58
|
end
|
59
59
|
|
60
|
-
case opts[:flow_control]
|
60
|
+
case opts[:flow_control].to_s.to_sym
|
61
61
|
when :hard
|
62
62
|
flow_control = SerialPort::HARD
|
63
63
|
when :soft
|
data/lib/pwn/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pwn
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.4.
|
4
|
+
version: 0.4.479
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- 0day Inc.
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-06-
|
11
|
+
date: 2022-06-07 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -310,14 +310,14 @@ dependencies:
|
|
310
310
|
requirements:
|
311
311
|
- - '='
|
312
312
|
- !ruby/object:Gem::Version
|
313
|
-
version: 2.
|
313
|
+
version: 2.4.0
|
314
314
|
type: :runtime
|
315
315
|
prerelease: false
|
316
316
|
version_requirements: !ruby/object:Gem::Requirement
|
317
317
|
requirements:
|
318
318
|
- - '='
|
319
319
|
- !ruby/object:Gem::Version
|
320
|
-
version: 2.
|
320
|
+
version: 2.4.0
|
321
321
|
- !ruby/object:Gem::Dependency
|
322
322
|
name: luhn
|
323
323
|
requirement: !ruby/object:Gem::Requirement
|
@@ -380,14 +380,14 @@ dependencies:
|
|
380
380
|
requirements:
|
381
381
|
- - '='
|
382
382
|
- !ruby/object:Gem::Version
|
383
|
-
version: 0.17.
|
383
|
+
version: 0.17.1
|
384
384
|
type: :runtime
|
385
385
|
prerelease: false
|
386
386
|
version_requirements: !ruby/object:Gem::Requirement
|
387
387
|
requirements:
|
388
388
|
- - '='
|
389
389
|
- !ruby/object:Gem::Version
|
390
|
-
version: 0.17.
|
390
|
+
version: 0.17.1
|
391
391
|
- !ruby/object:Gem::Dependency
|
392
392
|
name: net-openvpn
|
393
393
|
requirement: !ruby/object:Gem::Requirement
|
@@ -674,14 +674,14 @@ dependencies:
|
|
674
674
|
requirements:
|
675
675
|
- - '='
|
676
676
|
- !ruby/object:Gem::Version
|
677
|
-
version: 1.30.
|
677
|
+
version: 1.30.1
|
678
678
|
type: :runtime
|
679
679
|
prerelease: false
|
680
680
|
version_requirements: !ruby/object:Gem::Requirement
|
681
681
|
requirements:
|
682
682
|
- - '='
|
683
683
|
- !ruby/object:Gem::Version
|
684
|
-
version: 1.30.
|
684
|
+
version: 1.30.1
|
685
685
|
- !ruby/object:Gem::Dependency
|
686
686
|
name: rubocop-rake
|
687
687
|
requirement: !ruby/object:Gem::Requirement
|
@@ -828,14 +828,14 @@ dependencies:
|
|
828
828
|
requirements:
|
829
829
|
- - '='
|
830
830
|
- !ruby/object:Gem::Version
|
831
|
-
version: 1.
|
831
|
+
version: 1.1.0
|
832
832
|
type: :runtime
|
833
833
|
prerelease: false
|
834
834
|
version_requirements: !ruby/object:Gem::Requirement
|
835
835
|
requirements:
|
836
836
|
- - '='
|
837
837
|
- !ruby/object:Gem::Version
|
838
|
-
version: 1.
|
838
|
+
version: 1.1.0
|
839
839
|
- !ruby/object:Gem::Dependency
|
840
840
|
name: socksify
|
841
841
|
requirement: !ruby/object:Gem::Requirement
|