pwn 0.4.544 → 0.4.545
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop_todo.yml +19 -13
- data/Gemfile +3 -3
- data/README.md +2 -2
- data/bin/pwn_phone +1 -1
- data/lib/pwn/plugins/baresip.rb +265 -226
- data/lib/pwn/plugins/sock.rb +3 -3
- data/lib/pwn/plugins/thread_pool.rb +4 -1
- data/lib/pwn/reports/phone.rb +12 -3
- data/lib/pwn/version.rb +1 -1
- metadata +8 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a482ad2be090b5fc318d1048fd48f6936906ec7f50ec3e5732c7fbda412f17e0
|
4
|
+
data.tar.gz: 8a5d6ad28f6e45bbcbffe34e29a3f558f142b054c46360a0ebabf3dd8b66b7c0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3557a95e19c60f023ef6099c58351cee88c3e98f675de6c8e3806e360a7c0eeb4a26fcd0b44a6d306829d8460ba604e6b303e1593a6d26c923ea89e60cc1be69
|
7
|
+
data.tar.gz: 1a58439197b28adecbfd79a67922bd39a655df2f6cc1d2a83508c7c47a58bdb77251619ba3bb702f6827c4bd146246d8e2ff9f949b970851748a112f36982660
|
data/.rubocop_todo.yml
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# This configuration was generated by
|
2
2
|
# `rubocop --auto-gen-config`
|
3
|
-
# on 2022-
|
3
|
+
# on 2022-09-23 22:54:28 UTC using RuboCop version 1.36.0.
|
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
|
@@ -17,51 +17,51 @@ Layout/LineContinuationSpacing:
|
|
17
17
|
- 'packer/provisioners/wpscan.rb'
|
18
18
|
- 'vagrant/provisioners/beef.rb'
|
19
19
|
|
20
|
-
# Offense count:
|
20
|
+
# Offense count: 265
|
21
21
|
Lint/UselessAssignment:
|
22
22
|
Enabled: false
|
23
23
|
|
24
|
-
# Offense count:
|
24
|
+
# Offense count: 266
|
25
25
|
# Configuration parameters: AllowedMethods, AllowedPatterns, IgnoredMethods, CountRepeatedAttributes.
|
26
26
|
Metrics/AbcSize:
|
27
27
|
Max: 328
|
28
28
|
|
29
|
-
# Offense count:
|
29
|
+
# Offense count: 71
|
30
30
|
# Configuration parameters: CountComments, CountAsOne, ExcludedMethods, AllowedMethods, AllowedPatterns, IgnoredMethods.
|
31
31
|
# AllowedMethods: refine
|
32
32
|
Metrics/BlockLength:
|
33
33
|
Max: 196
|
34
34
|
|
35
|
-
# Offense count:
|
35
|
+
# Offense count: 46
|
36
36
|
# Configuration parameters: CountBlocks.
|
37
37
|
Metrics/BlockNesting:
|
38
38
|
Max: 5
|
39
39
|
|
40
|
-
# Offense count:
|
40
|
+
# Offense count: 96
|
41
41
|
# Configuration parameters: AllowedMethods, AllowedPatterns, IgnoredMethods.
|
42
42
|
Metrics/CyclomaticComplexity:
|
43
43
|
Max: 231
|
44
44
|
|
45
|
-
# Offense count:
|
45
|
+
# Offense count: 484
|
46
46
|
# Configuration parameters: CountComments, CountAsOne, ExcludedMethods, AllowedMethods, AllowedPatterns, IgnoredMethods.
|
47
47
|
Metrics/MethodLength:
|
48
48
|
Max: 466
|
49
49
|
|
50
|
-
# Offense count:
|
50
|
+
# Offense count: 48
|
51
51
|
# Configuration parameters: CountComments, CountAsOne.
|
52
52
|
Metrics/ModuleLength:
|
53
53
|
Max: 1186
|
54
54
|
|
55
|
-
# Offense count:
|
55
|
+
# Offense count: 88
|
56
56
|
# Configuration parameters: AllowedMethods, AllowedPatterns, IgnoredMethods.
|
57
57
|
Metrics/PerceivedComplexity:
|
58
58
|
Max: 51
|
59
59
|
|
60
|
-
# Offense count:
|
60
|
+
# Offense count: 164
|
61
61
|
Style/ClassVars:
|
62
62
|
Enabled: false
|
63
63
|
|
64
|
-
# Offense count:
|
64
|
+
# Offense count: 285
|
65
65
|
# This cop supports safe autocorrection (--autocorrect).
|
66
66
|
# Configuration parameters: EnforcedStyle, SingleLineConditionsOnly, IncludeTernaryExpressions.
|
67
67
|
# SupportedStyles: assign_to_condition, assign_inside_condition
|
@@ -74,6 +74,12 @@ Style/ExplicitBlockArgument:
|
|
74
74
|
Exclude:
|
75
75
|
- 'lib/pwn/plugins/nmap_it.rb'
|
76
76
|
|
77
|
+
# Offense count: 1
|
78
|
+
# This cop supports safe autocorrection (--autocorrect).
|
79
|
+
Style/IfUnlessModifier:
|
80
|
+
Exclude:
|
81
|
+
- 'lib/pwn/plugins/baresip.rb'
|
82
|
+
|
77
83
|
# Offense count: 1
|
78
84
|
# This cop supports safe autocorrection (--autocorrect).
|
79
85
|
Style/RedundantBegin:
|
@@ -87,12 +93,12 @@ Style/RedundantCondition:
|
|
87
93
|
- 'bin/pwn_simple_http_server'
|
88
94
|
- 'lib/pwn/plugins/packet.rb'
|
89
95
|
|
90
|
-
# Offense count:
|
96
|
+
# Offense count: 45
|
91
97
|
# This cop supports unsafe autocorrection (--autocorrect-all).
|
92
98
|
Style/SlicingWithRange:
|
93
99
|
Enabled: false
|
94
100
|
|
95
|
-
# Offense count:
|
101
|
+
# Offense count: 577
|
96
102
|
# This cop supports safe autocorrection (--autocorrect).
|
97
103
|
# Configuration parameters: AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, AllowedPatterns, IgnoredPatterns.
|
98
104
|
# URISchemes: http, https
|
data/Gemfile
CHANGED
@@ -57,12 +57,12 @@ gem 'rbvmomi', '3.0.0'
|
|
57
57
|
gem 'rdoc', '6.4.0'
|
58
58
|
gem 'rest-client', '2.1.0'
|
59
59
|
gem 'rex', '2.0.13'
|
60
|
-
gem 'rmagick', '4.
|
60
|
+
gem 'rmagick', '4.3.0'
|
61
61
|
gem 'rspec', '3.11.0'
|
62
62
|
gem 'rtesseract', '3.1.2'
|
63
63
|
gem 'rubocop', '1.36.0'
|
64
64
|
gem 'rubocop-rake', '0.6.0'
|
65
|
-
gem 'rubocop-rspec', '2.13.
|
65
|
+
gem 'rubocop-rspec', '2.13.2'
|
66
66
|
gem 'ruby-audio', '1.6.1'
|
67
67
|
gem 'ruby-nmap', '0.10.0'
|
68
68
|
gem 'ruby-saml', '1.14.0'
|
@@ -70,7 +70,7 @@ gem 'rvm', '1.11.3.9'
|
|
70
70
|
gem 'savon', '2.13.1'
|
71
71
|
gem 'selenium-devtools', '0.105.0'
|
72
72
|
gem 'serialport', '1.3.2'
|
73
|
-
gem 'sinatra', '
|
73
|
+
gem 'sinatra', '3.0.1'
|
74
74
|
gem 'slack-ruby-client', '1.1.0'
|
75
75
|
gem 'socksify', '1.7.1'
|
76
76
|
gem 'spreadsheet', '1.3.0'
|
data/README.md
CHANGED
@@ -37,7 +37,7 @@ $ rvm use ruby-3.1.2@pwn
|
|
37
37
|
$ rvm list gemsets
|
38
38
|
$ gem install --verbose pwn
|
39
39
|
$ pwn
|
40
|
-
pwn[v0.4.
|
40
|
+
pwn[v0.4.545]: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.1.2@pwn
|
|
52
52
|
$ gem uninstall --all --executables pwn
|
53
53
|
$ gem install --verbose pwn
|
54
54
|
$ pwn
|
55
|
-
pwn[v0.4.
|
55
|
+
pwn[v0.4.545]:001 >>> PWN.help
|
56
56
|
```
|
57
57
|
|
58
58
|
|
data/bin/pwn_phone
CHANGED
@@ -22,7 +22,7 @@ OptionParser.new do |options|
|
|
22
22
|
opts[:seconds_to_record] = s
|
23
23
|
end
|
24
24
|
|
25
|
-
options.on('-TTHREADS', '--max-threads=THREADS', '<Optional # Calls to Run Simultaneously (Defaults to 3
|
25
|
+
options.on('-TTHREADS', '--max-threads=THREADS', '<Optional # Calls to Run Simultaneously (Defaults to 3)>') do |t|
|
26
26
|
opts[:max_threads] = t
|
27
27
|
end
|
28
28
|
|
data/lib/pwn/plugins/baresip.rb
CHANGED
@@ -17,7 +17,7 @@ module PWN
|
|
17
17
|
private_class_method def self.baresip_http_call(opts = {})
|
18
18
|
baresip_obj = opts[:baresip_obj]
|
19
19
|
cmd = opts[:cmd]
|
20
|
-
http_listen_ip_port =
|
20
|
+
http_listen_ip_port = opts[:http_listen_ip_port]
|
21
21
|
baresip_url = "http://#{http_listen_ip_port}"
|
22
22
|
|
23
23
|
max_conn_attempts = 30
|
@@ -37,7 +37,7 @@ module PWN
|
|
37
37
|
)
|
38
38
|
|
39
39
|
Nokogiri::HTML.parse(response)
|
40
|
-
rescue Errno::ECONNREFUSED
|
40
|
+
rescue Errno::ECONNREFUSED => e
|
41
41
|
raise e if conn_attempt > max_conn_attempts
|
42
42
|
|
43
43
|
sleep 1
|
@@ -58,6 +58,7 @@ module PWN
|
|
58
58
|
# baresip_bin: 'Optional path of baresip binary (Defaults to /usr/bin/baresip)',
|
59
59
|
# config_root: 'Optional dir of baresip config (Defaults to ~/.baresip)',
|
60
60
|
# session_root: 'Optional dir of baresip session (Defaults to Dir.pwd)',
|
61
|
+
# screenlog_path: 'Optional path of screenlog file (Defaults to screenlog.txt)',
|
61
62
|
# screen_session: 'Optional name of screen session (Defaults baresip)'
|
62
63
|
# )
|
63
64
|
|
@@ -69,8 +70,6 @@ module PWN
|
|
69
70
|
)
|
70
71
|
baresip_bin ||= '/usr/bin/baresip'
|
71
72
|
|
72
|
-
baresip_obj = {}
|
73
|
-
|
74
73
|
session_root = opts[:session_root] if Dir.exist?(opts[:session_root].to_s)
|
75
74
|
|
76
75
|
config_root = opts[:config_root] if Dir.exist?(
|
@@ -84,7 +83,34 @@ module PWN
|
|
84
83
|
|
85
84
|
raise "no http_listen value found in #{config}." if http_list_entry.empty?
|
86
85
|
|
87
|
-
|
86
|
+
# Update http_listen value in respective config with random available port
|
87
|
+
random_port = -1
|
88
|
+
port_in_use = true
|
89
|
+
while port_in_use
|
90
|
+
random_port = Random.rand(1024..65_535)
|
91
|
+
port_in_use = PWN::Plugins::Sock.check_port_in_use(port: random_port)
|
92
|
+
end
|
93
|
+
http_listen_ip_port = "127.0.0.1:#{random_port}"
|
94
|
+
|
95
|
+
updated_config_content = ''
|
96
|
+
File.read(config).each_line do |line|
|
97
|
+
this_config_line = line
|
98
|
+
# Only allow one call per thread.
|
99
|
+
this_config_line = "call_max_calls 1\n" if line.match?(/^call_max_calls\s.+$/)
|
100
|
+
|
101
|
+
# One random HTTP listener / thread
|
102
|
+
if line.match?(/^http_listen\s.+$/)
|
103
|
+
this_config_line = "http_listen #{http_listen_ip_port}\n"
|
104
|
+
end
|
105
|
+
updated_config_content = "#{updated_config_content}#{this_config_line}"
|
106
|
+
end
|
107
|
+
File.write(config, updated_config_content)
|
108
|
+
|
109
|
+
baresip_obj = {}
|
110
|
+
|
111
|
+
screenlog_path = opts[:screenlog_path]
|
112
|
+
screenlog_path ||= "#{session_root}/screenlog.txt"
|
113
|
+
baresip_obj[:screenlog_path] = screenlog_path
|
88
114
|
|
89
115
|
screen_session = opts[:screen_session]
|
90
116
|
screen_session ||= 'baresip'
|
@@ -94,9 +120,6 @@ module PWN
|
|
94
120
|
baresip_obj[:session_root] = session_root
|
95
121
|
baresip_obj[:screen_session] = screen_session
|
96
122
|
|
97
|
-
screenlog_file = 'screenlog.txt'
|
98
|
-
baresip_obj[:screenlog_file] = screenlog_file
|
99
|
-
|
100
123
|
# Prefer running baresip in detached screen vs --daemon mode
|
101
124
|
# Since sndfile doesn't produce .wav files in --daemon mode
|
102
125
|
system(
|
@@ -105,7 +128,7 @@ module PWN
|
|
105
128
|
'xterm',
|
106
129
|
'-L',
|
107
130
|
'-Logfile',
|
108
|
-
|
131
|
+
screenlog_path,
|
109
132
|
'-S',
|
110
133
|
screen_session,
|
111
134
|
'-d',
|
@@ -116,7 +139,8 @@ module PWN
|
|
116
139
|
'-e',
|
117
140
|
'/insmod httpd',
|
118
141
|
'-e',
|
119
|
-
'/insmod sndfile'
|
142
|
+
'/insmod sndfile',
|
143
|
+
'-v'
|
120
144
|
)
|
121
145
|
|
122
146
|
baresip_obj[:session_thread] = init_session_thread(
|
@@ -155,17 +179,15 @@ module PWN
|
|
155
179
|
baresip_obj = opts[:baresip_obj]
|
156
180
|
|
157
181
|
session_root = baresip_obj[:session_root]
|
158
|
-
|
159
|
-
|
160
|
-
screenlog = "#{session_root}/#{screenlog_file}"
|
182
|
+
screenlog_path = baresip_obj[:screenlog_path]
|
161
183
|
|
162
184
|
# Spin up a baresip_obj session_thread
|
163
185
|
Thread.new do
|
164
186
|
loop do
|
165
|
-
next unless File.exist?(
|
187
|
+
next unless File.exist?(screenlog_path)
|
166
188
|
|
167
|
-
# Continuously consume contents of
|
168
|
-
@session_data = File.readlines(
|
189
|
+
# Continuously consume contents of screenlog_path
|
190
|
+
@session_data = File.readlines(screenlog_path)
|
169
191
|
@session_data.delete_if do |line|
|
170
192
|
line.include?('ua: using best effort AF: af=AF_INET')
|
171
193
|
end
|
@@ -203,10 +225,12 @@ module PWN
|
|
203
225
|
|
204
226
|
public_class_method def self.baresip_exec(opts = {})
|
205
227
|
baresip_obj = opts[:baresip_obj]
|
228
|
+
http_listen_ip_port = baresip_obj[:http_listen_ip_port]
|
206
229
|
cmd = opts[:cmd]
|
207
230
|
|
208
231
|
baresip_http_call(
|
209
232
|
baresip_obj: baresip_obj,
|
233
|
+
http_listen_ip_port: http_listen_ip_port,
|
210
234
|
cmd: cmd
|
211
235
|
)
|
212
236
|
rescue StandardError => e
|
@@ -227,15 +251,11 @@ module PWN
|
|
227
251
|
|
228
252
|
session_thread.terminate
|
229
253
|
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
screen_session,
|
235
|
-
'quit'
|
254
|
+
puts "STOPPING #{baresip_obj[:screen_session]}"
|
255
|
+
cmd_resp = baresip_exec(
|
256
|
+
baresip_obj: baresip_obj,
|
257
|
+
cmd: "/quit\r\n"
|
236
258
|
)
|
237
|
-
|
238
|
-
baresip_obj = nil
|
239
259
|
rescue StandardError => e
|
240
260
|
raise e
|
241
261
|
end
|
@@ -372,15 +392,11 @@ module PWN
|
|
372
392
|
|
373
393
|
# Supported Method Parameters::
|
374
394
|
# PWN::Plugins::BareSIP.recon(
|
375
|
-
# baresip_obj: 'Required - baresip_obj returned from #start method',
|
376
|
-
# target_num: 'Required - target destination to recon (i.e. phone number)',
|
377
|
-
# src_num_rules: 'Optional - Comma-delimited list of rules for src_num format (i.e. self, same_country, same_area, and/or same_prefix [Defaults to random src_num w/ same length as target_num])',
|
378
|
-
# seconds_to_record: 'Optional - Seconds to Record (Defaults to 60)',
|
379
|
-
# sox_bin: 'Optional - Path to SoX Binary, the Swiss Army knife of Audio (Defaults to /usr/bin/sox)'
|
380
395
|
# )
|
381
396
|
|
382
|
-
public_class_method def self.
|
397
|
+
public_class_method def self.dial_target_in_list(opts = {})
|
383
398
|
baresip_bin = opts[:baresip_bin]
|
399
|
+
target_num = opts[:target_num]
|
384
400
|
|
385
401
|
config_root = opts[:config_root] if Dir.exist?(
|
386
402
|
opts[:config_root].to_s
|
@@ -389,15 +405,16 @@ module PWN
|
|
389
405
|
|
390
406
|
session_root = opts[:session_root]
|
391
407
|
session_root ||= Dir.pwd
|
392
|
-
|
408
|
+
|
393
409
|
randomize = opts[:randomize]
|
394
410
|
src_num_rules = opts[:src_num_rules]
|
395
|
-
|
396
|
-
max_threads = 3 if max_threads.zero?
|
411
|
+
|
397
412
|
seconds_to_record = opts[:seconds_to_record].to_i
|
398
413
|
seconds_to_record = 60 if seconds_to_record.zero?
|
414
|
+
|
399
415
|
sox_bin = opts[:sox_bin] if File.exist?(opts[:sox_bin].to_s)
|
400
416
|
sox_bin ||= '/usr/bin/sox'
|
417
|
+
|
401
418
|
waveform_bin = 'waveform'
|
402
419
|
|
403
420
|
# Intialize empty baresip obj for ensure block below
|
@@ -410,222 +427,243 @@ module PWN
|
|
410
427
|
cayan = "\e[36m"
|
411
428
|
end_of_color = "\e[0m"
|
412
429
|
|
413
|
-
|
414
|
-
|
415
|
-
|
430
|
+
config_root_for_target_num = "#{config_root}-#{target_num}"
|
431
|
+
FileUtils.cp_r(config_root, config_root_for_target_num)
|
432
|
+
src_num = apply_src_num_rules(
|
433
|
+
config_root: config_root_for_target_num,
|
434
|
+
target_num: target_num,
|
435
|
+
src_num_rules: src_num_rules
|
416
436
|
)
|
417
437
|
|
418
|
-
|
419
|
-
|
420
|
-
|
421
|
-
|
422
|
-
|
423
|
-
|
424
|
-
|
425
|
-
|
426
|
-
#
|
427
|
-
|
428
|
-
|
429
|
-
|
430
|
-
|
431
|
-
|
432
|
-
|
433
|
-
|
434
|
-
|
435
|
-
|
436
|
-
|
437
|
-
|
438
|
-
|
439
|
-
|
440
|
-
|
441
|
-
|
442
|
-
|
443
|
-
call_info_hash = {}
|
438
|
+
call_resp_hash = {}
|
439
|
+
|
440
|
+
call_started = Time.now.strftime('%Y-%m-%d_%H.%M.%S')
|
441
|
+
|
442
|
+
call_resp_hash[:call_started] = call_started
|
443
|
+
call_resp_hash[:src_num] = src_num
|
444
|
+
call_resp_hash[:src_num_rules] = src_num_rules
|
445
|
+
call_resp_hash[:target_num] = target_num
|
446
|
+
target_num_root = "#{session_root}/#{target_num}-#{call_started}"
|
447
|
+
Dir.mkdir(target_num_root)
|
448
|
+
|
449
|
+
screenlog_path = "#{target_num_root}/screenlog-#{target_num}.txt"
|
450
|
+
screen_session = "#{File.basename($PROGRAM_NAME)}-#{target_num}"
|
451
|
+
|
452
|
+
# Start baresip in detached screen to support commands over HTTP
|
453
|
+
# and call recording to wav files
|
454
|
+
baresip_obj = start(
|
455
|
+
src_num: src_num,
|
456
|
+
baresip_bin: baresip_bin,
|
457
|
+
config_root: config_root_for_target_num,
|
458
|
+
session_root: session_root,
|
459
|
+
screenlog_path: screenlog_path,
|
460
|
+
screen_session: screen_session
|
461
|
+
)
|
444
462
|
|
445
|
-
|
463
|
+
# session_root = baresip_obj[:session_root]
|
464
|
+
config_root = baresip_obj[:config_root]
|
465
|
+
config = "#{config_root}/config"
|
446
466
|
|
447
|
-
|
448
|
-
|
449
|
-
call_info_hash[:src_num_rules] = src_num_rules
|
450
|
-
call_info_hash[:target_num] = target_num
|
467
|
+
puts "#{green}#{call_started} >>>#{end_of_color}"
|
468
|
+
puts "#{yellow}dialing #{target_num}#{end_of_color}"
|
451
469
|
|
452
|
-
|
470
|
+
cmd_resp = baresip_exec(
|
471
|
+
baresip_obj: baresip_obj,
|
472
|
+
cmd: "/dial #{target_num}\r\n"
|
473
|
+
)
|
474
|
+
puts "/dial #{target_num} RESP:"
|
475
|
+
puts cmd_resp.xpath('//pre').text
|
453
476
|
|
454
|
-
|
455
|
-
|
456
|
-
|
477
|
+
cmd_resp = baresip_exec(
|
478
|
+
baresip_obj: baresip_obj,
|
479
|
+
cmd: "/listcalls\r\n"
|
480
|
+
)
|
481
|
+
puts '/listcalls RESP:'
|
482
|
+
puts cmd_resp.xpath('//pre').text
|
483
|
+
|
484
|
+
puts red
|
485
|
+
# Conditions to hangup when less than seconds_to_record
|
486
|
+
terminated = 'terminated (duration:'
|
487
|
+
unavail = '503 Service Unavailable'
|
488
|
+
not_found = 'session closed: 404 Not Found'
|
489
|
+
|
490
|
+
reason = 'recording limit reached'
|
491
|
+
seconds_recorded = 0
|
492
|
+
seconds_to_record.downto(1).each do |countdown|
|
493
|
+
seconds_recorded += 1
|
494
|
+
print "#{seconds_to_record}s to record - remaining: #{format('%-9.9s', countdown)}"
|
495
|
+
print "\r"
|
496
|
+
|
497
|
+
if dump_session_data.select { |s| s.include?(terminated) }.length.positive?
|
498
|
+
reason = 'call terminated by other party'
|
499
|
+
break
|
500
|
+
end
|
457
501
|
|
458
|
-
|
459
|
-
|
460
|
-
|
461
|
-
|
462
|
-
baresip_bin: baresip_bin,
|
463
|
-
session_root: target_num_root,
|
464
|
-
screen_session: "#{File.basename($PROGRAM_NAME)}-#{target_num}"
|
465
|
-
)
|
502
|
+
if dump_session_data.select { |s| s.include?(unavail) }.length.positive?
|
503
|
+
reason = 'SIP 503 (service unavailable)'
|
504
|
+
break
|
505
|
+
end
|
466
506
|
|
467
|
-
|
468
|
-
|
469
|
-
|
507
|
+
if dump_session_data.select { |s| s.include?(not_found) }.length.positive?
|
508
|
+
reason = 'SIP 404 (not found)'
|
509
|
+
break
|
510
|
+
end
|
470
511
|
|
471
|
-
|
472
|
-
|
512
|
+
sleep 1
|
513
|
+
end
|
514
|
+
call_resp_hash[:seconds_recorded] = seconds_recorded
|
515
|
+
puts end_of_color
|
516
|
+
|
517
|
+
call_stopped = Time.now.strftime('%Y-%m-%d_%H.%M.%S')
|
518
|
+
puts "\n#{green}#{call_stopped} >>> #{reason} #{target_num}#{end_of_color}"
|
519
|
+
call_resp_hash[:call_stopped] = call_stopped
|
520
|
+
call_resp_hash[:reason] = reason
|
521
|
+
puts "call termination reason: #{reason}"
|
522
|
+
|
523
|
+
stop(baresip_obj: baresip_obj)
|
524
|
+
FileUtils.rm_rf(config_root_for_target_num)
|
525
|
+
|
526
|
+
absolute_recording = ''
|
527
|
+
relative_recording = ''
|
528
|
+
Dir.glob("#{session_root}/dump-*#{target_num}*.wav").each do |path|
|
529
|
+
wav = File.basename(path)
|
530
|
+
File.delete(path) if wav.match(/^dump-.+#{target_num}.+-enc\.wav$/)
|
531
|
+
next unless wav.match(/^dump-.+#{target_num}.+-dec.wav/)
|
532
|
+
|
533
|
+
FileUtils.mv(path, target_num_root)
|
534
|
+
absolute_recording = "#{target_num_root}/#{wav}"
|
535
|
+
relative_recording = "#{target_num}-#{call_started}/#{wav}"
|
536
|
+
end
|
473
537
|
|
474
|
-
|
475
|
-
|
476
|
-
|
538
|
+
screenlog_file = File.basename(screenlog_path)
|
539
|
+
relative_screenlog = "#{target_num}-#{call_started}/#{screenlog_file}"
|
540
|
+
|
541
|
+
call_resp_hash[:screenlog] = relative_screenlog
|
542
|
+
call_resp_hash[:recording] = '--'
|
543
|
+
call_resp_hash[:waveform] = '--'
|
544
|
+
call_resp_hash[:spectrogram] = '--'
|
545
|
+
|
546
|
+
unless absolute_recording.empty?
|
547
|
+
puts cayan
|
548
|
+
|
549
|
+
call_resp_hash[:recording] = relative_recording
|
550
|
+
|
551
|
+
absolute_spectrogram = "#{absolute_recording}-spectrogram.png"
|
552
|
+
relative_spectrogram = "#{relative_recording}-spectrogram.png"
|
553
|
+
print "Generating Audio Spectrogram for #{absolute_recording}..."
|
554
|
+
system(
|
555
|
+
sox_bin,
|
556
|
+
'--show-progress',
|
557
|
+
'--type',
|
558
|
+
'sndfile',
|
559
|
+
'--encoding',
|
560
|
+
'signed-integer',
|
561
|
+
'--bits',
|
562
|
+
'16',
|
563
|
+
'--endian',
|
564
|
+
'little',
|
565
|
+
'--channels',
|
566
|
+
'1',
|
567
|
+
'--rate',
|
568
|
+
'8000',
|
569
|
+
absolute_recording,
|
570
|
+
'-n',
|
571
|
+
'spectrogram',
|
572
|
+
'-o',
|
573
|
+
absolute_spectrogram,
|
574
|
+
'-d',
|
575
|
+
seconds_to_record.to_s
|
477
576
|
)
|
478
|
-
puts
|
479
|
-
|
480
|
-
|
481
|
-
|
482
|
-
|
483
|
-
|
577
|
+
puts 'complete.'
|
578
|
+
call_resp_hash[:spectrogram] = relative_spectrogram
|
579
|
+
|
580
|
+
absolute_waveform = "#{absolute_recording}-waveform.png"
|
581
|
+
relative_waveform = "#{relative_recording}-waveform.png"
|
582
|
+
print "Generating Audio Waveform for #{absolute_recording}..."
|
583
|
+
system(
|
584
|
+
waveform_bin,
|
585
|
+
'--method',
|
586
|
+
'peak',
|
587
|
+
'--color',
|
588
|
+
'#FF0000',
|
589
|
+
'--background',
|
590
|
+
'#000000',
|
591
|
+
'--force',
|
592
|
+
absolute_recording,
|
593
|
+
absolute_waveform
|
484
594
|
)
|
485
|
-
puts '
|
486
|
-
|
487
|
-
|
488
|
-
|
489
|
-
# Conditions to proceed less than seconds_to_record
|
490
|
-
terminated = 'terminated (duration:'
|
491
|
-
unavail = '503 Service Unavailable'
|
492
|
-
not_found = 'session closed: 404 Not Found'
|
493
|
-
|
494
|
-
reason = 'recording limit reached'
|
495
|
-
seconds_recorded = 0
|
496
|
-
seconds_to_record.downto(1).each do |countdown|
|
497
|
-
seconds_recorded += 1
|
498
|
-
print "#{seconds_to_record}s to record - remaining: #{format('%-9.9s', countdown)}"
|
499
|
-
print "\r"
|
500
|
-
|
501
|
-
if dump_session_data.select { |s| s.include?(terminated) }.length.positive?
|
502
|
-
reason = 'call terminated by other party'
|
503
|
-
break
|
504
|
-
end
|
595
|
+
puts 'complete.'
|
596
|
+
call_resp_hash[:waveform] = relative_waveform
|
597
|
+
puts end_of_color
|
598
|
+
end
|
505
599
|
|
506
|
-
|
507
|
-
|
508
|
-
|
509
|
-
|
600
|
+
call_resp_hash
|
601
|
+
rescue StandardError => e
|
602
|
+
raise e
|
603
|
+
end
|
510
604
|
|
511
|
-
|
512
|
-
|
513
|
-
|
514
|
-
end
|
605
|
+
# Supported Method Parameters::
|
606
|
+
# PWN::Plugins::BareSIP.recon(
|
607
|
+
# )
|
515
608
|
|
516
|
-
|
517
|
-
|
518
|
-
|
519
|
-
|
609
|
+
public_class_method def self.recon(opts = {})
|
610
|
+
baresip_bin = opts[:baresip_bin]
|
611
|
+
config_root = opts[:config_root] if Dir.exist?(
|
612
|
+
opts[:config_root].to_s
|
613
|
+
)
|
614
|
+
config_root ||= "#{Dir.home}/.baresip"
|
615
|
+
session_root = opts[:session_root]
|
616
|
+
session_root ||= Dir.pwd
|
617
|
+
target_file = opts[:target_file]
|
618
|
+
randomize = opts[:randomize]
|
619
|
+
src_num_rules = opts[:src_num_rules]
|
620
|
+
max_threads = opts[:max_threads].to_i
|
621
|
+
max_threads = 3 if max_threads.zero?
|
622
|
+
seconds_to_record = opts[:seconds_to_record].to_i
|
623
|
+
seconds_to_record = 60 if seconds_to_record.zero?
|
624
|
+
sox_bin = opts[:sox_bin] if File.exist?(opts[:sox_bin].to_s)
|
625
|
+
sox_bin ||= '/usr/bin/sox'
|
520
626
|
|
521
|
-
|
522
|
-
|
523
|
-
|
524
|
-
|
525
|
-
|
526
|
-
recording = ''
|
527
|
-
# BUGFIX: Sometimes recordings aren't generated
|
528
|
-
# Perhaps because previous session wasn't stopped properly?
|
529
|
-
Dir.entries(target_num_root).each do |entry|
|
530
|
-
recording = entry if entry.match(/^dump-.+-dec.wav/)
|
531
|
-
File.delete(entry) if entry.match(/^dump-.+-enc\.wav$/) && File.exist?(entry)
|
532
|
-
end
|
627
|
+
target_range = parse_target_file(
|
628
|
+
target_file: target_file,
|
629
|
+
randomize: randomize
|
630
|
+
)
|
533
631
|
|
534
|
-
|
535
|
-
|
536
|
-
|
537
|
-
|
538
|
-
|
539
|
-
|
540
|
-
|
541
|
-
|
542
|
-
|
543
|
-
|
544
|
-
|
545
|
-
|
546
|
-
|
547
|
-
|
548
|
-
|
549
|
-
|
550
|
-
|
551
|
-
|
552
|
-
|
553
|
-
|
554
|
-
|
555
|
-
|
556
|
-
|
557
|
-
|
558
|
-
'--rate',
|
559
|
-
'8000',
|
560
|
-
recording,
|
561
|
-
'-n',
|
562
|
-
'spectrogram',
|
563
|
-
'-o',
|
564
|
-
spectrogram,
|
565
|
-
'-d',
|
566
|
-
seconds_to_record.to_s
|
567
|
-
)
|
568
|
-
puts 'complete.'
|
569
|
-
call_info_hash[:spectrogram] = "#{target_num}-#{call_started}/#{spectrogram}"
|
570
|
-
|
571
|
-
waveform = "#{recording}-waveform.png"
|
572
|
-
print "Generating Audio Waveform for #{recording}..."
|
573
|
-
system(
|
574
|
-
waveform_bin,
|
575
|
-
'--method',
|
576
|
-
'peak',
|
577
|
-
'--color',
|
578
|
-
'#FF0000',
|
579
|
-
'--background',
|
580
|
-
'#000000',
|
581
|
-
'--force',
|
582
|
-
recording,
|
583
|
-
waveform
|
584
|
-
)
|
585
|
-
puts 'complete.'
|
586
|
-
call_info_hash[:waveform] = "#{target_num}-#{call_started}/#{waveform}"
|
587
|
-
puts end_of_color
|
588
|
-
end
|
632
|
+
results_hash = {
|
633
|
+
session_started: Time.now.strftime('%Y-%m-%d_%H.%M.%S'),
|
634
|
+
data: []
|
635
|
+
}
|
636
|
+
|
637
|
+
# Change to session_root _before_ executing threads
|
638
|
+
Dir.chdir(session_root)
|
639
|
+
|
640
|
+
# Multi-thread calls!
|
641
|
+
mutex = Mutex.new
|
642
|
+
PWN::Plugins::ThreadPool.fill(
|
643
|
+
enumerable_array: target_range,
|
644
|
+
max_threads: max_threads
|
645
|
+
) do |target_num|
|
646
|
+
call_resp_hash = dial_target_in_list(
|
647
|
+
baresip_bin: baresip_bin,
|
648
|
+
target_num: target_num,
|
649
|
+
config_root: config_root,
|
650
|
+
session_root: session_root,
|
651
|
+
randomize: randomize,
|
652
|
+
src_num_rules: src_num_rules,
|
653
|
+
seconds_to_record: seconds_to_record,
|
654
|
+
sox_bin: sox_bin
|
655
|
+
)
|
589
656
|
|
590
657
|
# Push Call Results to results_hash[:data]
|
591
|
-
|
592
|
-
|
593
|
-
# end
|
594
|
-
results_hash[:data].push(call_info_hash)
|
595
|
-
|
596
|
-
puts "call termination reason: #{reason}"
|
597
|
-
# Stop call to cd into next session root
|
598
|
-
stop(baresip_obj: baresip_obj)
|
599
|
-
|
600
|
-
seconds_to_delay_between_pool_of_calls = Random.rand(1..9)
|
601
|
-
seconds_to_delay_between_pool_of_calls.downto(1).each do |countdown|
|
602
|
-
print "#{red}ZZZ #{seconds_to_delay_between_pool_of_calls}s until next pool of calls: #{format('%-9.9s', countdown)}#{end_of_color}"
|
603
|
-
print "\r"
|
604
|
-
sleep 1
|
658
|
+
mutex.synchronize do
|
659
|
+
results_hash[:data].push(call_resp_hash)
|
605
660
|
end
|
606
|
-
puts "\n#{green}waking up for next call \\o/#{end_of_color}"
|
607
|
-
puts "\n\n\n"
|
608
661
|
end
|
609
662
|
results_hash[:session_ended] = Time.now.strftime('%Y-%m-%d_%H.%M.%S')
|
610
663
|
|
611
664
|
results_hash
|
612
665
|
rescue StandardError => e
|
613
666
|
raise e
|
614
|
-
ensure
|
615
|
-
stop(baresip_obj: baresip_obj) unless baresip_obj.empty?
|
616
|
-
end
|
617
|
-
|
618
|
-
# Supported Method Parameters::
|
619
|
-
# PWN::Plugins::BareSIP.killall
|
620
|
-
|
621
|
-
public_class_method def self.killall
|
622
|
-
system(
|
623
|
-
'killall',
|
624
|
-
'-15',
|
625
|
-
'baresip'
|
626
|
-
)
|
627
|
-
rescue StandardError => e
|
628
|
-
raise e
|
629
667
|
end
|
630
668
|
|
631
669
|
# Author(s):: 0day Inc. <request.pentest@0dayinc.com>
|
@@ -641,8 +679,11 @@ module PWN
|
|
641
679
|
public_class_method def self.help
|
642
680
|
puts "USAGE:
|
643
681
|
baresip_obj = #{self}.start(
|
644
|
-
|
682
|
+
src_num: 'Optional source phone number displayed',
|
683
|
+
baresip_bin: 'Optional path of baresip binary (Defaults to /usr/bin/baresip)',
|
645
684
|
config_root: 'Optional dir of baresip config (Defaults to ~/.baresip)',
|
685
|
+
session_root: 'Optional dir of baresip session (Defaults to Dir.pwd)',
|
686
|
+
screenlog_path: 'Optional path of screenlog file (Defaults to screenlog.txt)',
|
646
687
|
screen_session: 'Optional name of screen session (Defaults baresip)'
|
647
688
|
)
|
648
689
|
|
@@ -657,8 +698,6 @@ module PWN
|
|
657
698
|
screen_session: 'Required - screen session to stop'
|
658
699
|
)
|
659
700
|
|
660
|
-
#{self}.killall
|
661
|
-
|
662
701
|
#{self}.authors
|
663
702
|
"
|
664
703
|
end
|
data/lib/pwn/plugins/sock.rb
CHANGED
@@ -48,20 +48,20 @@ module PWN
|
|
48
48
|
end
|
49
49
|
|
50
50
|
# Supported Method Parameters::
|
51
|
-
# PWN::Plugins::Sock.
|
51
|
+
# PWN::Plugins::Sock.check_port_in_use(
|
52
52
|
# port: 'required - target port',
|
53
53
|
# server_ip: 'optional - target host or ip to check (Defaults to 127.0.0.1)',
|
54
54
|
# protocol: 'optional - :tcp || :udp (defaults to tcp)'
|
55
55
|
# )
|
56
56
|
|
57
|
-
public_class_method def self.
|
57
|
+
public_class_method def self.check_port_in_use(opts = {})
|
58
58
|
server_ip = opts[:server_ip]
|
59
59
|
server_ip ||= '127.0.0.1'
|
60
60
|
port = opts[:port]
|
61
61
|
protocol = opts[:protocol]
|
62
62
|
protocol ||= :tcp
|
63
63
|
|
64
|
-
ct =
|
64
|
+
ct = 1
|
65
65
|
s = Socket.tcp(server_ip, port, connect_timeout: ct) if protocol == :tcp
|
66
66
|
s = Socket.udp(server_ip, port, connect_timeout: ct) if protocol == :udp
|
67
67
|
s.close
|
@@ -14,8 +14,11 @@ module PWN
|
|
14
14
|
#
|
15
15
|
# Example:
|
16
16
|
# arr = [1, 2, 3, 4, 5, 6, 7, 8, 9]
|
17
|
+
# mutex = Mutex.new
|
17
18
|
# PWN::Plugins::ThreadPool.fill(enumerable_array: arr, max_threads: 9) do |integer|
|
18
|
-
#
|
19
|
+
# mutex.synchronize do
|
20
|
+
# puts integer
|
21
|
+
# end
|
19
22
|
# end
|
20
23
|
|
21
24
|
public_class_method def self.fill(opts = {})
|
data/lib/pwn/reports/phone.rb
CHANGED
@@ -104,9 +104,10 @@ module PWN
|
|
104
104
|
<a class="toggle-vis" data-column="5" href="#">Seconds Recorded</a> |
|
105
105
|
<a class="toggle-vis" data-column="6" href="#">Call Stopped</a>
|
106
106
|
<a class="toggle-vis" data-column="7" href="#">Reason</a>
|
107
|
-
<a class="toggle-vis" data-column="8" href="#">
|
108
|
-
<a class="toggle-vis" data-column="9" href="#">
|
109
|
-
<a class="toggle-vis" data-column="10" href="#">
|
107
|
+
<a class="toggle-vis" data-column="8" href="#">Screenlog</a> |
|
108
|
+
<a class="toggle-vis" data-column="9" href="#">Recording</a> |
|
109
|
+
<a class="toggle-vis" data-column="10" href="#">Spectrogram</a> |
|
110
|
+
<a class="toggle-vis" data-column="11" href="#">Waveform</a>
|
110
111
|
</div>
|
111
112
|
<br /><br />
|
112
113
|
|
@@ -122,6 +123,7 @@ module PWN
|
|
122
123
|
<th>Seconds Recorded</th>
|
123
124
|
<th>Call Stopped</th>
|
124
125
|
<th>Reason Stopped</th>
|
126
|
+
<th>Screenlog</th>
|
125
127
|
<th>Recording</th>
|
126
128
|
<th>Spectrogram</th>
|
127
129
|
<th>Waveform</th>
|
@@ -198,6 +200,13 @@ module PWN
|
|
198
200
|
"data": "reason",
|
199
201
|
"render": $.fn.dataTable.render.text()
|
200
202
|
},
|
203
|
+
{
|
204
|
+
"data": "screenlog",
|
205
|
+
"render": function (data, type, row, meta) {
|
206
|
+
var screenlog = htmlEntityEncode(data);
|
207
|
+
return '<a href="' + screenlog +'" target="_blank">' + screenlog + '</a>';
|
208
|
+
}
|
209
|
+
},
|
201
210
|
{
|
202
211
|
"data": "recording",
|
203
212
|
"render": function (data, type, row, meta) {
|
data/lib/pwn/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pwn
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.4.
|
4
|
+
version: 0.4.545
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- 0day Inc.
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-09-
|
11
|
+
date: 2022-09-26 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -646,14 +646,14 @@ dependencies:
|
|
646
646
|
requirements:
|
647
647
|
- - '='
|
648
648
|
- !ruby/object:Gem::Version
|
649
|
-
version: 4.
|
649
|
+
version: 4.3.0
|
650
650
|
type: :runtime
|
651
651
|
prerelease: false
|
652
652
|
version_requirements: !ruby/object:Gem::Requirement
|
653
653
|
requirements:
|
654
654
|
- - '='
|
655
655
|
- !ruby/object:Gem::Version
|
656
|
-
version: 4.
|
656
|
+
version: 4.3.0
|
657
657
|
- !ruby/object:Gem::Dependency
|
658
658
|
name: rspec
|
659
659
|
requirement: !ruby/object:Gem::Requirement
|
@@ -716,14 +716,14 @@ dependencies:
|
|
716
716
|
requirements:
|
717
717
|
- - '='
|
718
718
|
- !ruby/object:Gem::Version
|
719
|
-
version: 2.13.
|
719
|
+
version: 2.13.2
|
720
720
|
type: :runtime
|
721
721
|
prerelease: false
|
722
722
|
version_requirements: !ruby/object:Gem::Requirement
|
723
723
|
requirements:
|
724
724
|
- - '='
|
725
725
|
- !ruby/object:Gem::Version
|
726
|
-
version: 2.13.
|
726
|
+
version: 2.13.2
|
727
727
|
- !ruby/object:Gem::Dependency
|
728
728
|
name: ruby-audio
|
729
729
|
requirement: !ruby/object:Gem::Requirement
|
@@ -828,14 +828,14 @@ dependencies:
|
|
828
828
|
requirements:
|
829
829
|
- - '='
|
830
830
|
- !ruby/object:Gem::Version
|
831
|
-
version:
|
831
|
+
version: 3.0.1
|
832
832
|
type: :runtime
|
833
833
|
prerelease: false
|
834
834
|
version_requirements: !ruby/object:Gem::Requirement
|
835
835
|
requirements:
|
836
836
|
- - '='
|
837
837
|
- !ruby/object:Gem::Version
|
838
|
-
version:
|
838
|
+
version: 3.0.1
|
839
839
|
- !ruby/object:Gem::Dependency
|
840
840
|
name: slack-ruby-client
|
841
841
|
requirement: !ruby/object:Gem::Requirement
|