pwn 0.5.718 → 0.5.719
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/lib/pwn/ai/agent/loop.rb +0 -2
- data/lib/pwn/plugins/detect_os.rb +1 -2
- data/lib/pwn/plugins/exploit_db.rb +33 -9
- data/lib/pwn/version.rb +1 -1
- data/spec/lib/pwn/ai/agent/loop_spec.rb +1 -1
- data/spec/lib/pwn/plugins/detect_os_spec.rb +0 -14
- data/spec/lib/pwn/plugins/exploit_db_spec.rb +38 -3
- data/third_party/pwn_rdoc.jsonl +1 -0
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 898622177b06081e32121144c9ae5461d510482e70a85b62de425967933e4e24
|
|
4
|
+
data.tar.gz: ddfe5cac2e3db9bab8ab9cafdb1f48a2e2191545a2d0ad5bb7245cb7f45ab45f
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 2751aa2984fe13fe852a6f12577bd840f097e5d84f240a05642e374938bbf8fe9095dcaee15a607b0b1c3c4b90d65b787f041ffbda26ec3868f26f68a400b28b
|
|
7
|
+
data.tar.gz: db70fe6f75eaa22625849d30ab0e1a73dec982e160db005cce3096e625346eaea5d68653a4fb27a6e452f4ba01c63ab0313a5bd484b54a874f95bf44944ea149
|
data/lib/pwn/ai/agent/loop.rb
CHANGED
|
@@ -661,7 +661,6 @@ module PWN
|
|
|
661
661
|
|
|
662
662
|
private_class_method def self.declared_contract_unsatisfied?(opts = {})
|
|
663
663
|
return false if verify_passed?(messages: opts[:messages])
|
|
664
|
-
return false if write_or_read_evidenced?(messages: opts[:messages])
|
|
665
664
|
|
|
666
665
|
completion_unmet(opts).any?
|
|
667
666
|
rescue StandardError
|
|
@@ -670,7 +669,6 @@ module PWN
|
|
|
670
669
|
|
|
671
670
|
private_class_method def self.completion_unmet(opts = {})
|
|
672
671
|
return [] if verify_passed?(messages: opts[:messages])
|
|
673
|
-
return [] if write_or_read_evidenced?(messages: opts[:messages])
|
|
674
672
|
|
|
675
673
|
contract = declared_contract(request: opts[:request])
|
|
676
674
|
request = opts[:request].to_s
|
|
@@ -182,8 +182,7 @@ module PWN
|
|
|
182
182
|
end
|
|
183
183
|
found << name if ok
|
|
184
184
|
end
|
|
185
|
-
|
|
186
|
-
native = (found.map(&:to_s) - owned).reject(&:empty?).uniq.sort
|
|
185
|
+
native = found.map(&:to_s).reject(&:empty?).uniq.sort
|
|
187
186
|
cap = if opts.key?(:cap_net_raw)
|
|
188
187
|
opts[:cap_net_raw]
|
|
189
188
|
else
|
|
@@ -207,27 +207,51 @@ module PWN
|
|
|
207
207
|
end
|
|
208
208
|
|
|
209
209
|
private_class_method def self.gtfobins_json(opts = {})
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
210
|
+
raw = opts[:body]
|
|
211
|
+
raw = raw.to_s.b unless raw.nil?
|
|
212
|
+
stripped = raw.to_s.lstrip
|
|
213
|
+
if stripped.start_with?('{', '[')
|
|
214
|
+
parsed = JSON.parse(stripped)
|
|
215
|
+
raise 'ERROR: GTFOBins JSON was empty' if parsed.nil? || parsed.empty?
|
|
216
|
+
|
|
217
|
+
return stripped
|
|
218
|
+
end
|
|
213
219
|
|
|
214
220
|
bins = {}
|
|
215
|
-
Zlib::GzipReader.wrap(StringIO.new(
|
|
221
|
+
Zlib::GzipReader.wrap(StringIO.new(raw)) do |gz|
|
|
216
222
|
Gem::Package::TarReader.new(gz) do |tar|
|
|
217
223
|
tar.each do |entry|
|
|
218
224
|
next unless entry.file?
|
|
219
|
-
next unless entry.full_name.include?('_gtfobins/') && entry.full_name.end_with?('.md')
|
|
220
225
|
|
|
221
|
-
|
|
226
|
+
path = entry.full_name.to_s
|
|
227
|
+
next unless path.include?('/_gtfobins/') || path.start_with?('_gtfobins/')
|
|
228
|
+
|
|
229
|
+
base = File.basename(path)
|
|
230
|
+
next if base.empty? || base.start_with?('.')
|
|
231
|
+
|
|
232
|
+
name = base.sub(/\.md\z/i, '')
|
|
222
233
|
text = entry.read.to_s
|
|
223
|
-
funcs = text
|
|
234
|
+
funcs = gtfobins_functions(text: text)
|
|
224
235
|
bins[name] = { 'binary' => name, 'functions' => funcs }
|
|
225
236
|
end
|
|
226
237
|
end
|
|
227
238
|
end
|
|
239
|
+
raise 'ERROR: GTFOBins archive contained no _gtfobins entries' if bins.empty?
|
|
240
|
+
|
|
228
241
|
JSON.generate(bins)
|
|
229
|
-
|
|
230
|
-
|
|
242
|
+
end
|
|
243
|
+
|
|
244
|
+
private_class_method def self.gtfobins_functions(opts = {})
|
|
245
|
+
text = opts[:text].to_s
|
|
246
|
+
headed = text.scan(/^##\s+(.+)$/).flatten.map(&:strip)
|
|
247
|
+
return headed unless headed.empty?
|
|
248
|
+
|
|
249
|
+
if text =~ /^functions:\s*$/
|
|
250
|
+
keys = text.scan(/^(?: |\t)([A-Za-z0-9._-]+):\s*$/).flatten
|
|
251
|
+
return keys unless keys.empty?
|
|
252
|
+
end
|
|
253
|
+
|
|
254
|
+
[]
|
|
231
255
|
end
|
|
232
256
|
end
|
|
233
257
|
end
|
data/lib/pwn/version.rb
CHANGED
|
@@ -931,7 +931,7 @@ describe PWN::AI::Agent::Loop do # rubocop:disable Metrics/BlockLength
|
|
|
931
931
|
{
|
|
932
932
|
role: 'tool',
|
|
933
933
|
name: 'pwn_eval',
|
|
934
|
-
content: '{"success":true,"result":{"stdout":"Report saved to /tmp/
|
|
934
|
+
content: '{"success":true,"result":{"stdout":"Report saved to /tmp/pwn-spec-report.json"},"effect":"write"}'
|
|
935
935
|
},
|
|
936
936
|
{
|
|
937
937
|
role: 'assistant',
|
|
@@ -76,8 +76,6 @@ describe PWN::Plugins::DetectOS do
|
|
|
76
76
|
expect(row[:version]).to eq('2026.3')
|
|
77
77
|
expect(row[:arch]).to be_a(String)
|
|
78
78
|
expect(row[:endian]).to be_a(Symbol)
|
|
79
|
-
expect(row[:native]).to include('jq', 'yara')
|
|
80
|
-
expect(row[:native]).not_to include('gdb', 'r2', 'nuclei')
|
|
81
79
|
expect(row).not_to have_key(:missing)
|
|
82
80
|
expect(row[:summary]).to include('kali')
|
|
83
81
|
expect(row[:summary]).not_to include('missing=')
|
|
@@ -94,17 +92,5 @@ describe PWN::Plugins::DetectOS do
|
|
|
94
92
|
expect(row[:version]).to eq('3.20.0')
|
|
95
93
|
expect(row[:native]).to eq([])
|
|
96
94
|
end
|
|
97
|
-
|
|
98
|
-
it 'does not treat plugin required_bins gaps as the inventory' do
|
|
99
|
-
row = described_class.living_off_the_land(
|
|
100
|
-
os_release: "ID=debian\nVERSION_ID=12\n",
|
|
101
|
-
type: :linux,
|
|
102
|
-
pwn_bins: %w[gdb r2],
|
|
103
|
-
bins: %w[jq],
|
|
104
|
-
which: { 'jq' => true, 'gdb' => false }
|
|
105
|
-
)
|
|
106
|
-
expect(row[:native]).to include('jq')
|
|
107
|
-
expect(row[:native]).not_to include('gdb')
|
|
108
|
-
end
|
|
109
95
|
end
|
|
110
96
|
end
|
|
@@ -3,6 +3,9 @@
|
|
|
3
3
|
require 'spec_helper'
|
|
4
4
|
require 'tmpdir'
|
|
5
5
|
require 'fileutils'
|
|
6
|
+
require 'stringio'
|
|
7
|
+
require 'zlib'
|
|
8
|
+
require 'rubygems/package'
|
|
6
9
|
|
|
7
10
|
describe PWN::Plugins::ExploitDB do
|
|
8
11
|
it 'should display information for authors' do
|
|
@@ -36,23 +39,55 @@ describe PWN::Plugins::ExploitDB do
|
|
|
36
39
|
end
|
|
37
40
|
end
|
|
38
41
|
|
|
42
|
+
def gtfobins_tarball(opts = {})
|
|
43
|
+
name = (opts[:name] || 'tar').to_s
|
|
44
|
+
md = (opts[:body] || "---\nfunctions:\n file-read:\n - code: tar xf -\n SUID:\n - code: tar\n").to_s
|
|
45
|
+
sio = StringIO.new
|
|
46
|
+
sio.binmode
|
|
47
|
+
gz = Zlib::GzipWriter.new(sio)
|
|
48
|
+
Gem::Package::TarWriter.new(gz) do |tar|
|
|
49
|
+
path = "GTFOBins.github.io-master/_gtfobins/#{name}"
|
|
50
|
+
tar.add_file_simple(path, 0o644, md.bytesize) { |io| io.write(md) }
|
|
51
|
+
end
|
|
52
|
+
gz.close
|
|
53
|
+
sio.string
|
|
54
|
+
end
|
|
55
|
+
|
|
39
56
|
it 'sync fetches latest ExploitDB CSV and GTFOBins into ~/.pwn/intel' do
|
|
40
57
|
Dir.mktmpdir do |dir|
|
|
41
58
|
allow(Dir).to receive(:home).and_return(dir)
|
|
42
59
|
csv = "id,file,description,cve\n1,e.rb,Apache Log4j RCE,CVE-2021-44228\n"
|
|
43
|
-
|
|
60
|
+
tgz = gtfobins_tarball
|
|
44
61
|
get = lambda do |url|
|
|
45
|
-
url.to_s.include?('files_exploits') ? csv :
|
|
62
|
+
url.to_s.include?('files_exploits') ? csv : tgz
|
|
46
63
|
end
|
|
47
64
|
out = described_class.sync(get: get)
|
|
48
65
|
intel = File.join(dir, '.pwn', 'intel')
|
|
49
66
|
expect(out[:dest]).to eq(intel)
|
|
50
67
|
expect(File.read(File.join(intel, 'files_exploits.csv'))).to include('CVE-2021-44228')
|
|
51
|
-
|
|
68
|
+
json = File.read(File.join(intel, 'gtfobins.json'))
|
|
69
|
+
expect(json).not_to eq('{}')
|
|
70
|
+
expect(json).to include('tar')
|
|
71
|
+
expect(json).to include('file-read')
|
|
52
72
|
expect(out[:fetched]).to include('files_exploits.csv', 'gtfobins.json')
|
|
53
73
|
end
|
|
54
74
|
end
|
|
55
75
|
|
|
76
|
+
it 'refuses to write an empty gtfobins.json when the archive has no bins' do
|
|
77
|
+
Dir.mktmpdir do |dir|
|
|
78
|
+
allow(Dir).to receive(:home).and_return(dir)
|
|
79
|
+
sio = StringIO.new
|
|
80
|
+
sio.binmode
|
|
81
|
+
gz = Zlib::GzipWriter.new(sio)
|
|
82
|
+
Gem::Package::TarWriter.new(gz) { |tar| tar.mkdir('empty', 0o755) }
|
|
83
|
+
gz.close
|
|
84
|
+
get = lambda do |url|
|
|
85
|
+
url.to_s.include?('files_exploits') ? "id,file\n1,a\n" : sio.string
|
|
86
|
+
end
|
|
87
|
+
expect { described_class.sync(get: get) }.to raise_error(/GTFOBins/)
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
|
|
56
91
|
it 'does not copy from a tree-bundled etc/intel directory' do
|
|
57
92
|
src = File.read(described_class.method(:sync).source_location.first)
|
|
58
93
|
expect(src).not_to include('etc/intel')
|
data/third_party/pwn_rdoc.jsonl
CHANGED
|
@@ -2002,6 +2002,7 @@
|
|
|
2002
2002
|
{"messages":[{"role":"user","content":"PWN::Plugins::ExploitDB.authors Usage"},{"role":"assistant","content":"`PWN::Plugins::ExploitDB.authors`: "}]}
|
|
2003
2003
|
{"messages":[{"role":"user","content":"PWN::Plugins::ExploitDB.cve_for_cpe Usage"},{"role":"assistant","content":"`PWN::Plugins::ExploitDB.cve_for_cpe`: "}]}
|
|
2004
2004
|
{"messages":[{"role":"user","content":"PWN::Plugins::ExploitDB.gtfobins Usage"},{"role":"assistant","content":"`PWN::Plugins::ExploitDB.gtfobins`: "}]}
|
|
2005
|
+
{"messages":[{"role":"user","content":"PWN::Plugins::ExploitDB.gtfobins_functions Usage"},{"role":"assistant","content":"`PWN::Plugins::ExploitDB.gtfobins_functions`: "}]}
|
|
2005
2006
|
{"messages":[{"role":"user","content":"PWN::Plugins::ExploitDB.gtfobins_json Usage"},{"role":"assistant","content":"`PWN::Plugins::ExploitDB.gtfobins_json`: "}]}
|
|
2006
2007
|
{"messages":[{"role":"user","content":"PWN::Plugins::ExploitDB.help Usage"},{"role":"assistant","content":"`PWN::Plugins::ExploitDB.help`: "}]}
|
|
2007
2008
|
{"messages":[{"role":"user","content":"PWN::Plugins::ExploitDB.http_get Usage"},{"role":"assistant","content":"`PWN::Plugins::ExploitDB.http_get`: "}]}
|