Class: OneGadget::Gadget::Gadget

Inherits:
Object
  • Object
show all
Defined in:
lib/one_gadget/gadget.rb

Overview

Information of a gadget.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(offset, **options) ⇒ Gadget

Initialize method of OneGadget::Gadget::Gadget instance.

Examples:

OneGadget::Gadget::Gadget.new(0x12345, constraints: ['rax == 0'])

Parameters:

  • offset (Integer)

    The relative address offset of this gadget.

  • options (Hash)

    a customizable set of options

Options Hash (**options):

  • :constraints (Array<String>)

    The constraints need for this gadget. Defaults to [].



32
33
34
35
36
37
38
# File 'lib/one_gadget/gadget.rb', line 32

def initialize(offset, **options)
  @base = 0
  @offset = offset
  @constraints = prune_settled(options[:constraints] || [])
  @effect = options[:effect] || ''
  @closed_fds = options[:closed_fds] || []
end

Instance Attribute Details

#baseInteger

Returns Base address of libc. Default: 0.

Returns:

  • (Integer)

    Base address of libc. Default: 0.



15
16
17
# File 'lib/one_gadget/gadget.rb', line 15

def base
  @base
end

#closed_fdsArray<String> (readonly)

Returns Where each descriptor this gadget closes before the exec is read from, in the order it closes them (see #caveats).

Returns:

  • (Array<String>)

    Where each descriptor this gadget closes before the exec is read from, in the order it closes them (see #caveats).



24
25
26
# File 'lib/one_gadget/gadget.rb', line 24

def closed_fds
  @closed_fds
end

#constraintsArray<String> (readonly)

Returns The constraints need for this gadget.

Returns:

  • (Array<String>)

    The constraints need for this gadget.



19
20
21
# File 'lib/one_gadget/gadget.rb', line 19

def constraints
  @constraints
end

#effectString (readonly)

Returns The final result of this gadget.

Returns:

  • (String)

    The final result of this gadget.



21
22
23
# File 'lib/one_gadget/gadget.rb', line 21

def effect
  @effect
end

#offsetInteger (readonly)

Returns The gadget's address offset.

Returns:

  • (Integer)

    The gadget's address offset.



17
18
19
# File 'lib/one_gadget/gadget.rb', line 17

def offset
  @offset
end

Instance Method Details

#caveatsArray<String>

What the gadget costs the caller beyond its constraints: a descriptor it closes on the way to the exec. Each line names the close itself, so it reads as the code does and can be matched exactly, and says what the value must avoid for the spawned shell to keep its I/O.

Examples:

['close([rsp+0x44]): prevent it from being 0 (stdin) or 1 (stdout) ...']

Returns:

  • (Array<String>)


47
48
49
50
51
52
# File 'lib/one_gadget/gadget.rb', line 47

def caveats
  closed_fds.map do |fd|
    "close(#{fd}): prevent it from being 0 (stdin) or 1 (stdout) to sound " \
      'an interactive shell.'
  end
end

#inspectString

Returns a human-readable, colorized representation of this gadget, showing its address followed by the effect and constraints.

Returns:

  • (String)

    The multi-line pretty-printed gadget.



57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
# File 'lib/one_gadget/gadget.rb', line 57

def inspect
  str = "#{OneGadget::Helper.hex(value)} #{effect}\n"
  unless constraints.empty?
    str += "#{OneGadget::Helper.colorize('constraints')}:\n  "
    str += merge_constraints.join("\n  ")
  end
  unless caveats.empty?
    str += "\n" unless constraints.empty?
    str += "#{OneGadget::Helper.colorize('caveats')}:\n  "
    str += caveats.join("\n  ")
  end
  str.gsub!(/0x[\da-f]+/) { |s| OneGadget::Helper.colorize(s, sev: :integer) }
  OneGadget::ABI.all.each do |reg|
    str.gsub!(/([^\w])(#{reg})([^\w])/, "\\1#{OneGadget::Helper.colorize('\2', sev: :reg)}\\3")
  end
  "#{str}\n"
end

#met_by?(other) ⇒ Boolean

Whether other asks for everything this gadget asks for, so listing this one beside it tells the reader nothing new. Each constraint here has to be met by +other+'s list: named there, or -- for one that offers several options -- an option of it required there outright.

Examples:

An option required outright meets the constraint offering it.

met_by?(other) # where this asks "r8 == NULL || (u16)[r8] == 0x0"
               # and +other+ asks "(u16)[r8] == 0x0"

Parameters:

Returns:

  • (Boolean)


115
116
117
118
119
120
# File 'lib/one_gadget/gadget.rb', line 115

def met_by?(other)
  constraints.all? do |con|
    other.constraints.include?(con) ||
      con.split(DISJUNCTION).any? { |option| other.constraints.include?(option) }
  end
end

#scoreFloat

Returns The success probability of the constraints.

Returns:

  • (Float)

    The success probability of the constraints.



102
103
104
# File 'lib/one_gadget/gadget.rb', line 102

def score
  @score ||= constraints.reduce(1.0) { |s, c| s * calculate_score(c) }
end

#to_jsonString

Serializes this gadget into a JSON string.

Returns:

  • (String)

    The gadget in JSON format. See #to_obj for the keys.



90
91
92
# File 'lib/one_gadget/gadget.rb', line 90

def to_json(*)
  to_obj.to_json
end

#to_objHash{Symbol => Integer, String, Array<String>, Array<Integer>}

Converts this gadget into a plain hash, suitable for serialization.

Returns:

  • (Hash{Symbol => Integer, String, Array<String>, Array<Integer>})

    A hash with keys :value (the absolute address), :effect (the resulting function call), :constraints (the required constraints) and, when the gadget closes a descriptor, :closed_fds with the #caveats they carry.



81
82
83
84
85
86
# File 'lib/one_gadget/gadget.rb', line 81

def to_obj
  obj = { value:, effect:, constraints: }
  return obj if caveats.empty?

  obj.merge(closed_fds:, caveats:)
end

#valueInteger

Returns base plus offset.

Returns:

  • (Integer)

    Returns base plus offset.



96
97
98
# File 'lib/one_gadget/gadget.rb', line 96

def value
  base + offset
end