pwn 0.5.67 → 0.5.69
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 +4 -4
- data/.rubocop_todo.yml +16 -18
- data/Gemfile +1 -1
- data/README.md +3 -3
- data/bin/pwn +4 -379
- data/lib/pwn/plugins/monkey_patch.rb +164 -0
- data/lib/pwn/plugins/ollama.rb +11 -567
- data/lib/pwn/plugins/repl.rb +317 -0
- data/lib/pwn/plugins/vault.rb +5 -0
- data/lib/pwn/plugins.rb +2 -0
- data/lib/pwn/version.rb +1 -1
- data/spec/lib/pwn/plugins/monkey_patch_spec.rb +15 -0
- data/spec/lib/pwn/plugins/repl_spec.rb +15 -0
- metadata +7 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7e2be578588aa0e4172ddafce691a25711ad3afd796c293cf96df508d3c7fc84
|
4
|
+
data.tar.gz: c72375b8d8c69ceb9fd3909d33187f595f3f11c41918cc1dd2fe0ae8a44ed25e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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-
|
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:
|
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
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.
|
40
|
+
pwn[v0.5.69]:001 >>> PWN.help
|
41
41
|
```
|
42
42
|
|
43
43
|
[](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.
|
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.
|
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
|
-
|
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
|
-
|
36
|
+
ps_list_arr = PWN::Plugins::PS.list
|
412
37
|
|
413
|
-
kid_pids_arr =
|
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 =
|
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
|