pwn 0.5.524 → 0.5.526

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: 1ba5da2e21124d877eb9573e143517004d8b0552c4f8baee4146c772af9b61a5
4
- data.tar.gz: 3a327348c4ced35e77609f0a6cef0f8ff301875c2d738a01bce1f3bc38ba7d60
3
+ metadata.gz: a959493115414270b5d1d565548abc2e169ebcdacdde93f6162359a173b2a4c8
4
+ data.tar.gz: 8a66132150df20b5994f1492df6ef1da8abb9fd44d4b588f3e4fbb97c8305f50
5
5
  SHA512:
6
- metadata.gz: 944ed01471d1f104e1c6278d5b91a8ec76f3f04ee1b37d35225a889c3a81564410a1c8fe7aad99697e6149545d0bfe5cec21ac5505dd04f1a93525a303031a07
7
- data.tar.gz: 7b6a072f10b55a4a062e084c968b68a6668e2ed663cdf0164fd02f6d187f6a80da33b6e1820cb42576654d17f4add73afbaaa96ba3415a3215b96cc05759a810
6
+ metadata.gz: ea116c907d1f520583f386e3ec0c33f983ef8343e773ef2169c04571ecf8c04d3edd7ffb2cc4c9a4a7e07ccfb6409d649b13874e2e17c393245801470127650f
7
+ data.tar.gz: 0d7f4f1c1c3e89bc2ee6dd0afac1bbfaa20cc052fa9610fb3ca9e8a6491a99a18bd5ce07d16917f04d11b90157327bf92715b78f40f8e98c5994f41c62074446
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.524]:001 >>> PWN.help
40
+ pwn[v0.5.526]: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.524]:001 >>> PWN.help
55
+ pwn[v0.5.526]: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.524]:001 >>> PWN.help
65
+ pwn[v0.5.526]: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
@@ -135,34 +135,27 @@ begin
135
135
  scan_log = opts[:scan_log]
136
136
  decoder = opts[:decoder]
137
137
  location = opts[:location]
138
- keep_looping = opts[:keep_looping] ||= false
138
+ keep_looping = opts[:keep_looping]
139
139
 
140
140
  # Merge opts again to ensure we override profile values with CLI values
141
- loop_count = 1
142
- loop do
143
- PWN::SDR::GQRX.scan_range(
144
- gqrx_sock: gqrx_sock,
145
- start_freq: start_freq,
146
- target_freq: target_freq,
147
- demodulator_mode: demodulator_mode,
148
- bandwidth: bandwidth,
149
- audio_gain_db: audio_gain_db,
150
- squelch: squelch,
151
- precision: precision,
152
- strength_lock: strength_lock,
153
- rf_gain: rf_gain,
154
- intermediate_gain: intermediate_gain,
155
- baseband_gain: baseband_gain,
156
- scan_log: scan_log,
157
- decoder: decoder,
158
- location: location
159
- )
160
- break unless keep_looping
161
-
162
- loop_count += 1
163
- log_timestamp = Time.now.strftime('%Y-%m-%d')
164
- scan_log = "/tmp/pwn_sdr_gqrx_scan_#{PWN::SDR.hz_to_s(start_freq)}-#{PWN::SDR.hz_to_s(target_freq)}_#{log_timestamp}-l#{loop_count}.json"
165
- end
141
+ PWN::SDR::GQRX.scan_range(
142
+ gqrx_sock: gqrx_sock,
143
+ start_freq: start_freq,
144
+ target_freq: target_freq,
145
+ demodulator_mode: demodulator_mode,
146
+ bandwidth: bandwidth,
147
+ audio_gain_db: audio_gain_db,
148
+ squelch: squelch,
149
+ precision: precision,
150
+ strength_lock: strength_lock,
151
+ rf_gain: rf_gain,
152
+ intermediate_gain: intermediate_gain,
153
+ baseband_gain: baseband_gain,
154
+ scan_log: scan_log,
155
+ decoder: decoder,
156
+ location: location,
157
+ keep_looping: keep_looping
158
+ )
166
159
  puts 'Scan Complete.'
167
160
  rescue StandardError => e
168
161
  raise e
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) || attempts >= 500
181
+ strength_measured = true if (distance_between_unique_samples.positive? && distance_between_unique_samples < 5) || attempts >= 700
182
182
 
183
183
  break if strength_measured
184
184
 
@@ -652,205 +652,214 @@ module PWN
652
652
  # intermediate_gain: 'optional - Intermediate gain (defaults to 32.0)',
653
653
  # baseband_gain: 'optional - Baseband gain (defaults to 10.0)',
654
654
  # scan_log: 'optional - Path to save detected signals log (defaults to /tmp/pwn_sdr_gqrx_scan_<start_freq>-<target_freq>_<timestamp>.json)',
655
- # location: 'optional - Location string to include in AI analysis (e.g., "New York, NY", 90210, GPS coords, etc.)'
655
+ # location: 'optional - Location string to include in AI analysis (e.g., "New York, NY", 90210, GPS coords, etc.)',
656
+ # keep_looping: 'optional - Boolean to keep scanning indefinitely (defaults to false)'
656
657
  # )
657
658
 
658
659
  public_class_method def self.scan_range(opts = {})
659
660
  timestamp_start = Time.now.strftime('%Y-%m-%d %H:%M:%S%z')
660
- log_timestamp = Time.now.strftime('%Y-%m-%d')
661
661
 
662
- gqrx_sock = opts[:gqrx_sock]
662
+ loop_count = 1
663
+ loop do
664
+ gqrx_sock = opts[:gqrx_sock]
663
665
 
664
- start_freq = opts[:start_freq]
665
- hz_start = PWN::SDR.hz_to_i(start_freq)
666
+ start_freq = opts[:start_freq]
667
+ hz_start = PWN::SDR.hz_to_i(start_freq)
666
668
 
667
- target_freq = opts[:target_freq]
668
- hz_target = PWN::SDR.hz_to_i(target_freq)
669
+ target_freq = opts[:target_freq]
670
+ hz_target = PWN::SDR.hz_to_i(target_freq)
669
671
 
670
- demodulator_mode = opts[:demodulator_mode]
672
+ demodulator_mode = opts[:demodulator_mode]
671
673
 
672
- bandwidth = opts[:bandwidth] ||= '200.000'
673
-
674
- precision = opts[:precision] ||= 1
675
- strength_lock = opts[:strength_lock] ||= -70.0
676
- squelch = opts[:squelch] ||= (strength_lock - 3.0)
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]
679
- location = opts[:location] ||= 'United States'
674
+ bandwidth = opts[:bandwidth] ||= '200.000'
680
675
 
681
- step_hz = 10**(precision - 1)
682
- step_hz_direction = hz_start > hz_target ? -step_hz : step_hz
676
+ precision = opts[:precision] ||= 1
677
+ strength_lock = opts[:strength_lock] ||= -70.0
678
+ squelch = opts[:squelch] ||= (strength_lock - 3.0)
679
+ decoder = opts[:decoder]
683
680
 
684
- # Set squelch once for the scan
685
- change_squelch_resp = gqrx_cmd(
686
- gqrx_sock: gqrx_sock,
687
- cmd: "L SQL #{squelch}",
688
- resp_ok: 'RPRT 0'
689
- )
681
+ log_timestamp = Time.now.strftime('%Y-%m-%d')
682
+ 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}_l#{loop_count}.json"
683
+ location = opts[:location] ||= 'United States'
684
+ keep_looping = opts[:keep_looping] || false
690
685
 
691
- # We always disable RDS decoding at during the scan
692
- # to prevent unnecessary processing overhead.
693
- # We return the rds boolean in the scan_resp object
694
- # so it will be picked up and used appropriately
695
- # when calling analyze_scan or analyze_log methods.
696
- rds_resp = gqrx_cmd(
697
- gqrx_sock: gqrx_sock,
698
- cmd: 'U RDS 0',
699
- resp_ok: 'RPRT 0'
700
- )
686
+ step_hz = 10**(precision - 1)
687
+ step_hz_direction = hz_start > hz_target ? -step_hz : step_hz
701
688
 
702
- # Set demodulator mode & passband once for the scan
703
- mode_str = demodulator_mode.to_s.upcase
704
- passband_hz = PWN::SDR.hz_to_i(bandwidth)
705
- gqrx_cmd(
706
- gqrx_sock: gqrx_sock,
707
- cmd: "M #{mode_str} #{passband_hz}",
708
- resp_ok: 'RPRT 0'
709
- )
689
+ # Set squelch once for the scan
690
+ change_squelch_resp = gqrx_cmd(
691
+ gqrx_sock: gqrx_sock,
692
+ cmd: "L SQL #{squelch}",
693
+ resp_ok: 'RPRT 0'
694
+ )
710
695
 
711
- audio_gain_db = opts[:audio_gain_db] ||= 6.0
712
- audio_gain_db = audio_gain_db.to_f
713
- audio_gain_db_resp = gqrx_cmd(
714
- gqrx_sock: gqrx_sock,
715
- cmd: "L AF #{audio_gain_db}",
716
- resp_ok: 'RPRT 0'
717
- )
696
+ # We always disable RDS decoding at during the scan
697
+ # to prevent unnecessary processing overhead.
698
+ # We return the rds boolean in the scan_resp object
699
+ # so it will be picked up and used appropriately
700
+ # when calling analyze_scan or analyze_log methods.
701
+ rds_resp = gqrx_cmd(
702
+ gqrx_sock: gqrx_sock,
703
+ cmd: 'U RDS 0',
704
+ resp_ok: 'RPRT 0'
705
+ )
718
706
 
719
- rf_gain = opts[:rf_gain] ||= 0.0
720
- rf_gain = rf_gain.to_f
721
- rf_gain_resp = gqrx_cmd(
722
- gqrx_sock: gqrx_sock,
723
- cmd: "L RF_GAIN #{rf_gain}",
724
- resp_ok: 'RPRT 0'
725
- )
707
+ # Set demodulator mode & passband once for the scan
708
+ mode_str = demodulator_mode.to_s.upcase
709
+ passband_hz = PWN::SDR.hz_to_i(bandwidth)
710
+ gqrx_cmd(
711
+ gqrx_sock: gqrx_sock,
712
+ cmd: "M #{mode_str} #{passband_hz}",
713
+ resp_ok: 'RPRT 0'
714
+ )
726
715
 
727
- intermediate_gain = opts[:intermediate_gain] ||= 32.0
728
- intermediate_gain = intermediate_gain.to_f
729
- intermediate_resp = gqrx_cmd(
730
- gqrx_sock: gqrx_sock,
731
- cmd: "L IF_GAIN #{intermediate_gain}",
732
- resp_ok: 'RPRT 0'
733
- )
716
+ audio_gain_db = opts[:audio_gain_db] ||= 6.0
717
+ audio_gain_db = audio_gain_db.to_f
718
+ audio_gain_db_resp = gqrx_cmd(
719
+ gqrx_sock: gqrx_sock,
720
+ cmd: "L AF #{audio_gain_db}",
721
+ resp_ok: 'RPRT 0'
722
+ )
734
723
 
735
- baseband_gain = opts[:baseband_gain] ||= 10.0
736
- baseband_gain = baseband_gain.to_f
737
- baseband_resp = gqrx_cmd(
738
- gqrx_sock: gqrx_sock,
739
- cmd: "L BB_GAIN #{baseband_gain}",
740
- resp_ok: 'RPRT 0'
741
- )
724
+ rf_gain = opts[:rf_gain] ||= 0.0
725
+ rf_gain = rf_gain.to_f
726
+ rf_gain_resp = gqrx_cmd(
727
+ gqrx_sock: gqrx_sock,
728
+ cmd: "L RF_GAIN #{rf_gain}",
729
+ resp_ok: 'RPRT 0'
730
+ )
742
731
 
743
- prev_freq_obj = init_freq(
744
- gqrx_sock: gqrx_sock,
745
- freq: hz_start,
746
- demodulator_mode: demodulator_mode,
747
- bandwidth: bandwidth,
748
- squelch: squelch,
749
- decoder: decoder,
750
- suppress_details: true,
751
- keep_alive: true
752
- )
732
+ intermediate_gain = opts[:intermediate_gain] ||= 32.0
733
+ intermediate_gain = intermediate_gain.to_f
734
+ intermediate_resp = gqrx_cmd(
735
+ gqrx_sock: gqrx_sock,
736
+ cmd: "L IF_GAIN #{intermediate_gain}",
737
+ resp_ok: 'RPRT 0'
738
+ )
753
739
 
754
- candidate_signals = []
740
+ baseband_gain = opts[:baseband_gain] ||= 10.0
741
+ baseband_gain = baseband_gain.to_f
742
+ baseband_resp = gqrx_cmd(
743
+ gqrx_sock: gqrx_sock,
744
+ cmd: "L BB_GAIN #{baseband_gain}",
745
+ resp_ok: 'RPRT 0'
746
+ )
755
747
 
756
- # Begin scanning range
757
- puts "\n"
758
- puts '-' * 86
759
- puts "INFO: Scanning from #{PWN::SDR.hz_to_s(hz_start)} to #{PWN::SDR.hz_to_s(hz_target)} in steps of #{PWN::SDR.hz_to_s(step_hz_direction.abs)} Hz."
760
- puts "If scans are slow and/or you're experiencing false positives/negatives,"
761
- puts 'consider adjusting the following:'
762
- puts "1. The SDR's sample rate in GQRX"
763
- puts "\s\s- Click on `Configure I/O devices`."
764
- puts "\s\s- A lower `Input rate` value seems counter-intuitive but works well (e.g. ADALM PLUTO ~ 1000000)."
765
- puts '2. Adjust the :strength_lock parameter.'
766
- puts '3. Adjust the :precision parameter.'
767
- puts '4. Disable AI introspection in PWN::Env'
768
- puts 'Happy scanning!'
769
- puts '-' * 86
770
- puts "\n\n\n"
771
-
772
- signals_arr = []
773
- hz = hz_start
774
-
775
- while step_hz_direction.positive? ? hz <= hz_target : hz >= hz_target
776
- tune_to(gqrx_sock: gqrx_sock, hz: hz)
777
- strength_db = measure_signal_strength(
748
+ prev_freq_obj = init_freq(
778
749
  gqrx_sock: gqrx_sock,
779
- freq: hz,
780
- strength_lock: strength_lock,
781
- phase: :find_candidates
750
+ freq: hz_start,
751
+ demodulator_mode: demodulator_mode,
752
+ bandwidth: bandwidth,
753
+ squelch: squelch,
754
+ decoder: decoder,
755
+ suppress_details: true,
756
+ keep_alive: true
782
757
  )
783
758
 
784
- if strength_db >= strength_lock
785
- puts '-' * 86
786
- # Find left and right edges of the signal
787
- candidate_signals = edge_detection(
788
- gqrx_sock: gqrx_sock,
789
- hz: hz,
790
- step_hz: step_hz,
791
- strength_lock: strength_lock
792
- )
793
- elsif candidate_signals.length.positive?
794
- best_peak = find_best_peak(
759
+ candidate_signals = []
760
+
761
+ # Begin scanning range
762
+ puts "\n"
763
+ puts '-' * 86
764
+ puts "INFO: Scanning from #{PWN::SDR.hz_to_s(hz_start)} to #{PWN::SDR.hz_to_s(hz_target)} in steps of #{PWN::SDR.hz_to_s(step_hz_direction.abs)} Hz."
765
+ puts "If scans are slow and/or you're experiencing false positives/negatives,"
766
+ puts 'consider adjusting the following:'
767
+ puts "1. The SDR's sample rate in GQRX"
768
+ puts "\s\s- Click on `Configure I/O devices`."
769
+ puts "\s\s- A lower `Input rate` value seems counter-intuitive but works well (e.g. ADALM PLUTO ~ 1000000)."
770
+ puts '2. Adjust the :strength_lock parameter.'
771
+ puts '3. Adjust the :precision parameter.'
772
+ puts '4. Disable AI introspection in PWN::Env'
773
+ puts 'Happy scanning!'
774
+ puts '-' * 86
775
+ puts "\n\n\n"
776
+
777
+ signals_arr = []
778
+ hz = hz_start
779
+
780
+ while step_hz_direction.positive? ? hz <= hz_target : hz >= hz_target
781
+ tune_to(gqrx_sock: gqrx_sock, hz: hz)
782
+ strength_db = measure_signal_strength(
795
783
  gqrx_sock: gqrx_sock,
796
- candidate_signals: candidate_signals,
797
- step_hz: step_hz,
798
- strength_lock: strength_lock
784
+ freq: hz,
785
+ strength_lock: strength_lock,
786
+ phase: :find_candidates
799
787
  )
800
788
 
801
- if best_peak[:hz] && best_peak[:strength_db] > strength_lock
802
- puts "\n**** Detected Signal ****"
803
- best_freq = PWN::SDR.hz_to_s(best_peak[:hz])
804
- best_strength_db = best_peak[:strength_db]
805
- prev_freq_obj = init_freq(
789
+ if strength_db >= strength_lock
790
+ puts '-' * 86
791
+ # Find left and right edges of the signal
792
+ candidate_signals = edge_detection(
806
793
  gqrx_sock: gqrx_sock,
807
- freq: best_freq,
808
- demodulator_mode: demodulator_mode,
809
- bandwidth: bandwidth,
810
- squelch: squelch,
811
- decoder: decoder,
812
- suppress_details: true,
813
- keep_alive: true
794
+ hz: hz,
795
+ step_hz: step_hz,
796
+ strength_lock: strength_lock
814
797
  )
815
- prev_freq_obj[:strength_lock] = strength_lock
816
- prev_freq_obj[:strength_db] = best_strength_db
817
-
818
- system_role_content = "Analyze signal data captured by a software-defined-radio using GQRX at the following location: #{location}. Respond with just FCC information about the transmission if available. If the frequency is unlicensed or not found in FCC records, state that clearly. Be clear and concise in your analysis."
819
- ai_analysis = PWN::AI::Introspection.reflect_on(
820
- request: prev_freq_obj.to_json,
821
- system_role_content: system_role_content,
822
- suppress_pii_warning: true
798
+ elsif candidate_signals.length.positive?
799
+ best_peak = find_best_peak(
800
+ gqrx_sock: gqrx_sock,
801
+ candidate_signals: candidate_signals,
802
+ step_hz: step_hz,
803
+ strength_lock: strength_lock
823
804
  )
824
805
 
825
- prev_freq_obj[:ai_analysis] = ai_analysis unless ai_analysis.nil?
826
- puts JSON.pretty_generate(prev_freq_obj)
827
- puts '-' * 86
828
- puts "\n\n\n"
829
- signals_arr.push(prev_freq_obj)
830
- log_signals(
831
- signals_arr: signals_arr,
832
- timestamp_start: timestamp_start,
833
- scan_log: scan_log
834
- )
835
- hz = candidate_signals.last[:hz]
836
- # gets
806
+ if best_peak[:hz] && best_peak[:strength_db] > strength_lock
807
+ puts "\n**** Detected Signal ****"
808
+ best_freq = PWN::SDR.hz_to_s(best_peak[:hz])
809
+ best_strength_db = best_peak[:strength_db]
810
+ prev_freq_obj = init_freq(
811
+ gqrx_sock: gqrx_sock,
812
+ freq: best_freq,
813
+ demodulator_mode: demodulator_mode,
814
+ bandwidth: bandwidth,
815
+ squelch: squelch,
816
+ decoder: decoder,
817
+ suppress_details: true,
818
+ keep_alive: true
819
+ )
820
+ prev_freq_obj[:strength_lock] = strength_lock
821
+ prev_freq_obj[:strength_db] = best_strength_db
822
+
823
+ system_role_content = "Analyze signal data captured by a software-defined-radio using GQRX at the following location: #{location}. Respond with just FCC information about the transmission if available. If the frequency is unlicensed or not found in FCC records, state that clearly. Be clear and concise in your analysis."
824
+ ai_analysis = PWN::AI::Introspection.reflect_on(
825
+ request: prev_freq_obj.to_json,
826
+ system_role_content: system_role_content,
827
+ suppress_pii_warning: true
828
+ )
829
+
830
+ prev_freq_obj[:ai_analysis] = ai_analysis unless ai_analysis.nil?
831
+ puts JSON.pretty_generate(prev_freq_obj)
832
+ puts '-' * 86
833
+ puts "\n\n\n"
834
+ signals_arr.push(prev_freq_obj)
835
+ log_signals(
836
+ signals_arr: signals_arr,
837
+ timestamp_start: timestamp_start,
838
+ scan_log: scan_log
839
+ )
840
+ hz = candidate_signals.last[:hz]
841
+ # gets
842
+ end
843
+ candidate_signals.clear
837
844
  end
838
- candidate_signals.clear
845
+ hz += step_hz_direction
839
846
  end
840
- hz += step_hz_direction
841
- end
842
847
 
843
- log_signals(
844
- signals_arr: signals_arr,
845
- timestamp_start: timestamp_start,
846
- scan_log: scan_log
847
- )
848
+ log_signals(
849
+ signals_arr: signals_arr,
850
+ timestamp_start: timestamp_start,
851
+ scan_log: scan_log
852
+ )
853
+ break unless keep_looping
854
+
855
+ loop_count += 1
856
+ end
848
857
  rescue Interrupt
849
858
  puts "\nCTRL+C detected - goodbye."
850
859
  rescue StandardError => e
851
860
  raise e
852
861
  ensure
853
- disconnect(gqrx_sock: gqrx_sock)
862
+ disconnect(gqrx_sock: gqrx_sock) if defined?(gqrx_sock) && gqrx_sock.is_a?(TCPSocket)
854
863
  end
855
864
 
856
865
  # Supported Method Parameters::
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.524'
4
+ VERSION = '0.5.526'
5
5
  end
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.524
4
+ version: 0.5.526
5
5
  platform: ruby
6
6
  authors:
7
7
  - 0day Inc.