pwn 0.4.476 → 0.4.479

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8ef8af0c110613df805e43c7194ba3c2583c7e18b1d6c0a214f693a3d8b5d8f8
4
- data.tar.gz: 646b090115b4f9180d26f14222d1fea8ad57b31b083e38ae71ffeaa44aa62273
3
+ metadata.gz: 5ca99e7a8fee7afaa96d59d48264cf78faaf50b54d9d355b2efa1064f50bc618
4
+ data.tar.gz: 416841cc29f3d57207d6b61b783636af8d9b93e29af36b901132492b70066405
5
5
  SHA512:
6
- metadata.gz: cab4b7f4c5a4e4c1b03a4f2d79ab502a9a4472589631485b3022ef59396d75b143f4c58b9e82a78f508f00cabe4108f218edc95483f67ae992f31f3965d5d4e5
7
- data.tar.gz: 2fc157515f103b9869314c6fead5d88c5de7464e472ef2555e29d97f38558f0c2962ec4ac7166e7d8654e2be75bdbf85e08ee3d09f18e4c186c6c96959b8c51a
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.3.0'
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.0'
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.0'
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.0.0'
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.476]:001 >>> PWN.help
40
+ pwn[v0.4.479]:001 >>> PWN.help
41
41
  ```
42
42
 
43
43
  [![Installing the pwn Security Automation Framework](https://raw.githubusercontent.com/0dayInc/pwn/master/documentation/pwn_install.png)](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.476]:001 >>> PWN.help
55
+ pwn[v0.4.479]:001 >>> PWN.help
56
56
  ```
57
57
 
58
58
 
@@ -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.to_json
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.to_json
193
+ f.puts JSON.pretty_generate(ipinfo_struc)
194
194
  end
195
195
  end
196
196
  end
@@ -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 9600)>') do |b|
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 none)>') do |f|
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
- # TODO: Parse Binary Bits to Derive Readable Configuration
72
- # e.g. 'Read & Write All Three Tracks' if binary_resp == '11101111'
73
- # Probably better to split each bit and then evaluate
74
- # binary_resp_arr = binary_resp.chars
75
- # --------------------------------------------------
76
- # Bit|Bit = 0 |Bit = 1
77
- # --------------------------------------------------
78
- # 0 |Track 1 Read not present |Track 1 Read present
79
- # 1 |Track 2 Read not present |Track 2 Read present
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 Bits: #{exec_resp[:binary].first}"
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 = 'READY TO READ - PLEASE SWIPE CARD'
114
+ menu_msg = 'READ CARD'
123
115
  # Read Card
124
- track_data = PWN::Plugins::MSR206.wait_for_swipe(
125
- msr206_obj: msr206_obj,
126
- type: :arm_to_read
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 = 'READY TO COPY - PLEASE SWIPE ORIGINAL CARD'
130
- # Read Original Card
131
- track_data = PWN::Plugins::MSR206.wait_for_swipe(
132
- msr206_obj: msr206_obj,
133
- type: :arm_to_read
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 = 'READY TO EDIT - PLEASE SWIPE TARGET CARD'
138
+ menu_msg = 'EDIT'
141
139
  # Read Target Card
142
- track_data = PWN::Plugins::MSR206.wait_for_swipe(
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
@@ -73,7 +73,7 @@ begin
73
73
  end
74
74
  end
75
75
  end
76
- File.write(raw_query_results_file, raw_results_arr.to_json)
76
+ File.write(raw_query_results_file, JSON.pretty_generate(raw_results_arr))
77
77
  rescue SystemExit, Interrupt
78
78
  puts "\nGoodbye."
79
79
  end
@@ -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||:hard||:soft (defaults to :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] = :none unless 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*').reverse)
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
- a_cmd_r_len = 0
348
- last_a_cmd_r_len = 0
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
- bytes_in_cmd_resp = cmd_resp.split.length if cmd_resp
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 a_cmd_r_len > last_a_cmd_r_len
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] = :na
406
+ response[:msg] = :response
397
407
  end
398
408
 
399
409
  next_response_detected = false
400
- last_a_cmd_r_len = a_cmd_r_len
410
+ last_raw_byte_arr_len = raw_byte_arr_len
401
411
  keep_parsing_responses = false
402
412
  end
403
413
 
404
- response[:raw] = raw_byte_arr
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].to_s.scrub.strip.chomp
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 :tx_custom_data_forward_track1, :load_custom_data_for_writing_track1
477
+ when :load_custom_data_for_writing_track1
463
478
  cmd_bytes = [0x45]
464
- when :tx_custom_data_forward_track2, :load_custom_data_for_writing_track2
479
+ when :load_custom_data_for_writing_track2
465
480
  cmd_bytes = [0x46]
466
- when :tx_custom_data_forward_track3, :load_custom_data_for_writing_track3
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 += params_bytes unless params_bytes.empty?
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
- # PWN::Plugins::MSR206.wait_for_swipe(
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
- public_class_method def self.wait_for_swipe(opts = {})
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
- types_arr = %i[
565
- arm_to_read
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 = PWN::Plugins::MSR206.exec(
601
+ exec_resp = exec(
587
602
  msr206_obj: msr206_obj,
588
- cmd: type
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: :green_on
799
+ cmd: :green_off
594
800
  )
801
+ end
595
802
 
596
- exec_resp = PWN::Plugins::MSR206.exec(
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
- cmd: :card_edge_detect
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
- print 'Ready. Please Swipe Card Now:'
857
+ file = ''
858
+ backup_msg = ''
602
859
  loop do
603
- exec_resp = parse_responses(
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: :card_edge_detect
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
- puts "\n*** ISO Track Format: Standard #{'*' * 17}"
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: :tx_iso_std_data_track1
887
+ cmd: :yellow_off
616
888
  )
617
- puts exec_resp[:decoded]
618
- puts exec_resp.inspect
619
- track_data[:track1] = exec_resp
620
-
621
- # (1..3).each do |n|
622
- # print ">> Track 1 (ALT DATA) ISO Track Format: #{n}\n"
623
- # exec_resp = exec(
624
- # msr206_obj: msr206_obj,
625
- # cmd: :alt_tx_iso_std_data_track1,
626
- # params: [n.to_s]
627
- # )
628
- # puts exec_resp.inspect
629
- # end
630
-
631
- print "\nTRACK 2 >>> "
632
- exec_resp = exec(
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
- cmd: :tx_iso_std_data_track2
914
+ type: :arm_to_write_no_raw,
915
+ encoding: encoding,
916
+ track_data: track_data
635
917
  )
636
- puts exec_resp[:decoded]
637
- puts exec_resp.inspect
638
- track_data[:track2] = exec_resp
639
-
640
- # (1..3).each do |n|
641
- # print ">> Track 2 (ALT DATA) ISO Track Format: #{n}\n"
642
- # exec_resp = exec(
643
- # msr206_obj: msr206_obj,
644
- # cmd: :alt_tx_iso_std_data_track2,
645
- # params: [n.to_s]
646
- # )
647
- # puts exec_resp.inspect
648
- # end
649
-
650
- print "\nTRACK 3 >>> "
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: :tx_iso_std_data_track3
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
- puts exec_resp[:decoded]
656
- puts exec_resp.inspect
657
- track_data[:track3] = exec_resp
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
- ensure
672
- exec_resp = exec(
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
- cmd: :green_off
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||:hard||:soft (defaults to :none)'
1105
+ flow_control: 'optional - :none|:hard|:soft (defaults to :none)'
710
1106
  )
711
1107
 
712
1108
  cmds = #{self}.list_cmds
@@ -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
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module PWN
4
- VERSION = '0.4.476'
4
+ VERSION = '0.4.479'
5
5
  end
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.476
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-04 00:00:00.000000000 Z
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.3.0
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.3.0
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.0
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.0
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.0
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.0
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.0.0
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.0.0
838
+ version: 1.1.0
839
839
  - !ruby/object:Gem::Dependency
840
840
  name: socksify
841
841
  requirement: !ruby/object:Gem::Requirement