pwn 0.4.544 → 0.4.545

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: f8944f6a6ce43d7ce2fe3948eb8bf4b8de7c5accc94d8f37be86b7581cb952e0
4
- data.tar.gz: f1ef22cee1d4ab5cacdd64b14245632d19e3c02a67a064d59ab8d3fd0be291ae
3
+ metadata.gz: a482ad2be090b5fc318d1048fd48f6936906ec7f50ec3e5732c7fbda412f17e0
4
+ data.tar.gz: 8a5d6ad28f6e45bbcbffe34e29a3f558f142b054c46360a0ebabf3dd8b66b7c0
5
5
  SHA512:
6
- metadata.gz: c72fd4c00372738bdc81e0f5c5c8525d76a853af4f763dffc56e368acda60cc81558bf2ae0cc6131744605aaeb0ef0f378c9aea253cf7717858ca8b3f39a5982
7
- data.tar.gz: 5edcca18466c004b1490dbb8e3ee724f6ea3f1b514cad39db54677bc4cbaa1a6d375f7bc4f190a3115420350ebd77c27382a8f33c409ced50132c5553337ae16
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-08-29 16:58:30 UTC using RuboCop version 1.35.1.
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: 264
20
+ # Offense count: 265
21
21
  Lint/UselessAssignment:
22
22
  Enabled: false
23
23
 
24
- # Offense count: 264
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: 68
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: 44
35
+ # Offense count: 46
36
36
  # Configuration parameters: CountBlocks.
37
37
  Metrics/BlockNesting:
38
38
  Max: 5
39
39
 
40
- # Offense count: 94
40
+ # Offense count: 96
41
41
  # Configuration parameters: AllowedMethods, AllowedPatterns, IgnoredMethods.
42
42
  Metrics/CyclomaticComplexity:
43
43
  Max: 231
44
44
 
45
- # Offense count: 482
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: 47
50
+ # Offense count: 48
51
51
  # Configuration parameters: CountComments, CountAsOne.
52
52
  Metrics/ModuleLength:
53
53
  Max: 1186
54
54
 
55
- # Offense count: 86
55
+ # Offense count: 88
56
56
  # Configuration parameters: AllowedMethods, AllowedPatterns, IgnoredMethods.
57
57
  Metrics/PerceivedComplexity:
58
58
  Max: 51
59
59
 
60
- # Offense count: 162
60
+ # Offense count: 164
61
61
  Style/ClassVars:
62
62
  Enabled: false
63
63
 
64
- # Offense count: 284
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: 43
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: 570
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.2.6'
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.1'
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', '2.2.2'
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.544]:001 >>> PWN.help
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.544]:001 >>> PWN.help
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 - update "call_max_calls" in ~/.baresip/config if > 4)>') do |t|
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
 
@@ -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 = baresip_obj[: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
- http_listen_ip_port = http_list_entry.last.split.grep(/:/).last
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
- screenlog_file,
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
- screenlog_file = baresip_obj[:screenlog_file]
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?(screenlog)
187
+ next unless File.exist?(screenlog_path)
166
188
 
167
- # Continuously consume contents of screenlog.0
168
- @session_data = File.readlines(screenlog)
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
- system(
231
- 'screen',
232
- '-X',
233
- '-S',
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.recon(opts = {})
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
- target_file = opts[:target_file]
408
+
393
409
  randomize = opts[:randomize]
394
410
  src_num_rules = opts[:src_num_rules]
395
- max_threads = opts[:max_threads].to_i
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
- target_range = parse_target_file(
414
- target_file: target_file,
415
- randomize: randomize
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
- results_hash = {
419
- session_started: Time.now.strftime('%Y-%m-%d_%H.%M.%S'),
420
- data: []
421
- }
422
-
423
- # TODO: Multi-thread!
424
- # mutex = Mutex.new
425
- # PWN::Plugins::ThreadPool.fill(
426
- # enumerable_array: target_range,
427
- # max_threads: max_threads
428
- # ) do |target_num|
429
- target_range.each_with_index do |target_num, index|
430
- call_count = index + 1
431
- puts "Call #{call_count} of #{target_range.length}..."
432
-
433
- # Change to session_root _before_ starting to ensure
434
- # wav files are stored in the proper location
435
- Dir.chdir(session_root)
436
-
437
- src_num = apply_src_num_rules(
438
- config_root: config_root,
439
- target_num: target_num,
440
- src_num_rules: src_num_rules
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
- call_started = Time.now.strftime('%Y-%m-%d_%H.%M.%S')
463
+ # session_root = baresip_obj[:session_root]
464
+ config_root = baresip_obj[:config_root]
465
+ config = "#{config_root}/config"
446
466
 
447
- call_info_hash[:call_started] = call_started
448
- call_info_hash[:src_num] = src_num
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
- target_num_root = "#{session_root}/#{target_num}-#{call_started}"
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
- # TODO: Determine what to do w/ existing Directory
455
- Dir.mkdir(target_num_root)
456
- Dir.chdir(target_num_root)
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
- # Start baresip in detached screen to support commands over HTTP
459
- # and call recording to wav files
460
- baresip_obj = start(
461
- src_num: src_num,
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
- # session_root = baresip_obj[:session_root]
468
- config_root = baresip_obj[:config_root]
469
- config = "#{config_root}/config"
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
- puts "#{green}#{call_started} >>>#{end_of_color}"
472
- puts "#{yellow}dialing #{target_num}#{end_of_color}"
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
- cmd_resp = baresip_exec(
475
- baresip_obj: baresip_obj,
476
- cmd: "/dial #{target_num}\r\n"
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 "/dial #{target_num} RESP:"
479
- puts cmd_resp.xpath('//pre').text
480
-
481
- cmd_resp = baresip_exec(
482
- baresip_obj: baresip_obj,
483
- cmd: "/listcalls\r\n"
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 '/listcalls RESP:'
486
- puts cmd_resp.xpath('//pre').text
487
-
488
- puts red
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
- if dump_session_data.select { |s| s.include?(unavail) }.length.positive?
507
- reason = 'SIP 503 (service unavailable)'
508
- break
509
- end
600
+ call_resp_hash
601
+ rescue StandardError => e
602
+ raise e
603
+ end
510
604
 
511
- if dump_session_data.select { |s| s.include?(not_found) }.length.positive?
512
- reason = 'SIP 404 (not found)'
513
- break
514
- end
605
+ # Supported Method Parameters::
606
+ # PWN::Plugins::BareSIP.recon(
607
+ # )
515
608
 
516
- sleep 1
517
- end
518
- call_info_hash[:seconds_recorded] = seconds_recorded
519
- puts end_of_color
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
- call_stopped = Time.now.strftime('%Y-%m-%d_%H.%M.%S')
522
- puts "\n#{green}#{call_stopped} >>> #{reason} #{target_num}#{end_of_color}"
523
- call_info_hash[:call_stopped] = call_stopped
524
- call_info_hash[:reason] = reason
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
- call_info_hash[:recording] = '--'
535
- call_info_hash[:waveform] = '--'
536
- call_info_hash[:spectrogram] = '--'
537
-
538
- unless recording.empty?
539
- puts cayan
540
-
541
- call_info_hash[:recording] = "#{target_num}-#{call_started}/#{recording}"
542
-
543
- spectrogram = "#{recording}-spectrogram.png"
544
- print "Generating Audio Spectrogram for #{recording}..."
545
- system(
546
- sox_bin,
547
- '--show-progress',
548
- '--type',
549
- 'sndfile',
550
- '--encoding',
551
- 'signed-integer',
552
- '--bits',
553
- '16',
554
- '--endian',
555
- 'little',
556
- '--channels',
557
- '1',
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
- # mutex.synchronize do
592
- # results_hash[:data].push(call_info_hash)
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
- baresip_bin: 'Optional path of baresip binary (Defaults to /usr/bin/baresip)'
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
@@ -48,20 +48,20 @@ module PWN
48
48
  end
49
49
 
50
50
  # Supported Method Parameters::
51
- # PWN::Plugins::Sock.check_port_availability(
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.check_port_availability(opts = {})
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 = 0.1
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
- # puts integer
19
+ # mutex.synchronize do
20
+ # puts integer
21
+ # end
19
22
  # end
20
23
 
21
24
  public_class_method def self.fill(opts = {})
@@ -104,9 +104,10 @@ module PWN
104
104
  <a class="toggle-vis" data-column="5" href="#">Seconds Recorded</a>&nbsp;|&nbsp;
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="#">Recording</a>&nbsp;|&nbsp;
108
- <a class="toggle-vis" data-column="9" href="#">Spectrogram</a>&nbsp;|&nbsp;
109
- <a class="toggle-vis" data-column="10" href="#">Waveform</a>
107
+ <a class="toggle-vis" data-column="8" href="#">Screenlog</a>&nbsp;|&nbsp;
108
+ <a class="toggle-vis" data-column="9" href="#">Recording</a>&nbsp;|&nbsp;
109
+ <a class="toggle-vis" data-column="10" href="#">Spectrogram</a>&nbsp;|&nbsp;
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
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module PWN
4
- VERSION = '0.4.544'
4
+ VERSION = '0.4.545'
5
5
  end
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.544
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-19 00:00:00.000000000 Z
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.2.6
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.2.6
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.1
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.1
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: 2.2.2
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: 2.2.2
838
+ version: 3.0.1
839
839
  - !ruby/object:Gem::Dependency
840
840
  name: slack-ruby-client
841
841
  requirement: !ruby/object:Gem::Requirement