pwn 0.5.40 → 0.5.42
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile +1 -1
- data/README.md +3 -3
- data/bin/pwn +33 -17
- data/lib/pwn/plugins/assembly.rb +34 -10
- data/lib/pwn/plugins/black_duck_binary_analysis.rb +15 -0
- data/lib/pwn/version.rb +1 -1
- metadata +4 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 132c78ae9112e7c2da8c02d5b2d7d32370953c7bc05686026e097ad04d5c4ba0
|
4
|
+
data.tar.gz: 2d51b81f19297ba49e61288998df35b4bc3c88a2dff0ca05a0ba44b6db1c3f65
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 23a021b1d27dc5fd2352c61e9c00afea1aa9ffe98e7a6040e5d0cb913c5261eebd9e429a2f416304f3177c9c726bc8ca0cfec1c2d8bcc2a7cf7025852758d44a
|
7
|
+
data.tar.gz: 7a71c1e70bb63993f113b4c5ee7d6ce4162b6252da72b4795c2d9e320b740b7f8ef871179c5a65c4c77d1e6590008480e16127f15be868a403cea8362e021c5c
|
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.42]: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.
|
55
|
+
pwn[v0.5.42]: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.42]: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
@@ -49,8 +49,8 @@ begin
|
|
49
49
|
if pi.config.pwn_asm
|
50
50
|
pi.config.prompt_name = 'pwn.asm'
|
51
51
|
name = "\001\e[1m\002\001\e[37m\002#{pi.config.prompt_name}\001\e[0m\002"
|
52
|
-
dchars = "\001\e[32m\002>>>\001\e[
|
53
|
-
dchars = "\001\e[33m\002***\001\e[
|
52
|
+
dchars = "\001\e[32m\002>>>\001\e[33m\002"
|
53
|
+
dchars = "\001\e[33m\002***\001\e[33m\002" if mode == :splat
|
54
54
|
end
|
55
55
|
|
56
56
|
if pi.config.pwn_gpt
|
@@ -157,7 +157,11 @@ begin
|
|
157
157
|
eval_string = @eval_string
|
158
158
|
reset_eval_string
|
159
159
|
|
160
|
-
result = evaluate_ruby(eval_string)
|
160
|
+
result = evaluate_ruby(eval_string) unless config.pwn_gpt ||
|
161
|
+
config.pwn_asm
|
162
|
+
|
163
|
+
result = eval_string if config.pwn_gpt ||
|
164
|
+
config.pwn_asm
|
161
165
|
rescue RescuableException, *jruby_exceptions => e
|
162
166
|
# Eliminate following warning:
|
163
167
|
# warning: singleton on non-persistent Java type X
|
@@ -179,10 +183,10 @@ begin
|
|
179
183
|
|
180
184
|
# Ensure the return value in pwn_gpt mode reflects the input
|
181
185
|
def evaluate_ruby(code)
|
182
|
-
if config.pwn_gpt || config.pwn_asm
|
183
|
-
|
184
|
-
|
185
|
-
end
|
186
|
+
# if config.pwn_gpt || config.pwn_asm
|
187
|
+
# result = message = code.to_s
|
188
|
+
# return
|
189
|
+
# end
|
186
190
|
inject_sticky_locals!
|
187
191
|
exec_hook :before_eval, code, self
|
188
192
|
|
@@ -218,9 +222,6 @@ begin
|
|
218
222
|
def process
|
219
223
|
pi = pry_instance
|
220
224
|
pi.config.pwn_asm ? pi.config.pwn_asm = false : pi.config.pwn_asm = true
|
221
|
-
|
222
|
-
pi.config.color = false if pi.config.pwn_asm
|
223
|
-
pi.config.color = true unless pi.config.pwn_asm
|
224
225
|
end
|
225
226
|
end
|
226
227
|
|
@@ -230,7 +231,6 @@ begin
|
|
230
231
|
def process
|
231
232
|
pi = pry_instance
|
232
233
|
pi.config.pwn_gpt ? pi.config.pwn_gpt = false : pi.config.pwn_gpt = true
|
233
|
-
|
234
234
|
pi.config.color = false if pi.config.pwn_gpt
|
235
235
|
pi.config.color = true unless pi.config.pwn_gpt
|
236
236
|
end
|
@@ -273,19 +273,34 @@ begin
|
|
273
273
|
Pry.config.hooks.add_hook(:after_read, :pwn_asm_hook) do |request, pi|
|
274
274
|
if pi.config.pwn_asm && !request.chomp.empty?
|
275
275
|
request = pi.input.line_buffer
|
276
|
-
|
277
|
-
|
278
|
-
|
276
|
+
|
277
|
+
# Analyze request to determine if it should be processed as opcodes or asm.
|
278
|
+
straight_hex = /^[a-fA-F0-9\s]+$/
|
279
|
+
hex_esc_strings = /\\x[\da-fA-F]{2}/
|
280
|
+
hex_comma_delim_w_dbl_qt = /"(?:[0-9a-fA-F]{2})",?/
|
281
|
+
hex_comma_delim_w_sng_qt = /'(?:[0-9a-fA-F]{2})',?/
|
282
|
+
hex_byte_array_as_str = /^\[\s*(?:"[0-9a-fA-F]{2}",\s*)*"[0-9a-fA-F]{2}"\s*\]$/
|
283
|
+
|
284
|
+
if request.match?(straight_hex) ||
|
285
|
+
request.match?(hex_esc_strings) ||
|
286
|
+
request.match?(hex_comma_delim_w_dbl_qt) ||
|
287
|
+
request.match?(hex_comma_delim_w_sng_qt) ||
|
288
|
+
request.match?(hex_byte_array_as_str)
|
289
|
+
|
290
|
+
response = PWN::Plugins::Assembly.opcodes_to_asm(
|
291
|
+
opcodes: request,
|
292
|
+
opcodes_always_strings_obj: true
|
293
|
+
)
|
279
294
|
else
|
280
295
|
response = PWN::Plugins::Assembly.asm_to_opcodes(asm: request)
|
281
296
|
end
|
282
|
-
puts "\
|
297
|
+
puts "\001\e[31m\002#{response}\001\e[0m\002"
|
283
298
|
end
|
284
299
|
end
|
285
300
|
|
286
301
|
Pry.config.hooks.add_hook(:after_read, :pwn_gpt_hook) do |request, pi|
|
287
302
|
if pi.config.pwn_gpt && !request.chomp.empty?
|
288
|
-
request = pi.input.line_buffer
|
303
|
+
request = pi.input.line_buffer.to_s
|
289
304
|
debug = pi.config.pwn_gpt_debug
|
290
305
|
open_ai_key = pi.config.pwn_gpt_key
|
291
306
|
open_ai_key ||= ''
|
@@ -305,7 +320,8 @@ begin
|
|
305
320
|
response_history: response_history,
|
306
321
|
speak_answer: speak_answer
|
307
322
|
)
|
308
|
-
|
323
|
+
last_response = response[:choices].last[:content]
|
324
|
+
puts "\n\001\e[32m\002#{last_response}\001\e[0m\002\n\n"
|
309
325
|
|
310
326
|
response_history = {
|
311
327
|
id: response[:id],
|
data/lib/pwn/plugins/assembly.rb
CHANGED
@@ -11,12 +11,14 @@ module PWN
|
|
11
11
|
# Supported Method Parameters::
|
12
12
|
# PWN::Plugins::Assembly.opcodes_to_asm(
|
13
13
|
# opcodes: 'required - hex escaped opcode(s) (e.g. "\x90\x90\x90")',
|
14
|
+
# opcodes_always_string_obj: 'optional - always interpret opcodes passed in as a string object (defaults to false)',
|
14
15
|
# arch: 'optional - architecture returned from objdump --info (defaults to PWN::Plugins::DetectOS.arch)',
|
15
16
|
# endian: 'optional - endianess (defaults to :little)'
|
16
17
|
# )
|
17
18
|
|
18
19
|
public_class_method def self.opcodes_to_asm(opts = {})
|
19
20
|
opcodes = opts[:opcodes]
|
21
|
+
opcodes_always_string_obj = opts[:opcodes_always_string_obj] ||= false
|
20
22
|
arch = opts[:arch] ||= PWN::Plugins::DetectOS.arch
|
21
23
|
endian = opts[:endian] ||= :little
|
22
24
|
|
@@ -40,28 +42,43 @@ module PWN
|
|
40
42
|
# '909090'
|
41
43
|
opcodes_orig_len = opcodes.length
|
42
44
|
opcodes = opcodes.join(',') if opcodes.is_a?(Array)
|
45
|
+
# puts opcodes.inspect
|
43
46
|
opcodes = CGI.escape(opcodes)
|
44
47
|
# puts opcodes.inspect
|
45
|
-
#
|
46
|
-
# known to work with:
|
48
|
+
# known to work (when method is called directly) with:
|
47
49
|
# 'ffe4'
|
48
50
|
# 'ff,e4'
|
51
|
+
# 'ff e4'
|
49
52
|
# "ff,e4"
|
53
|
+
# "ff e4"
|
50
54
|
# ['ff', 'e4']
|
51
55
|
# ["ff", "e4"]
|
52
56
|
# '\xff\xe4'
|
53
57
|
# "\xff\xe4"
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
58
|
+
# "'ff', 'e4'"
|
59
|
+
# '"ff", "e4"'
|
60
|
+
# only known to work in pwn REPL driver with:
|
61
|
+
# ffe4
|
62
|
+
# ff e4
|
63
|
+
# puts opcodes.inspect
|
64
|
+
# More stripping if passed in via pwn REPL driver
|
65
|
+
# if opcodes_always_string_obj
|
66
|
+
# end
|
67
|
+
|
68
|
+
opcodes.delete!('%5B')
|
69
|
+
opcodes.delete!('%5D')
|
70
|
+
opcodes.delete!('%5Cx')
|
71
|
+
opcodes.delete!('%2C')
|
72
|
+
opcodes.delete!('%22')
|
73
|
+
opcodes.delete!('%27')
|
74
|
+
opcodes.delete!('+')
|
75
|
+
opcodes.delete!('%')
|
76
|
+
|
60
77
|
# puts opcodes.inspect
|
61
78
|
opcodes = [opcodes].pack('H*')
|
62
79
|
# puts opcodes.inspect
|
63
80
|
|
64
|
-
Metasm::Shellcode.disassemble(arch_obj, opcodes).to_s
|
81
|
+
Metasm::Shellcode.disassemble(arch_obj, opcodes).to_s.squeeze("\n")
|
65
82
|
rescue StandardError => e
|
66
83
|
raise e
|
67
84
|
end
|
@@ -95,7 +112,13 @@ module PWN
|
|
95
112
|
raise "Unsupported architecture: #{arch}"
|
96
113
|
end
|
97
114
|
|
98
|
-
Metasm::Shellcode.assemble(arch_obj, asm).encode_string
|
115
|
+
opcodes = Metasm::Shellcode.assemble(arch_obj, asm).encode_string
|
116
|
+
hex_encoded_opcodes = opcodes.bytes.map { |b| format('\x%02x', b) }.join
|
117
|
+
|
118
|
+
"\n#{hex_encoded_opcodes}\n"
|
119
|
+
rescue Metasm::ParseError
|
120
|
+
puts "Invalid assembly instruction(s) provided:\n#{asm}"
|
121
|
+
# Should we try to call opcode_to_asm here or just raise the error?
|
99
122
|
rescue StandardError => e
|
100
123
|
raise e
|
101
124
|
end
|
@@ -114,6 +137,7 @@ module PWN
|
|
114
137
|
puts "USAGE:
|
115
138
|
#{self}.opcodes_to_asm(
|
116
139
|
opcodes: 'required - hex escaped opcode(s) (e.g. \"\\x90\\x90\\x90\")',
|
140
|
+
opcodes_always_string_obj: 'optional - always interpret opcodes passed in as a string object (defaults to false)',
|
117
141
|
arch: 'optional - architecture returned from objdump --info (defaults to PWN::Plugins::DetectOS.arch)',
|
118
142
|
endian: 'optional - endianess (defaults to :little)'
|
119
143
|
)
|
@@ -47,6 +47,9 @@ module PWN
|
|
47
47
|
spinner = TTY::Spinner.new
|
48
48
|
spinner.auto_spin
|
49
49
|
|
50
|
+
max_request_attempts = 3
|
51
|
+
tot_request_attempts ||= 1
|
52
|
+
|
50
53
|
case http_method
|
51
54
|
when :delete, :get
|
52
55
|
headers[:params] = params
|
@@ -90,6 +93,18 @@ module PWN
|
|
90
93
|
end
|
91
94
|
|
92
95
|
raise e
|
96
|
+
rescue IO::TimeoutError => e
|
97
|
+
raise e if tot_request_attempts == max_request_attempts
|
98
|
+
|
99
|
+
puts "\nTCP Connection Unavailable."
|
100
|
+
puts "Attempt (#{tot_request_attempts} of #{max_request_attempts}) in 60s"
|
101
|
+
60.downto(1) do
|
102
|
+
print '.'
|
103
|
+
sleep 1
|
104
|
+
end
|
105
|
+
tot_request_attempts += 1
|
106
|
+
|
107
|
+
retry
|
93
108
|
rescue StandardError => e
|
94
109
|
case e.message
|
95
110
|
when '400 Bad Request', '404 Resource Not Found'
|
data/lib/pwn/version.rb
CHANGED
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.5.
|
4
|
+
version: 0.5.42
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- 0day Inc.
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-02-
|
11
|
+
date: 2024-02-28 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -1164,14 +1164,14 @@ dependencies:
|
|
1164
1164
|
requirements:
|
1165
1165
|
- - '='
|
1166
1166
|
- !ruby/object:Gem::Version
|
1167
|
-
version: 2.
|
1167
|
+
version: 2.8.0
|
1168
1168
|
type: :runtime
|
1169
1169
|
prerelease: false
|
1170
1170
|
version_requirements: !ruby/object:Gem::Requirement
|
1171
1171
|
requirements:
|
1172
1172
|
- - '='
|
1173
1173
|
- !ruby/object:Gem::Version
|
1174
|
-
version: 2.
|
1174
|
+
version: 2.8.0
|
1175
1175
|
description: https://github.com/0dayinc/pwn/README.md
|
1176
1176
|
email:
|
1177
1177
|
- request.pentest@0dayinc.com
|