pwn 0.5.532 → 0.5.534
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 +4 -4
- data/.rubocop.yml +1 -1
- data/.rubocop_todo.yml +25 -3
- data/Gemfile +6 -5
- data/README.md +3 -3
- data/lib/pwn/plugins/burp_suite.rb +24 -10
- data/lib/pwn/plugins/file_fu.rb +50 -0
- data/lib/pwn/plugins/sock.rb +111 -48
- data/lib/pwn/sdr/decoder/flex.rb +257 -0
- data/lib/pwn/sdr/decoder/pocsag.rb +182 -57
- data/lib/pwn/sdr/decoder/rds.rb +4 -4
- data/lib/pwn/sdr/decoder.rb +1 -0
- data/lib/pwn/sdr/frequency_allocation.rb +13 -6
- data/lib/pwn/sdr/gqrx.rb +426 -170
- data/lib/pwn/version.rb +1 -1
- data/spec/lib/pwn/sdr/decoder/flex_spec.rb +15 -0
- data/third_party/pwn_rdoc.jsonl +10 -7
- metadata +28 -12
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: db3ea69e1f438111e509b6804f35881807e884b9fc78f24ce1709b7b9eb48a81
|
|
4
|
+
data.tar.gz: abc44bd86a1c8e7e96021a01781695cc042d42ae80268e9f3628809c8952db3e
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: a4d6cb9b3a97311baad192e618e0124cbfa11d29b172860cbbc247109d62de675f0f9279ebc487b923b5cb2d482d478a6261e7cbd6bf6fcd3b498dcef59fb89f
|
|
7
|
+
data.tar.gz: 4e44bdb57b158c6b5129b969dd3411f6a47c2cb15f663399a68df5043ad5bf48f50a20c484e20a05c16607d752d64ae5d1381cdaf53aadf5342ba10a09941cf6
|
data/.rubocop.yml
CHANGED
data/.rubocop_todo.yml
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# This configuration was generated by
|
|
2
2
|
# `rubocop --auto-gen-config`
|
|
3
|
-
# on
|
|
3
|
+
# on 2026-01-26 19:15:57 UTC using RuboCop version 1.82.1.
|
|
4
4
|
# The point is for the user to remove these configuration records
|
|
5
5
|
# one by one as the offenses are removed from the code base.
|
|
6
6
|
# Note that changes in the inspected code, or installation of new
|
|
@@ -30,7 +30,13 @@ Lint/RedundantTypeConversion:
|
|
|
30
30
|
- 'lib/pwn/plugins/jenkins.rb'
|
|
31
31
|
- 'lib/pwn/plugins/repl.rb'
|
|
32
32
|
|
|
33
|
-
# Offense count:
|
|
33
|
+
# Offense count: 4
|
|
34
|
+
Lint/ShadowedException:
|
|
35
|
+
Exclude:
|
|
36
|
+
- 'lib/pwn/sdr/decoder/flex.rb'
|
|
37
|
+
- 'lib/pwn/sdr/decoder/pocsag.rb'
|
|
38
|
+
|
|
39
|
+
# Offense count: 301
|
|
34
40
|
# This cop supports safe autocorrection (--autocorrect).
|
|
35
41
|
Lint/UselessAssignment:
|
|
36
42
|
Enabled: false
|
|
@@ -137,11 +143,13 @@ Style/MultipleComparison:
|
|
|
137
143
|
- 'lib/pwn/www/duckduckgo.rb'
|
|
138
144
|
- 'lib/pwn/www/twitter.rb'
|
|
139
145
|
|
|
140
|
-
# Offense count:
|
|
146
|
+
# Offense count: 5
|
|
141
147
|
# This cop supports safe autocorrection (--autocorrect).
|
|
142
148
|
Style/RedundantBegin:
|
|
143
149
|
Exclude:
|
|
144
150
|
- 'lib/pwn/plugins/transparent_browser.rb'
|
|
151
|
+
- 'lib/pwn/sdr/decoder/flex.rb'
|
|
152
|
+
- 'lib/pwn/sdr/decoder/pocsag.rb'
|
|
145
153
|
|
|
146
154
|
# Offense count: 94
|
|
147
155
|
# This cop supports safe autocorrection (--autocorrect).
|
|
@@ -151,6 +159,13 @@ Style/RedundantCondition:
|
|
|
151
159
|
Exclude:
|
|
152
160
|
- 'lib/pwn/plugins/packet.rb'
|
|
153
161
|
|
|
162
|
+
# Offense count: 2
|
|
163
|
+
# This cop supports safe autocorrection (--autocorrect).
|
|
164
|
+
Style/RedundantSelf:
|
|
165
|
+
Exclude:
|
|
166
|
+
- 'lib/pwn/sdr/decoder/flex.rb'
|
|
167
|
+
- 'lib/pwn/sdr/decoder/pocsag.rb'
|
|
168
|
+
|
|
154
169
|
# Offense count: 12
|
|
155
170
|
# This cop supports safe autocorrection (--autocorrect).
|
|
156
171
|
Style/RedundantStringEscape:
|
|
@@ -161,6 +176,13 @@ Style/RedundantStringEscape:
|
|
|
161
176
|
- 'lib/pwn/sast/redos.rb'
|
|
162
177
|
- 'vagrant/provisioners/kali_customize.rb'
|
|
163
178
|
|
|
179
|
+
# Offense count: 6
|
|
180
|
+
# This cop supports safe autocorrection (--autocorrect).
|
|
181
|
+
Style/RescueModifier:
|
|
182
|
+
Exclude:
|
|
183
|
+
- 'lib/pwn/sdr/decoder/flex.rb'
|
|
184
|
+
- 'lib/pwn/sdr/decoder/pocsag.rb'
|
|
185
|
+
|
|
164
186
|
# Offense count: 19
|
|
165
187
|
# This cop supports unsafe autocorrection (--autocorrect-all).
|
|
166
188
|
Style/SlicingWithRange:
|
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.2'
|
|
22
22
|
gem 'bson', '5.2.0'
|
|
23
|
-
gem 'bundler', '>=4.0.
|
|
23
|
+
gem 'bundler', '>=4.0.4'
|
|
24
24
|
gem 'bundler-audit', '>=0.9.3'
|
|
25
25
|
gem 'bunny', '2.24.0'
|
|
26
26
|
gem 'colorize', '1.1.0'
|
|
@@ -29,7 +29,7 @@ gem 'curses', '1.5.3'
|
|
|
29
29
|
gem 'diffy', '3.4.4'
|
|
30
30
|
gem 'eventmachine', '1.2.7'
|
|
31
31
|
gem 'executable-hooks', '1.7.1'
|
|
32
|
-
gem 'faker', '3.
|
|
32
|
+
gem 'faker', '3.6.0'
|
|
33
33
|
gem 'faye-websocket', '0.12.0'
|
|
34
34
|
gem 'ffi', '1.17.3'
|
|
35
35
|
# gem 'fftw3', '0.3'
|
|
@@ -49,6 +49,7 @@ 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 'mcp', '0.6.0'
|
|
52
53
|
gem 'meshtastic', '0.0.151'
|
|
53
54
|
gem 'metasm', '1.0.5'
|
|
54
55
|
gem 'mongo', '2.22.0'
|
|
@@ -69,11 +70,11 @@ gem 'packetgen', '4.1.1'
|
|
|
69
70
|
gem 'pdf-reader', '2.15.1'
|
|
70
71
|
gem 'pg', '1.6.3'
|
|
71
72
|
gem 'pry', '0.16.0'
|
|
72
|
-
gem 'pry-doc', '1.
|
|
73
|
+
gem 'pry-doc', '1.7.0'
|
|
73
74
|
gem 'rake', '13.3.1'
|
|
74
75
|
gem 'rb-readline', '0.5.5'
|
|
75
76
|
gem 'rbvmomi2', '3.8.0'
|
|
76
|
-
gem 'rdoc', '7.0
|
|
77
|
+
gem 'rdoc', '7.1.0'
|
|
77
78
|
gem 'rest-client', '2.1.0'
|
|
78
79
|
gem 'rex', '2.0.13'
|
|
79
80
|
gem 'rmagick', '6.1.5'
|
|
@@ -89,7 +90,7 @@ gem 'ruby-saml', '1.18.1'
|
|
|
89
90
|
gem 'rvm', '1.11.3.9'
|
|
90
91
|
gem 'savon', '2.15.1'
|
|
91
92
|
gem 'selenium-devtools', '0.143.0'
|
|
92
|
-
gem 'selenium-webdriver', '4.
|
|
93
|
+
gem 'selenium-webdriver', '4.40.0'
|
|
93
94
|
gem 'slack-ruby-client', '3.1.0'
|
|
94
95
|
gem 'socksify', '1.8.1'
|
|
95
96
|
gem 'spreadsheet', '1.3.4'
|
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.
|
|
40
|
+
pwn[v0.5.534]:001 >>> PWN.help
|
|
41
41
|
```
|
|
42
42
|
|
|
43
43
|
[](https://youtu.be/G7iLUY4FzsI)
|
|
@@ -52,7 +52,7 @@ $ rvm use ruby-4.0.0@pwn
|
|
|
52
52
|
$ gem uninstall --all --executables pwn
|
|
53
53
|
$ gem install --verbose pwn
|
|
54
54
|
$ pwn
|
|
55
|
-
pwn[v0.5.
|
|
55
|
+
pwn[v0.5.534]: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-4.0.0@pwn
|
|
|
62
62
|
$ rvmsudo gem uninstall --all --executables pwn
|
|
63
63
|
$ rvmsudo gem install --verbose pwn
|
|
64
64
|
$ pwn
|
|
65
|
-
pwn[v0.5.
|
|
65
|
+
pwn[v0.5.534]: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:
|
|
@@ -124,6 +124,7 @@ module PWN
|
|
|
124
124
|
highlight_color
|
|
125
125
|
end
|
|
126
126
|
|
|
127
|
+
default_http_ports = [80, 443]
|
|
127
128
|
loop do
|
|
128
129
|
# TODO: Implement repeater into the loop? This reduces load to LLM but is slooow.
|
|
129
130
|
# Repeater should analyze the reqesut/response pair and suggest
|
|
@@ -133,15 +134,20 @@ module PWN
|
|
|
133
134
|
sitemap = get_sitemap(burp_obj: burp_obj)
|
|
134
135
|
proxy_history = get_proxy_history(burp_obj: burp_obj)
|
|
135
136
|
proxy_history.each do |entry|
|
|
136
|
-
next unless entry.key?(:comment) && entry[:comment].to_s.strip.empty?
|
|
137
|
-
|
|
138
137
|
request = entry[:request]
|
|
139
138
|
response = entry[:response]
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
139
|
+
http_service = entry[:http_service]
|
|
140
|
+
protocol = http_service[:protocol]
|
|
141
|
+
host = http_service[:host]
|
|
142
|
+
port = http_service[:port]
|
|
143
143
|
next if request.nil? || response.nil? || host.nil? || port.nil? || protocol.nil?
|
|
144
144
|
|
|
145
|
+
uri = "#{protocol}://#{host}"
|
|
146
|
+
uri = "#{protocol}://#{host}:#{port}" unless default_http_ports.include?(port)
|
|
147
|
+
next unless in_scope(burp_obj: burp_obj, uri: uri)
|
|
148
|
+
|
|
149
|
+
next unless entry.key?(:comment) && entry[:comment].to_s.strip.empty?
|
|
150
|
+
|
|
145
151
|
# If sitemap comment and highlight color exists, use that instead of re-analyzing
|
|
146
152
|
sitemap_entry = nil
|
|
147
153
|
if sitemap.any?
|
|
@@ -186,15 +192,20 @@ module PWN
|
|
|
186
192
|
proxy_history = get_proxy_history(burp_obj: burp_obj)
|
|
187
193
|
sitemap = get_sitemap(burp_obj: burp_obj)
|
|
188
194
|
sitemap.each do |entry|
|
|
189
|
-
next unless entry.key?(:comment) && entry[:comment].to_s.strip.empty?
|
|
190
|
-
|
|
191
195
|
request = entry[:request]
|
|
192
196
|
response = entry[:response]
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
197
|
+
http_service = entry[:http_service]
|
|
198
|
+
protocol = http_service[:protocol]
|
|
199
|
+
host = http_service[:host]
|
|
200
|
+
port = http_service[:port]
|
|
196
201
|
next if request.nil? || response.nil? || host.nil? || port.nil? || protocol.nil?
|
|
197
202
|
|
|
203
|
+
uri = "#{protocol}://#{host}"
|
|
204
|
+
uri = "#{protocol}://#{host}:#{port}" unless default_http_ports.include?(port)
|
|
205
|
+
next unless in_scope(burp_obj: burp_obj, uri: uri)
|
|
206
|
+
|
|
207
|
+
next unless entry.key?(:comment) && entry[:comment].to_s.strip.empty?
|
|
208
|
+
|
|
198
209
|
proxy_history_entry = nil
|
|
199
210
|
if proxy_history.any?
|
|
200
211
|
proxy_history_entry = proxy_history.find do |proxy_entry|
|
|
@@ -236,6 +247,9 @@ module PWN
|
|
|
236
247
|
when :websocket_history
|
|
237
248
|
websocket_history = get_websocket_history(burp_obj: burp_obj)
|
|
238
249
|
websocket_history.each do |entry|
|
|
250
|
+
uri = entry[:url]
|
|
251
|
+
next unless in_scope(burp_obj: burp_obj, uri: uri)
|
|
252
|
+
|
|
239
253
|
next unless entry.key?(:comment) && entry[:comment].to_s.strip.empty?
|
|
240
254
|
|
|
241
255
|
web_socket_id = entry[:web_socket_id]
|
data/lib/pwn/plugins/file_fu.rb
CHANGED
|
@@ -60,6 +60,50 @@ module PWN
|
|
|
60
60
|
raise e
|
|
61
61
|
end
|
|
62
62
|
|
|
63
|
+
# Supported Method Parameters:
|
|
64
|
+
# PWN::Plugins::FileFu.shift_file_up(
|
|
65
|
+
# path: 'required - path to file to shift up',
|
|
66
|
+
# bytes: 'required - number of bytes to shift up (remove from beginning)',
|
|
67
|
+
# buffer_size: 'optional - buffer size to use when shifting (default: 256KB)'
|
|
68
|
+
# )
|
|
69
|
+
|
|
70
|
+
public_class_method def self.shift_file_up(opts = {})
|
|
71
|
+
path = opts[:path].to_s.scrub
|
|
72
|
+
raise "PWN Error: File #{path} does not exist" unless File.exist?(path)
|
|
73
|
+
|
|
74
|
+
bytes = opts[:bytes].to_i
|
|
75
|
+
raise 'PWN Error: bytes must be greater than or equal to 0' unless bytes >= 0
|
|
76
|
+
|
|
77
|
+
# Default buffer size = 256 KiB — good general-purpose value
|
|
78
|
+
buffer_size = (opts[:buffer_size] || (256 * 1024)).to_i
|
|
79
|
+
raise 'PWN Error: buffer_size must be greater than 0' unless buffer_size.positive?
|
|
80
|
+
|
|
81
|
+
# 'r+b' = read/write + binary mode
|
|
82
|
+
File.open(path, 'r+b') do |f|
|
|
83
|
+
size = f.stat.size
|
|
84
|
+
break if bytes >= size
|
|
85
|
+
|
|
86
|
+
read_pos = bytes
|
|
87
|
+
write_pos = 0
|
|
88
|
+
buffer = String.new(capacity: buffer_size)
|
|
89
|
+
|
|
90
|
+
while read_pos < size
|
|
91
|
+
f.seek(read_pos)
|
|
92
|
+
chunk = f.read(buffer_size, buffer) or break
|
|
93
|
+
|
|
94
|
+
bytes_read = chunk.bytesize
|
|
95
|
+
|
|
96
|
+
f.seek(write_pos)
|
|
97
|
+
f.write(buffer.byteslice(0, bytes_read))
|
|
98
|
+
|
|
99
|
+
read_pos += bytes_read
|
|
100
|
+
write_pos += bytes_read
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
f.truncate(size - bytes)
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
|
|
63
107
|
# Author(s):: 0day Inc. <support@0dayinc.com>
|
|
64
108
|
|
|
65
109
|
public_class_method def self.authors
|
|
@@ -85,6 +129,12 @@ module PWN
|
|
|
85
129
|
destination: 'required - destination folder to save extracted contents'
|
|
86
130
|
)
|
|
87
131
|
|
|
132
|
+
#{self}.shift_file_up(
|
|
133
|
+
path: 'required - path to file to shift up',
|
|
134
|
+
bytes: 'required - number of bytes to shift up',
|
|
135
|
+
buffer_size: 'optional - buffer size to use when shifting file up (default: 256 * 1024 / i.e 256KB)'
|
|
136
|
+
)
|
|
137
|
+
|
|
88
138
|
#{self}.authors
|
|
89
139
|
"
|
|
90
140
|
end
|
data/lib/pwn/plugins/sock.rb
CHANGED
|
@@ -113,89 +113,151 @@ module PWN
|
|
|
113
113
|
|
|
114
114
|
# Supported Method Parameters::
|
|
115
115
|
# PWN::Plugins::Sock.check_port_in_use(
|
|
116
|
-
# server_ip: 'optional - target host or ip to check (Defaults to 127.0.0.1)',
|
|
117
116
|
# port: 'required - target port',
|
|
117
|
+
# server_ip: 'optional - target host or ip to check (Defaults to 127.0.0.1)',
|
|
118
118
|
# protocol: 'optional - :tcp || :udp (defaults to tcp)'
|
|
119
119
|
# )
|
|
120
120
|
|
|
121
121
|
public_class_method def self.check_port_in_use(opts = {})
|
|
122
|
-
server_ip = opts[:server_ip]
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
protocol = opts[:protocol]
|
|
126
|
-
protocol ||= :tcp
|
|
122
|
+
server_ip = opts[:server_ip] ||= '127.0.0.1'
|
|
123
|
+
port = opts[:port]
|
|
124
|
+
protocol = (opts[:protocol] ||= :tcp).to_s.downcase.to_sym
|
|
127
125
|
|
|
128
|
-
#
|
|
126
|
+
ct = 0.5 # connect timeout in seconds
|
|
129
127
|
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
128
|
+
case protocol
|
|
129
|
+
when :tcp
|
|
130
|
+
# Use &:close intead of block
|
|
131
|
+
Socket.tcp(server_ip, port, connect_timeout: ct, &:close)
|
|
132
|
+
# Port is already in use (or no permission)
|
|
133
|
+
true
|
|
134
134
|
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
135
|
+
when :udp
|
|
136
|
+
socket = UDPSocket.new
|
|
137
|
+
socket.bind(server_ip, port)
|
|
138
|
+
# Port is NOT in use (or at least we can use it)
|
|
139
|
+
false
|
|
140
|
+
else
|
|
141
|
+
raise "Unsupported protocol: #{protocol}"
|
|
142
|
+
end
|
|
143
|
+
rescue Errno::EADDRINUSE, # address already in use
|
|
144
|
+
Errno::EACCES # permission denied
|
|
145
|
+
|
|
146
|
+
state = true if protocol == :udp
|
|
147
|
+
state = false if protocol == :tcp
|
|
148
|
+
|
|
149
|
+
state
|
|
150
|
+
rescue Errno::ECONNREFUSED, # connection refused (usually means port exists but no listener)
|
|
151
|
+
Errno::EHOSTUNREACH, # host unreachable
|
|
152
|
+
Errno::ETIMEDOUT # connection timed out
|
|
153
|
+
|
|
154
|
+
# Port is NOT in use (or at least we can use it)
|
|
155
|
+
false
|
|
156
|
+
rescue SocketError => e
|
|
157
|
+
# Usually means invalid address / interface
|
|
158
|
+
raise "Socket error while checking port #{port}: #{e.message}"
|
|
159
|
+
rescue StandardError => e
|
|
160
|
+
warn "[!] Unexpected error while checking port: #{e.class} – #{e.message}"
|
|
139
161
|
false
|
|
162
|
+
ensure
|
|
163
|
+
socket.close if protocol == :udp && !socket.nil?
|
|
140
164
|
end
|
|
141
165
|
|
|
142
166
|
# Supported Method Parameters::
|
|
143
|
-
# PWN::Plugins::Sock.listen(
|
|
144
|
-
# server_ip: 'required - target host or ip to listen',
|
|
167
|
+
# listen_obj = PWN::Plugins::Sock.listen(
|
|
145
168
|
# port: 'required - target port',
|
|
169
|
+
# server_ip: 'optional - target host or ip to listen (Defaults to 127.0.0.1')',
|
|
146
170
|
# protocol: 'optional - :tcp || :udp (defaults to tcp)',
|
|
147
|
-
# tls: 'optional - boolean listen on TLS-enabled socket (defaults to false)'
|
|
171
|
+
# tls: 'optional - boolean listen on TLS-enabled socket (defaults to false)',
|
|
172
|
+
# detach: 'optional - boolean to detach listener to background (defaults to false)'
|
|
148
173
|
# )
|
|
149
174
|
|
|
150
175
|
public_class_method def self.listen(opts = {})
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
176
|
+
port = opts[:port]
|
|
177
|
+
raise 'ERROR: Missing required parameter: port' if port.nil?
|
|
178
|
+
|
|
179
|
+
server_ip = opts[:server_ip] ||= '127.0.0.1'
|
|
180
|
+
protocol = (opts[:protocol] ||= :tcp).to_s.downcase.to_sym
|
|
181
|
+
tls = opts[:tls] || false
|
|
182
|
+
detach = opts[:detach] || false
|
|
183
|
+
|
|
184
|
+
listen_obj = nil
|
|
156
185
|
|
|
157
186
|
case protocol
|
|
158
187
|
when :tcp
|
|
188
|
+
server = TCPServer.open(server_ip, port)
|
|
189
|
+
|
|
159
190
|
if tls
|
|
160
|
-
# Multi-threaded - Not working
|
|
161
|
-
sock = TCPServer.open(server_ip, port)
|
|
162
191
|
tls_context = OpenSSL::SSL::SSLContext.new
|
|
163
192
|
tls_context.set_params(verify_mode: OpenSSL::SSL::VERIFY_NONE)
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
# Thread.start(listen_obj.accept) do |client_thread|
|
|
167
|
-
# while (client_input = client_thread.gets)
|
|
168
|
-
# puts client_input
|
|
169
|
-
# end
|
|
170
|
-
# client_thread.close
|
|
171
|
-
# end
|
|
172
|
-
# end
|
|
193
|
+
# TODO: min_version, ciphers, etc.
|
|
194
|
+
listen_obj = OpenSSL::SSL::SSLServer.new(server, tls_context)
|
|
173
195
|
else
|
|
174
|
-
|
|
175
|
-
|
|
196
|
+
listen_obj = server
|
|
197
|
+
end
|
|
198
|
+
|
|
199
|
+
unless detach
|
|
200
|
+
# Default blocking mode - simple accept-and-handle loop
|
|
201
|
+
# puts "[*] Listening on #{server_ip}:#{port} (#{tls ? 'TLS' : 'plain'} TCP)..."
|
|
202
|
+
|
|
176
203
|
loop do
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
204
|
+
client = listen_obj.accept
|
|
205
|
+
Thread.new(client) do |c|
|
|
206
|
+
peer = c.peeraddr
|
|
207
|
+
puts "[+] Connection from #{peer}"
|
|
208
|
+
|
|
209
|
+
while (data = c.gets)
|
|
210
|
+
puts "[#{peer}] #{data.strip}"
|
|
211
|
+
# Optional: echo back
|
|
212
|
+
# c.puts "ECHO: #{data}"
|
|
180
213
|
end
|
|
181
|
-
|
|
214
|
+
rescue Errno::ECONNRESET, Errno::EPIPE, IOError
|
|
215
|
+
# Client disconnected
|
|
216
|
+
ensure
|
|
217
|
+
client.close unless client.nil?
|
|
182
218
|
end
|
|
183
219
|
end
|
|
184
220
|
end
|
|
221
|
+
|
|
185
222
|
when :udp
|
|
186
|
-
# Single Threaded
|
|
187
223
|
listen_obj = UDPSocket.new
|
|
188
224
|
listen_obj.bind(server_ip, port)
|
|
189
|
-
|
|
190
|
-
|
|
225
|
+
|
|
226
|
+
# puts "[*] Listening on #{server_ip}:#{port} (UDP)..."
|
|
227
|
+
|
|
228
|
+
unless detach
|
|
229
|
+
# Simple single-threaded UDP receive loop
|
|
230
|
+
loop do
|
|
231
|
+
msg, addrinfo = listen_obj.recvmsg
|
|
232
|
+
next unless msg && !msg.empty?
|
|
233
|
+
|
|
234
|
+
peer = "#{addrinfo.ip_address}:#{addrinfo.ip_port}"
|
|
235
|
+
puts "[#{peer}] #{msg.inspect}"
|
|
236
|
+
# Optional: echo back
|
|
237
|
+
# listen_obj.send("ECHO: #{msg}", 0, addrinfo.ip_address, addrinfo.ip_port)
|
|
238
|
+
end
|
|
191
239
|
end
|
|
240
|
+
|
|
192
241
|
else
|
|
193
242
|
raise "Unsupported protocol: #{protocol}"
|
|
194
243
|
end
|
|
244
|
+
|
|
245
|
+
loop do
|
|
246
|
+
listening = check_port_in_use(
|
|
247
|
+
server_ip: server_ip,
|
|
248
|
+
port: port,
|
|
249
|
+
protocol: protocol
|
|
250
|
+
)
|
|
251
|
+
break if listening
|
|
252
|
+
end
|
|
253
|
+
|
|
254
|
+
listen_obj
|
|
255
|
+
rescue Interrupt
|
|
256
|
+
puts "\n[!] Caught interrupt, shutting down listener..."
|
|
195
257
|
rescue StandardError => e
|
|
196
|
-
raise
|
|
258
|
+
raise
|
|
197
259
|
ensure
|
|
198
|
-
listen_obj
|
|
260
|
+
listen_obj.close unless listen_obj.nil? || detach
|
|
199
261
|
end
|
|
200
262
|
|
|
201
263
|
# Supported Method Parameters::
|
|
@@ -275,11 +337,12 @@ module PWN
|
|
|
275
337
|
protocol: 'optional - :tcp || :udp (defaults to tcp)'
|
|
276
338
|
)
|
|
277
339
|
|
|
278
|
-
#{self}.listen(
|
|
279
|
-
server_ip: 'required - target host or ip to listen',
|
|
340
|
+
listen_obj = #{self}.listen(
|
|
280
341
|
port: 'required - target port',
|
|
342
|
+
server_ip: 'optional - target host or ip to listen (Defaults to 127.0.0.1')',
|
|
281
343
|
protocol: 'optional - :tcp || :udp (defaults to tcp)',
|
|
282
|
-
tls: 'optional - boolean listen on TLS-enabled socket (defaults to false)'
|
|
344
|
+
tls: 'optional - boolean listen on TLS-enabled socket (defaults to false)',
|
|
345
|
+
detach: 'optional - boolean to detach listener to background (defaults to false)'
|
|
283
346
|
)
|
|
284
347
|
|
|
285
348
|
cert_obj = #{self}.get_tls_cert(
|