pwn 0.5.510 → 0.5.512

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: d58d781b8c20f486edb8e75e754abf3ecef32c5452e37b95db9cdc42d99b00c5
4
- data.tar.gz: 3ad4a359bc29b32b0075ab742251049f29ee7fc0e71404205cb799fd3674703b
3
+ metadata.gz: 0e7b1030cb5ce3e024a16630a46f404f8919da6d799e385133be3be4da8286e9
4
+ data.tar.gz: e19976ea7a052f608f9b17e50e76e06e070926146749bed674a30e39f91dccce
5
5
  SHA512:
6
- metadata.gz: 38e23042f38a7f1774e67f1bda23b3e77a9ff1d2242aee7c59d47957cddff06ec831d3fee6fec16681795bab6e450fb178bbb705e1d44a3624d1c8260d55625b
7
- data.tar.gz: 1edb0154984ee110ef2b4d87eddf5f007a98d7977f50cb33fbb1b735d79fc64725ba75bfff288822bbdd723bf893ba25f3022b9aff1094ec4a068dd953cae2ef
6
+ metadata.gz: 69ce103c6b63b5691adb551adb86540373671f15455a2614d94230f7530c80f8d24b2e46503c52852208e428d015d86185b64df1cd8fcf29e18c75e7b9103287
7
+ data.tar.gz: 99d2a4f9b47e9f2e3226c81539854a102b22b3956d36be70dbd75c62b5d0bd09c36563589e590d2796cec9ddef9b68736fb2649bb1d2320d666bac844f97524a
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.0'
23
+ gem 'bundler', '>=4.0.2'
24
24
  gem 'bundler-audit', '>=0.9.3'
25
25
  gem 'bunny', '2.24.0'
26
26
  gem 'colorize', '1.1.0'
@@ -44,12 +44,12 @@ gem 'jenkins_api_client2', '1.9.0'
44
44
  gem 'js-beautify', '0.1.8'
45
45
  gem 'json', '>=2.13.2'
46
46
  gem 'jsonpath', '1.1.5'
47
- gem 'json_schemer', '2.4.0'
47
+ gem 'json_schemer', '2.5.0'
48
48
  gem 'jwt', '3.1.2'
49
49
  gem 'libusb', '0.7.2'
50
50
  gem 'luhn', '3.0.0'
51
51
  gem 'mail', '2.9.0'
52
- gem 'meshtastic', '0.0.147'
52
+ gem 'meshtastic', '0.0.149'
53
53
  gem 'metasm', '1.0.5'
54
54
  gem 'mongo', '2.22.0'
55
55
  gem 'msfrpc-client', '1.1.2'
@@ -73,14 +73,14 @@ gem 'pry-doc', '1.6.0'
73
73
  gem 'rake', '13.3.1'
74
74
  gem 'rb-readline', '0.5.5'
75
75
  gem 'rbvmomi2', '3.8.0'
76
- gem 'rdoc', '6.16.1'
76
+ gem 'rdoc', '6.17.0'
77
77
  gem 'rest-client', '2.1.0'
78
78
  gem 'rex', '2.0.13'
79
79
  gem 'rmagick', '6.1.4'
80
80
  gem 'rqrcode', '3.1.1'
81
81
  gem 'rspec', '3.13.2'
82
82
  gem 'rtesseract', '3.1.4'
83
- gem 'rubocop', '1.81.7'
83
+ gem 'rubocop', '1.82.0'
84
84
  gem 'rubocop-rake', '0.7.1'
85
85
  gem 'rubocop-rspec', '3.8.0'
86
86
  gem 'ruby-audio', '1.6.1'
@@ -88,8 +88,8 @@ gem 'ruby-nmap', '1.0.3'
88
88
  gem 'ruby-saml', '1.18.1'
89
89
  gem 'rvm', '1.11.3.9'
90
90
  gem 'savon', '2.15.1'
91
- gem 'selenium-devtools', '0.142.0'
92
- gem 'selenium-webdriver', '4.38.0'
91
+ gem 'selenium-devtools', '0.143.0'
92
+ gem 'selenium-webdriver', '4.39.0'
93
93
  gem 'slack-ruby-client', '3.1.0'
94
94
  gem 'socksify', '1.8.1'
95
95
  gem 'spreadsheet', '1.3.4'
@@ -104,4 +104,4 @@ gem 'webrick', '1.9.2'
104
104
  gem 'whois', '6.0.3'
105
105
  gem 'whois-parser', '2.0.0'
106
106
  gem 'wicked_pdf', '2.8.2'
107
- gem 'yard', '0.9.37'
107
+ gem 'yard', '0.9.38'
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.510]:001 >>> PWN.help
40
+ pwn[v0.5.512]: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.510]:001 >>> PWN.help
55
+ pwn[v0.5.512]: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.510]:001 >>> PWN.help
65
+ pwn[v0.5.512]: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
@@ -13,12 +13,12 @@ PWN::Driver::Parser.new do |options|
13
13
  opts[:list_scan_profiles] = l
14
14
  end
15
15
 
16
- options.on('-tFREQ', '--target-freq=FREQ', '<Required if "--assume-profile" is Nil - Frequency to Conclude Scanning (e.g. 900.000.000 == 900 mHz>') do |e|
17
- opts[:target_freq] = e
16
+ options.on('-sFREQ', '--start-freq=FREQ', '<Required if "--assume-profile" is Nil - Frequency to Start Scanning (e.g. 800.000.000 == 800 mHz>') do |s|
17
+ opts[:start_freq] = s
18
18
  end
19
19
 
20
- options.on('-sFREQ', '--start-freq=FREQ', '<Optional - Frequency to Set when Scanning Begins (Defaults to last known frequency)>') do |s|
21
- opts[:start_freq] = s
20
+ options.on('-tFREQ', '--target-freq=FREQ', '<Required if "--assume-profile" is Nil - Frequency to Conclude Scanning (e.g. 900.000.000 == 900 mHz>') do |e|
21
+ opts[:target_freq] = e
22
22
  end
23
23
 
24
24
  options.on('-hHOST', '--host=HOST', '<Optional - GQRX Host (Defaults to 127.0.0.1)>') do |h|
@@ -29,7 +29,7 @@ PWN::Driver::Parser.new do |options|
29
29
  opts[:port] = p
30
30
  end
31
31
 
32
- options.on('-AFLOAT', '--audio-gain=FLOAT', '<Optional - Set audio gain -80.0 to 50.0 (Defaults to 1.0)>') do |a|
32
+ options.on('-AFLOAT', '--audio-gain=FLOAT', '<Optional - Set audio gain -80.0 to 50.0 (Defaults to 9.0)>') do |a|
33
33
  opts[:audio_gain_db] = a
34
34
  end
35
35
 
@@ -37,6 +37,10 @@ PWN::Driver::Parser.new do |options|
37
37
  opts[:bandwidth] = b
38
38
  end
39
39
 
40
+ options.on('-OLAP', '--overlap-protection', '<Optional - Enable Overlap Protection to prevent false positives when scanning (Defaults to false)>') do |o|
41
+ opts[:overlap_protection] = o
42
+ end
43
+
40
44
  options.on('-DMODE', '--demodulator-mode=MODE', '<Optional - Set Demodulator Mode OFF | RAW | AM | FM | WFM | WFM_ST | WFM_ST_OIRT | LSB | USB | CW | CWL | CWU (Defaults to WFM_ST)>') do |d|
41
45
  opts[:demodulator_mode] = d
42
46
  end
@@ -45,44 +49,58 @@ PWN::Driver::Parser.new do |options|
45
49
  opts[:precision] = p
46
50
  end
47
51
 
48
- options.on('-SFLOAT', '--strength-lock=FLOAT', '<Optional - Strength to lock onto frequency (Defaults to -45.0)>') do |s|
52
+ options.on('-SFLOAT', '--strength-lock=FLOAT', '<Optional - Strength to lock onto frequency (Defaults to -70.0)>') do |s|
49
53
  opts[:strength_lock] = s
50
54
  end
51
55
 
52
- options.on('-LFLOAT', '--lock-freq-duration=FLOAT', '<Optional - Duration to lock onto Freqency when Strength < --strength-lock value (Defaults to 0.5)>') do |l|
56
+ options.on('-LFLOAT', '--lock-freq-duration=FLOAT', '<Optional - Duration to lock onto Freqency when Strength < --strength-lock value (Defaults to 0.04)>') do |l|
53
57
  opts[:lock_freq_duration] = l
54
58
  end
55
59
 
56
- options.on('-QFLOAT', '--squelch=FLOAT', '<Optional - Squelch Threshold -150.0 to 0 (Defaults to -50.0)>') do |q|
60
+ options.on('-QFLOAT', '--squelch=FLOAT', '<Optional - Squelch Threshold -150.0 to 0 (Defaults to --strength-lock - 3)>') do |q|
57
61
  opts[:squelch] = q
58
62
  end
59
63
 
60
- options.on('-RFLOAT', '--rf-gain=FLOAT', '<Optional - RF Gain 0.0-16.0(Defaults to 16.0)>') do |r|
64
+ options.on('-RFLOAT', '--rf-gain=FLOAT', '<Optional - RF Gain 0.0-16.0(Defaults to 0.0)>') do |r|
61
65
  opts[:rf_gain] = r
62
66
  end
63
67
 
64
- options.on('-IFLOAT', '--intermediate-gain=FLOAT', '<Optional - Intermediate Gain 0.0-40.0 (Defaults to 40.0)>') do |i|
68
+ options.on('-IFLOAT', '--intermediate-gain=FLOAT', '<Optional - Intermediate Gain 0.0-40.0 (Defaults to 32.0)>') do |i|
65
69
  opts[:intermediate_gain] = i
66
70
  end
67
71
 
68
72
  options.on('-BFLOAT', '--basedband-gain=FLOAT', '<Optional - Baseband Gain 0.0-62.0 (Defaults to 10.0)>') do |b|
69
73
  opts[:baseband_gain] = b
70
74
  end
75
+
76
+ options.on('-LFILE', '--scan-log=FILE', '<Optional - Path to log scan results to (Defaults to /tmp/pwn_sdr_gqrx_scan_<start_freq>-<target_freq>_<timestamp>.json)>') do |l|
77
+ opts[:scan_log] = l
78
+ end
79
+
80
+ options.on('-LOC', '--location', '<Optional - Location string to include in AI analysis (e.g. "New York, NY", 90210, GPS coords, etc.)>') do |l|
81
+ opts[:location] = l
82
+ end
71
83
  end.parse!
72
84
 
73
85
  begin
74
86
  pwn_provider = 'ruby-gem'
75
87
  pwn_provider = ENV.fetch('PWN_PROVIDER') if ENV.keys.any? { |s| s == 'PWN_PROVIDER' }
76
88
 
89
+ profiles_available = PWN::SDR::FrequencyAllocation.profiles
90
+
77
91
  list_scan_profiles = opts[:list_scan_profiles]
78
92
  if list_scan_profiles
79
- profiles_available = PWN::SDR::GQRX.list_scan_profiles
80
93
  puts JSON.pretty_generate(profiles_available)
81
94
  exit 0
82
95
  end
83
96
 
84
97
  profile = opts[:profile]
85
- opts = PWN::SDR::GQRX.assume_profile(profile: profile) unless profile.nil?
98
+ opts.merge!(profiles_available[profile.to_sym]) unless profile.nil?
99
+
100
+ start_freq = opts[:start_freq]
101
+ start_freq = start_freq.to_s.delete('.') unless start_freq.nil?
102
+ start_freq = start_freq.to_i
103
+ raise 'ERROR: Invalid start frequency.' if !start_freq.nil? && start_freq.zero?
86
104
 
87
105
  target_freq = opts[:target_freq]
88
106
  target_freq = target_freq.to_s.delete('.') unless target_freq.nil?
@@ -95,96 +113,53 @@ begin
95
113
  puts "Connecting to GQRX at #{host}:#{port}..."
96
114
  gqrx_sock = PWN::SDR::GQRX.connect(target: host, port: port)
97
115
 
98
- start_freq = opts[:start_freq]
99
- start_freq = start_freq.to_s.delete('.') unless start_freq.nil?
100
- start_freq = start_freq.to_i
101
- if start_freq.zero?
102
- start_freq = PWN::SDR::GQRX.gqrx_cmd(
103
- gqrx_sock: gqrx_sock, cmd: 'f',
104
- resp_ok: 'RPRT 0'
105
- ).to_i
106
- end
116
+ demodulator_mode = opts[:demodulator_mode]
117
+ bandwidth = opts[:bandwidth]
118
+ overlap_protection = opts[:overlap_protection]
107
119
 
108
- demodulator_mode = opts[:demodulator_mode] ||= 'WFM_ST'
109
- puts "Demodulator Mode: #{demodulator_mode}"
110
- # demodulator_mode.upcase! if opts[:demodulator_mode]
111
- demodulator_modes = %i[OFF RAW AM FM WFM WFM_ST WFM_ST_OIRT LSB USB CW CWL CWU]
112
- raise "ERROR: Invalid demodulator mode: #{demodulator_mode}" unless demodulator_modes.include?(demodulator_mode)
120
+ audio_gain_db = opts[:audio_gain_db]
121
+ audio_gain_db = audio_gain_db.to_f unless audio_gain_db.nil?
113
122
 
114
- bandwidth = opts[:bandwidth] ||= '200.000'
115
-
116
- puts "Setting demodulator mode to #{demodulator_mode} and bandwidth to #{bandwidth}..."
117
- bandwidth = bandwidth.to_s.delete('.').to_i unless bandwidth.nil?
118
- demod_resp = PWN::SDR::GQRX.gqrx_cmd(
119
- gqrx_sock: gqrx_sock,
120
- cmd: "M #{demodulator_mode} #{bandwidth}",
121
- resp_ok: 'RPRT 0'
122
- )
123
-
124
- audio_gain_db = opts[:audio_gain_db] ||= 1.0
125
- audio_gain_db = audio_gain_db.to_f
126
- audio_gain_db_resp = PWN::SDR::GQRX.gqrx_cmd(
127
- gqrx_sock: gqrx_sock,
128
- cmd: "L AF #{audio_gain_db}",
129
- resp_ok: 'RPRT 0'
130
- )
131
-
132
- squelch = opts[:squelch] ||= -63.0
133
- squelch = squelch.to_f
134
- squelch_resp = PWN::SDR::GQRX.gqrx_cmd(
135
- gqrx_sock: gqrx_sock,
136
- cmd: "L SQL #{squelch}",
137
- resp_ok: 'RPRT 0'
138
- )
123
+ squelch = opts[:squelch]
124
+ squelch = squelch.to_f unless squelch.nil?
139
125
 
140
126
  precision = opts[:precision] ||= 5
141
127
  precision = precision.to_i
142
128
  raise "ERROR: Invalid precision: #{precision}" unless (1..12).include?(precision)
143
129
 
144
- lock_freq_duration = opts[:lock_freq_duration] ||= 0.5
145
- lock_freq_duration = lock_freq_duration.to_f
146
-
147
- strength_lock = opts[:strength_lock] ||= -60.0
148
- strength_lock = strength_lock.to_f
130
+ lock_freq_duration = opts[:lock_freq_duration]
131
+ strength_lock = opts[:strength_lock]
132
+ strength_lock = strength_lock.to_f unless strength_lock.nil?
149
133
 
150
- rf_gain = opts[:rf_gain] ||= 0.0
151
- rf_gain = rf_gain.to_f
152
- rf_gain_resp = PWN::SDR::GQRX.gqrx_cmd(
153
- gqrx_sock: gqrx_sock,
154
- cmd: "L RF_GAIN #{rf_gain}",
155
- resp_ok: 'RPRT 0'
156
- )
134
+ rf_gain = opts[:rf_gain]
135
+ rf_gain = rf_gain.to_f unless rf_gain.nil?
157
136
 
158
- intermediate_gain = opts[:intermediate_gain] ||= 32.0
159
- intermediate_gain = intermediate_gain.to_f
160
- intermediate_resp = PWN::SDR::GQRX.gqrx_cmd(
161
- gqrx_sock: gqrx_sock,
162
- cmd: "L IF_GAIN #{intermediate_gain}",
163
- resp_ok: 'RPRT 0'
164
- )
137
+ intermediate_gain = opts[:intermediate_gain]
138
+ intermediate_gain = intermediate_gain.to_f unless intermediate_gain.nil?
165
139
 
166
- baseband_gain = opts[:baseband_gain] ||= 10.0
167
- baseband_gain = baseband_gain.to_f
168
- baseband_resp = PWN::SDR::GQRX.gqrx_cmd(
169
- gqrx_sock: gqrx_sock,
170
- cmd: "L BB_GAIN #{baseband_gain}",
171
- resp_ok: 'RPRT 0'
172
- )
140
+ baseband_gain = opts[:baseband_gain]
141
+ baseband_gain = baseband_gain.to_f unless baseband_gain.nil?
173
142
 
174
- s_freq_pretty = start_freq.to_s.chars.insert(-4, '.').insert(-8, '.').join
175
- t_freq_pretty = target_freq.to_s.chars.insert(-4, '.').insert(-8, '.').join
176
- puts "*** Scanning from #{s_freq_pretty} to #{t_freq_pretty}\n\n\n"
143
+ scan_log = opts[:scan_log]
144
+ location = opts[:location]
177
145
 
178
146
  PWN::SDR::GQRX.scan_range(
179
147
  gqrx_sock: gqrx_sock,
180
- demodulator_mode: demodulator_mode,
181
- bandwidth: bandwidth,
182
148
  start_freq: start_freq,
183
149
  target_freq: target_freq,
150
+ demodulator_mode: demodulator_mode,
151
+ bandwidth: bandwidth,
152
+ overlap_protection: overlap_protection,
184
153
  precision: precision,
185
154
  lock_freq_duration: lock_freq_duration,
186
155
  strength_lock: strength_lock,
187
- squelch: squelch
156
+ squelch: squelch,
157
+ audio_gain_db: audio_gain_db,
158
+ rf_gain: rf_gain,
159
+ intermediate_gain: intermediate_gain,
160
+ baseband_gain: baseband_gain,
161
+ scan_log: scan_log,
162
+ location: location
188
163
  )
189
164
  puts 'Scan Complete.'
190
165
  rescue StandardError => e
@@ -18,7 +18,7 @@ rvmsudo gem update --system
18
18
 
19
19
  if [[ $old_ruby_version == $new_ruby_version ]]; then
20
20
  export rvmsudo_secure_path=1
21
- rvmsudo /bin/bash --login -c "cd ${pwn_root} && ./reinstall_pwn_gemset.sh"
21
+ rvmsudo /bin/bash --login -c "cd ${pwn_root} && ./reinstall_gemset.sh"
22
22
  cd /tmp && cd $pwn_root
23
23
  rvmsudo rake
24
24
  rvmsudo rake install
@@ -11,9 +11,9 @@ if (( $# == 3 )); then
11
11
  git pull
12
12
  git add . --all
13
13
  echo 'Updating Gems to Latest Versions in Gemfile...'
14
- ./find_latest_gem_versions_per_Gemfile.sh
14
+ ./upgrade_Gemfile_gems.sh
15
15
  if [[ $? -ne 0 ]]; then
16
- echo 'ERROR: find_latest_gem_versions_per_Gemfile.sh failed!'
16
+ echo 'ERROR: upgrade_Gemfile_gems.sh failed!'
17
17
  exit 1
18
18
  fi
19
19
 
@@ -34,9 +34,9 @@ if (( $# == 3 )); then
34
34
  fi
35
35
 
36
36
  git commit -a -S --author="${1} <${2}>" -m "${3}"
37
- ./update_pwn.sh
37
+ ./upgrade_pwn.sh
38
38
  if [[ $? -ne 0 ]]; then
39
- echo 'ERROR: update_pwn.sh failed!'
39
+ echo 'ERROR: upgrade_pwn.sh failed!'
40
40
  exit 1
41
41
  fi
42
42
 
@@ -15,15 +15,13 @@ module PWN
15
15
 
16
16
  # Starts the live decoding thread.
17
17
  def self.start(opts = {})
18
- gqrx_obj = opts[:gqrx_obj]
19
- raise ':ERROR: :gqrx_obj is required' unless gqrx_obj.is_a?(Hash)
18
+ freq_obj = opts[:freq_obj]
19
+ raise ':ERROR: :freq_obj is required' unless freq_obj.is_a?(Hash)
20
20
 
21
- record_path = gqrx_obj[:record_path]
22
- frequency = gqrx_obj[:frequency]
23
- sample_rate = gqrx_obj[:bandwidth].to_i
24
- gqrx_sock = gqrx_obj[:gqrx_sock]
25
-
26
- gqrx_obj[:decoder_stop_flag] ||= [false]
21
+ gqrx_sock = freq_obj[:gqrx_sock]
22
+ freq = freq_obj[:freq]
23
+ bandwidth = freq_obj[:bandwidth].to_i
24
+ record_path = freq_obj[:record_path]
27
25
 
28
26
  sleep 0.1 until File.exist?(record_path)
29
27
 
@@ -32,12 +30,10 @@ module PWN
32
30
 
33
31
  bytes_read = HEADER_SIZE
34
32
 
35
- puts "GSM Decoder started for frequency: #{frequency}, sample_rate: #{sample_rate}"
33
+ puts "GSM Decoder started for freq: #{freq}, bandwidth: #{bandwidth}"
36
34
 
37
35
  Thread.new do
38
36
  loop do
39
- break if gqrx_obj[:decoder_stop_flag][0]
40
-
41
37
  current_size = File.size(record_path)
42
38
  if current_size > bytes_read
43
39
  new_bytes = current_size - bytes_read
@@ -46,8 +42,8 @@ module PWN
46
42
  data = File.binread(record_path, new_bytes, bytes_read)
47
43
  process_chunk(
48
44
  data: data,
49
- sample_rate: sample_rate,
50
- frequency: frequency
45
+ bandwidth: bandwidth,
46
+ freq: freq
51
47
  )
52
48
  bytes_read = current_size
53
49
  end
@@ -63,12 +59,11 @@ module PWN
63
59
 
64
60
  # Stops the decoding thread.
65
61
  def self.stop(opts = {})
66
- thread = opts[:thread]
67
- gqrx_obj = opts[:gqrx_obj]
68
- raise ':ERROR: :thread and :gqrx_obj are required' unless thread && gqrx_obj.is_a?(Hash)
62
+ freq_obj = opts[:freq_obj]
63
+ raise 'ERROR: :freq_obj is required' unless freq_obj.is_a?(Hash)
69
64
 
70
- gqrx_obj[:decoder_stop_flag][0] = true
71
- thread.join(1.0)
65
+ decoder_thread = freq_obj[:decoder_thread]
66
+ decoder_thread.kill if decoder_thread.is_a?(Thread)
72
67
  end
73
68
 
74
69
  class << self
@@ -76,9 +71,9 @@ module PWN
76
71
 
77
72
  def process_chunk(opts = {})
78
73
  data = opts[:data]
79
- sample_rate = opts[:sample_rate]
80
- frequency = opts[:frequency]
81
- raise ':ERROR: :data, :sample_rate, and :frequency are required' unless data && sample_rate && frequency
74
+ bandwidth = opts[:bandwidth]
75
+ freq = opts[:freq]
76
+ raise ':ERROR: :data, :bandwidth, and :freq are required' unless data && bandwidth && freq
82
77
 
83
78
  samples = data.unpack('f< *')
84
79
  return if samples.length.odd? # Skip incomplete
@@ -88,7 +83,7 @@ module PWN
88
83
  complex_samples << Complex(samples[i], samples[i + 1])
89
84
  end
90
85
 
91
- window_size = [(sample_rate * BURST_DURATION_SEC).round, complex_samples.length].min
86
+ window_size = [(bandwidth * BURST_DURATION_SEC).round, complex_samples.length].min
92
87
  return if window_size <= 0
93
88
 
94
89
  # Simplified power on sliding windows
@@ -112,10 +107,10 @@ module PWN
112
107
  return unless burst_start >= 0 && burst_start + 148 <= bits.length
113
108
 
114
109
  data_bits = extract_data_bits(bits, burst_start)
115
- puts "Burst synchronized at offset #{sync_offset} for #{frequency} Hz (power: #{max_power.round(4)})"
110
+ puts "Burst synchronized at offset #{sync_offset} for #{freq} Hz (power: #{max_power.round(4)})"
116
111
  decode_imsi(
117
112
  data_bits: data_bits,
118
- frequency: frequency
113
+ freq: freq
119
114
  )
120
115
  end
121
116
 
@@ -159,8 +154,8 @@ module PWN
159
154
 
160
155
  def decode_imsi(opts = {})
161
156
  data_bits = opts[:data_bits]
162
- frequency = opts[:frequency]
163
- raise ':ERROR: :data_bits and :frequency are required' unless data_bits && frequency
157
+ freq = opts[:freq]
158
+ raise ':ERROR: :data_bits and :freq are required' unless data_bits && freq
164
159
 
165
160
  # Simplified "IMSI extraction": Interpret first ~60 bits as packed digits (4 bits per digit, BCD-like).
166
161
  # In reality: Deinterleave (over bursts), Viterbi decode convolutional code (polys G0=10011b, G1=11011b),
@@ -180,7 +175,7 @@ module PWN
180
175
  msin = imsi_digits[6, 9].join
181
176
  imsi = "#{mcc.ljust(3, '0')}#{mnc.ljust(3, '0')}#{msin.ljust(9, '0')}"
182
177
 
183
- puts "Decoded IMSI: #{imsi} at #{frequency} Hz"
178
+ puts "Decoded IMSI: #{imsi} at #{freq} Hz"
184
179
  # TODO: Integrate full L3 parser (e.g., from ruby-gsm gem or custom).
185
180
  end
186
181
 
@@ -208,18 +203,12 @@ module PWN
208
203
  public_class_method def self.help
209
204
  puts "USAGE:
210
205
  gsm_decoder_thread = PWN::SDR::Decoder::GSM.start(
211
- gqrx_obj: {
212
- record_path: 'path/to/record.wav',
213
- frequency: 935_000_000, # Frequency in Hz
214
- bandwidth: 200_000, # Sample rate in Hz
215
- gqrx_sock: gqrx_socket_object
216
- }
206
+ freq_obj: 'required - freq_obj returned from PWN::SDR::Receiver::GQRX.init_freq method'
217
207
  )
218
208
 
219
209
  # To stop the decoder thread:
220
210
  PWN::SDR::Decoder::GSM.stop(
221
- thread: gsm_decoder_thread,
222
- gqrx_obj: gqrx_object_used_to_start_decoder
211
+ freq_obj: 'required - freq_obj returned from PWN::SDR::Receiver::GQRX.init_freq method'
223
212
  )
224
213
 
225
214
  #{self}.authors