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:


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

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:


117
118
119
120
121
122
123
124
125
126
127
# File 'lib/one_gadget/emulators/lambda.rb', line 117

def parse(argument, predefined: {})
  arg = argument.dup
  return Integer(arg) if OneGadget::Helper.integer?(arg)
  # nested []
  return parse(arg[1...arg.rindex(']')], predefined: predefined).deref if arg[0] == '['

  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:


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

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:


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

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

#derefLambda

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

Returns:


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

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 with 1.


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

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.


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

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 with 1.

Returns:

  • (self)

Raises:

  • (Error::InstrutionArgumentError)

    When this object cannot be referenced anymore.


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

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.


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

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