Class: OneGadget::Emulators::Lambda

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

Overview

A Lambda object can be:

  1. String (variable name)

  2. Numeric

  3. Lambda + Numeric

  4. dereferenced Lambda

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(obj) ⇒ Lambda

Instantiate a OneGadget::Emulators::Lambda object.

Parameters:



20
21
22
23
24
# File 'lib/one_gadget/emulators/lambda.rb', line 20

def initialize(obj)
  @immi = 0
  @obj = obj
  @deref_count = 0
end

Instance Attribute Details

#deref_countInteger

Returns The times of dereference.

Returns:

  • (Integer)

    The times of dereference.



16
17
18
# File 'lib/one_gadget/emulators/lambda.rb', line 16

def deref_count
  @deref_count
end

#immiInteger

Returns The immidiate value currently added.

Returns:

  • (Integer)

    The immidiate value currently added.



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

def immi
  @immi
end

#objString, Lambda

Returns The object currently related to.

Returns:

  • (String, Lambda)

    The object currently related to.



14
15
16
# File 'lib/one_gadget/emulators/lambda.rb', line 14

def obj
  @obj
end

Class Method Details

.parse(argument, predefined: {}) ⇒ OneGadget::Emulators::Lambda, Integer

Target: parse string like [rsp+0x50] into a OneGadget::Emulators::Lambda object.

Examples:

obj = Lambda.parse('[rsp+0x50]')
#=> #<Lambda @obj='rsp', @immi=80, @deref_count=1>
Lambda.parse('obj+0x30', predefined: { 'obj' => obj }).to_s
#=> '[rsp+0x50]+0x30'
Lambda.parse('[x0, -104]')
#=> #<Lambda @obj='x0', @immi=-104, @deref_count=1>

Parameters:

  • argument (String)
  • predefined (Hash{String => Lambda}) (defaults to: {})

    Predefined values.

Returns:



118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
# File 'lib/one_gadget/emulators/lambda.rb', line 118

def parse(argument, predefined: {})
  arg = argument.dup
  return 0 if arg.empty? || arg == '!'
  return Integer(arg) if OneGadget::Helper.integer?(arg)

  # nested []
  if arg[0] == '['
    ridx = arg.rindex(']')
    immi = parse(arg[(ridx + 1)..-1])
    lm = parse(arg[1...ridx], predefined: predefined).deref
    lm += immi unless immi.zero?
    return lm
  end

  base, disp = mem_obj(arg)
  obj = predefined[base] || Lambda.new(base)
  obj += disp unless disp.zero?
  obj
end

Instance Method Details

#+(other) ⇒ Lambda

Implement addition with Numeric.

Parameters:

  • other (Numeric)

    Value to add.

Returns:

Raises:



29
30
31
32
33
34
35
36
37
38
39
40
# File 'lib/one_gadget/emulators/lambda.rb', line 29

def +(other)
  raise Error::InstructionArgumentError, "Expect other(#{other}) to be numeric." unless other.is_a?(Numeric)

  if deref_count.positive?
    ret = Lambda.new(self)
  else
    ret = Lambda.new(obj)
    ret.immi = immi
  end
  ret.immi += other
  ret
end

#-(other) ⇒ Lambda

Implement subtract with Numeric.

Parameters:

  • other (Numeric)

    Value to substract.

Returns:



45
46
47
# File 'lib/one_gadget/emulators/lambda.rb', line 45

def -(other)
  self.+(-other)
end

#derefLambda

A new OneGadget::Emulators::Lambda object with dereference count increase 1.

Returns:



67
68
69
70
71
72
# File 'lib/one_gadget/emulators/lambda.rb', line 67

def deref
  ret = Lambda.new(obj)
  ret.immi = immi
  ret.deref_count = deref_count + 1
  ret
end

#deref!void

This method returns an undefined value.

Increase dereference count by 1.



51
52
53
# File 'lib/one_gadget/emulators/lambda.rb', line 51

def deref!
  @deref_count += 1
end

#evaluate(context) ⇒ Integer

Evaluates the value of lambda. Only supports rsp0x30+ form.

Examples:

l = Lambda.parse('rax+0x30')
l.evaluate('rax' => 2)
#=> 50

Parameters:

  • context (Hash{String => Integer})

    The context.

Returns:

  • (Integer)

    Result of evaluation.



94
95
96
97
98
99
100
# File 'lib/one_gadget/emulators/lambda.rb', line 94

def evaluate(context)
  if deref_count.positive? || (obj && !context.key?(obj))
    raise Error::InstructionArgumentError, "Can't eval #{self}"
  end

  context[obj] + immi
end

#ref!self

Decrease dereference count by 1.

Returns:

  • (self)

Raises:

  • (Error::InstrutionArgumentError)

    When this object cannot be referenced anymore.



58
59
60
61
62
63
# File 'lib/one_gadget/emulators/lambda.rb', line 58

def ref!
  raise Error::InstructionArgumentError, 'Cannot reference anymore!' if @deref_count <= 0

  @deref_count -= 1
  self
end

#to_sString

Expand the lambda presentation.

Returns:

  • (String)

    The expand result.



76
77
78
79
80
81
82
83
# File 'lib/one_gadget/emulators/lambda.rb', line 76

def to_s
  str = ''
  str += '[' * deref_count
  str += obj.to_s unless obj.nil?
  str += OneGadget::Helper.hex(immi, psign: true) unless immi.zero?
  str += ']' * deref_count
  str
end