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 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