Module: Msf::Assembly::AArch64

Defined in:
lib/msf/core/assembly/a_arch64.rb

Overview

Encodes the subset of AArch64 instructions needed by the framework.

Metasm 1.0.6 cannot parse all required AArch64 assembly text, so this helper selects opcodes and populates their encoded fields directly. These are Metasm internals and must be checked when updating that dependency.

Class Method Summary collapse

Class Method Details

.adr(instruction_address:, destination:, register:) ⇒ String

Returns Encoded little-endian ADR instruction.

Parameters:

  • instruction_address (Integer) —

    Address of the ADR instruction.

  • destination (Integer) —

    Address to load.

  • register (Integer) —

    Destination register number.

Returns:

  • (String) —

    Encoded little-endian ADR instruction.

Raises:

  • (RangeError)


54
55
56
57
58
59
60
61
62
# File 'lib/msf/core/assembly/a_arch64.rb', line 54

def adr(instruction_address:, destination:, register:)
  immediate = destination - instruction_address
  minimum = -(1 << 20)
  maximum = (1 << 20) - 1
  raise RangeError, 'AArch64 ADR destination is too far away' unless immediate.between?(minimum, maximum)

  encoded = ((immediate & 3) << 29) | (((immediate >> 2) & 0x7ffff) << 5)
  instruction('adr', rt: register, i19_5_2_29: encoded)
end

.branch(name, instruction_address:, destination:, bits: 19, field: :i19_5, **fields) ⇒ String

Returns Encoded little-endian branch instruction.

Parameters:

  • name (String) —

    Metasm branch instruction name.

  • instruction_address (Integer) —

    Address of the branch instruction.

  • destination (Integer) —

    Address to branch to.

  • bits (Integer) (defaults to: 19) —

    Width of the signed immediate field.

  • field (Symbol) (defaults to: :i19_5) —

    Metasm opcode field holding the immediate.

  • fields (Hash{Symbol => Integer}) —

    Additional Metasm opcode fields and values.

Returns:

  • (String) —

    Encoded little-endian branch instruction.

Raises:

  • (RangeError)


38
39
40
41
42
43
44
45
46
47
48
# File 'lib/msf/core/assembly/a_arch64.rb', line 38

def branch(name, instruction_address:, destination:, bits: 19, field: :i19_5, **fields)
  displacement = destination - instruction_address
  raise RangeError, 'AArch64 branch destination is not instruction-aligned' unless (displacement % 4).zero?

  immediate = displacement / 4
  minimum = -(1 << (bits - 1))
  maximum = (1 << (bits - 1)) - 1
  raise RangeError, 'AArch64 branch destination is too far away' unless immediate.between?(minimum, maximum)

  instruction(name, **fields.merge(field => immediate))
end

.instruction(name, **fields) ⇒ String

Returns Encoded little-endian instruction.

Parameters:

  • name (String) —

    Metasm instruction name.

  • fields (Hash{Symbol => Integer}) —

    Metasm opcode fields and values.

Returns:

  • (String) —

    Encoded little-endian instruction.

Raises:

  • (Metasm::EncodeError)


18
19
20
21
22
23
24
25
26
27
28
29
# File 'lib/msf/core/assembly/a_arch64.rb', line 18

def instruction(name, **fields)
  opcode = processor.opcode_list_byname.fetch(name).find do |candidate|
    candidate.args == fields.keys && !candidate.props[:r_32] && !candidate.props[:mem_incr]
  end
  raise Metasm::EncodeError, "Unsupported AArch64 instruction: #{name}" unless opcode

  word = fields.reduce(opcode.bin) do |encoded, (field, value)|
    mask, shift = opcode.fields.fetch(field)
    encoded | ((value & mask) << shift)
  end
  [word].pack('V')
end