pwn 0.5.518 → 0.5.519

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: 4782a5ea26c616b61254cbc43ba1fa0fbee4f71890b48ac3b0197a0586965356
4
- data.tar.gz: 987fdf3e321dd0790ca1f059c483a045bcee5239f63ba5f2bfbd065e5f85c24f
3
+ metadata.gz: aa61097c1923666d760cb38ba2e264d708b3e125a22867f39f137971cfd78da3
4
+ data.tar.gz: 0da0c261593fc8b0594082d57fbfa0009d079a48fae509c8d2e1e17ef8be9bd5
5
5
  SHA512:
6
- metadata.gz: 4417e4d4bbcffc1596d854c0d37eb2911b65456257c8d5520afeb1706bda670f1cb4881f312ca521951ae8d47eba063af98ac4f89d981c34b50f5e2acc052c7b
7
- data.tar.gz: c989b552b031669fb6a2a96580d53ad4f240607d68f7ee2d4b9f65a9b0e48c6d1b5666613782a356a5edb11fb5d2178b30501a7e3bfa2fc6057eda39d3a70299
6
+ metadata.gz: 5a54d9ce67a87f690f52412c987190f0db2cf24ac9e101089a5b93d39cf11fb8e146c0e1af9a7efed91e2db7b21279e286a0e713c6a2607838acf406ab9d3bc9
7
+ data.tar.gz: 8ab8b6d9c214317b2e08422c09a1ca7adfadcde302fe3c5ef871ae181343280702bf4ba34c148500733dc72ed92ae5649926a2a377bc401757ce1e1d49200697
data/Gemfile CHANGED
@@ -20,7 +20,7 @@ gem 'base32', '0.3.4'
20
20
  gem 'bitcoin-ruby', '0.0.20'
21
21
  gem 'brakeman', '7.1.1'
22
22
  gem 'bson', '5.2.0'
23
- gem 'bundler', '>=4.0.2'
23
+ gem 'bundler', '>=4.0.3'
24
24
  gem 'bundler-audit', '>=0.9.3'
25
25
  gem 'bunny', '2.24.0'
26
26
  gem 'colorize', '1.1.0'
data/README.md CHANGED
@@ -37,7 +37,7 @@ $ cd /opt/pwn
37
37
  $ ./install.sh
38
38
  $ ./install.sh ruby-gem
39
39
  $ pwn
40
- pwn[v0.5.518]:001 >>> PWN.help
40
+ pwn[v0.5.519]: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.4.7@pwn
52
52
  $ gem uninstall --all --executables pwn
53
53
  $ gem install --verbose pwn
54
54
  $ pwn
55
- pwn[v0.5.518]:001 >>> PWN.help
55
+ pwn[v0.5.519]:001 >>> PWN.help
56
56
  ```
57
57
 
58
58
  If you're using a multi-user install of RVM do:
@@ -62,7 +62,7 @@ $ rvm use ruby-3.4.7@pwn
62
62
  $ rvmsudo gem uninstall --all --executables pwn
63
63
  $ rvmsudo gem install --verbose pwn
64
64
  $ pwn
65
- pwn[v0.5.518]:001 >>> PWN.help
65
+ pwn[v0.5.519]:001 >>> PWN.help
66
66
  ```
67
67
 
68
68
  PWN periodically upgrades to the latest version of Ruby which is reflected in `/opt/pwn/.ruby-version`. The easiest way to upgrade to the latest version of Ruby from a previous PWN installation is to run the following script:
data/bin/pwn_gqrx_scanner CHANGED
@@ -45,10 +45,6 @@ PWN::Driver::Parser.new do |options|
45
45
  opts[:demodulator_mode] = d
46
46
  end
47
47
 
48
- options.on('-rRDS', '--rds', '<Optional - Enable RDS Decoding when in WFM or WFM_ST Demodulator Mode (Defaults to false)>') do |r|
49
- opts[:rds] = r
50
- end
51
-
52
48
  options.on('-PINT', '--precision=INT', '<Optional - Precision of Frequency 1-12 (Defaults to 5)>') do |p|
53
49
  opts[:precision] = p
54
50
  end
@@ -116,7 +112,6 @@ begin
116
112
  gqrx_sock = PWN::SDR::GQRX.connect(target: host, port: port)
117
113
 
118
114
  demodulator_mode = opts[:demodulator_mode]
119
- rds = opts[:rds]
120
115
  bandwidth = opts[:bandwidth]
121
116
  overlap_protection = opts[:overlap_protection]
122
117
 
@@ -144,6 +139,7 @@ begin
144
139
  baseband_gain = baseband_gain.to_f unless baseband_gain.nil?
145
140
 
146
141
  scan_log = opts[:scan_log]
142
+ decoder = opts[:decoder]
147
143
  location = opts[:location]
148
144
 
149
145
  # Merge opts again to ensure we override profile values with CLI values
@@ -152,7 +148,6 @@ begin
152
148
  start_freq: start_freq,
153
149
  target_freq: target_freq,
154
150
  demodulator_mode: demodulator_mode,
155
- rds: rds,
156
151
  bandwidth: bandwidth,
157
152
  overlap_protection: overlap_protection,
158
153
  audio_gain_db: audio_gain_db,
@@ -164,6 +159,7 @@ begin
164
159
  intermediate_gain: intermediate_gain,
165
160
  baseband_gain: baseband_gain,
166
161
  scan_log: scan_log,
162
+ decoder: decoder,
167
163
  location: location
168
164
  )
169
165
  puts 'Scan Complete.'
@@ -1,5 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'json'
4
+ require 'tty-spinner'
5
+
3
6
  module PWN
4
7
  module SDR
5
8
  module Decoder
@@ -7,90 +10,74 @@ module PWN
7
10
  module RDS
8
11
  # Supported Method Parameters::
9
12
  # rds_resp = PWN::SDR::GQRX.decode_rds(
10
- # gqrx_sock: 'required - GQRX socket object returned from #connect method'
13
+ # freq_obj: 'required - GQRX socket object returned from #connect method'
11
14
  # )
12
-
13
- # private_class_method def self.rds(opts = {})
14
15
  public_class_method def self.decode(opts = {})
15
- gqrx_sock = opts[:gqrx_sock]
16
+ freq_obj = opts[:freq_obj]
17
+ gqrx_sock = freq_obj[:gqrx_sock]
16
18
 
17
- # We toggle RDS off and on to reset the decoder
18
- rds_resp = PWN::SDR::GQRX.gqrx_cmd(
19
+ freq_obj = freq_obj.dup
20
+ freq_obj.delete(:gqrx_sock)
21
+ skip_rds = "\n"
22
+ puts JSON.pretty_generate(freq_obj)
23
+ puts "\n*** FM Radio RDS Decoder ***"
24
+ puts '(Press [ENTER] to continue)...'
25
+
26
+ # Toggle RDS off and on to reset the decoder
27
+ PWN::SDR::GQRX.gqrx_cmd(
19
28
  gqrx_sock: gqrx_sock,
20
29
  cmd: 'U RDS 0',
21
30
  resp_ok: 'RPRT 0'
22
31
  )
23
32
 
24
- rds_resp = PWN::SDR::GQRX.gqrx_cmd(
33
+ PWN::SDR::GQRX.gqrx_cmd(
25
34
  gqrx_sock: gqrx_sock,
26
35
  cmd: 'U RDS 1',
27
36
  resp_ok: 'RPRT 0'
28
37
  )
29
38
 
30
- rds_resp = {}
31
- attempts = 0
32
- max_attempts = 120
33
- skip_rds = "\n"
34
- print 'INFO: Decoding FM radio RDS data (Press ENTER to skip)...'
35
- max_attempts.times do
36
- attempts += 1
37
- rds_resp[:rds_pi] = PWN::SDR::GQRX.gqrx_cmd(gqrx_sock: gqrx_sock, cmd: 'p RDS_PI')
38
- rds_resp[:rds_ps_name] = PWN::SDR::GQRX.gqrx_cmd(gqrx_sock: gqrx_sock, cmd: 'p RDS_PS_NAME')
39
- rds_resp[:rds_radiotext] = PWN::SDR::GQRX.gqrx_cmd(gqrx_sock: gqrx_sock, cmd: 'p RDS_RADIOTEXT')
40
-
41
- # Break if ENTER key pressed
42
- # This is useful if no RDS data is available
43
- # on the current frequency (e.g. false+)
44
- break if $stdin.ready? && $stdin.read_nonblock(1) == skip_rds
45
-
46
- break if rds_resp[:rds_pi] != '0000' && !rds_resp[:rds_ps_name].empty? && !rds_resp[:rds_radiotext].empty?
47
-
48
- print '.'
49
- sleep 0.1
50
- end
51
- puts 'complete.'
52
- rds_resp
53
- rescue StandardError => e
54
- raise e
55
- end
56
-
57
- # Starts the live decoding thread.
58
- def self.start(opts = {})
59
- freq_obj = opts[:freq_obj]
60
- raise ':ERROR: :freq_obj is required' unless freq_obj.is_a?(Hash)
61
-
62
- gqrx_sock = freq_obj[:gqrx_sock]
63
- freq = freq_obj[:freq]
64
- bandwidth = freq_obj[:bandwidth].to_i
65
- record_path = freq_obj[:record_path]
66
-
67
- sleep 0.1 until File.exist?(record_path)
68
-
69
- header = File.binread(record_path, HEADER_SIZE)
70
- raise 'Invalid WAV header' unless header.start_with?('RIFF') && header.include?('WAVE')
71
-
72
- bytes_read = HEADER_SIZE
73
-
74
- puts "GSM Decoder started for freq: #{freq}, bandwidth: #{bandwidth}"
75
-
76
- Thread.new do
77
- loop do
78
- sleep 1
39
+ # Use TTY::Spinner correctly with a dynamic :title token
40
+ spinner = TTY::Spinner.new('[:spinner] :title', format: :arrow_pulse)
41
+ spinner.update(title: 'INFO: Decoding FM radio RDS data...')
42
+ spinner.auto_spin # Background thread handles smooth animation
43
+
44
+ last_resp = {}
45
+
46
+ loop do
47
+ rds_resp = {
48
+ rds_pi: PWN::SDR::GQRX.gqrx_cmd(gqrx_sock: gqrx_sock, cmd: 'p RDS_PI').to_s.strip.chomp,
49
+ rds_ps_name: PWN::SDR::GQRX.gqrx_cmd(gqrx_sock: gqrx_sock, cmd: 'p RDS_PS_NAME').to_s.strip.chomp,
50
+ rds_radiotext: PWN::SDR::GQRX.gqrx_cmd(gqrx_sock: gqrx_sock, cmd: 'p RDS_RADIOTEXT').to_s.strip.chomp
51
+ }
52
+
53
+ # Only update the displayed message when we have new, complete, valid RDS data
54
+ if rds_resp[:rds_pi] != '0000' &&
55
+ !rds_resp[:rds_ps_name].empty? &&
56
+ !rds_resp[:rds_radiotext].empty? &&
57
+ rds_resp != last_resp
58
+
59
+ status = "Program ID: #{rds_resp[:rds_pi]} | Station Name: #{rds_resp[:rds_ps_name].ljust(8)} | Radio Text: #{rds_resp[:rds_radiotext]}"
60
+ spinner.update(title: status)
61
+ last_resp = rds_resp.dup
79
62
  end
80
- rescue StandardError => e
81
- puts "Decoder error: #{e.message}"
82
- ensure
83
- cleanup(record_path: record_path)
84
- end
85
- end
86
63
 
87
- # Stops the decoding thread.
88
- def self.stop(opts = {})
89
- freq_obj = opts[:freq_obj]
90
- raise 'ERROR: :freq_obj is required' unless freq_obj.is_a?(Hash)
64
+ # Non-blocking check for ENTER key
65
+ if $stdin.wait_readable(0)
66
+ begin
67
+ char = $stdin.read_nonblock(1)
68
+ break if char == skip_rds
69
+ rescue IO::WaitReadable, EOFError
70
+ # No-op
71
+ end
72
+ end
91
73
 
92
- decoder_thread = freq_obj[:decoder_thread]
93
- decoder_thread.kill if decoder_thread.is_a?(Thread)
74
+ sleep 0.01
75
+ end
76
+ rescue StandardError => e
77
+ spinner.error('Decoding failed') if defined?(spinner)
78
+ raise e
79
+ ensure
80
+ spinner.stop if spinner
94
81
  end
95
82
 
96
83
  # Author(s):: 0day Inc. <support@0dayinc.com>
@@ -105,12 +92,7 @@ module PWN
105
92
 
106
93
  public_class_method def self.help
107
94
  puts "USAGE:
108
- gsm_decoder_thread = #{self}.start(
109
- freq_obj: 'required - freq_obj returned from PWN::SDR::Receiver::GQRX.init_freq method'
110
- )
111
-
112
- # To stop the decoder thread:
113
- #{self}.stop(
95
+ #{self}.decode(
114
96
  freq_obj: 'required - freq_obj returned from PWN::SDR::Receiver::GQRX.init_freq method'
115
97
  )
116
98
 
@@ -180,9 +180,9 @@ module PWN
180
180
  start_freq: '87.900.000',
181
181
  target_freq: '108.000.000',
182
182
  demodulator_mode: :WFM_ST,
183
- rds: true,
184
183
  bandwidth: '200.000',
185
- precision: 6
184
+ precision: 6,
185
+ decoder: :rds
186
186
  },
187
187
  frs: {
188
188
  start_freq: '462.562.500',
data/lib/pwn/sdr/gqrx.rb CHANGED
@@ -178,7 +178,7 @@ module PWN
178
178
  distance_between_unique_samples = (strength_db - prev_strength_db).abs.round(2)
179
179
  strength_measured = true if distance_between_unique_samples.positive? && strength_lock > strength_db
180
180
  end
181
- strength_measured = true if distance_between_unique_samples.positive? && distance_between_unique_samples < 5
181
+ strength_measured = true if (distance_between_unique_samples.positive? && distance_between_unique_samples < 5) || attempts >= 500
182
182
 
183
183
  break if strength_measured
184
184
 
@@ -187,7 +187,8 @@ module PWN
187
187
  end
188
188
  # Uncomment for debugging strength measurement attempts
189
189
  # which translates to speed and accuracy refinement
190
- puts "\tStrength Measurement Attempts: #{attempts} | Freq: #{freq} | Phase: #{phase} | Unique Samples: #{unique_samples} | dbFS Distance Unique Samples: #{distance_between_unique_samples}"
190
+ puts "\tStrength Measurement Attempts: #{attempts} | Freq: #{freq} | Phase: #{phase}"
191
+ puts "\tUnique Samples: #{unique_samples} | dbFS Distance Unique Samples: #{distance_between_unique_samples}"
191
192
 
192
193
  strength_db.round(1)
193
194
  rescue StandardError => e
@@ -469,7 +470,6 @@ module PWN
469
470
  # gqrx_sock: 'required - GQRX socket object returned from #connect method',
470
471
  # freq: 'required - Frequency to set',
471
472
  # demodulator_mode: 'optional - Demodulator mode (defaults to WFM)',
472
- # rds: 'optional - Boolean to enable/disable RDS decoding (defaults to false)',
473
473
  # bandwidth: 'optional - Bandwidth (defaults to "200.000")',
474
474
  # squelch: 'optional - Squelch level to set (Defaults to current value)',
475
475
  # decoder: 'optional - Decoder key (e.g., :gsm) to start live decoding (starts recording if provided)',
@@ -498,8 +498,6 @@ module PWN
498
498
  demodulator_mode = opts[:demodulator_mode] ||= :WFM
499
499
  raise "ERROR: Invalid demodulator_mode '#{demodulator_mode}'. Valid modes: #{valid_demodulator_modes.join(', ')}" unless valid_demodulator_modes.include?(demodulator_mode.to_sym)
500
500
 
501
- rds = opts[:rds] ||= false
502
-
503
501
  bandwidth = opts[:bandwidth] ||= '200.000'
504
502
  squelch = opts[:squelch]
505
503
  decoder = opts[:decoder]
@@ -537,8 +535,8 @@ module PWN
537
535
  freq: freq,
538
536
  demodulator_mode: demodulator_mode,
539
537
  bandwidth: bandwidth,
540
- rds: rds,
541
- strength_db: strength_db
538
+ strength_db: strength_db,
539
+ decoder: decoder
542
540
  }
543
541
 
544
542
  unless suppress_details
@@ -572,58 +570,56 @@ module PWN
572
570
  cmd: 'l BB_GAIN'
573
571
  )
574
572
 
575
- rds_resp = nil
576
- rds_resp = PWN::SDR::Decoder::RDS.decode(gqrx_sock: gqrx_sock) if rds
577
-
578
573
  freq_obj[:audio_gain_db] = audio_gain_db
579
574
  freq_obj[:demod_mode_n_passband] = demod_n_passband
580
575
  freq_obj[:bb_gain] = bb_gain
581
576
  freq_obj[:if_gain] = if_gain
582
577
  freq_obj[:rf_gain] = rf_gain
583
578
  freq_obj[:squelch] = squelch
584
- freq_obj[:rds] = rds_resp
585
- end
586
-
587
- # Start recording and decoding if decoder provided
588
- decoder_module = nil
589
- decoder_thread = nil
590
- record_path = nil
591
- if decoder
592
- # Resolve decoder module via case statement for extensibility
593
- case decoder
594
- when :gsm
595
- decoder_module = PWN::SDR::Decoder::GSM
596
- when :rds
597
- decoder_module = PWN::SDR::Decoder::RDS
598
- else
599
- raise "ERROR: Unknown decoder key: #{decoder}. Supported: :gsm"
600
- end
601
-
602
- # Ensure recording is off before starting
603
- record_status = gqrx_cmd(gqrx_sock: gqrx_sock, cmd: 'u RECORD')
604
- gqrx_cmd(gqrx_sock: gqrx_sock, cmd: 'U RECORD 0', resp_ok: 'RPRT 0') if record_status == '1'
605
-
606
- # Start recording
607
- gqrx_cmd(gqrx_sock: gqrx_sock, cmd: 'U RECORD 1', resp_ok: 'RPRT 0')
608
-
609
- # Prepare for decoder
610
- start_time = Time.now
611
- expected_filename = "gqrx_#{start_time.strftime('%Y%m%d_%H%M%S')}_#{current_freq_raw}.wav"
612
- record_path = File.join(record_dir, expected_filename)
613
-
614
- # Build partial gqrx_obj for decoder start
615
- freq_obj[:record_path] = record_path
616
579
 
617
- # Initialize and start decoder (module style: .start returns thread)
618
- freq_obj[:gqrx_sock] = gqrx_sock
619
- decoder_thread = decoder_module.start(freq_obj: freq_obj)
620
- freq_obj.delete(:gqrx_sock)
580
+ # Start recording and decoding if decoder provided
581
+ if decoder
582
+ decoder = decoder.to_s.to_sym
583
+ decoder_module = nil
584
+ decoder_thread = nil
585
+ record_path = nil
586
+
587
+ # Resolve decoder module via case statement for extensibility
588
+ case decoder
589
+ when :gsm
590
+ decoder_module = PWN::SDR::Decoder::GSM
591
+ when :rds
592
+ decoder_module = PWN::SDR::Decoder::RDS
593
+ else
594
+ raise "ERROR: Unknown decoder key: #{decoder}. Supported: :gsm"
595
+ end
621
596
 
622
- freq_obj[:freq] = current_freq
623
- freq_obj[:decoder] = decoder
624
- freq_obj[:decoder_module] = decoder_module
625
- freq_obj[:decoder_thread] = decoder_thread
626
- freq_obj[:record_path] = record_path
597
+ # Ensure recording is off before starting
598
+ # unless decoder == :rds
599
+ # puts decoder.inspect
600
+ # record_status = gqrx_cmd(gqrx_sock: gqrx_sock, cmd: 'u RECORD')
601
+ # gqrx_cmd(gqrx_sock: gqrx_sock, cmd: 'U RECORD 0', resp_ok: 'RPRT 0') if record_status == '1'
602
+
603
+ # # Start recording
604
+ # gqrx_cmd(gqrx_sock: gqrx_sock, cmd: 'U RECORD 1', resp_ok: 'RPRT 0')
605
+
606
+ # # Prepare for decoder
607
+ # start_time = Time.now
608
+ # expected_filename = "gqrx_#{start_time.strftime('%Y%m%d_%H%M%S')}_#{current_freq_raw}.wav"
609
+ # record_path = File.join(record_dir, expected_filename)
610
+
611
+ # # Build partial gqrx_obj for decoder start
612
+ # freq_obj[:record_path] = record_path
613
+ # end
614
+
615
+ # Initialize and start decoder (module style: .start returns thread)
616
+ freq_obj[:gqrx_sock] = gqrx_sock
617
+ freq_obj[:decoder_module] = decoder_module
618
+ freq_obj[:record_path] = record_path
619
+ decoder_module.decode(freq_obj: freq_obj)
620
+ # decoder_thread = decoder_module.start(freq_obj: freq_obj)
621
+ # freq_obj[:decoder_thread] = decoder_thread
622
+ end
627
623
  end
628
624
 
629
625
  freq_obj
@@ -631,14 +627,13 @@ module PWN
631
627
  raise e
632
628
  ensure
633
629
  # Ensure decoder recording stops
634
- if decoder
635
- gqrx_cmd(
636
- gqrx_sock: gqrx_sock,
637
- cmd: 'U RECORD 0',
638
- resp_ok: 'RPRT 0'
639
- )
640
- decoder_module.stop(freq_obj: freq_obj)
641
- end
630
+ # if decoder && decoder != :rds
631
+ # gqrx_cmd(
632
+ # gqrx_sock: gqrx_sock,
633
+ # cmd: 'U RECORD 0',
634
+ # resp_ok: 'RPRT 0'
635
+ # )
636
+ # end
642
637
  disconnect(gqrx_sock: gqrx_sock) if gqrx_sock.is_a?(TCPSocket) && !keep_alive
643
638
  end
644
639
 
@@ -648,7 +643,6 @@ module PWN
648
643
  # start_freq: 'required - Start frequency of scan range',
649
644
  # target_freq: 'required - Target frequency of scan range',
650
645
  # demodulator_mode: 'optional - Demodulator mode (e.g. WFM, AM, FM, USB, LSB, RAW, CW, RTTY / defaults to WFM)',
651
- # rds: 'optional - Boolean to enable/disable RDS decoding (defaults to false)',
652
646
  # bandwidth: 'optional - Bandwidth in Hz (Defaults to "200.000")',
653
647
  # precision: 'optional - Frequency step precision (number of digits; defaults to 1)',
654
648
  # strength_lock: 'optional - Strength lock in dBFS (defaults to -70.0)',
@@ -674,7 +668,6 @@ module PWN
674
668
  hz_target = PWN::SDR.hz_to_i(target_freq)
675
669
 
676
670
  demodulator_mode = opts[:demodulator_mode]
677
- rds = opts[:rds] ||= false
678
671
 
679
672
  bandwidth = opts[:bandwidth] ||= '200.000'
680
673
 
@@ -682,6 +675,7 @@ module PWN
682
675
  strength_lock = opts[:strength_lock] ||= -70.0
683
676
  squelch = opts[:squelch] ||= (strength_lock - 3.0)
684
677
  scan_log = opts[:scan_log] ||= "/tmp/pwn_sdr_gqrx_scan_#{PWN::SDR.hz_to_s(hz_start)}-#{PWN::SDR.hz_to_s(hz_target)}_#{log_timestamp}.json"
678
+ decoder = opts[:decoder]
685
679
  location = opts[:location] ||= 'United States'
686
680
 
687
681
  step_hz = 10**(precision - 1)
@@ -750,9 +744,9 @@ module PWN
750
744
  gqrx_sock: gqrx_sock,
751
745
  freq: hz_start,
752
746
  demodulator_mode: demodulator_mode,
753
- rds: rds,
754
747
  bandwidth: bandwidth,
755
748
  squelch: squelch,
749
+ decoder: decoder,
756
750
  suppress_details: true,
757
751
  keep_alive: true
758
752
  )
@@ -811,8 +805,8 @@ module PWN
811
805
  prev_freq_obj = init_freq(
812
806
  gqrx_sock: gqrx_sock,
813
807
  freq: best_freq,
814
- rds: rds,
815
808
  suppress_details: true,
809
+ decoder: decoder,
816
810
  keep_alive: true
817
811
  )
818
812
  prev_freq_obj[:strength_lock] = strength_lock
@@ -874,6 +868,7 @@ module PWN
874
868
  )
875
869
 
876
870
  scan_resp[:signals].each do |signal|
871
+ # puts JSON.pretty_generate(signal)
877
872
  signal[:gqrx_sock] = gqrx_sock
878
873
  # This is required to keep connection alive during analysis
879
874
  signal[:keep_alive] = true
@@ -881,9 +876,11 @@ module PWN
881
876
  freq_obj = signal.merge(freq_obj)
882
877
  # Redact gqrx_sock from output
883
878
  freq_obj.delete(:gqrx_sock)
884
- puts JSON.pretty_generate(freq_obj)
885
- print 'Press [ENTER] to continue...'
886
- gets
879
+ unless freq_obj[:decoder]
880
+ puts JSON.pretty_generate(freq_obj)
881
+ print 'Press [ENTER] to continue...'
882
+ gets
883
+ end
887
884
  puts "\n" * 3
888
885
  end
889
886
  rescue Interrupt
@@ -958,7 +955,6 @@ module PWN
958
955
  gqrx_sock: 'required - GQRX socket object returned from #connect method',
959
956
  freq: 'required - Frequency to set',
960
957
  demodulator_mode: 'optional - Demodulator mode (defaults to WFM)',
961
- rds: 'optional - Boolean to enable/disable RDS decoding (defaults to false)',
962
958
  bandwidth: 'optional - Bandwidth (defaults to \"200.000\")',
963
959
  decoder: 'optional - Decoder key (e.g., :gsm) to start live decoding (starts recording if provided)',
964
960
  record_dir: 'optional - Directory where GQRX saves recordings (required if decoder provided; defaults to /tmp/gqrx_recordings)',
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.5.518'
4
+ VERSION = '0.5.519'
5
5
  end
@@ -1274,11 +1274,18 @@
1274
1274
  {"messages":[{"role":"user","content":"PWN::SAST::WindowLocationHash.scan Usage"},{"role":"assistant","content":"`PWN::SAST::WindowLocationHash.scan`: Supported Method Parameters\n\nPWN::SAST::WindowLocationHash.scan(\n\ndir_path: 'optional path to dir defaults to .'\ngit_repo_root_uri: 'optional http uri of git repo scanned'\n\n)\n"}]}
1275
1275
  {"messages":[{"role":"user","content":"PWN::SAST::WindowLocationHash.security_references Usage"},{"role":"assistant","content":"`PWN::SAST::WindowLocationHash.security_references`: "}]}
1276
1276
  {"messages":[{"role":"user","content":"PWN::SDR.help Usage"},{"role":"assistant","content":"`PWN::SDR.help`: "}]}
1277
+ {"messages":[{"role":"user","content":"PWN::SDR.hz_to_i Usage"},{"role":"assistant","content":"`PWN::SDR.hz_to_i`: "}]}
1278
+ {"messages":[{"role":"user","content":"PWN::SDR.hz_to_s Usage"},{"role":"assistant","content":"`PWN::SDR.hz_to_s`: "}]}
1277
1279
  {"messages":[{"role":"user","content":"PWN::SDR::Decoder.help Usage"},{"role":"assistant","content":"`PWN::SDR::Decoder.help`: "}]}
1278
1280
  {"messages":[{"role":"user","content":"PWN::SDR::Decoder::GSM.authors Usage"},{"role":"assistant","content":"`PWN::SDR::Decoder::GSM.authors`: Author(s)\n\n0day Inc. <support@0dayinc.com>\n"}]}
1279
1281
  {"messages":[{"role":"user","content":"PWN::SDR::Decoder::GSM.help Usage"},{"role":"assistant","content":"`PWN::SDR::Decoder::GSM.help`: "}]}
1280
1282
  {"messages":[{"role":"user","content":"PWN::SDR::Decoder::GSM.start Usage"},{"role":"assistant","content":"`PWN::SDR::Decoder::GSM.start`: "}]}
1281
1283
  {"messages":[{"role":"user","content":"PWN::SDR::Decoder::GSM.stop Usage"},{"role":"assistant","content":"`PWN::SDR::Decoder::GSM.stop`: "}]}
1284
+ {"messages":[{"role":"user","content":"PWN::SDR::Decoder::RDS.authors Usage"},{"role":"assistant","content":"`PWN::SDR::Decoder::RDS.authors`: Author(s)\n\n0day Inc. <support@0dayinc.com>\n"}]}
1285
+ {"messages":[{"role":"user","content":"PWN::SDR::Decoder::RDS.decode Usage"},{"role":"assistant","content":"`PWN::SDR::Decoder::RDS.decode`: "}]}
1286
+ {"messages":[{"role":"user","content":"PWN::SDR::Decoder::RDS.help Usage"},{"role":"assistant","content":"`PWN::SDR::Decoder::RDS.help`: "}]}
1287
+ {"messages":[{"role":"user","content":"PWN::SDR::Decoder::RDS.start Usage"},{"role":"assistant","content":"`PWN::SDR::Decoder::RDS.start`: "}]}
1288
+ {"messages":[{"role":"user","content":"PWN::SDR::Decoder::RDS.stop Usage"},{"role":"assistant","content":"`PWN::SDR::Decoder::RDS.stop`: "}]}
1282
1289
  {"messages":[{"role":"user","content":"PWN::SDR::FlipperZero.authors Usage"},{"role":"assistant","content":"`PWN::SDR::FlipperZero.authors`: Author(s)\n\n0day Inc. <support@0dayinc.com>\n"}]}
1283
1290
  {"messages":[{"role":"user","content":"PWN::SDR::FlipperZero.connect Usage"},{"role":"assistant","content":"`PWN::SDR::FlipperZero.connect`: Supported Method Parameters\n\nflipper_zero_obj = PWN::SDR::FlipperZero.connect(\n\nblock_dev: 'optional serial block device path (defaults to /dev/ttyACM0)',\nbaud: 'optional (defaults to 9600)',\ndata_bits: 'optional (defaults to 8)',\nstop_bits: 'optional (defaults to 1)',\nparity: 'optional - :even||:odd|:none (defaults to :none)'\n\n)\n"}]}
1284
1291
  {"messages":[{"role":"user","content":"PWN::SDR::FlipperZero.connect_via_screen Usage"},{"role":"assistant","content":"`PWN::SDR::FlipperZero.connect_via_screen`: Supported Method Parameters\n\nPWN::SDR::FlipperZero.connect_via_screen(\n\nblock_dev: 'optional - serial block device path (defaults to /dev/ttyACM0)'\n\n)\n"}]}
@@ -1292,18 +1299,16 @@
1292
1299
  {"messages":[{"role":"user","content":"PWN::SDR::GQRX.analyze_scan Usage"},{"role":"assistant","content":"`PWN::SDR::GQRX.analyze_scan`: Supported Method Parameters\n\nPWN::SDR::GQRX.analyze_scan(\n\nscan_resp: 'required - Scan response hash returned from #scan_range method',\ntarget: 'optional - GQRX target IP address (defaults to 127.0.0.1)',\nport: 'optional - GQRX target port (defaults to 7356)'\n\n)\n"}]}
1293
1300
  {"messages":[{"role":"user","content":"PWN::SDR::GQRX.authors Usage"},{"role":"assistant","content":"`PWN::SDR::GQRX.authors`: Author(s)\n\n0day Inc. <support@0dayinc.com>\n"}]}
1294
1301
  {"messages":[{"role":"user","content":"PWN::SDR::GQRX.connect Usage"},{"role":"assistant","content":"`PWN::SDR::GQRX.connect`: Supported Method Parameters\n\ngqrx_sock = PWN::SDR::GQRX.connect(\n\ntarget: 'optional - GQRX target IP address (defaults to 127.0.0.1)',\nport: 'optional - GQRX target port (defaults to 7356)'\n\n)\n"}]}
1295
- {"messages":[{"role":"user","content":"PWN::SDR::GQRX.decode_rds Usage"},{"role":"assistant","content":"`PWN::SDR::GQRX.decode_rds`: Supported Method Parameters\n\nrds_resp = PWN::SDR::GQRX.decode_rds(\n\ngqrx_sock: 'required - GQRX socket object returned from #connect method'\n\n)\n"}]}
1296
1302
  {"messages":[{"role":"user","content":"PWN::SDR::GQRX.disconnect Usage"},{"role":"assistant","content":"`PWN::SDR::GQRX.disconnect`: Supported Method Parameters\n\nPWN::SDR::GQRX.disconnect(\n\ngqrx_sock: 'required - GQRX socket object returned from #connect method'\n\n)\n"}]}
1297
1303
  {"messages":[{"role":"user","content":"PWN::SDR::GQRX.edge_detection Usage"},{"role":"assistant","content":"`PWN::SDR::GQRX.edge_detection`: Supported Method Parameters\n\ncandidate_signals = PWN::SDR::GQRX.edge_detection(\n\ngqrx_sock: 'required - GQRX socket object returned from #connect method',\nhz: 'required - Frequency to start edge detection from',\nstep_hz: 'required - Frequency step in Hz for edge detection',\nstrength_lock: 'required - Strength lock in dBFS to determine signal edges'\n\n)\n"}]}
1304
+ {"messages":[{"role":"user","content":"PWN::SDR::GQRX.find_best_peak Usage"},{"role":"assistant","content":"`PWN::SDR::GQRX.find_best_peak`: Supported Method Parameters\n\nbest_peak = PWN::SDR::GQRX.find_best_peak(\n\ngqrx_sock: 'required - GQRX socket object returned from #connect method',\ncandidate_signals: 'required - Array of candidate signals from edge_detection',\nstep_hz: 'required - Frequency step in Hz for peak finding',\nstrength_lock: 'required - Strength lock in dBFS to determine signal edges'\n\n)\n"}]}
1298
1305
  {"messages":[{"role":"user","content":"PWN::SDR::GQRX.gqrx_cmd Usage"},{"role":"assistant","content":"`PWN::SDR::GQRX.gqrx_cmd`: Supported Method Parameters\n\ngqrx_resp = PWN::SDR::GQRX.gqrx_cmd(\n\ngqrx_sock: 'required - GQRX socket object returned from #connect method',\ncmd: 'required - GQRX command to execute',\nresp_ok: 'optional - Expected response from GQRX to indicate success'\n\n)\n"}]}
1299
1306
  {"messages":[{"role":"user","content":"PWN::SDR::GQRX.help Usage"},{"role":"assistant","content":"`PWN::SDR::GQRX.help`: "}]}
1300
- {"messages":[{"role":"user","content":"PWN::SDR::GQRX.init_freq Usage"},{"role":"assistant","content":"`PWN::SDR::GQRX.init_freq`: Supported Method Parameters\n\nfreq_obj = PWN::SDR::GQRX.init_freq(\n\ngqrx_sock: 'required - GQRX socket object returned from #connect method',\nfreq: 'required - Frequency to set',\ndemodulator_mode: 'optional - Demodulator mode (defaults to WFM)',\nrds: 'optional - Boolean to enable/disable RDS decoding (defaults to false)',\nbandwidth: 'optional - Bandwidth (defaults to 200_000)',\nsquelch: 'optional - Squelch level to set (Defaults to current value)',\ndecoder: 'optional - Decoder key (e.g., :gsm) to start live decoding (starts recording if provided)',\nrecord_dir: 'optional - Directory where GQRX saves recordings (required if decoder provided; defaults to /tmp/gqrx_recordings)',\nsuppress_details: 'optional - Boolean to include extra frequency details in return hash (defaults to false)',\nkeep_alive: 'optional - Boolean to keep GQRX connection alive after method completion (defaults to false)'\n\n)\n"}]}
1307
+ {"messages":[{"role":"user","content":"PWN::SDR::GQRX.init_freq Usage"},{"role":"assistant","content":"`PWN::SDR::GQRX.init_freq`: Supported Method Parameters\n\nfreq_obj = PWN::SDR::GQRX.init_freq(\n\ngqrx_sock: 'required - GQRX socket object returned from #connect method',\nfreq: 'required - Frequency to set',\ndemodulator_mode: 'optional - Demodulator mode (defaults to WFM)',\nrds: 'optional - Boolean to enable/disable RDS decoding (defaults to false)',\nbandwidth: 'optional - Bandwidth (defaults to \"200.000\")',\nsquelch: 'optional - Squelch level to set (Defaults to current value)',\ndecoder: 'optional - Decoder key (e.g., :gsm) to start live decoding (starts recording if provided)',\nrecord_dir: 'optional - Directory where GQRX saves recordings (required if decoder provided; defaults to /tmp/gqrx_recordings)',\nsuppress_details: 'optional - Boolean to include extra frequency details in return hash (defaults to false)',\nkeep_alive: 'optional - Boolean to keep GQRX connection alive after method completion (defaults to false)'\n\n)\n"}]}
1301
1308
  {"messages":[{"role":"user","content":"PWN::SDR::GQRX.log_signals Usage"},{"role":"assistant","content":"`PWN::SDR::GQRX.log_signals`: Supported Method Parameters\n\nscan_resp = PWN::SDR::GQRX.log_signals(\n\nsignals_arr: 'required - Array of detected signals',\ntimestamp_start: 'required - Scan start timestamp',\nscan_log: 'required - Path to save detected signals log'\n\n)\n"}]}
1302
- {"messages":[{"role":"user","content":"PWN::SDR::GQRX.measure_signal_strength Usage"},{"role":"assistant","content":"`PWN::SDR::GQRX.measure_signal_strength`: Supported Method Parameters\n\nstrength_db = PWN::SDR::GQRX.measure_signal_strength(\n\ngqrx_sock: 'required - GQRX socket object returned from #connect method',\nstrength_lock: 'optional - Strength lock in dBFS to determine signal edges (defaults to -70.0)'\n\n)\n"}]}
1303
- {"messages":[{"role":"user","content":"PWN::SDR::GQRX.scan_range Usage"},{"role":"assistant","content":"`PWN::SDR::GQRX.scan_range`: Supported Method Parameters\n\nscan_resp = PWN::SDR::GQRX.scan_range(\n\ngqrx_sock: 'required - GQRX socket object returned from #connect method',\nstart_freq: 'required - Start frequency of scan range',\ntarget_freq: 'required - Target frequency of scan range',\ndemodulator_mode: 'optional - Demodulator mode (e.g. WFM, AM, FM, USB, LSB, RAW, CW, RTTY / defaults to WFM)',\nrds: 'optional - Boolean to enable/disable RDS decoding (defaults to false)',\nbandwidth: 'optional - Bandwidth in Hz (Defaults to 200_000)',\nprecision: 'optional - Frequency step precision (number of digits; defaults to 1)',\nstrength_lock: 'optional - Strength lock in dBFS (defaults to -70.0)',\nsquelch: 'optional - Squelch level in dBFS (defaults to strength_lock - 3.0)',\naudio_gain_db: 'optional - Audio gain in dB (defaults to 6.0)',\nrf_gain: 'optional - RF gain (defaults to 0.0)',\nintermediate_gain: 'optional - Intermediate gain (defaults to 32.0)',\nbaseband_gain: 'optional - Baseband gain (defaults to 10.0)',\nscan_log: 'optional - Path to save detected signals log (defaults to /tmp/pwn_sdr_gqrx_scan_<start_freq>-<target_freq>_<timestamp>.json)',\nlocation: 'optional - Location string to include in AI analysis (e.g., \"New York, NY\", 90210, GPS coords, etc.)'\n\n)\n"}]}
1309
+ {"messages":[{"role":"user","content":"PWN::SDR::GQRX.measure_signal_strength Usage"},{"role":"assistant","content":"`PWN::SDR::GQRX.measure_signal_strength`: Supported Method Parameters\n\nstrength_db = PWN::SDR::GQRX.measure_signal_strength(\n\ngqrx_sock: 'required - GQRX socket object returned from #connect method',\nfreq: 'required - Frequency to measure signal strength',\nstrength_lock: 'optional - Strength lock in dBFS to determine signal edges (defaults to -70.0)',\nphase: 'optional - Phase of measurement for logging purposes (defaults to :find_candidates)'\n\n)\n"}]}
1310
+ {"messages":[{"role":"user","content":"PWN::SDR::GQRX.scan_range Usage"},{"role":"assistant","content":"`PWN::SDR::GQRX.scan_range`: Supported Method Parameters\n\nscan_resp = PWN::SDR::GQRX.scan_range(\n\ngqrx_sock: 'required - GQRX socket object returned from #connect method',\nstart_freq: 'required - Start frequency of scan range',\ntarget_freq: 'required - Target frequency of scan range',\ndemodulator_mode: 'optional - Demodulator mode (e.g. WFM, AM, FM, USB, LSB, RAW, CW, RTTY / defaults to WFM)',\nrds: 'optional - Boolean to enable/disable RDS decoding (defaults to false)',\nbandwidth: 'optional - Bandwidth in Hz (Defaults to \"200.000\")',\nprecision: 'optional - Frequency step precision (number of digits; defaults to 1)',\nstrength_lock: 'optional - Strength lock in dBFS (defaults to -70.0)',\nsquelch: 'optional - Squelch level in dBFS (defaults to strength_lock - 3.0)',\naudio_gain_db: 'optional - Audio gain in dB (defaults to 6.0)',\nrf_gain: 'optional - RF gain (defaults to 0.0)',\nintermediate_gain: 'optional - Intermediate gain (defaults to 32.0)',\nbaseband_gain: 'optional - Baseband gain (defaults to 10.0)',\nscan_log: 'optional - Path to save detected signals log (defaults to /tmp/pwn_sdr_gqrx_scan_<start_freq>-<target_freq>_<timestamp>.json)',\nlocation: 'optional - Location string to include in AI analysis (e.g., \"New York, NY\", 90210, GPS coords, etc.)'\n\n)\n"}]}
1304
1311
  {"messages":[{"role":"user","content":"PWN::SDR::GQRX.tune_to Usage"},{"role":"assistant","content":"`PWN::SDR::GQRX.tune_to`: Supported Method Parameters\n\ntune_resp = PWN::SDR::GQRX.tune_to(\n\ngqrx_sock: 'required - GQRX socket object returned from #connect method',\nhz: 'required - Frequency to tune to'\n\n)\n"}]}
1305
- {"messages":[{"role":"user","content":"PWN::SDR::GQRX.cast_to_pretty_hz Usage"},{"role":"assistant","content":"`PWN::SDR::GQRX.cast_to_pretty_hz`: "}]}
1306
- {"messages":[{"role":"user","content":"PWN::SDR::GQRX.cast_to_raw_hz Usage"},{"role":"assistant","content":"`PWN::SDR::GQRX.cast_to_raw_hz`: "}]}
1307
1312
  {"messages":[{"role":"user","content":"PWN::SDR::RFIDler.authors Usage"},{"role":"assistant","content":"`PWN::SDR::RFIDler.authors`: Author(s)\n\n0day Inc. <support@0dayinc.com>\n"}]}
1308
1313
  {"messages":[{"role":"user","content":"PWN::SDR::RFIDler.connect_via_screen Usage"},{"role":"assistant","content":"`PWN::SDR::RFIDler.connect_via_screen`: Supported Method Parameters\n\nPWN::SDR::RFIDler.connect_via_screen(\n\nblock_dev: 'optional - serial block device path (defaults to /dev/ttyUSB0)'\n\n)\n"}]}
1309
1314
  {"messages":[{"role":"user","content":"PWN::SDR::RFIDler.help Usage"},{"role":"assistant","content":"`PWN::SDR::RFIDler.help`: "}]}
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pwn
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.518
4
+ version: 0.5.519
5
5
  platform: ruby
6
6
  authors:
7
7
  - 0day Inc.
@@ -141,14 +141,14 @@ dependencies:
141
141
  requirements:
142
142
  - - ">="
143
143
  - !ruby/object:Gem::Version
144
- version: 4.0.2
144
+ version: 4.0.3
145
145
  type: :development
146
146
  prerelease: false
147
147
  version_requirements: !ruby/object:Gem::Requirement
148
148
  requirements:
149
149
  - - ">="
150
150
  - !ruby/object:Gem::Version
151
- version: 4.0.2
151
+ version: 4.0.3
152
152
  - !ruby/object:Gem::Dependency
153
153
  name: bundler-audit
154
154
  requirement: !ruby/object:Gem::Requirement
@@ -2447,7 +2447,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
2447
2447
  - !ruby/object:Gem::Version
2448
2448
  version: '0'
2449
2449
  requirements: []
2450
- rubygems_version: 4.0.2
2450
+ rubygems_version: 4.0.3
2451
2451
  specification_version: 4
2452
2452
  summary: Automated Security Testing for CI/CD Pipelines & Beyond
2453
2453
  test_files: []