pwn 0.5.51 → 0.5.53

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: cfe0f518a0867cb7c25b3fa05d62b9497971f740288cf12cade05dfd32428063
4
- data.tar.gz: 3a79b2526bb5b1a8d312c42b335eea3bba9ff0518e5aa05fcbf663c11276064b
3
+ metadata.gz: 8d7b279b641bea38f8be26582ae7a126014489e2190f28752a48c4ea09410512
4
+ data.tar.gz: 691b05b08f109cc027cf108d6e601fba9f76d1c794a72e8ddb946cdbefc3a40f
5
5
  SHA512:
6
- metadata.gz: cf5419afa046d2259be2497bb82f994495530144f13873990c31691c869055205fe4106a9844f1c150be413afff1e7c38e0e24656b09134aca31b1acd2c63dae
7
- data.tar.gz: 06b5f917e2e63e88eee092751b39d308d7397dff0769a8ea786e6df4d18124865d698c7dcfa518db40f529ff2d609b50c2b8afbccd6f12538e42df461a50991d
6
+ metadata.gz: bb6a6d1c1a39c9a29af063304af7329ae094b801cdc4eab6f0f092fc65bf416c7f32301bd093bedf3a44eae5bea19c94005cdf7cde9e36cdc66bbea1a623c303
7
+ data.tar.gz: 7400d10c061b0f2bb4f0a89efe80a9244f3eced6df20f95905525abb48808b745ce343a6e434b1f1ca750e85640a4f1c7c36da9f2f4b3d9dd22a4ac1a7ebb714
data/Gemfile CHANGED
@@ -52,7 +52,7 @@ gem 'net-ldap', '0.19.0'
52
52
  gem 'net-openvpn', '0.8.7'
53
53
  gem 'net-smtp', '0.4.0.1'
54
54
  gem 'nexpose', '7.3.0'
55
- gem 'nokogiri', '1.16.2'
55
+ gem 'nokogiri', '1.16.3'
56
56
  gem 'nokogiri-diff', '0.3.0'
57
57
  gem 'oily_png', '1.2.1'
58
58
  gem 'open3', '0.2.1'
@@ -87,7 +87,7 @@ gem 'serialport', '1.3.2'
87
87
  gem 'slack-ruby-client', '2.3.0'
88
88
  gem 'socksify', '1.7.1'
89
89
  gem 'spreadsheet', '1.3.1'
90
- gem 'sqlite3', '1.7.2'
90
+ gem 'sqlite3', '1.7.3'
91
91
  gem 'thin', '1.8.2'
92
92
  gem 'tty-prompt', '0.23.1'
93
93
  gem 'tty-spinner', '0.9.3'
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.51]:001 >>> PWN.help
40
+ pwn[v0.5.53]: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.3.0@pwn
52
52
  $ gem uninstall --all --executables pwn
53
53
  $ gem install --verbose pwn
54
54
  $ pwn
55
- pwn[v0.5.51]:001 >>> PWN.help
55
+ pwn[v0.5.53]: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.3.0@pwn
62
62
  $ rvmsudo gem uninstall --all --executables pwn
63
63
  $ rvmsudo gem install --verbose pwn
64
64
  $ pwn
65
- pwn[v0.5.51]:001 >>> PWN.help
65
+ pwn[v0.5.53]: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
@@ -2,6 +2,7 @@
2
2
  # frozen_string_literal: false
3
3
 
4
4
  require 'pwn'
5
+ require 'json'
5
6
  require 'optparse'
6
7
 
7
8
  opts = {}
@@ -14,10 +15,6 @@ OptionParser.new do |options|
14
15
  opts[:target_freq] = e
15
16
  end
16
17
 
17
- options.on('-dMODE', '--demodulator-mode=MODE', '<Optional - Set Demodulator ModeOFF | RAW | AM | FM | WFM | WFM_ST | WFM_ST_OIRT | LSB |USB | CW | CWL | CWU (Defaults to AM)>') do |d|
18
- opts[:demodulator_mode] = d
19
- end
20
-
21
18
  options.on('-sFREQ', '--start-freq=FREQ', '<Optional - Frequency to Set when Scanning Begins (Defaults to last known frequency)>') do |s|
22
19
  opts[:start_freq] = s
23
20
  end
@@ -30,12 +27,32 @@ OptionParser.new do |options|
30
27
  opts[:port] = p
31
28
  end
32
29
 
33
- options.on('-PPLACE', '--precision=PLACE', '<Optional - Precision of Frequency 1-12 (Defaults to 3)>') do |p|
30
+ options.on('-AFLOAT', '--audio-gain=FLOAT', '<Optional - Set audio gain -80.0 to 50.0 (Defaults to 1.0)>') do |a|
31
+ opts[:audio_gain_db] = a
32
+ end
33
+
34
+ options.on('-BHZ', '--bandwidth=HZ', '<Optional - Set Bandwidth (Defaults to 240.000)>') do |b|
35
+ opts[:bandwidth] = b
36
+ end
37
+
38
+ options.on('-DMODE', '--demodulator-mode=MODE', '<Optional - Set Demodulator ModeOFF | RAW | AM | FM | WFM | WFM_ST | WFM_ST_OIRT | LSB |USB | CW | CWL | CWU (Defaults to WFM_ST)>') do |d|
39
+ opts[:demodulator_mode] = d
40
+ end
41
+
42
+ options.on('-LFLOAT', '--lock-freq-duration=FLOAT', '<Optional - Duration to lock onto Freqency when Strength < --strength value (Defaults to 3)>') do |l|
43
+ opts[:lock_on_freq_duration] = l
44
+ end
45
+
46
+ options.on('-QFLOAT', '--squelch=FLOAT', '<Optional - Squelch Threshold -150 to 0(Defaults to -63.0)>') do |q|
47
+ opts[:squelch] = q
48
+ end
49
+
50
+ options.on('-PINT', '--precision=INT', '<Optional - Precision of Frequency 1-12 (Defaults to 6)>') do |p|
34
51
  opts[:precision] = p
35
52
  end
36
53
 
37
- options.on('-SFLOAT', '--sleep-between-hops=FLOAT', '<Optional - Float to Sleep Between Hops (Defaults to 0)>') do |s|
38
- opts[:sleep_between_hops] = s
54
+ options.on('-SFLOAT', '--strength=FLOAT', '<Optional - Strength to trigger sleep (Defaults to -63.3)>') do |s|
55
+ opts[:strength] = s
39
56
  end
40
57
  end.parse!
41
58
 
@@ -45,76 +62,204 @@ if opts.empty?
45
62
  end
46
63
 
47
64
  def gqrx_cmd(opts = {})
48
- # f - Get frequency [Hz]
49
- # F - Set frequency [Hz]
50
- # m - Get demodulator mode
51
- # M - Set demodulator mode (OFF, RAW, AM, FM, WFM, WFM_ST,
52
- # WFM_ST_OIRT, LSB, USB, CW, CWL, CWU)
53
- # l STRENGTH - Get signal strength [dBFS]
54
- # l SQL - Get squelch threshold [dBFS]
55
- # L SQL <sql> - Set squelch threshold to <sql> [dBFS]
56
- # u RECORD - Get status of audio recorder
57
- # U RECORD <status> - Set status of audio recorder to <status>
58
- # c - Close connection
59
- # AOS - Acquisition of signal (AOS) event, start audio recording
60
- # LOS - Loss of signal (LOS) event, stop audio recording
61
- # \dump_state - Dump state (only usable for compatibility)
62
65
  gqrx_sock = opts[:gqrx_sock]
63
66
  cmd = opts[:cmd]
67
+ resp_ok = opts[:resp_ok]
68
+
69
+ # Most Recent GQRX Command Set:
70
+ # https://raw.githubusercontent.com/gqrx-sdr/gqrx/master/resources/remote-control.txt
71
+ # Supported commands:
72
+ # f Get frequency [Hz]
73
+ # F <frequency> Set frequency [Hz]
74
+ # m Get demodulator mode and passband
75
+ # M <mode> [passband]
76
+ # Set demodulator mode and passband [Hz]
77
+ # Passing a '?' as the first argument instead of 'mode' will return
78
+ # a space separated list of radio backend supported modes.
79
+ # l|L ?
80
+ # Get a space separated list of settings available for reading (l) or writing (L).
81
+ # l STRENGTH
82
+ # Get signal strength [dBFS]
83
+ # l SQL
84
+ # Get squelch threshold [dBFS]
85
+ # L SQL <sql>
86
+ # Set squelch threshold to <sql> [dBFS]
87
+ # l AF
88
+ # Get audio gain [dB]
89
+ # L AF <gain>
90
+ # Set audio gain to <gain> [dB]
91
+ # l <gain_name>_GAIN
92
+ # Get the value of the gain setting with the name <gain_name>
93
+ # L <gain_name>_GAIN <value>
94
+ # Set the value of the gain setting with the name <gain_name> to <value>
95
+ # p RDS_PI
96
+ # Get the RDS PI code (in hexadecimal). Returns 0000 if not applicable.
97
+ # u RECORD
98
+ # Get status of audio recorder
99
+ # U RECORD <status>
100
+ # Set status of audio recorder to <status>
101
+ # u DSP
102
+ # Get DSP (SDR receiver) status
103
+ # U DSP <status>
104
+ # Set DSP (SDR receiver) status to <status>
105
+ # u RDS
106
+ # Get RDS decoder to <status>. Only functions in WFM mode.
107
+ # U RDS <status>
108
+ # Set RDS decoder to <status>. Only functions in WFM mode.
109
+ # q|Q
110
+ # Close connection
111
+ # AOS
112
+ # Acquisition of signal (AOS) event, start audio recording
113
+ # LOS
114
+ # Loss of signal (LOS) event, stop audio recording
115
+ # LNB_LO [frequency]
116
+ # If frequency [Hz] is specified set the LNB LO frequency used for
117
+ # display. Otherwise print the current LNB LO frequency [Hz].
118
+ # \chk_vfo
119
+ # Get VFO option status (only usable for hamlib compatibility)
120
+ # \dump_state
121
+ # Dump state (only usable for hamlib compatibility)
122
+ # \get_powerstat
123
+ # Get power status (only usable for hamlib compatibility)
124
+ # v
125
+ # Get 'VFO' (only usable for hamlib compatibility)
126
+ # V
127
+ # Set 'VFO' (only usable for hamlib compatibility)
128
+ # s
129
+ # Get 'Split' mode (only usable for hamlib compatibility)
130
+ # S
131
+ # Set 'Split' mode (only usable for hamlib compatibility)
132
+ # _
133
+ # Get version
134
+ #
135
+ # Reply:
136
+ # RPRT 0
137
+ # Command successful
138
+ # RPRT 1
139
+ # Command failed
64
140
 
65
141
  gqrx_sock.write("#{cmd}\n")
66
- does_respond = gqrx_sock.wait_readable
67
- gqrx_sock.readline.chomp if does_respond
142
+ response = []
143
+ got_freq = false
144
+ # Read all responses from gqrx_sock.write
145
+ timeout = 0.01 if timeout.nil?
146
+ begin
147
+ response.push(gqrx_sock.readline.chomp) while gqrx_sock.wait_readable(timeout)
148
+ raise IOError if response.empty?
149
+ rescue IOError
150
+ timeout += 0.001
151
+ retry
152
+ end
153
+
154
+ got_int_value_in_resp = true if response.first.to_i.positive?
155
+ response = response.first if response.length == 1
156
+
157
+ raise "ERROR!!! Command: #{cmd} Expected Resp: #{resp_ok}, Got: #{response}" if resp_ok && response != resp_ok
158
+
159
+ if got_int_value_in_resp
160
+ fixed_len_freq = format('%0.12d', response.to_i)
161
+ freq_segments = fixed_len_freq.scan(/.{3}/)
162
+ first_non_zero_index = freq_segments.index { |s| s.to_i.positive? }
163
+ freq_segments = freq_segments[first_non_zero_index..-1]
164
+ freq_segments[0] = freq_segments.first.to_i.to_s
165
+ response = freq_segments.join('.')
166
+ end
167
+
168
+ # DEBUG
169
+ # puts response.inspect
170
+ # puts response.length
171
+
172
+ response
68
173
  end
69
174
 
70
175
  def init_freq(opts = {})
71
176
  gqrx_sock = opts[:gqrx_sock]
177
+ demodulator_mode = opts[:demodulator_mode]
178
+ bandwidth = opts[:bandwidth]
72
179
  this_freq = opts[:this_freq]
73
- sleep_between_hops = opts[:sleep_between_hops]
180
+ lock_on_freq_duration = opts[:lock_on_freq_duration]
181
+ strength = opts[:strength]
182
+
183
+ demod_n_passband = gqrx_cmd(
184
+ gqrx_sock: gqrx_sock,
185
+ cmd: 'm'
186
+ )
74
187
 
75
- resp = gqrx_cmd(
188
+ change_freq_resp = gqrx_cmd(
76
189
  gqrx_sock: gqrx_sock,
77
- cmd: "F #{this_freq}"
190
+ cmd: "F #{this_freq}",
191
+ resp_ok: 'RPRT 0'
78
192
  )
79
- raise "ERROR: Failed to set frequency to #{this_freq}" unless resp == 'RPRT 0'
80
193
 
81
- resp = gqrx_cmd(
194
+ current_freq = gqrx_cmd(
82
195
  gqrx_sock: gqrx_sock,
83
196
  cmd: 'f'
84
197
  )
85
198
 
86
- # Split the response from NNNNNNNNN
87
- # to NNN.NNN.NNN
88
- this_freq = resp.to_s.chars.insert(-4, '.').insert(-8, '.').join
89
- puts ">>> #{this_freq}"
90
- sleep sleep_between_hops
199
+ current_strength = gqrx_cmd(
200
+ gqrx_sock: gqrx_sock,
201
+ cmd: 'l STRENGTH'
202
+ ).to_f
203
+
204
+ current_squelch = gqrx_cmd(
205
+ gqrx_sock: gqrx_sock,
206
+ cmd: 'l SQL'
207
+ ).to_f
208
+
209
+ audio_gain_db = gqrx_cmd(
210
+ gqrx_sock: gqrx_sock,
211
+ cmd: 'l AF'
212
+ ).to_f
213
+
214
+ init_freq_hash = {
215
+ demod_mode_n_passband: demod_n_passband,
216
+ frequency: current_freq,
217
+ audio_gain_db: audio_gain_db,
218
+ squelch: current_squelch,
219
+ strength: current_strength,
220
+ trigger_lock_on_freq_strength: strength
221
+ }
222
+ puts JSON.pretty_generate(init_freq_hash)
223
+
224
+ sleep lock_on_freq_duration if current_strength < strength
225
+
226
+ init_freq_hash
91
227
  end
92
228
 
93
229
  def scan_range(opts = {})
94
230
  gqrx_sock = opts[:gqrx_sock]
231
+ demodulator_mode = opts[:demodulator_mode]
232
+ bandwidth = opts[:bandwidth]
95
233
  start_freq = opts[:start_freq]
96
234
  target_freq = opts[:target_freq]
97
235
  precision = opts[:precision]
98
- sleep_between_hops = opts[:sleep_between_hops]
236
+ lock_on_freq_duration = opts[:lock_on_freq_duration]
237
+ strength = opts[:strength]
99
238
 
100
239
  multiplier = 10**(precision - 1)
101
240
  if start_freq > target_freq
102
241
  start_freq.downto(target_freq) do |this_freq|
103
242
  next unless (i % multiplier).zero?
104
243
 
105
- init_freq(
244
+ init_freq_hash = init_freq(
106
245
  gqrx_sock: gqrx_sock,
246
+ demodulator_mode: demodulator_mode,
247
+ bandwidth: bandwidth,
107
248
  this_freq: this_freq,
108
- sleep_between_hops: sleep_between_hops
249
+ lock_on_freq_duration: lock_on_freq_duration,
250
+ strength: strength
109
251
  )
110
252
  end
111
253
  else
112
254
  this_freq = start_freq
113
255
  while this_freq <= target_freq
114
- init_freq(
256
+ init_freq_hash = init_freq(
115
257
  gqrx_sock: gqrx_sock,
258
+ demodulator_mode: demodulator_mode,
259
+ bandwidth: bandwidth,
116
260
  this_freq: this_freq,
117
- sleep_between_hops: sleep_between_hops
261
+ lock_on_freq_duration: lock_on_freq_duration,
262
+ strength: strength
118
263
  )
119
264
 
120
265
  this_freq += multiplier
@@ -126,46 +271,81 @@ begin
126
271
  pwn_provider = 'ruby-gem'
127
272
  pwn_provider = ENV.fetch('PWN_PROVIDER') if ENV.keys.any? { |s| s == 'PWN_PROVIDER' }
128
273
 
129
- demodulator_mode = opts[:demodulator_mode] ||= 'AM'
130
- demodulator_mode.upcase!
131
- raise "ERROR: Invalid demodulator mode: #{demodulator_mode}" unless %w[OFF RAW AM FM WFM WFM_ST WFM_ST_OIRT LSB USB CW CWL CWU].include?(demodulator_mode)
274
+ target_freq = opts[:target_freq]
275
+ target_freq = target_freq.to_s.delete('.') unless target_freq.nil?
276
+ target_freq = target_freq.to_i
277
+ raise "ERROR: Invalid target frequency #{target_freq}" if target_freq.zero?
132
278
 
133
279
  host = opts[:host] ||= '127.0.0.1'
134
280
  port = opts[:port] ||= 7356
135
- puts "Connecting to GQRX at #{host}:#{port}..."
136
281
 
282
+ puts "Connecting to GQRX at #{host}:#{port}..."
137
283
  gqrx_sock = PWN::Plugins::Sock.connect(target: host, port: port)
138
- puts "Setting demodulator mode to #{demodulator_mode}..."
139
- demod_resp = gqrx_cmd(gqrx_sock: gqrx_sock, cmd: "M #{demodulator_mode}")
140
- puts demod_resp
141
284
 
142
285
  start_freq = opts[:start_freq]
143
- start_freq = start_freq.to_s.delete('.').to_i unless start_freq.nil?
144
- start_freq = gqrx_cmd(gqrx_sock: gqrx_sock, cmd: 'f').to_i if start_freq.nil?
286
+ start_freq = start_freq.to_s.delete('.') unless start_freq.nil?
287
+ start_freq = start_freq.to_i
288
+ start_freq = gqrx_cmd(gqrx_sock: gqrx_sock, cmd: 'f', resp_ok: 'RPRT 0').to_i if start_freq.zero?
145
289
 
146
- target_freq = opts[:target_freq]
147
- target_freq = target_freq.to_s.delete('.').to_i unless target_freq.nil?
148
- raise 'ERROR: Invalid end frequency' if target_freq.nil?
290
+ demodulator_mode = opts[:demodulator_mode] ||= 'WFM_ST'
291
+ demodulator_mode.upcase!
292
+ raise "ERROR: Invalid demodulator mode: #{demodulator_mode}" unless %w[OFF RAW AM FM WFM WFM_ST WFM_ST_OIRT LSB USB CW CWL CWU].include?(demodulator_mode)
149
293
 
150
- puts "Scanning from #{start_freq} to #{target_freq}..."
294
+ bandwidth = opts[:bandwidth] ||= '240.000'
151
295
 
152
- precision = opts[:precision] ||= 3
296
+ puts "Setting demodulator mode to #{demodulator_mode} and bandwidth to #{bandwidth}..."
297
+ bandwidth = bandwidth.to_s.delete('.').to_i unless bandwidth.nil?
298
+ demod_resp = gqrx_cmd(
299
+ gqrx_sock: gqrx_sock,
300
+ cmd: "M #{demodulator_mode} #{bandwidth}",
301
+ resp_ok: 'RPRT 0'
302
+ )
303
+
304
+ squelch = opts[:squelch] ||= -63.0
305
+ squelch = squelch.to_f
306
+ squelch_resp = gqrx_cmd(
307
+ gqrx_sock: gqrx_sock,
308
+ cmd: "L SQL #{squelch}",
309
+ resp_ok: 'RPRT 0'
310
+ )
311
+
312
+ precision = opts[:precision] ||= 6
153
313
  precision = precision.to_i
154
314
  raise "ERROR: Invalid precision: #{precision}" unless (1..12).include?(precision)
155
315
 
156
- sleep_between_hops = opts[:sleep_between_hops] ||= 0
157
- sleep_between_hops = sleep_between_hops.to_f
316
+ lock_on_freq_duration = opts[:lock_on_freq_duration] ||= 3
317
+ lock_on_freq_duration = lock_on_freq_duration.to_f
318
+
319
+ strength = opts[:strength] ||= -63.3
320
+ strength = strength.to_f
321
+
322
+ audio_gain_db = opts[:audio_gain_db] ||= 1.0
323
+ audio_gain_db = audio_gain_db.to_f
324
+ audio_gain_db_resp = gqrx_cmd(
325
+ gqrx_sock: gqrx_sock,
326
+ cmd: "L AF #{audio_gain_db}",
327
+ resp_ok: 'RPRT 0'
328
+ )
329
+
330
+ s_freq_pretty = start_freq.to_s.chars.insert(-4, '.').insert(-8, '.').join
331
+ t_freq_pretty = target_freq.to_s.chars.insert(-4, '.').insert(-8, '.').join
332
+ puts "*** Scanning from #{s_freq_pretty} to #{t_freq_pretty}"
158
333
 
159
334
  scan_range(
160
335
  gqrx_sock: gqrx_sock,
336
+ demodulator_mode: demodulator_mode,
161
337
  start_freq: start_freq,
162
338
  target_freq: target_freq,
163
339
  precision: precision,
164
- sleep_between_hops: sleep_between_hops
340
+ lock_on_freq_duration: lock_on_freq_duration,
341
+ strength: strength,
342
+ squelch: squelch
165
343
  )
166
- rescue SystemExit, Interrupt
344
+ puts 'Scan Complete.'
345
+ rescue StandardError => e
346
+ raise e
347
+ rescue Interrupt, SystemExit
167
348
  puts "\nGoodbye."
168
349
  ensure
169
- resp = gqrx_cmd(gqrx_sock: gqrx_sock, cmd: 'c')
170
350
  gqrx_sock = PWN::Plugins::Sock.disconnect(sock_obj: gqrx_sock)
171
351
  end
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.51'
4
+ VERSION = '0.5.53'
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.51
4
+ version: 0.5.53
5
5
  platform: ruby
6
6
  authors:
7
7
  - 0day Inc.
@@ -562,14 +562,14 @@ dependencies:
562
562
  requirements:
563
563
  - - '='
564
564
  - !ruby/object:Gem::Version
565
- version: 1.16.2
565
+ version: 1.16.3
566
566
  type: :runtime
567
567
  prerelease: false
568
568
  version_requirements: !ruby/object:Gem::Requirement
569
569
  requirements:
570
570
  - - '='
571
571
  - !ruby/object:Gem::Version
572
- version: 1.16.2
572
+ version: 1.16.3
573
573
  - !ruby/object:Gem::Dependency
574
574
  name: nokogiri-diff
575
575
  requirement: !ruby/object:Gem::Requirement
@@ -1038,14 +1038,14 @@ dependencies:
1038
1038
  requirements:
1039
1039
  - - '='
1040
1040
  - !ruby/object:Gem::Version
1041
- version: 1.7.2
1041
+ version: 1.7.3
1042
1042
  type: :runtime
1043
1043
  prerelease: false
1044
1044
  version_requirements: !ruby/object:Gem::Requirement
1045
1045
  requirements:
1046
1046
  - - '='
1047
1047
  - !ruby/object:Gem::Version
1048
- version: 1.7.2
1048
+ version: 1.7.3
1049
1049
  - !ruby/object:Gem::Dependency
1050
1050
  name: thin
1051
1051
  requirement: !ruby/object:Gem::Requirement