pwn 0.5.715 → 0.5.716

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 146297356f4ed277ec4d96fafaa37ceada293450ed65899f36fd0c87b791941e
4
- data.tar.gz: 95b240666596894709e70488300794a0af67a8a04b4da0b2f82c9a907c3e851d
3
+ metadata.gz: 7c150ee7139d2079946756fe2751fab31308638e437a01429a4258c71abced27
4
+ data.tar.gz: e59a0e5214fc91f3aea199a17a2e9877af881ae7a79009c948ad7e4fe876de25
5
5
  SHA512:
6
- metadata.gz: d840608a734d085d102064010d0a83daa4d3941ef36854fe2e2a4bf445ef994f331599e9ef3dfc9d24ea40b26fed8b383677cf53901ff7904a0a3a02e00d3d12
7
- data.tar.gz: b118fad0b02e1a1e3587243487b8896c469f679d49c76518e76487324918e21d0cccb6c50687e74e366a6e633c8ad6666a51e7cc53f9ca0fbc2b48d653a5aa91
6
+ metadata.gz: 597caaccaf0f1b9a4d439ecc4abd2f5ab93229779ae27e0147c45f5afd375f98a6af777864040868ce49667c27a9c614d73123928b09996864bcfad25e0d9f07
7
+ data.tar.gz: d7209f26b10365db59e3532ebb6c6c6cfc29c95d6a251d476cf5e167d76e320cc22e69d8aadf682367468bdd4c9dc2759d02c58158e42e28b51f01a217380dea
@@ -27,6 +27,16 @@ module PWN
27
27
  'mswin' => :windows
28
28
  }.freeze
29
29
 
30
+ PATH_NOISE = %w[
31
+ sh bash zsh fish csh tcsh dash true false echo test pwd ls cat cp mv rm
32
+ mkdir rmdir chmod chown chgrp ln touch head tail more less grep egrep fgrep
33
+ sed awk sort uniq wc find xargs tar gzip gunzip zcat bzip2 xz make
34
+ python python2 python3 ruby perl php node java git svn hg
35
+ vi vim nvi nano ed ex
36
+ apt apt-get dpkg rpm yum dnf pacman brew port pkg pkg_add
37
+ sudo doas su login id whoami uname hostname env export
38
+ ].freeze
39
+
30
40
  public_class_method def self.type
31
41
  os = :cygwin if OS.cygwin?
32
42
  os = :freebsd if OS.freebsd?
@@ -162,7 +172,8 @@ module PWN
162
172
  # PWN::Plugins::DetectOS.living_off_the_land(
163
173
  # os_release: 'optional - /etc/os-release body (defaults to reading the file)',
164
174
  # which: 'optional - Hash of binary name => present Boolean (skips live PATH)',
165
- # bins: 'optional - extra binary names to probe besides plugin required_bins'
175
+ # bins: 'optional - extra host binary names to include when present',
176
+ # pwn_bins: 'optional - Array of names pwn setup already installs (skipped)'
166
177
  # )
167
178
 
168
179
  public_class_method def self.living_off_the_land(opts = {})
@@ -171,18 +182,19 @@ module PWN
171
182
  ver = version(opts)
172
183
  cpu = opts[:arch] || arch
173
184
  endn = opts[:endian] || endian
174
- names = inventory_names(bins: opts[:bins])
175
- which = opts[:which]
176
- present = []
177
- missing = []
178
- names.each do |name|
179
- ok = if which.is_a?(Hash)
180
- which[name] || which[name.to_sym]
185
+ found = host_path_names(opts)
186
+ extra = Array(opts[:bins]).map(&:to_s).reject(&:empty?)
187
+ extra.each do |name|
188
+ ok = if opts[:which].is_a?(Hash)
189
+ opts[:which][name] || opts[:which][name.to_sym]
181
190
  else
182
191
  bin_present?(name: name)
183
192
  end
184
- (ok ? present : missing) << name
193
+ found << name if ok
185
194
  end
195
+ owned = pwn_installed_bins(pwn_bins: opts[:pwn_bins])
196
+ native = (found.map(&:to_s) - owned - PATH_NOISE).reject(&:empty?).uniq.sort
197
+ native = native.first(256)
186
198
  cap = if opts.key?(:cap_net_raw)
187
199
  opts[:cap_net_raw]
188
200
  else
@@ -193,15 +205,15 @@ module PWN
193
205
  else
194
206
  docker_live
195
207
  end
196
- summary = "#{flavor} #{ver} #{cpu} present=#{present.first(24).join(',')} missing=#{missing.first(12).join(',')}"
208
+ sample = native.first(24).join(',')
209
+ summary = "#{flavor} #{ver} #{cpu} native=#{sample}"
197
210
  {
198
211
  type: os_type,
199
212
  distro: flavor,
200
213
  version: ver,
201
214
  arch: cpu.to_s,
202
215
  endian: endn,
203
- present: present,
204
- missing: missing,
216
+ native: native,
205
217
  cap_net_raw: cap,
206
218
  docker: docker,
207
219
  summary: summary
@@ -250,14 +262,15 @@ module PWN
250
262
  version: 'optional - force a version string instead of detecting'
251
263
  )
252
264
 
253
- # Profile this host: distro, arch, and which plugin bins are on PATH.
265
+ # Inventory extra PATH binaries on this host that pwn plugins do not already wrap.
254
266
  #{self}.living_off_the_land(
255
267
  os_release: 'optional - /etc/os-release body (defaults to reading the file)',
256
268
  lsb_release: 'optional - /etc/lsb-release body',
257
269
  build_prop: 'optional - Android /system/build.prop body',
258
270
  type: 'optional - OS family from #type',
259
271
  which: 'optional - Hash of binary name => true/false (skips live PATH when set)',
260
- bins: 'optional - extra binary names to probe besides plugin required_bins',
272
+ bins: 'optional - extra host binary names to include when present on PATH',
273
+ pwn_bins: 'optional - extra names to treat as already wrapped (skipped from native)',
261
274
  arch: 'optional - CPU arch override',
262
275
  endian: 'optional - :little or :big override',
263
276
  cap_net_raw: 'optional - Boolean CAP_NET_RAW override',
@@ -270,14 +283,46 @@ module PWN
270
283
  constants.sort
271
284
  end
272
285
 
273
- private_class_method def self.inventory_names(opts = {})
274
- extra = Array(opts[:bins]).map(&:to_s).reject(&:empty?)
286
+ private_class_method def self.host_path_names(opts = {})
287
+ return Array(opts[:path_names]).map(&:to_s) if opts.key?(:path_names)
288
+
289
+ if opts.key?(:which)
290
+ which = opts[:which]
291
+ return [] unless which.is_a?(Hash)
292
+
293
+ return which.select { |_n, ok| ok }.keys.map(&:to_s)
294
+ end
295
+
296
+ scan_path_executables
297
+ end
298
+
299
+ private_class_method def self.scan_path_executables(opts = {})
300
+ return [] if opts[:skip]
301
+
302
+ names = []
303
+ ENV.fetch('PATH', '').split(File::PATH_SEPARATOR).each do |dir|
304
+ next unless File.directory?(dir)
305
+
306
+ Dir.children(dir).each do |base|
307
+ path = File.join(dir, base)
308
+ next unless File.file?(path) && File.executable?(path)
309
+
310
+ names << base.sub(/\.(exe|bat|cmd|com)\z/i, '')
311
+ end
312
+ rescue StandardError
313
+ next
314
+ end
315
+ names.uniq
316
+ end
317
+
318
+ private_class_method def self.pwn_installed_bins(opts = {})
319
+ extra = Array(opts[:pwn_bins]).map(&:to_s)
275
320
  deps = if defined?(PWN::Plugins::PreflightChecker::PLUGIN_DEPS)
276
- PWN::Plugins::PreflightChecker::PLUGIN_DEPS.values.flat_map { |row| Array(row[:bins]) }
321
+ PWN::Plugins::PreflightChecker::PLUGIN_DEPS.values.flat_map { |row| Array(row[:bins]).map(&:to_s) }
277
322
  else
278
323
  []
279
324
  end
280
- (deps + extra).map(&:to_s).reject(&:empty?).uniq
325
+ (extra + deps).reject(&:empty?).uniq
281
326
  end
282
327
 
283
328
  private_class_method def self.bin_present?(opts = {})
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.715'
4
+ VERSION = '0.5.716'
5
5
  end
@@ -64,42 +64,48 @@ describe PWN::Plugins::DetectOS do
64
64
  end
65
65
 
66
66
  describe '.living_off_the_land' do
67
- it 'profiles distro, arch, and which host bins are present from fixtures' do
67
+ it 'reports extra PATH binaries that pwn setup does not install' do
68
68
  body = "ID=kali\nVERSION_ID=\"2026.3\"\n"
69
69
  row = described_class.living_off_the_land(
70
70
  os_release: body,
71
71
  type: :linux,
72
- which: { 'gdb' => true, 'r2' => true, 'nuclei' => false }
72
+ pwn_bins: %w[gdb r2 nuclei],
73
+ which: { 'jq' => true, 'gdb' => true, 'r2' => true, 'yara' => true, 'nuclei' => false }
73
74
  )
74
75
  expect(row[:distro]).to eq(:kali)
75
76
  expect(row[:version]).to eq('2026.3')
76
77
  expect(row[:arch]).to be_a(String)
77
78
  expect(row[:endian]).to be_a(Symbol)
78
- expect(row[:present]).to include('gdb', 'r2')
79
- expect(row[:missing]).to include('nuclei')
80
- expect(row[:present]).not_to include('nuclei')
79
+ expect(row[:native]).to include('jq', 'yara')
80
+ expect(row[:native]).not_to include('gdb', 'r2', 'nuclei')
81
+ expect(row).not_to have_key(:missing)
81
82
  expect(row[:summary]).to include('kali')
82
- expect(row[:summary]).to include('gdb')
83
+ expect(row[:summary]).to include('jq')
84
+ expect(row[:summary]).not_to include('missing=')
83
85
  end
84
86
 
85
87
  it 'does not fall through to live os-release when fixtures are passed' do
86
88
  row = described_class.living_off_the_land(
87
89
  os_release: "ID=alpine\nVERSION_ID=3.20.0\n",
88
90
  type: :linux,
91
+ pwn_bins: %w[],
89
92
  which: {}
90
93
  )
91
94
  expect(row[:distro]).to eq(:alpine)
92
95
  expect(row[:version]).to eq('3.20.0')
96
+ expect(row[:native]).to eq([])
93
97
  end
94
98
 
95
- it 'probes extra bins from opts without inventing a PATH dump' do
99
+ it 'does not treat plugin required_bins gaps as the inventory' do
96
100
  row = described_class.living_off_the_land(
97
101
  os_release: "ID=debian\nVERSION_ID=12\n",
98
102
  type: :linux,
103
+ pwn_bins: %w[gdb r2],
99
104
  bins: %w[jq],
100
- which: { 'jq' => true }
105
+ which: { 'jq' => true, 'gdb' => false }
101
106
  )
102
- expect(row[:present]).to include('jq')
107
+ expect(row[:native]).to include('jq')
108
+ expect(row[:native]).not_to include('gdb')
103
109
  end
104
110
  end
105
111
  end
@@ -1974,16 +1974,18 @@
1974
1974
  {"messages":[{"role":"user","content":"PWN::Plugins::DetectOS.docker_live Usage"},{"role":"assistant","content":"`PWN::Plugins::DetectOS.docker_live`: "}]}
1975
1975
  {"messages":[{"role":"user","content":"PWN::Plugins::DetectOS.endian Usage"},{"role":"assistant","content":"`PWN::Plugins::DetectOS.endian`: "}]}
1976
1976
  {"messages":[{"role":"user","content":"PWN::Plugins::DetectOS.help Usage"},{"role":"assistant","content":"`PWN::Plugins::DetectOS.help`: "}]}
1977
- {"messages":[{"role":"user","content":"PWN::Plugins::DetectOS.inventory_names Usage"},{"role":"assistant","content":"`PWN::Plugins::DetectOS.inventory_names`: "}]}
1977
+ {"messages":[{"role":"user","content":"PWN::Plugins::DetectOS.host_path_names Usage"},{"role":"assistant","content":"`PWN::Plugins::DetectOS.host_path_names`: "}]}
1978
1978
  {"messages":[{"role":"user","content":"PWN::Plugins::DetectOS.ios_host? Usage"},{"role":"assistant","content":"`PWN::Plugins::DetectOS.ios_host?`: "}]}
1979
1979
  {"messages":[{"role":"user","content":"PWN::Plugins::DetectOS.live_sw_vers Usage"},{"role":"assistant","content":"`PWN::Plugins::DetectOS.live_sw_vers`: "}]}
1980
1980
  {"messages":[{"role":"user","content":"PWN::Plugins::DetectOS.live_uname_r Usage"},{"role":"assistant","content":"`PWN::Plugins::DetectOS.live_uname_r`: "}]}
1981
1981
  {"messages":[{"role":"user","content":"PWN::Plugins::DetectOS.live_uname_s Usage"},{"role":"assistant","content":"`PWN::Plugins::DetectOS.live_uname_s`: "}]}
1982
1982
  {"messages":[{"role":"user","content":"PWN::Plugins::DetectOS.live_win_ver Usage"},{"role":"assistant","content":"`PWN::Plugins::DetectOS.live_win_ver`: "}]}
1983
- {"messages":[{"role":"user","content":"PWN::Plugins::DetectOS.living_off_the_land Usage"},{"role":"assistant","content":"`PWN::Plugins::DetectOS.living_off_the_land`: Supported Method Parameters\n\nPWN::Plugins::DetectOS.living_off_the_land(\n\nos_release: 'optional - /etc/os-release body (defaults to reading the file)',\nwhich: 'optional - Hash of binary name => present Boolean (skips live PATH)',\nbins: 'optional - extra binary names to probe besides plugin required_bins'\n\n)\n"}]}
1983
+ {"messages":[{"role":"user","content":"PWN::Plugins::DetectOS.living_off_the_land Usage"},{"role":"assistant","content":"`PWN::Plugins::DetectOS.living_off_the_land`: Supported Method Parameters\n\nPWN::Plugins::DetectOS.living_off_the_land(\n\nos_release: 'optional - /etc/os-release body (defaults to reading the file)',\nwhich: 'optional - Hash of binary name => present Boolean (skips live PATH)',\nbins: 'optional - extra host binary names to include when present',\npwn_bins: 'optional - Array of names pwn setup already installs (skipped)'\n\n)\n"}]}
1984
1984
  {"messages":[{"role":"user","content":"PWN::Plugins::DetectOS.normalize_id Usage"},{"role":"assistant","content":"`PWN::Plugins::DetectOS.normalize_id`: "}]}
1985
1985
  {"messages":[{"role":"user","content":"PWN::Plugins::DetectOS.parse_kv Usage"},{"role":"assistant","content":"`PWN::Plugins::DetectOS.parse_kv`: "}]}
1986
+ {"messages":[{"role":"user","content":"PWN::Plugins::DetectOS.pwn_installed_bins Usage"},{"role":"assistant","content":"`PWN::Plugins::DetectOS.pwn_installed_bins`: "}]}
1986
1987
  {"messages":[{"role":"user","content":"PWN::Plugins::DetectOS.read_if_present Usage"},{"role":"assistant","content":"`PWN::Plugins::DetectOS.read_if_present`: "}]}
1988
+ {"messages":[{"role":"user","content":"PWN::Plugins::DetectOS.scan_path_executables Usage"},{"role":"assistant","content":"`PWN::Plugins::DetectOS.scan_path_executables`: "}]}
1987
1989
  {"messages":[{"role":"user","content":"PWN::Plugins::DetectOS.type Usage"},{"role":"assistant","content":"`PWN::Plugins::DetectOS.type`: "}]}
1988
1990
  {"messages":[{"role":"user","content":"PWN::Plugins::DetectOS.version Usage"},{"role":"assistant","content":"`PWN::Plugins::DetectOS.version`: Supported Method Parameters\n\nPWN::Plugins::DetectOS.version(\n\nos_release: 'optional - /etc/os-release body',\nlsb_release: 'optional - /etc/lsb-release body',\nbuild_prop: 'optional - Android build.prop body',\nsw_vers: 'optional - macOS/iOS product version',\nwin_ver: 'optional - Windows ver output',\nuname_r: 'optional - uname -r string',\ntype: 'optional - OS family from #type'\n\n)\n"}]}
1989
1991
  {"messages":[{"role":"user","content":"PWN::Plugins::EIN.authors Usage"},{"role":"assistant","content":"`PWN::Plugins::EIN.authors`: Author(s)\n\n0day Inc. <support@0dayinc.com>\n"}]}
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.715
4
+ version: 0.5.716
5
5
  platform: ruby
6
6
  authors:
7
7
  - 0day Inc.