pwn 0.5.67 → 0.5.69

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: 8fd794ce6149bca1bcacf6eb83e4116d26dddad3f7007829cec0ff4520eb9f59
4
- data.tar.gz: 056c7e6727ec6afb5ec98563b912ab65fdca366067296f0aa12501d5d7ae63d1
3
+ metadata.gz: 7e2be578588aa0e4172ddafce691a25711ad3afd796c293cf96df508d3c7fc84
4
+ data.tar.gz: c72375b8d8c69ceb9fd3909d33187f595f3f11c41918cc1dd2fe0ae8a44ed25e
5
5
  SHA512:
6
- metadata.gz: 0764f4c9956e10475675ed33769d07b94ba19090c2db59937ff45ed1f110dad1860a6c02b8eaca71d7e5269dacb4c460472777dfb3285d2ec963c4a0c59975e2
7
- data.tar.gz: 651a021f5476d9e6735c08f126411c23c6cfba3b0d9455ad1561b0fa9a46793f1c1b4bf6025a49f1d0c50f557ed9e150cd339aefed44003298a5f3100fa85e94
6
+ metadata.gz: 47b720e8b8e98b3adf7c04c5e5af2fda98d614c70e29c43b1a5e781b0bf6bf960c60134496f245586656aeebc6349b8a3d8260af12632d1814a0a5dbbc74675e
7
+ data.tar.gz: 3db9a37a60de63e47a700bb0fdd8385a68c2314015ddd8818fe218372a07dda3cb5dfa47126974d7783fffa1c0166cd55d0da235cdaa4bb1508065398bbec623
data/.rubocop_todo.yml CHANGED
@@ -1,6 +1,6 @@
1
1
  # This configuration was generated by
2
2
  # `rubocop --auto-gen-config`
3
- # on 2024-03-25 22:25:57 UTC using RuboCop version 1.62.1.
3
+ # on 2024-03-26 16:48:38 UTC using RuboCop version 1.62.1.
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
@@ -35,6 +35,12 @@ Layout/LineLength:
35
35
  - 'lib/pwn/reports/uri_buster.rb'
36
36
  - 'lib/pwn/sast/banned_function_calls_c.rb'
37
37
 
38
+ # Offense count: 7
39
+ # Configuration parameters: AllowedMethods, AllowedPatterns.
40
+ Lint/NestedMethodDefinition:
41
+ Exclude:
42
+ - 'lib/pwn/plugins/repl.rb'
43
+
38
44
  # Offense count: 311
39
45
  # This cop supports unsafe autocorrection (--autocorrect-all).
40
46
  # Configuration parameters: AutoCorrect.
@@ -88,6 +94,14 @@ Metrics/ModuleLength:
88
94
  - 'lib/pwn/plugins/open_ai.rb'
89
95
  - 'lib/pwn/plugins/packet.rb'
90
96
 
97
+ # Offense count: 1
98
+ # This cop supports safe autocorrection (--autocorrect).
99
+ # Configuration parameters: EnforcedStyle.
100
+ # SupportedStyles: prefer_alias, prefer_alias_method
101
+ Style/Alias:
102
+ Exclude:
103
+ - 'lib/pwn/plugins/monkey_patch.rb'
104
+
91
105
  # Offense count: 160
92
106
  Style/ClassVars:
93
107
  Enabled: false
@@ -105,11 +119,10 @@ Style/ExplicitBlockArgument:
105
119
  Exclude:
106
120
  - 'lib/pwn/plugins/nmap_it.rb'
107
121
 
108
- # Offense count: 3
122
+ # Offense count: 2
109
123
  # This cop supports safe autocorrection (--autocorrect).
110
124
  Style/IfUnlessModifier:
111
125
  Exclude:
112
- - 'bin/pwn'
113
126
  - 'lib/pwn/plugins/baresip.rb'
114
127
  - 'lib/pwn/plugins/mail_agent.rb'
115
128
 
@@ -133,18 +146,3 @@ Style/RedundantStringEscape:
133
146
  # This cop supports unsafe autocorrection (--autocorrect-all).
134
147
  Style/SlicingWithRange:
135
148
  Enabled: false
136
-
137
- # Offense count: 1
138
- # This cop supports safe autocorrection (--autocorrect).
139
- # Configuration parameters: AllowModifier.
140
- Style/SoleNestedConditional:
141
- Exclude:
142
- - 'bin/pwn'
143
-
144
- # Offense count: 1
145
- # This cop supports safe autocorrection (--autocorrect).
146
- # Configuration parameters: EnforcedStyle, ConsistentQuotesInMultiline.
147
- # SupportedStyles: single_quotes, double_quotes
148
- Style/StringLiterals:
149
- Exclude:
150
- - 'bin/pwn'
data/Gemfile CHANGED
@@ -50,7 +50,7 @@ gem 'msfrpc-client', '1.1.2'
50
50
  gem 'netaddr', '2.0.6'
51
51
  gem 'net-ldap', '0.19.0'
52
52
  gem 'net-openvpn', '0.8.7'
53
- gem 'net-smtp', '0.4.0.1'
53
+ gem 'net-smtp', '0.5.0'
54
54
  gem 'nexpose', '7.3.0'
55
55
  gem 'nokogiri', '1.16.3'
56
56
  gem 'nokogiri-diff', '0.3.0'
data/README.md CHANGED
@@ -37,7 +37,7 @@ $ cd /opt/pwn
37
37
  $ ./install.sh
38
38
  $ ./install.sh ruby-gem
39
39
  $ pwn
40
- pwn[v0.5.67]:001 >>> PWN.help
40
+ pwn[v0.5.69]: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.3.0@pwn
52
52
  $ gem uninstall --all --executables pwn
53
53
  $ gem install --verbose pwn
54
54
  $ pwn
55
- pwn[v0.5.67]:001 >>> PWN.help
55
+ pwn[v0.5.69]:001 >>> PWN.help
56
56
  ```
57
57
 
58
58
  If you're using a multi-user install of RVM do:
@@ -62,7 +62,7 @@ $ rvm use ruby-3.3.0@pwn
62
62
  $ rvmsudo gem uninstall --all --executables pwn
63
63
  $ rvmsudo gem install --verbose pwn
64
64
  $ pwn
65
- pwn[v0.5.67]:001 >>> PWN.help
65
+ pwn[v0.5.69]:001 >>> PWN.help
66
66
  ```
67
67
 
68
68
  PWN periodically upgrades to the latest version of Ruby which is reflected in `/opt/pwn/.ruby-version`. The easiest way to upgrade to the latest version of Ruby from a previous PWN installation is to run the following script:
data/bin/pwn CHANGED
@@ -3,9 +3,6 @@
3
3
 
4
4
  require 'optparse'
5
5
  require 'pwn'
6
- require 'pry'
7
- require 'tty-prompt'
8
- require 'yaml'
9
6
 
10
7
  opts = {}
11
8
  OptionParser.new do |options|
@@ -31,391 +28,19 @@ OptionParser.new do |options|
31
28
  end.parse!
32
29
 
33
30
  begin
34
- def refresh_ps1_proc(opts = {})
35
- mode = opts[:mode]
36
-
37
- proc do |_target_self, _nest_level, pi|
38
- pi.config.pwn_repl_line += 1
39
- line_pad = format(
40
- '%0.3d',
41
- pi.config.pwn_repl_line
42
- )
43
-
44
- pi.config.prompt_name = :pwn
45
- name = "\001\e[1m\002\001\e[31m\002#{pi.config.prompt_name}\001\e[0m\002"
46
- version = "\001\e[36m\002v#{PWN::VERSION}\001\e[0m\002"
47
- line_count = "\001\e[34m\002#{line_pad}\001\e[0m\002"
48
- dchars = "\001\e[32m\002>>>\001\e[0m\002"
49
- dchars = "\001\e[33m\002***\001\e[0m\002" if mode == :splat
50
-
51
- if pi.config.pwn_asm
52
- pi.config.prompt_name = 'pwn.asm'
53
- name = "\001\e[1m\002\001\e[37m\002#{pi.config.prompt_name}\001\e[0m\002"
54
- dchars = "\001\e[32m\002>>>\001\e[33m\002"
55
- dchars = "\001\e[33m\002***\001\e[33m\002" if mode == :splat
56
- end
57
-
58
- if pi.config.pwn_ai
59
- pi.config.prompt_name = 'pwn.ai'
60
- pi.config.prompt_name = 'pwn.ai.SPEAKING' if pi.config.pwn_ai_speak
61
- name = "\001\e[1m\002\001\e[33m\002#{pi.config.prompt_name}\001\e[0m\002"
62
- dchars = "\001\e[32m\002>>>\001\e[33m\002"
63
- dchars = "\001\e[33m\002***\001\e[33m\002" if mode == :splat
64
- if pi.config.pwn_ai_debug
65
- dchars = "\001\e[32m\002(DEBUG) >>>\001\e[33m\002"
66
- dchars = "\001\e[33m\002(DEBUG) ***\001\e[33m\002" if mode == :splat
67
- end
68
- end
69
-
70
- "#{name}[#{version}]:#{line_count} #{dchars} ".to_s.scrub
71
- end
72
- end
73
-
74
- # Pry Monkey Patches \_(--)_/
75
- class Pry
76
- # Overwrite Pry::History.push method in History class to get duplicate history entries
77
- # in order to properly replay automation in this prototyping driver
78
- class History
79
- def push(line)
80
- return line if line.empty? || invalid_readline_line?(line)
81
-
82
- begin
83
- last_line = @history[-1]
84
- rescue IndexError
85
- last_line = nil
86
- end
87
-
88
- @history << line
89
- @history_line_count += 1
90
- @saver.call(line) if !should_ignore?(line) &&
91
- Pry.config.history_save
92
-
93
- line
94
- end
95
- alias << push
96
- end
97
-
98
- def handle_line(line, options)
99
- if line.nil?
100
- config.control_d_handler.call(self)
101
- return
102
- end
103
-
104
- ensure_correct_encoding!(line)
105
- Pry.history << line unless options[:generated]
106
-
107
- @suppress_output = false
108
- inject_sticky_locals!
109
- begin
110
- unless process_command_safely(line)
111
- @eval_string += "#{line.chomp}\n" if !line.empty? || !@eval_string.empty?
112
- end
113
- rescue RescuableException => e
114
- self.last_exception = e
115
- result = e
116
-
117
- Pry.critical_section do
118
- show_result(result)
119
- end
120
- return
121
- end
122
-
123
- # This hook is supposed to be executed after each line of ruby code
124
- # has been read (regardless of whether eval_string is yet a complete expression)
125
- exec_hook :after_read, eval_string, self
126
-
127
- begin
128
- complete_expr = true if config.pwn_ai || config.pwn_asm
129
- complete_expr = Pry::Code.complete_expression?(@eval_string) unless config.pwn_ai || config.pwn_asm
130
- rescue SyntaxError => e
131
- output.puts e.message.gsub(/^.*syntax error, */, "SyntaxError: ")
132
- reset_eval_string
133
- end
134
-
135
- if complete_expr
136
- @suppress_output = true if @eval_string =~ /;\Z/ ||
137
- @eval_string.empty? ||
138
- @eval_string =~ /\A *#.*\n\z/ ||
139
- config.pwn_ai ||
140
- config.pwn_asm
141
-
142
- # A bug in jruby makes java.lang.Exception not rescued by
143
- # `rescue Pry::RescuableException` clause.
144
- #
145
- # * https://github.com/pry/pry/issues/854
146
- # * https://jira.codehaus.org/browse/JRUBY-7100
147
- #
148
- # Until that gets fixed upstream, treat java.lang.Exception
149
- # as an additional exception to be rescued explicitly.
150
- #
151
- # This workaround has a side effect: java exceptions specified
152
- # in `Pry.config.unrescued_exceptions` are ignored.
153
- jruby_exceptions = []
154
- jruby_exceptions << Java::JavaLang::Exception if Helpers::Platform.jruby?
155
-
156
- begin
157
- # Reset eval string, in case we're evaluating Ruby that does something
158
- # like open a nested REPL on this instance.
159
- eval_string = @eval_string
160
- reset_eval_string
161
-
162
- result = evaluate_ruby(eval_string) unless config.pwn_ai ||
163
- config.pwn_asm
164
-
165
- result = eval_string if config.pwn_ai ||
166
- config.pwn_asm
167
- rescue RescuableException, *jruby_exceptions => e
168
- # Eliminate following warning:
169
- # warning: singleton on non-persistent Java type X
170
- # (http://wiki.jruby.org/Persistence)
171
- if Helpers::Platform.jruby? && e.class.respond_to?('__persistent__')
172
- e.class.__persistent__ = true
173
- end
174
- self.last_exception = e
175
- result = e
176
- end
177
-
178
- Pry.critical_section do
179
- show_result(result)
180
- end
181
- end
182
-
183
- throw(:breakout) if current_binding.nil?
184
- end
185
-
186
- # Ensure the return value in pwn_ai mode reflects the input
187
- def evaluate_ruby(code)
188
- # if config.pwn_ai || config.pwn_asm
189
- # result = message = code.to_s
190
- # return
191
- # end
192
- inject_sticky_locals!
193
- exec_hook :before_eval, code, self
194
-
195
- result = current_binding.eval(code, Pry.eval_path, Pry.current_line)
196
- set_last_result(result, code)
197
- ensure
198
- update_input_history(code)
199
- exec_hook :after_eval, result, self
200
- end
201
- end
202
-
203
- # Define Custom REPL Commands
204
- Pry::Commands.create_command 'welcome-banner' do
205
- description 'Display the random welcome banner, including basic usage.'
206
-
207
- def process
208
- puts PWN::Banner.welcome
209
- end
210
- end
211
-
212
- Pry::Commands.create_command 'toggle-pager' do
213
- description 'Toggle less on returned objects surpassing the terminal.'
214
-
215
- def process
216
- pi = pry_instance
217
- pi.config.pager ? pi.config.pager = false : pi.config.pager = true
218
- end
219
- end
220
-
221
- # class PWNCompleter < Pry::InputCompleter
222
- # def call(input)
223
- # end
224
- # end
225
-
226
- Pry::Commands.create_command 'pwn-asm' do
227
- description 'Initiate pwn.asm shell.'
228
-
229
- def process
230
- pi = pry_instance
231
- pi.config.pwn_asm = true
232
- pi.custom_completions = proc do
233
- prompt = TTY::Prompt.new
234
- [pi.input.line_buffer]
235
- # prompt.select(pi.input.line_buffer)
236
- end
237
- end
238
- end
239
-
240
- Pry::Commands.create_command 'pwn-ai' do
241
- description 'Initiate pwn.ai chat interface.'
242
-
243
- def process
244
- pi = pry_instance
245
- pi.config.pwn_ai = true
246
- pi.config.color = false if pi.config.pwn_ai
247
- pi.config.color = true unless pi.config.pwn_ai
248
- end
249
- end
250
-
251
- Pry::Commands.create_command 'toggle-pwn-ai-debug' do
252
- description 'Display the response_history object while using pwn.ai'
253
-
254
- def process
255
- pi = pry_instance
256
- pi.config.pwn_ai_debug ? pi.config.pwn_ai_debug = false : pi.config.pwn_ai_debug = true
257
- end
258
- end
259
-
260
- Pry::Commands.create_command 'toggle-pwn-ai-speaks' do
261
- description 'Use speech capabilities within pwn.ai to speak answers.'
262
-
263
- def process
264
- pi = pry_instance
265
- pi.config.pwn_ai_speak ? pi.config.pwn_ai_speak = false : pi.config.pwn_ai_speak = true
266
- end
267
- end
268
-
269
- Pry::Commands.create_command 'back' do
270
- description 'Jump back to pwn REPL when in pwn-asm || pwn-ai.'
271
-
272
- def process
273
- pi = pry_instance
274
- pi.config.pwn_asm = false if pi.config.pwn_asm
275
- pi.config.pwn_ai = false if pi.config.pwn_ai
276
- pi.config.pwn_ai_debug = false if pi.config.pwn_ai_debug
277
- pi.config.pwn_ai_speak = false if pi.config.pwn_ai_speak
278
- pi.config.completer = Pry::InputCompleter
279
- end
280
- end
281
-
282
- # Define REPL Hooks
283
- # Welcome Banner Hook
284
- Pry.config.hooks.add_hook(:before_session, :welcome) do |output, _binding, _pi|
285
- output.puts PWN::Banner.welcome
286
- end
287
-
288
- # pwn.ai Hooks
289
- Pry.config.hooks.add_hook(:before_session, :init_opts) do |_output, _binding, pi|
290
- if opts[:yaml_config_path] && File.exist?(opts[:yaml_config_path])
291
- yaml_config_path = opts[:yaml_config_path]
292
- is_encrypted = PWN::Plugins::Vault.file_encrypted?(file: yaml_config_path)
293
-
294
- if is_encrypted
295
- # TODO: Implement "something you know, something you have, && something you are?"
296
- decryption_file = opts[:decryption_file] ||= "#{Dir.home}/pwn.decryptor.yaml"
297
- yaml_decryptor = YAML.load_file(decryption_file, symbolize_names: true) if File.exist?(decryption_file)
298
-
299
- key = opts[:key] ||= yaml_decryptor[:key] ||= ENV.fetch('PWN_DECRYPTOR_KEY')
300
- key = PWN::Plugins::AuthenticationHelper.mask_password(prompt: 'Decryption Key') if key.nil?
301
-
302
- iv = opts[:iv] ||= yaml_decryptor[:iv] ||= ENV.fetch('PWN_DECRYPTOR_IV')
303
- iv = PWN::Plugins::AuthenticationHelper.mask_password(prompt: 'Decryption IV') if iv.nil?
304
-
305
- decrypted_yaml_config = PWN::Plugins::Vault.dump(
306
- file: yaml_config_path,
307
- key: key,
308
- iv: iv
309
- )
310
- yaml_config = YAML.load(decrypted_yaml_config, symbolize_names: true)
311
- else
312
- yaml_config = YAML.load_file(yaml_config_path, symbolize_names: true)
313
- end
314
-
315
- pi.config.pwn_ai_key = yaml_config[:ai_key]
316
- Pry.config.pwn_ai_key = pi.config.pwn_ai_key
317
- end
318
- end
319
-
320
- Pry.config.hooks.add_hook(:after_read, :pwn_asm_hook) do |request, pi|
321
- if pi.config.pwn_asm && !request.chomp.empty?
322
- request = pi.input.line_buffer
323
-
324
- # Analyze request to determine if it should be processed as opcodes or asm.
325
- straight_hex = /^[a-fA-F0-9\s]+$/
326
- hex_esc_strings = /\\x[\da-fA-F]{2}/
327
- hex_comma_delim_w_dbl_qt = /"(?:[0-9a-fA-F]{2})",?/
328
- hex_comma_delim_w_sng_qt = /'(?:[0-9a-fA-F]{2})',?/
329
- hex_byte_array_as_str = /^\[\s*(?:"[0-9a-fA-F]{2}",\s*)*"[0-9a-fA-F]{2}"\s*\]$/
330
-
331
- if request.match?(straight_hex) ||
332
- request.match?(hex_esc_strings) ||
333
- request.match?(hex_comma_delim_w_dbl_qt) ||
334
- request.match?(hex_comma_delim_w_sng_qt) ||
335
- request.match?(hex_byte_array_as_str)
336
-
337
- response = PWN::Plugins::Assembly.opcodes_to_asm(
338
- opcodes: request,
339
- opcodes_always_strings_obj: true
340
- )
341
- else
342
- response = PWN::Plugins::Assembly.asm_to_opcodes(asm: request)
343
- end
344
- puts "\001\e[31m\002#{response}\001\e[0m\002"
345
- end
346
- end
347
-
348
- Pry.config.hooks.add_hook(:after_read, :pwn_ai_hook) do |request, pi|
349
- if pi.config.pwn_ai && !request.chomp.empty?
350
- request = pi.input.line_buffer.to_s
351
- debug = pi.config.pwn_ai_debug
352
- ai_key = pi.config.pwn_ai_key
353
- ai_key ||= ''
354
- if ai_key.empty?
355
- ai_key = PWN::Plugins::AuthenticationHelper.mask_password(
356
- prompt: 'OpenAI API Key'
357
- )
358
- pi.config.pwn_ai_key = ai_key
359
- end
360
-
361
- response_history = pi.config.pwn_ai_response_history
362
- speak_answer = pi.config.pwn_ai_speak
363
- response = PWN::Plugins::OpenAI.chat(
364
- token: ai_key,
365
- request: request.chomp,
366
- temp: 1,
367
- response_history: response_history,
368
- speak_answer: speak_answer
369
- )
370
- last_response = response[:choices].last[:content]
371
- puts "\n\001\e[32m\002#{last_response}\001\e[0m\002\n\n"
372
-
373
- response_history = {
374
- id: response[:id],
375
- object: response[:object],
376
- model: response[:model],
377
- usage: response[:usage]
378
- }
379
- response_history[:choices] ||= response[:choices]
380
-
381
- if debug
382
- puts 'DEBUG: response_history => '
383
- pp response_history
384
- puts "\nresponse_history[:choices] Length: #{response_history[:choices].length}\n" unless response_history.nil?
385
- end
386
- pi.config.pwn_ai_response_history = response_history
387
- end
388
- end
389
-
390
- # Define PS1 Prompt
391
- Pry.config.pwn_repl_line = 0
392
- Pry.config.prompt_name = :pwn
393
- arrow_ps1_proc = refresh_ps1_proc
394
- splat_ps1_proc = refresh_ps1_proc(mode: :splat)
395
- prompt_ps1 = [arrow_ps1_proc, splat_ps1_proc]
396
- prompt = Pry::Prompt.new(
397
- :pwn,
398
- 'PWN Prototyping REPL',
399
- prompt_ps1
400
- )
401
-
402
- # Start PWN REPL
403
31
  pwn_pid = Process.pid
404
- Pry.start(
405
- self,
406
- prompt: prompt
407
- )
32
+ PWN::Plugins::REPL.start(opts)
408
33
  rescue StandardError => e
409
34
  raise e
410
35
  ensure
411
- proc_list_arr = PWN::Plugins::PS.list
36
+ ps_list_arr = PWN::Plugins::PS.list
412
37
 
413
- kid_pids_arr = proc_list_arr.select { |proc_line| proc_line[3] == pwn_pid.to_s }
38
+ kid_pids_arr = ps_list_arr.select { |ps_line| ps_line[3] == pwn_pid.to_s }
414
39
  # pp kid_pids_arr
415
40
 
416
41
  grandkid_pids_arr = []
417
42
  kid_pids_arr.each do |kid_pid|
418
- gk_arr = proc_list_arr.select { |proc_line| proc_line[3] == kid_pid[2] }
43
+ gk_arr = ps_list_arr.select { |ps_line| ps_line[3] == kid_pid[2] }
419
44
  gk_arr.each { |gk| grandkid_pids_arr.push(gk) }
420
45
  end
421
46
  # pp grandkid_pids_arr
@@ -0,0 +1,164 @@
1
+ # frozen_string_literal: true
2
+
3
+ module PWN
4
+ module Plugins
5
+ # This module provides the abilty to centralize monkey patches used in PWN
6
+ module MonkeyPatch
7
+ # Supported Method Parameters::
8
+ # PWN::Plugins::MonkeyPatch.pry
9
+
10
+ public_class_method def self.pry
11
+ # Overwrite Pry::History.push method in History class
12
+ # to get duplicate history entries in order to properly
13
+ # replay automation in this prototyping driver
14
+ Pry::History.class_eval do
15
+ def push(line)
16
+ return line if line.empty? || invalid_readline_line?(line)
17
+
18
+ begin
19
+ last_line = @history[-1]
20
+ rescue IndexError
21
+ last_line = nil
22
+ end
23
+
24
+ @history << line
25
+ @history_line_count += 1
26
+ @saver.call(line) if !should_ignore?(line) &&
27
+ Pry.config.history_save
28
+
29
+ line
30
+ end
31
+ alias << push
32
+ end
33
+
34
+ Pry.class_eval do
35
+ def handle_line(line, options)
36
+ if line.nil?
37
+ config.control_d_handler.call(self)
38
+ return
39
+ end
40
+
41
+ ensure_correct_encoding!(line)
42
+ Pry.history << line unless options[:generated]
43
+
44
+ @suppress_output = false
45
+ inject_sticky_locals!
46
+ begin
47
+ # unless process_command_safely(line)
48
+ unless process_command_safely(line) && (
49
+ line.empty? || @eval_string.empty?
50
+ )
51
+ # @eval_string += "#{line.chomp}\n" if !line.empty? || !@eval_string.empty?
52
+ @eval_string += "#{line.chomp}\n"
53
+ end
54
+ rescue Pry::RescuableException => e
55
+ self.last_exception = e
56
+ result = e
57
+
58
+ Pry.critical_section do
59
+ show_result(result)
60
+ end
61
+ return
62
+ end
63
+
64
+ # This hook is supposed to be executed after each line of ruby code
65
+ # has been read (regardless of whether eval_string is yet a complete expression)
66
+ exec_hook :after_read, eval_string, self
67
+
68
+ begin
69
+ complete_expr = true if config.pwn_ai || config.pwn_asm
70
+ complete_expr = Pry::Code.complete_expression?(@eval_string) unless config.pwn_ai || config.pwn_asm
71
+ rescue SyntaxError => e
72
+ output.puts e.message.gsub(/^.*syntax error, */, 'SyntaxError: ')
73
+ reset_eval_string
74
+ end
75
+
76
+ if complete_expr
77
+ @suppress_output = true if @eval_string =~ /;\Z/ ||
78
+ @eval_string.empty? ||
79
+ @eval_string =~ /\A *#.*\n\z/ ||
80
+ config.pwn_ai ||
81
+ config.pwn_asm
82
+
83
+ # A bug in jruby makes java.lang.Exception not rescued by
84
+ # `rescue Pry::RescuableException` clause.
85
+ #
86
+ # * https://github.com/pry/pry/issues/854
87
+ # * https://jira.codehaus.org/browse/JRUBY-7100
88
+ #
89
+ # Until that gets fixed upstream, treat java.lang.Exception
90
+ # as an additional exception to be rescued explicitly.
91
+ #
92
+ # This workaround has a side effect: java exceptions specified
93
+ # in `Pry.config.unrescued_exceptions` are ignored.
94
+ jruby_exceptions = []
95
+ jruby_exceptions << Java::JavaLang::Exception if Pry::Helpers::Platform.jruby?
96
+
97
+ begin
98
+ # Reset eval string, in case we're evaluating Ruby that does something
99
+ # like open a nested REPL on this instance.
100
+ eval_string = @eval_string
101
+ reset_eval_string
102
+
103
+ result = evaluate_ruby(eval_string) unless config.pwn_ai ||
104
+ config.pwn_asm
105
+
106
+ result = eval_string if config.pwn_ai ||
107
+ config.pwn_asm
108
+ rescue Pry::RescuableException, *jruby_exceptions => e
109
+ # Eliminate following warning:
110
+ # warning: singleton on non-persistent Java type X
111
+ # (http://wiki.jruby.org/Persistence)
112
+ e.class.__persistent__ = true if Pry::Helpers::Platform.jruby? && e.class.respond_to?('__persistent__')
113
+ self.last_exception = e
114
+ result = e
115
+ end
116
+
117
+ Pry.critical_section do
118
+ show_result(result)
119
+ end
120
+ end
121
+
122
+ throw(:breakout) if current_binding.nil?
123
+ end
124
+
125
+ # Ensure the return value in pwn_ai mode reflects the input
126
+ def evaluate_ruby(code)
127
+ # if config.pwn_ai || config.pwn_asm
128
+ # result = message = code.to_s
129
+ # return
130
+ # end
131
+ inject_sticky_locals!
132
+ exec_hook :before_eval, code, self
133
+
134
+ result = current_binding.eval(code, Pry.eval_path, Pry.current_line)
135
+ set_last_result(result, code)
136
+ ensure
137
+ update_input_history(code)
138
+ exec_hook :after_eval, result, self
139
+ end
140
+ end
141
+ rescue StandardError => e
142
+ raise e
143
+ end
144
+
145
+ # Author(s):: 0day Inc. <request.pentest@0dayinc.com>
146
+
147
+ public_class_method def self.authors
148
+ "AUTHOR(S):
149
+ 0day Inc. <request.pentest@0dayinc.com>
150
+ "
151
+ end
152
+
153
+ # Display Usage for this Module
154
+
155
+ public_class_method def self.help
156
+ puts "USAGE:
157
+ #{self}.pry
158
+
159
+ #{self}.authors
160
+ "
161
+ end
162
+ end
163
+ end
164
+ end