pwn 0.5.613 → 0.5.617
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/Gemfile +10 -10
- data/README.md +117 -17
- data/bin/pwn +47 -2
- data/bin/pwn_gqrx_scanner +75 -18
- data/documentation/AI-Integration.md +36 -0
- data/documentation/BurpSuite.md +26 -0
- data/documentation/Contributing.md +31 -0
- data/documentation/Diagrams.md +140 -0
- data/documentation/Drivers.md +25 -0
- data/documentation/General-PWN-Usage.md +60 -0
- data/documentation/Home.md +78 -0
- data/documentation/How-PWN-Works.md +62 -0
- data/documentation/Installation.md +75 -0
- data/documentation/NmapIt.md +18 -0
- data/documentation/Plugins.md +59 -0
- data/documentation/Reporting.md +28 -0
- data/documentation/SAST.md +32 -0
- data/documentation/Skills-Memory-Learning.md +44 -0
- data/documentation/Transparent-Browser.md +32 -0
- data/documentation/Troubleshooting.md +38 -0
- data/documentation/What-is-PWN.md +53 -0
- data/documentation/Why-PWN.md +48 -0
- data/documentation/diagrams/ai-integration-tool-calling.svg +172 -0
- data/documentation/diagrams/build.sh +20 -0
- data/documentation/diagrams/burp-vs-zap-preference.svg +69 -0
- data/documentation/diagrams/code-scanning-sast.svg +172 -0
- data/documentation/diagrams/dot/_THEME.md +27 -0
- data/documentation/diagrams/dot/agent-tool-registry.dot +59 -0
- data/documentation/diagrams/dot/ai-integration-tool-calling.dot +50 -0
- data/documentation/diagrams/dot/aws-cloud-security.dot +48 -0
- data/documentation/diagrams/dot/burp-vs-zap-preference.dot +26 -0
- data/documentation/diagrams/dot/code-scanning-sast.dot +49 -0
- data/documentation/diagrams/dot/cron-scheduling.dot +40 -0
- data/documentation/diagrams/dot/driver-framework.dot +39 -0
- data/documentation/diagrams/dot/extrospection-world-awareness.dot +55 -0
- data/documentation/diagrams/dot/fuzzing-workflow.dot +47 -0
- data/documentation/diagrams/dot/history-to-drivers.dot +34 -0
- data/documentation/diagrams/dot/memory-skills-detailed.dot +60 -0
- data/documentation/diagrams/dot/network-infra-testing.dot +54 -0
- data/documentation/diagrams/dot/overall-pwn-architecture.dot +115 -0
- data/documentation/diagrams/dot/penetration-testing-workflow.dot +60 -0
- data/documentation/diagrams/dot/plugin-ecosystem.dot +45 -0
- data/documentation/diagrams/dot/pwn-ai-feedback-learning-loop.dot +98 -0
- data/documentation/diagrams/dot/pwn-repl-prototyping.dot +56 -0
- data/documentation/diagrams/dot/reporting-pipeline.dot +46 -0
- data/documentation/diagrams/dot/reverse-engineering-flow.dot +43 -0
- data/documentation/diagrams/dot/sdr-radio-flow.dot +45 -0
- data/documentation/diagrams/dot/sessions-cron-automation.dot +44 -0
- data/documentation/diagrams/dot/swarm-multi-agent.dot +70 -0
- data/documentation/diagrams/dot/web-application-testing.dot +49 -0
- data/documentation/diagrams/dot/zero-day-research-flow.dot +49 -0
- data/documentation/diagrams/driver-framework.svg +111 -0
- data/documentation/diagrams/fuzzing-workflow.svg +160 -0
- data/documentation/diagrams/history-to-drivers.svg +119 -0
- data/documentation/diagrams/memory-skills-detailed.svg +202 -0
- data/documentation/diagrams/network-infra-testing.svg +183 -0
- data/documentation/diagrams/overall-pwn-architecture.svg +405 -0
- data/documentation/diagrams/penetration-testing-workflow.svg +201 -0
- data/documentation/diagrams/plugin-ecosystem.svg +276 -0
- data/documentation/diagrams/pwn-ai-feedback-learning-loop.svg +306 -0
- data/documentation/diagrams/pwn-repl-prototyping.svg +168 -0
- data/documentation/diagrams/reporting-pipeline.svg +151 -0
- data/documentation/diagrams/reverse-engineering-flow.svg +134 -0
- data/documentation/diagrams/sessions-cron-automation.svg +136 -0
- data/documentation/diagrams/web-application-testing.svg +173 -0
- data/documentation/diagrams/zero-day-research-flow.svg +153 -0
- data/documentation/pwn-REPL.md +33 -0
- data/documentation/pwn-ai-Agent.md +43 -0
- data/git_commit.sh +1 -1
- data/lib/pwn/ai/agent/assembly.rb +1 -1
- data/lib/pwn/ai/agent/btc.rb +1 -1
- data/lib/pwn/ai/agent/burp_suite.rb +1 -1
- data/lib/pwn/ai/agent/extrospection.rb +618 -0
- data/lib/pwn/ai/agent/gqrx.rb +2 -2
- data/lib/pwn/ai/agent/hacker_one.rb +1 -1
- data/lib/pwn/ai/agent/introspection.rb +91 -0
- data/lib/pwn/ai/agent/learning.rb +379 -0
- data/lib/pwn/ai/agent/loop.rb +33 -3
- data/lib/pwn/ai/agent/metrics.rb +155 -0
- data/lib/pwn/ai/agent/prompt_builder.rb +32 -3
- data/lib/pwn/ai/agent/sast.rb +1 -1
- data/lib/pwn/ai/agent/swarm.rb +437 -0
- data/lib/pwn/ai/agent/tools/cron.rb +163 -0
- data/lib/pwn/ai/agent/tools/extrospection.rb +280 -0
- data/lib/pwn/ai/agent/tools/learning.rb +221 -0
- data/lib/pwn/ai/agent/tools/memory.rb +27 -0
- data/lib/pwn/ai/agent/tools/metrics.rb +61 -0
- data/lib/pwn/ai/agent/tools/sessions.rb +139 -0
- data/lib/pwn/ai/agent/tools/skills.rb +124 -8
- data/lib/pwn/ai/agent/tools/swarm.rb +229 -0
- data/lib/pwn/ai/agent/transparent_browser.rb +1 -1
- data/lib/pwn/ai/agent/vuln_gen.rb +2 -2
- data/lib/pwn/ai/agent.rb +5 -0
- data/lib/pwn/ai/anthropic.rb +19 -4
- data/lib/pwn/ai/grok.rb +249 -106
- data/lib/pwn/ai.rb +0 -1
- data/lib/pwn/config.rb +96 -36
- data/lib/pwn/cron.rb +16 -7
- data/lib/pwn/plugins/monkey_patch.rb +2 -2
- data/lib/pwn/plugins/repl.rb +158 -284
- data/lib/pwn/sdr/decoder/base.rb +251 -0
- data/lib/pwn/sdr/decoder/gsm.rb +84 -185
- data/lib/pwn/sdr/decoder/pocsag.rb +62 -217
- data/lib/pwn/sdr/decoder.rb +1 -0
- data/lib/pwn/sdr/gqrx.rb +446 -65
- data/lib/pwn/version.rb +1 -1
- data/spec/lib/pwn/ai/agent/extrospection_spec.rb +15 -0
- data/spec/lib/pwn/ai/agent/introspection_spec.rb +15 -0
- data/spec/lib/pwn/ai/agent/learning_spec.rb +68 -0
- data/spec/lib/pwn/ai/agent/metrics_spec.rb +27 -0
- data/spec/lib/pwn/ai/agent/swarm_spec.rb +34 -0
- data/spec/lib/pwn/ai/agent/tools/cron_spec.rb +40 -0
- data/spec/lib/pwn/ai/agent/tools/extrospection_spec.rb +40 -0
- data/spec/lib/pwn/ai/agent/tools/learning_spec.rb +30 -0
- data/spec/lib/pwn/ai/agent/tools/metrics_spec.rb +20 -0
- data/spec/lib/pwn/ai/agent/tools/sessions_spec.rb +35 -0
- data/spec/lib/pwn/ai/agent/tools/swarm_spec.rb +17 -0
- data/spec/lib/pwn/{ai/introspection_spec.rb → sdr/decoder/base_spec.rb} +3 -3
- data/third_party/pwn_rdoc.jsonl +178 -33
- metadata +110 -36
- data/documentation/PWN.png +0 -0
- data/documentation/PWN_Contributors_and_Users.png +0 -0
- data/documentation/fax-spectrogram.png +0 -0
- data/documentation/fax-waveform.png +0 -0
- data/documentation/frozen_string_literal_files_changed_from_false_to_true.txt +0 -54
- data/documentation/lifecycle_authz_replay.example.yaml +0 -27
- data/documentation/pwn_android_war_dialer_session.png +0 -0
- data/documentation/pwn_install.png +0 -0
- data/documentation/pwn_wallpaper.jpg +0 -0
- data/documentation/ringing-spectrogram.png +0 -0
- data/documentation/ringing-waveform.png +0 -0
- data/documentation/vulnerability_report_template.md +0 -37
- data/lib/pwn/ai/introspection.rb +0 -76
|
@@ -1,244 +1,87 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require 'json'
|
|
4
|
-
require 'open3'
|
|
5
|
-
require 'tty-spinner'
|
|
6
|
-
require 'io/wait'
|
|
7
|
-
|
|
8
3
|
module PWN
|
|
9
4
|
module SDR
|
|
10
5
|
module Decoder
|
|
11
|
-
# POCSAG
|
|
6
|
+
# POCSAG (CCIR Radiopaging Code No. 1) decoder for pager networks.
|
|
7
|
+
#
|
|
8
|
+
# Pipeline: GQRX UDP audio → sox 48k→22.05k → multimon-ng POCSAG512/1200/2400.
|
|
9
|
+
#
|
|
10
|
+
# multimon-ng emits lines of the form:
|
|
11
|
+
# POCSAG1200: Address: 123456 Function: 3 Alpha: FIRE ALARM ZONE 4
|
|
12
|
+
# POCSAG512: Address: 000042 Function: 0 Numeric: 5551234
|
|
13
|
+
# POCSAG2400: Address: 987654 Function: 1 Skyper: ...
|
|
14
|
+
# POCSAG1200: Address: 123456 Function: 2 Alpha: <partial><EOT>
|
|
15
|
+
#
|
|
16
|
+
# This module parses those into { protocol, baud, address, function,
|
|
17
|
+
# function_desc, type, type_desc, message } and JSON-logs each page.
|
|
12
18
|
module POCSAG
|
|
19
|
+
FUNCTION_DESC = {
|
|
20
|
+
0 => 'Numeric (Tone/A)',
|
|
21
|
+
1 => 'Tone only (B)',
|
|
22
|
+
2 => 'Tone only (C)',
|
|
23
|
+
3 => 'Alphanumeric (D)'
|
|
24
|
+
}.freeze
|
|
25
|
+
|
|
26
|
+
TYPE_DESC = {
|
|
27
|
+
'Alpha' => 'Alphanumeric text (7-bit ASCII)',
|
|
28
|
+
'Numeric' => 'Numeric-only (BCD)',
|
|
29
|
+
'Skyper' => 'Skyper network encoded',
|
|
30
|
+
'Tone' => 'Tone-only alert (no message body)'
|
|
31
|
+
}.freeze
|
|
32
|
+
|
|
13
33
|
# Supported Method Parameters::
|
|
14
|
-
#
|
|
15
|
-
# freq_obj: 'required -
|
|
34
|
+
# PWN::SDR::Decoder::POCSAG.decode(
|
|
35
|
+
# freq_obj: 'required - freq_obj returned from PWN::SDR::GQRX.init_freq'
|
|
16
36
|
# )
|
|
17
37
|
|
|
18
38
|
public_class_method def self.decode(opts = {})
|
|
19
39
|
freq_obj = opts[:freq_obj]
|
|
20
|
-
gqrx_sock = freq_obj[:gqrx_sock]
|
|
21
|
-
udp_ip = freq_obj[:udp_ip] || '127.0.0.1'
|
|
22
|
-
udp_port = freq_obj[:udp_port] || 7355
|
|
23
|
-
|
|
24
|
-
freq_obj.delete(:gqrx_sock)
|
|
25
|
-
|
|
26
|
-
skip_freq_char = "\n"
|
|
27
|
-
|
|
28
|
-
puts JSON.pretty_generate(freq_obj)
|
|
29
|
-
puts 'Press [ENTER] to Continue to next frequency...'
|
|
30
|
-
|
|
31
|
-
# Spinner setup with dynamic terminal width awareness
|
|
32
|
-
spinner = TTY::Spinner.new(
|
|
33
|
-
'[:spinner] :status',
|
|
34
|
-
format: :arrow_pulse,
|
|
35
|
-
clear: true,
|
|
36
|
-
hide_cursor: true
|
|
37
|
-
)
|
|
38
|
-
|
|
39
|
-
spinner_overhead = 12
|
|
40
|
-
max_title_length = [TTY::Screen.width - spinner_overhead, 50].max
|
|
41
|
-
|
|
42
|
-
initial_title = "INFO: Decoding #{self.to_s.split('::').last} on udp://#{udp_ip}:#{udp_port} ..."
|
|
43
|
-
initial_title = initial_title[0...max_title_length] if initial_title.length > max_title_length
|
|
44
|
-
spinner.update(status: initial_title)
|
|
45
|
-
spinner.auto_spin
|
|
46
40
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
41
|
+
PWN::SDR::Decoder::Base.run_pipeline(
|
|
42
|
+
freq_obj: freq_obj,
|
|
43
|
+
protocol: 'POCSAG',
|
|
44
|
+
required_bins: %w[sox multimon-ng],
|
|
45
|
+
decode_cmd: 'multimon-ng -q -t raw -e -u -p ' \
|
|
46
|
+
'-a POCSAG512 -a POCSAG1200 -a POCSAG2400 -f auto -',
|
|
47
|
+
line_match: /^POCSAG(?:512|1200|2400):/,
|
|
48
|
+
parser: proc { |line| parse_line(line: line) }
|
|
53
49
|
)
|
|
50
|
+
end
|
|
54
51
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
sox -t raw -e signed-integer -b 16 -r 48000 -c 1 - \
|
|
58
|
-
-t raw -e signed-integer -b 16 -r 22050 -c 1 - | \
|
|
59
|
-
multimon-ng -t raw \
|
|
60
|
-
-a POCSAG512 \
|
|
61
|
-
-a POCSAG1200 \
|
|
62
|
-
-a POCSAG2400 \
|
|
63
|
-
-
|
|
64
|
-
'
|
|
65
|
-
|
|
66
|
-
mm_stdin, mm_stdout, mm_stderr, mm_wait_thr = Open3.popen3(decode_cmd)
|
|
67
|
-
|
|
68
|
-
current_title = 'Waiting for data frames...'
|
|
52
|
+
# Supported Method Parameters::
|
|
53
|
+
# PWN::SDR::Decoder::POCSAG.parse_line(line: 'POCSAG1200: Address: ...')
|
|
69
54
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
loop do
|
|
74
|
-
data, _sender = udp_listener.recv(4096)
|
|
75
|
-
next unless data.to_s.bytesize.positive?
|
|
55
|
+
public_class_method def self.parse_line(opts = {})
|
|
56
|
+
line = opts[:line].to_s
|
|
57
|
+
out = { protocol: 'POCSAG' }
|
|
76
58
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
end
|
|
80
|
-
rescue IOError, Errno::EPIPE, EOFError, Errno::ECONNRESET
|
|
81
|
-
# normal exit path when shutting down
|
|
82
|
-
end
|
|
59
|
+
if (m = line.match(/^POCSAG(\d+):/))
|
|
60
|
+
out[:baud] = m[1].to_i
|
|
83
61
|
end
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
# buffer = +''
|
|
88
|
-
buffer = ''
|
|
89
|
-
|
|
90
|
-
valid_types = %w[ALN BIN HEX NUM TON TONE UNK]
|
|
91
|
-
loop do
|
|
92
|
-
begin
|
|
93
|
-
chunk = mm_stdout.readpartial(4096)
|
|
94
|
-
# buffer << chunk
|
|
95
|
-
buffer = "#{buffer}#{chunk}"
|
|
96
|
-
|
|
97
|
-
while (line = buffer.slice!(/^.*\n/))
|
|
98
|
-
line = line.chomp
|
|
99
|
-
next if line.empty? || !line.start_with?('POCSAG')
|
|
100
|
-
|
|
101
|
-
decoded_at = Time.now.strftime('%Y-%m-%d %H:%M:%S%z')
|
|
102
|
-
dec_msg = { decoded_at: decoded_at }
|
|
103
|
-
dec_msg[:raw_inspected] = line.inspect
|
|
104
|
-
|
|
105
|
-
protocol = line[0..8]
|
|
106
|
-
protocol = line[0..9] unless protocol == 'POCSAG512'
|
|
107
|
-
dec_msg[:protocol] = protocol
|
|
108
|
-
|
|
109
|
-
# ────────────────────────────── Detect format ──────────────────────────────
|
|
110
|
-
# Sometimes POCSAG is space delimited, sometimes pipe delimited
|
|
111
|
-
# FLEX_NEXT appears to always be pipe delimited
|
|
112
|
-
|
|
113
|
-
delimiter = '|'
|
|
114
|
-
space_delim = false
|
|
115
|
-
if line.start_with?('FLEX: ')
|
|
116
|
-
delimiter = ' '
|
|
117
|
-
space_delim = true
|
|
118
|
-
end
|
|
119
|
-
|
|
120
|
-
flex_pipe_delim = false
|
|
121
|
-
flex_pipe_delim = true if line.start_with?('FLEX|')
|
|
122
|
-
|
|
123
|
-
parts = line.split(delimiter)
|
|
124
|
-
|
|
125
|
-
# protocol index already used
|
|
126
|
-
idx_already_used = [0]
|
|
127
|
-
target_parts_idx = 1
|
|
128
|
-
target_parts_idx += 1 if flex_pipe_delim
|
|
129
|
-
target_parts_idx += 2 if space_delim
|
|
130
|
-
dec_msg[:speed] = parts[target_parts_idx] if parts[target_parts_idx]
|
|
131
|
-
idx_already_used.push(target_parts_idx)
|
|
132
|
-
|
|
133
|
-
target_parts_idx += 2
|
|
134
|
-
dec_msg[:capcode] = parts[target_parts_idx] if parts[target_parts_idx]
|
|
135
|
-
idx_already_used.push(target_parts_idx)
|
|
136
|
-
|
|
137
|
-
target_parts_idx -= 1
|
|
138
|
-
dec_msg[:capcode_loc] = parts[target_parts_idx] if parts[target_parts_idx]
|
|
139
|
-
idx_already_used.push(target_parts_idx)
|
|
140
|
-
|
|
141
|
-
while target_parts_idx < parts.size
|
|
142
|
-
if idx_already_used.include?(target_parts_idx)
|
|
143
|
-
target_parts_idx += 1
|
|
144
|
-
next
|
|
145
|
-
end
|
|
146
|
-
|
|
147
|
-
key = parts[target_parts_idx]
|
|
148
|
-
key = 'long_sequence_number' if key == 'LS'
|
|
149
|
-
|
|
150
|
-
if key && valid_types.include?(key)
|
|
151
|
-
dec_msg[:type] = key
|
|
152
|
-
|
|
153
|
-
dec_msg[:type_desc] = case key
|
|
154
|
-
when 'ALN'
|
|
155
|
-
'Human-readable text'
|
|
156
|
-
when 'BIN'
|
|
157
|
-
'Binary / data payload (typically 32 bit words)'
|
|
158
|
-
when 'HEX'
|
|
159
|
-
'Raw hex representation of data'
|
|
160
|
-
when 'NUM'
|
|
161
|
-
'Numbers only'
|
|
162
|
-
when 'TON', 'TONE'
|
|
163
|
-
'Just alert tone, no message'
|
|
164
|
-
when 'UNK'
|
|
165
|
-
'Decoded but type unknown / unsupported format'
|
|
166
|
-
end
|
|
167
|
-
|
|
168
|
-
target_parts_idx += 1
|
|
169
|
-
payload_parts = parts[target_parts_idx..]
|
|
170
|
-
dec_msg[:type_payload] = payload_parts.join(delimiter)
|
|
171
|
-
|
|
172
|
-
break
|
|
173
|
-
else
|
|
174
|
-
target_parts_idx += 1
|
|
175
|
-
dec_msg[key] = parts[target_parts_idx] if parts[target_parts_idx]
|
|
176
|
-
end
|
|
177
|
-
|
|
178
|
-
idx_already_used.push(target_parts_idx)
|
|
179
|
-
target_parts_idx += 1
|
|
180
|
-
end
|
|
181
|
-
|
|
182
|
-
final_msg = freq_obj.merge(dec_msg)
|
|
183
|
-
puts JSON.pretty_generate(final_msg)
|
|
184
|
-
# TODO: Append dec_msg to a log file in a better way
|
|
185
|
-
flex_log_file = "/tmp/flex_decoder_#{Time.now.strftime('%Y%m%d')}.log"
|
|
186
|
-
File.open(flex_log_file, 'a') do |f|
|
|
187
|
-
f.puts("#{JSON.generate(final_msg)},")
|
|
188
|
-
end
|
|
189
|
-
end
|
|
190
|
-
rescue EOFError, IOError
|
|
191
|
-
break
|
|
192
|
-
end
|
|
193
|
-
end
|
|
62
|
+
if (m = line.match(/Address:\s*(\d+)/i))
|
|
63
|
+
out[:address] = m[1].to_i
|
|
64
|
+
out[:capcode] = m[1]
|
|
194
65
|
end
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
# Non-blocking ENTER check to exit gracefully
|
|
200
|
-
next unless $stdin.wait_readable(0)
|
|
201
|
-
|
|
202
|
-
begin
|
|
203
|
-
char = $stdin.read_nonblock(1)
|
|
204
|
-
next unless char == skip_freq_char
|
|
205
|
-
|
|
206
|
-
skip_freq = true
|
|
207
|
-
puts "\n[!] ENTER pressed → stopping decoder..."
|
|
208
|
-
|
|
209
|
-
break
|
|
210
|
-
rescue IO::WaitReadable, EOFError
|
|
211
|
-
# ignore
|
|
212
|
-
end
|
|
213
|
-
|
|
214
|
-
break if skip_freq
|
|
66
|
+
if (m = line.match(/Function:\s*(\d+)/i))
|
|
67
|
+
fn = m[1].to_i
|
|
68
|
+
out[:function] = fn
|
|
69
|
+
out[:function_desc] = FUNCTION_DESC[fn] || 'Unknown'
|
|
215
70
|
end
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
ensure
|
|
222
|
-
# Cleanup
|
|
223
|
-
[receiver_thread, decoder_thread].each do |thread|
|
|
224
|
-
thread.kill if thread.alive?
|
|
71
|
+
if (m = line.match(/\b(Alpha|Numeric|Skyper|Tone):\s*(.*)$/i))
|
|
72
|
+
type = m[1].capitalize
|
|
73
|
+
out[:type] = type
|
|
74
|
+
out[:type_desc] = TYPE_DESC[type] || 'Unknown'
|
|
75
|
+
out[:message] = m[2].to_s.gsub(/<[A-Z]{2,3}>/, '').strip
|
|
225
76
|
end
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
mm_wait_thr&.value rescue nil
|
|
230
|
-
|
|
231
|
-
PWN::SDR::GQRX.disconnect_udp(udp_listener: udp_listener) if defined?(udp_listener) && udp_listener
|
|
232
|
-
|
|
233
|
-
spinner.stop if defined?(spinner) && spinner
|
|
77
|
+
out[:summary] = "POCSAG#{out[:baud]} RIC=#{out[:capcode]} F#{out[:function]} #{out[:type]}: #{out[:message]}"
|
|
78
|
+
out
|
|
234
79
|
end
|
|
235
80
|
|
|
236
81
|
# Author(s):: 0day Inc. <support@0dayinc.com>
|
|
237
82
|
|
|
238
83
|
public_class_method def self.authors
|
|
239
|
-
"AUTHOR(S)
|
|
240
|
-
0day Inc. <support@0dayinc.com>
|
|
241
|
-
"
|
|
84
|
+
"AUTHOR(S):\n 0day Inc. <support@0dayinc.com>\n"
|
|
242
85
|
end
|
|
243
86
|
|
|
244
87
|
# Display Usage for this Module
|
|
@@ -246,9 +89,11 @@ module PWN
|
|
|
246
89
|
public_class_method def self.help
|
|
247
90
|
puts "USAGE:
|
|
248
91
|
#{self}.decode(
|
|
249
|
-
freq_obj: 'required - freq_obj returned from PWN::SDR::GQRX.init_freq
|
|
92
|
+
freq_obj: 'required - freq_obj returned from PWN::SDR::GQRX.init_freq'
|
|
250
93
|
)
|
|
251
94
|
|
|
95
|
+
#{self}.parse_line(line: 'POCSAG1200: Address: 123456 Function: 3 Alpha: HELLO')
|
|
96
|
+
|
|
252
97
|
#{self}.authors
|
|
253
98
|
"
|
|
254
99
|
end
|
data/lib/pwn/sdr/decoder.rb
CHANGED