Class: OneGadget::Emulators::Processor

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

Overview

Base class of a processor.

Direct Known Subclasses

AArch64, X86

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(registers, sp) ⇒ Processor

Instantiate a OneGadget::Emulators::Processor object.

Parameters:

  • registers (Array<String>)

    Registers that supported in the architecture.

  • sp (String)

    The stack register.



21
22
23
24
25
26
27
28
29
30
31
# File 'lib/one_gadget/emulators/processor.rb', line 21

def initialize(registers, sp)
  @registers = registers.map { |reg| [reg, to_lambda(reg)] }.to_h
  @sp = sp
  @constraints = []
  @sp_based_stack = Hash.new do |h, k|
    h[k] = OneGadget::Emulators::Lambda.new(sp).tap do |lmda|
      lmda.immi = k
      lmda.deref!
    end
  end
end

Instance Attribute Details

#pcString (readonly)

Returns Program counter.

Returns:

  • (String)

    Program counter.



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

def pc
  @pc
end

#registersHash{String => OneGadget::Emulators::Lambda} (readonly)

Returns The current registers’ state.

Returns:



11
12
13
# File 'lib/one_gadget/emulators/processor.rb', line 11

def registers
  @registers
end

#spString (readonly)

Returns Stack pointer.

Returns:

  • (String)

    Stack pointer.



13
14
15
# File 'lib/one_gadget/emulators/processor.rb', line 13

def sp
  @sp
end

#sp_based_stackHash{Integer => OneGadget::Emulators::Lambda} (readonly)

Returns Stack content based on sp.

Returns:



12
13
14
# File 'lib/one_gadget/emulators/processor.rb', line 12

def sp_based_stack
  @sp_based_stack
end

Class Method Details

.bitsInteger

32 or 64.

Returns:

  • (Integer)

    32 or 64.

Raises:

  • (NotImplementedError)


155
156
# File 'lib/one_gadget/emulators/processor.rb', line 155

def bits; raise NotImplementedError
end

Instance Method Details

#argument(_idx) ⇒ Lambda, Integer

To be inherited.

Parameters:

  • _idx (Integer)

    The idx-th argument.

Returns:

  • (Lambda, Integer)

    Return value can be a Lambda or an Integer.

Raises:

  • (NotImplementedError)


78
79
# File 'lib/one_gadget/emulators/processor.rb', line 78

def argument(_idx); raise NotImplementedError
end

#constraintsArray<String>

Returns Extra constraints found during execution.

Returns:

  • (Array<String>)

    Extra constraints found during execution.



83
84
85
86
87
88
89
90
91
92
93
94
95
# File 'lib/one_gadget/emulators/processor.rb', line 83

def constraints
  return [] if @constraints.empty?

  # we have these types:
  # * :writable
  # * :raw
  cons = @constraints.uniq do |type, obj|
    next obj unless type == :writable

    obj.deref_count.zero? ? obj.obj.to_s : obj.to_s
  end
  cons.map { |type, obj| type == :writable ? "writable: #{obj}" : obj }.sort
end

#get_corresponding_stack(obj) ⇒ Hash{Integer => Lambda}?

Method need to be implemented in inheritors.

Parameters:

  • obj (String | Lambda)

    A lambda object or its string.

Returns:

  • (Hash{Integer => Lambda}, nil)

    The corresponding stack that obj used, or nil if obj doesn’t use the stack.

Raises:

  • (NotImplementedError)


104
105
# File 'lib/one_gadget/emulators/processor.rb', line 104

def get_corresponding_stack(obj); raise NotImplementedError
end

#instructionsArray<Instruction>

Method need to be implemented in inheritors.

Returns:

Raises:

  • (NotImplementedError)


68
69
# File 'lib/one_gadget/emulators/processor.rb', line 68

def instructions; raise NotImplementedError
end

#parse(cmd) ⇒ (Instruction, Array<String>)

Parse one command into instruction and arguments.

Parameters:

  • cmd (String)

    One line of result of objdump.

Returns:

  • ((Instruction, Array<String>))

    The parsing result.

Raises:



37
38
39
40
41
42
# File 'lib/one_gadget/emulators/processor.rb', line 37

def parse(cmd)
  inst = instructions.find { |i| i.match?(cmd) }
  raise Error::UnsupportedInstructionError, "Not implemented instruction in #{cmd}" if inst.nil?

  [inst, inst.fetch_args(cmd)]
end

#process(cmd) ⇒ Boolean

Process one command, without raising any exceptions.

Parameters:

  • cmd (String)

    See #process! for more information.

Returns:

  • (Boolean)


48
49
50
51
52
53
# File 'lib/one_gadget/emulators/processor.rb', line 48

def process(cmd)
  process!(cmd)
# rescue OneGadget::Error::UnsupportedError => e; p e # for debugging
rescue OneGadget::Error::Error
  false
end

#process!(_cmd) ⇒ Boolean

Method need to be implemented in inheritors.

Process one command. Will raise exceptions when encounter unhandled instruction.

Parameters:

  • _cmd (String)

    One line from result of objdump.

Returns:

  • (Boolean)

    If successfully processed.

Raises:

  • (NotImplementedError)


63
64
# File 'lib/one_gadget/emulators/processor.rb', line 63

def process!(_cmd); raise NotImplementedError
end