pwn 0.5.67 → 0.5.69

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,317 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'pry'
4
+ require 'tty-prompt'
5
+ require 'yaml'
6
+
7
+ module PWN
8
+ module Plugins
9
+ # This module contains methods related to the pwn REPL Driver.
10
+ module REPL
11
+ # Supported Method Parameters::
12
+ # PWN::Plugins::REPL.refresh_ps1_proc(
13
+ # mode: 'required - :splat or nil'
14
+ # )
15
+
16
+ public_class_method def self.refresh_ps1_proc(opts = {})
17
+ mode = opts[:mode]
18
+
19
+ proc do |_target_self, _nest_level, pi|
20
+ pi.config.pwn_repl_line += 1
21
+ line_pad = format(
22
+ '%0.3d',
23
+ pi.config.pwn_repl_line
24
+ )
25
+
26
+ pi.config.prompt_name = :pwn
27
+ name = "\001\e[1m\002\001\e[31m\002#{pi.config.prompt_name}\001\e[0m\002"
28
+ version = "\001\e[36m\002v#{PWN::VERSION}\001\e[0m\002"
29
+ line_count = "\001\e[34m\002#{line_pad}\001\e[0m\002"
30
+ dchars = "\001\e[32m\002>>>\001\e[0m\002"
31
+ dchars = "\001\e[33m\002***\001\e[0m\002" if mode == :splat
32
+
33
+ if pi.config.pwn_asm
34
+ pi.config.prompt_name = 'pwn.asm'
35
+ name = "\001\e[1m\002\001\e[37m\002#{pi.config.prompt_name}\001\e[0m\002"
36
+ dchars = "\001\e[32m\002>>>\001\e[33m\002"
37
+ dchars = "\001\e[33m\002***\001\e[33m\002" if mode == :splat
38
+ end
39
+
40
+ if pi.config.pwn_ai
41
+ pi.config.prompt_name = 'pwn.ai'
42
+ pi.config.prompt_name = 'pwn.ai.SPEAKING' if pi.config.pwn_ai_speak
43
+ name = "\001\e[1m\002\001\e[33m\002#{pi.config.prompt_name}\001\e[0m\002"
44
+ dchars = "\001\e[32m\002>>>\001\e[33m\002"
45
+ dchars = "\001\e[33m\002***\001\e[33m\002" if mode == :splat
46
+ if pi.config.pwn_ai_debug
47
+ dchars = "\001\e[32m\002(DEBUG) >>>\001\e[33m\002"
48
+ dchars = "\001\e[33m\002(DEBUG) ***\001\e[33m\002" if mode == :splat
49
+ end
50
+ end
51
+
52
+ "#{name}[#{version}]:#{line_count} #{dchars} ".to_s.scrub
53
+ end
54
+ rescue StandardError => e
55
+ raise e
56
+ end
57
+
58
+ # Supported Method Parameters::
59
+ # PWN::Plugins::REPL.add_commands
60
+
61
+ public_class_method def self.add_commands
62
+ # Define Custom REPL Commands
63
+ Pry::Commands.create_command 'welcome-banner' do
64
+ description 'Display the random welcome banner, including basic usage.'
65
+
66
+ def process
67
+ puts PWN::Banner.welcome
68
+ end
69
+ end
70
+
71
+ Pry::Commands.create_command 'toggle-pager' do
72
+ description 'Toggle less on returned objects surpassing the terminal.'
73
+
74
+ def process
75
+ pi = pry_instance
76
+ pi.config.pager ? pi.config.pager = false : pi.config.pager = true
77
+ end
78
+ end
79
+
80
+ # class PWNCompleter < Pry::InputCompleter
81
+ # def call(input)
82
+ # end
83
+ # end
84
+
85
+ Pry::Commands.create_command 'pwn-asm' do
86
+ description 'Initiate pwn.asm shell.'
87
+
88
+ def process
89
+ pi = pry_instance
90
+ pi.config.pwn_asm = true
91
+ pi.custom_completions = proc do
92
+ prompt = TTY::Prompt.new
93
+ [pi.input.line_buffer]
94
+ # prompt.select(pi.input.line_buffer)
95
+ end
96
+ end
97
+ end
98
+
99
+ Pry::Commands.create_command 'pwn-ai' do
100
+ description 'Initiate pwn.ai chat interface.'
101
+
102
+ def process
103
+ pi = pry_instance
104
+ pi.config.pwn_ai = true
105
+ pi.config.color = false if pi.config.pwn_ai
106
+ pi.config.color = true unless pi.config.pwn_ai
107
+ end
108
+ end
109
+
110
+ Pry::Commands.create_command 'toggle-pwn-ai-debug' do
111
+ description 'Display the response_history object while using pwn.ai'
112
+
113
+ def process
114
+ pi = pry_instance
115
+ pi.config.pwn_ai_debug ? pi.config.pwn_ai_debug = false : pi.config.pwn_ai_debug = true
116
+ end
117
+ end
118
+
119
+ Pry::Commands.create_command 'toggle-pwn-ai-speaks' do
120
+ description 'Use speech capabilities within pwn.ai to speak answers.'
121
+
122
+ def process
123
+ pi = pry_instance
124
+ pi.config.pwn_ai_speak ? pi.config.pwn_ai_speak = false : pi.config.pwn_ai_speak = true
125
+ end
126
+ end
127
+
128
+ Pry::Commands.create_command 'back' do
129
+ description 'Jump back to pwn REPL when in pwn-asm || pwn-ai.'
130
+
131
+ def process
132
+ pi = pry_instance
133
+ pi.config.pwn_asm = false if pi.config.pwn_asm
134
+ pi.config.pwn_ai = false if pi.config.pwn_ai
135
+ pi.config.pwn_ai_debug = false if pi.config.pwn_ai_debug
136
+ pi.config.pwn_ai_speak = false if pi.config.pwn_ai_speak
137
+ pi.config.completer = Pry::InputCompleter
138
+ end
139
+ end
140
+ rescue StandardError => e
141
+ raise e
142
+ end
143
+
144
+ # Supported Method Parameters::
145
+ # PWN::Plugins::REPL.add_hooks(
146
+ # opts: 'required - Hash object passed in via pwn OptParser'
147
+ # )
148
+
149
+ public_class_method def self.add_hooks(opts = {})
150
+ # Define REPL Hooks
151
+ # Welcome Banner Hook
152
+ Pry.config.hooks.add_hook(:before_session, :welcome) do |output, _binding, _pi|
153
+ output.puts PWN::Banner.welcome
154
+ end
155
+
156
+ # pwn.ai Hooks
157
+ Pry.config.hooks.add_hook(:before_session, :init_opts) do |_output, _binding, pi|
158
+ if opts[:yaml_config_path] && File.exist?(opts[:yaml_config_path])
159
+ yaml_config_path = opts[:yaml_config_path]
160
+ is_encrypted = PWN::Plugins::Vault.file_encrypted?(file: yaml_config_path)
161
+
162
+ if is_encrypted
163
+ # TODO: Implement "something you know, something you have, && something you are?"
164
+ decryption_file = opts[:decryption_file] ||= "#{Dir.home}/pwn.decryptor.yaml"
165
+ yaml_decryptor = YAML.load_file(decryption_file, symbolize_names: true) if File.exist?(decryption_file)
166
+
167
+ key = opts[:key] ||= yaml_decryptor[:key] ||= ENV.fetch('PWN_DECRYPTOR_KEY')
168
+ key = PWN::Plugins::AuthenticationHelper.mask_password(prompt: 'Decryption Key') if key.nil?
169
+
170
+ iv = opts[:iv] ||= yaml_decryptor[:iv] ||= ENV.fetch('PWN_DECRYPTOR_IV')
171
+ iv = PWN::Plugins::AuthenticationHelper.mask_password(prompt: 'Decryption IV') if iv.nil?
172
+
173
+ decrypted_yaml_config = PWN::Plugins::Vault.dump(
174
+ file: yaml_config_path,
175
+ key: key,
176
+ iv: iv
177
+ )
178
+ yaml_config = YAML.load(decrypted_yaml_config, symbolize_names: true)
179
+ else
180
+ yaml_config = YAML.load_file(yaml_config_path, symbolize_names: true)
181
+ end
182
+
183
+ pi.config.pwn_ai_key = yaml_config[:ai_key]
184
+ Pry.config.pwn_ai_key = pi.config.pwn_ai_key
185
+ end
186
+ end
187
+
188
+ Pry.config.hooks.add_hook(:after_read, :pwn_asm_hook) do |request, pi|
189
+ if pi.config.pwn_asm && !request.chomp.empty?
190
+ request = pi.input.line_buffer
191
+
192
+ # Analyze request to determine if it should be processed as opcodes or asm.
193
+ straight_hex = /^[a-fA-F0-9\s]+$/
194
+ hex_esc_strings = /\\x[\da-fA-F]{2}/
195
+ hex_comma_delim_w_dbl_qt = /"(?:[0-9a-fA-F]{2})",?/
196
+ hex_comma_delim_w_sng_qt = /'(?:[0-9a-fA-F]{2})',?/
197
+ hex_byte_array_as_str = /^\[\s*(?:"[0-9a-fA-F]{2}",\s*)*"[0-9a-fA-F]{2}"\s*\]$/
198
+
199
+ if request.match?(straight_hex) ||
200
+ request.match?(hex_esc_strings) ||
201
+ request.match?(hex_comma_delim_w_dbl_qt) ||
202
+ request.match?(hex_comma_delim_w_sng_qt) ||
203
+ request.match?(hex_byte_array_as_str)
204
+
205
+ response = PWN::Plugins::Assembly.opcodes_to_asm(
206
+ opcodes: request,
207
+ opcodes_always_strings_obj: true
208
+ )
209
+ else
210
+ response = PWN::Plugins::Assembly.asm_to_opcodes(asm: request)
211
+ end
212
+ puts "\001\e[31m\002#{response}\001\e[0m\002"
213
+ end
214
+ end
215
+
216
+ Pry.config.hooks.add_hook(:after_read, :pwn_ai_hook) do |request, pi|
217
+ if pi.config.pwn_ai && !request.chomp.empty?
218
+ request = pi.input.line_buffer.to_s
219
+ debug = pi.config.pwn_ai_debug
220
+ ai_key = pi.config.pwn_ai_key
221
+ ai_key ||= ''
222
+ if ai_key.empty?
223
+ ai_key = PWN::Plugins::AuthenticationHelper.mask_password(
224
+ prompt: 'OpenAI API Key'
225
+ )
226
+ pi.config.pwn_ai_key = ai_key
227
+ end
228
+
229
+ response_history = pi.config.pwn_ai_response_history
230
+ speak_answer = pi.config.pwn_ai_speak
231
+ response = PWN::Plugins::OpenAI.chat(
232
+ token: ai_key,
233
+ request: request.chomp,
234
+ temp: 1,
235
+ response_history: response_history,
236
+ speak_answer: speak_answer
237
+ )
238
+ last_response = response[:choices].last[:content]
239
+ puts "\n\001\e[32m\002#{last_response}\001\e[0m\002\n\n"
240
+
241
+ response_history = {
242
+ id: response[:id],
243
+ object: response[:object],
244
+ model: response[:model],
245
+ usage: response[:usage]
246
+ }
247
+ response_history[:choices] ||= response[:choices]
248
+
249
+ if debug
250
+ puts 'DEBUG: response_history => '
251
+ pp response_history
252
+ puts "\nresponse_history[:choices] Length: #{response_history[:choices].length}\n" unless response_history.nil?
253
+ end
254
+ pi.config.pwn_ai_response_history = response_history
255
+ end
256
+ end
257
+ rescue StandardError => e
258
+ raise e
259
+ end
260
+
261
+ # Supported Method Parameters::
262
+ # PWN::Plugins::REPL.start(
263
+ # opts: 'required - Hash object passed in via pwn OptParser'
264
+ # )
265
+
266
+ public_class_method def self.start(opts = {})
267
+ # Monkey Patch Pry, add commands, && hooks
268
+ PWN::Plugins::MonkeyPatch.pry
269
+ add_commands
270
+ add_hooks(opts)
271
+
272
+ # Define PS1 Prompt
273
+ Pry.config.pwn_repl_line = 0
274
+ Pry.config.prompt_name = :pwn
275
+ arrow_ps1_proc = refresh_ps1_proc
276
+ splat_ps1_proc = refresh_ps1_proc(mode: :splat)
277
+ ps1 = [arrow_ps1_proc, splat_ps1_proc]
278
+ prompt = Pry::Prompt.new(:pwn, 'PWN Prototyping REPL', ps1)
279
+
280
+ # Start PWN REPL
281
+ Pry.start(self, prompt: prompt)
282
+ rescue StandardError => e
283
+ raise e
284
+ end
285
+
286
+ # Author(s):: 0day Inc. <request.pentest@0dayinc.com>
287
+
288
+ public_class_method def self.authors
289
+ "AUTHOR(S):
290
+ 0day Inc. <request.pentest@0dayinc.com>
291
+ "
292
+ end
293
+
294
+ # Display Usage for this Module
295
+
296
+ public_class_method def self.help
297
+ puts "USAGE:
298
+ #{self}.refresh_ps1_proc(
299
+ mode: 'required - :splat or nil'
300
+ )
301
+
302
+ #{self}.add_commands
303
+
304
+ #{self}.add_hooks(
305
+ opts: 'required - Hash object passed in via pwn OptParser'
306
+ )
307
+
308
+ #{self}.start(
309
+ opts: 'required - Hash object passed in via pwn OptParser'
310
+ )
311
+
312
+ #{self}.authors
313
+ "
314
+ end
315
+ end
316
+ end
317
+ end
@@ -72,6 +72,9 @@ module PWN
72
72
 
73
73
  raise 'ERROR: key and iv parameters are required.' if key.nil? || iv.nil?
74
74
 
75
+ is_encrypted = file_encrypted?(file: file)
76
+ raise 'ERROR: File is not encrypted.' unless is_encrypted
77
+
75
78
  cipher = OpenSSL::Cipher.new('aes-256-cbc')
76
79
  cipher.decrypt
77
80
  cipher.key = Base64.strict_decode64(key)
@@ -195,6 +198,8 @@ module PWN
195
198
 
196
199
  file_contents = File.read(file)
197
200
  file_contents.is_a?(String) && Base64.strict_encode64(Base64.strict_decode64(file_contents)) == file_contents
201
+ rescue ArgumentError
202
+ false
198
203
  rescue StandardError => e
199
204
  raise e
200
205
  end
data/lib/pwn/plugins.rb CHANGED
@@ -37,6 +37,7 @@ module PWN
37
37
  autoload :Log, 'pwn/plugins/log'
38
38
  autoload :MailAgent, 'pwn/plugins/mail_agent'
39
39
  autoload :Metasploit, 'pwn/plugins/metasploit'
40
+ autoload :MonkeyPatch, 'pwn/plugins/monkey_patch'
40
41
  autoload :MSR206, 'pwn/plugins/msr206'
41
42
  autoload :NessusCloud, 'pwn/plugins/nessus_cloud'
42
43
  autoload :NexposeVulnScan, 'pwn/plugins/nexpose_vuln_scan'
@@ -52,6 +53,7 @@ module PWN
52
53
  autoload :Pony, 'pwn/plugins/pony'
53
54
  autoload :PS, 'pwn/plugins/ps'
54
55
  autoload :RabbitMQ, 'pwn/plugins/rabbit_mq'
56
+ autoload :REPL, 'pwn/plugins/repl'
55
57
  autoload :RFIDler, 'pwn/plugins/rfidler'
56
58
  autoload :ScannableCodes, 'pwn/plugins/scannable_codes'
57
59
  autoload :Serial, 'pwn/plugins/serial'
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.5.67'
4
+ VERSION = '0.5.69'
5
5
  end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe PWN::Plugins::MonkeyPatch do
6
+ it 'should display information for authors' do
7
+ authors_response = PWN::Plugins::MonkeyPatch
8
+ expect(authors_response).to respond_to :authors
9
+ end
10
+
11
+ it 'should display information for existing help method' do
12
+ help_response = PWN::Plugins::MonkeyPatch
13
+ expect(help_response).to respond_to :help
14
+ end
15
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'spec_helper'
4
+
5
+ describe PWN::Plugins::REPL do
6
+ it 'should display information for authors' do
7
+ authors_response = PWN::Plugins::REPL
8
+ expect(authors_response).to respond_to :authors
9
+ end
10
+
11
+ it 'should display information for existing help method' do
12
+ help_response = PWN::Plugins::REPL
13
+ expect(help_response).to respond_to :help
14
+ end
15
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pwn
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.67
4
+ version: 0.5.69
5
5
  platform: ruby
6
6
  authors:
7
7
  - 0day Inc.
@@ -534,14 +534,14 @@ dependencies:
534
534
  requirements:
535
535
  - - '='
536
536
  - !ruby/object:Gem::Version
537
- version: 0.4.0.1
537
+ version: 0.5.0
538
538
  type: :runtime
539
539
  prerelease: false
540
540
  version_requirements: !ruby/object:Gem::Requirement
541
541
  requirements:
542
542
  - - '='
543
543
  - !ruby/object:Gem::Version
544
- version: 0.4.0.1
544
+ version: 0.5.0
545
545
  - !ruby/object:Gem::Dependency
546
546
  name: nexpose
547
547
  requirement: !ruby/object:Gem::Requirement
@@ -1767,6 +1767,7 @@ files:
1767
1767
  - lib/pwn/plugins/log.rb
1768
1768
  - lib/pwn/plugins/mail_agent.rb
1769
1769
  - lib/pwn/plugins/metasploit.rb
1770
+ - lib/pwn/plugins/monkey_patch.rb
1770
1771
  - lib/pwn/plugins/msr206.rb
1771
1772
  - lib/pwn/plugins/nessus_cloud.rb
1772
1773
  - lib/pwn/plugins/nexpose_vuln_scan.rb
@@ -1783,6 +1784,7 @@ files:
1783
1784
  - lib/pwn/plugins/ps.rb
1784
1785
  - lib/pwn/plugins/pwn_logger.rb
1785
1786
  - lib/pwn/plugins/rabbit_mq.rb
1787
+ - lib/pwn/plugins/repl.rb
1786
1788
  - lib/pwn/plugins/rfidler.rb
1787
1789
  - lib/pwn/plugins/scannable_codes.rb
1788
1790
  - lib/pwn/plugins/serial.rb
@@ -2094,6 +2096,7 @@ files:
2094
2096
  - spec/lib/pwn/plugins/log_spec.rb
2095
2097
  - spec/lib/pwn/plugins/mail_agent_spec.rb
2096
2098
  - spec/lib/pwn/plugins/metasploit_spec.rb
2099
+ - spec/lib/pwn/plugins/monkey_patch_spec.rb
2097
2100
  - spec/lib/pwn/plugins/msr206_spec.rb
2098
2101
  - spec/lib/pwn/plugins/nessus_cloud_spec.rb
2099
2102
  - spec/lib/pwn/plugins/nexpose_vuln_scan_spec.rb
@@ -2110,6 +2113,7 @@ files:
2110
2113
  - spec/lib/pwn/plugins/ps_spec.rb
2111
2114
  - spec/lib/pwn/plugins/pwn_logger_spec.rb
2112
2115
  - spec/lib/pwn/plugins/rabbit_mq_spec.rb
2116
+ - spec/lib/pwn/plugins/repl_spec.rb
2113
2117
  - spec/lib/pwn/plugins/rfidler_spec.rb
2114
2118
  - spec/lib/pwn/plugins/scannable_codes_spec.rb
2115
2119
  - spec/lib/pwn/plugins/serial_spec.rb