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 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