Module: PWN::Plugins::BinWorkspace

Defined in:
lib/pwn/plugins/bin_workspace.rb

Overview

Persistent per-binary analysis workspace keyed by sha256.

Constant Summary collapse

ROOT =
File.join(Dir.home, '.pwn', 'binws')

Class Method Summary collapse

Class Method Details

.annotate(opts = {}) ⇒ Object



26
27
28
29
30
31
32
33
34
35
36
37
38
39
# File 'lib/pwn/plugins/bin_workspace.rb', line 26

public_class_method def self.annotate(opts = {})
  ws = self.for(opts)
  store = JSON.parse(File.read(ws[:notes]), symbolize_names: true)
  addr = (opts[:addr] || opts[:address]).to_s
  raise 'ERROR: addr is required' if addr.empty?

  store[addr.to_sym] = {
    kind: (opts[:kind] || 'comment').to_s,
    text: opts[:text].to_s,
    name: opts[:name].to_s
  }
  File.write(ws[:notes], JSON.pretty_generate(store))
  store[addr.to_sym].merge(sha256: ws[:sha256])
end

.authorsObject



47
48
49
# File 'lib/pwn/plugins/bin_workspace.rb', line 47

public_class_method def self.authors
  "AUTHOR(S):\n  0day Inc. <[email protected]>\n"
end

.for(opts = {}) ⇒ Object



13
14
15
16
17
18
19
20
21
22
23
24
# File 'lib/pwn/plugins/bin_workspace.rb', line 13

public_class_method def self.for(opts = {})
  path = (opts[:path] || opts[:bin]).to_s
  raise 'ERROR: path is required' if path.empty?
  raise "ERROR: file not found: #{path}" unless File.file?(path)

  sha = Digest::SHA256.file(path).hexdigest
  dir = File.join(ROOT, sha)
  FileUtils.mkdir_p(dir)
  notes = File.join(dir, 'notes.json')
  File.write(notes, JSON.generate({})) unless File.file?(notes)
  { sha256: sha, dir: dir, path: path, notes: notes }
end

.helpObject



51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
# File 'lib/pwn/plugins/bin_workspace.rb', line 51

public_class_method def self.help
  puts "USAGE:
    # Open or create ~/.pwn/binws/<sha256> for a binary.
    #{self}.for(
      path: 'required - filesystem path of the binary',
      bin: 'optional - alias for path'
    )

    # Record a rename, comment, or tag at an address.
    #{self}.annotate(
      path: 'required - filesystem path of the binary',
      addr: 'required - address or symbol',
      address: 'optional - alias for addr',
      kind: 'optional - comment|rename|tag (defaults to comment)',
      text: 'optional - annotation body',
      name: 'optional - renamed symbol'
    )

    # Return the annotation map for a binary workspace.
    #{self}.notes(
      path: 'required - filesystem path of the binary'
    )

    # Print the AUTHOR(S) string for this module.
    #{self}.authors
  "
  constants.sort
end

.notes(opts = {}) ⇒ Object



41
42
43
44
45
# File 'lib/pwn/plugins/bin_workspace.rb', line 41

public_class_method def self.notes(opts = {})
  path = (opts[:path] || opts[:bin]).to_s
  ws = self.for(path: path)
  JSON.parse(File.read(ws[:notes]), symbolize_names: true)
end