class Ronin::ASM::Program
Represents a full Assembly program.
Constants
- PARSERS
The Assembly Parsers
- SYNTAX
Supported Assembly Syntaxs
Attributes
The registers used by the program
The targeted architecture
The instructions of the program
The targeted Operating System
The registers available to the program
@return [Hash{Symbol => Register}]
The names and registers.
The syscalls available to the program
@return [Hash{Symbol => Integer}]
The syscall names and numbers.
The default word size
Public Class Methods
Initializes a new Assembly Program
.
@param [Hash] options
Additional options.
@option options [String, Symbol] :arch (:x86)
The Architecture to target.
@option options [String, Symbol] :os
The Operating System to target.
@option options [Hash{Symbol => Object}] :define
Constants to define in the program.
@yield []
The given block will be evaluated within the program.
@example
Program.new(arch: :amd64) do push rax push rbx mov rsp, rax mov rax[8], rbx end
# File lib/ronin/asm/program.rb, line 105 def initialize(options={},&block) @arch = options.fetch(:arch,:x86).to_sym arch = Archs.const_get(@arch.to_s.upcase) @word_size = arch::WORD_SIZE @registers = arch::REGISTERS extend Archs.const_get(@arch.to_s.upcase) @syscalls = {} if options.has_key?(:os) @os = options[:os].to_s @syscalls = OS::SYSCALLS[@os][@arch] extend OS.const_get(@os) end if options[:define] options[:define].each do |name,value| instance_variable_set("@#{name}",value) end end @allocated_registers = [] @instructions = [] instance_eval(&block) if block end
Public Instance Methods
Assembles the program.
@param [String] output
The path for the assembled program.
@param [Hash] options
Additional options.
@option options [Symbol, String] :syntax (:intel)
The syntax to compile the program to.
@option options [Symbol] :format (:bin)
The format of the assembled executable. May be one of: * `:dbg` - Trace of all info passed to object format module. * `:bin` - Flat format binary. * `:dosexe` - DOS .EXE format binary. * `:elf` - ELF. * `:elf32` - ELF (32-bit). * `:elf64` - ELF (64-bit). * `:coff` - COFF (DJGPP). * `:macho` - Mac OS X ABI Mach-O File Format. * `:macho32` - Mac OS X ABI Mach-O File Format (32-bit). * `:macho64` - Mac OS X ABI Mach-O File Format (64-bit). * `:rdf` - Relocatable Dynamic Object File Format (RDOFF) v2.0. * `:win32` - Win32. * `:win64` / `:x64` - Win64. * `:xdf` - Extended Dynamic Object.
@return [String]
The path to the assembled program.
# File lib/ronin/asm/program.rb, line 453 def assemble(output,options={}) syntax = options.fetch(:syntax,:intel) format = options.fetch(:format,:bin) parser = PARSERS[syntax] source = Tempfile.new(['ronin-asm', '.s']) source.write(to_asm(syntax)) source.close YASM::Program.assemble( file: source.path, parser: PARSERS[syntax], target: @arch, output_format: format, output: output ) return output end
Creates an operand of size 1 (byte).
@param [MemoryOperand, Integer] op
The value of the operand.
@return [MemoryOperand, ImmediateOperand]
The new operand value.
# File lib/ronin/asm/program.rb, line 202 def byte(op) case op when MemoryOperand MemoryOperand.new(op.base,op.offset,op.index,op.scale,1) else ImmediateOperand.new(op,1) end end
Defines a critical region, where the specified Registers should be saved and then reloaded.
@param [Array<Symbol>] regs
The registers to save and reload.
@yield []
The given block will be evaluated after the registers have been saved.
# File lib/ronin/asm/program.rb, line 385 def critical(*regs,&block) regs.each { |name| register_save(name) } instance_eval(&block) regs.reverse_each { |name| register_load(name) } end
Creates a operand of size 4 (bytes).
@param [MemoryOperand, Integer] op
The value of the operand.
@return [ImmediateOperand]
The new operand value.
# File lib/ronin/asm/program.rb, line 238 def dword(op) case op when MemoryOperand MemoryOperand.new(op.base,op.offset,op.index,op.scale,4) else ImmediateOperand.new(op,4) end end
Evaluates code within the Program
.
@yield []
The code to evaluate.
# File lib/ronin/asm/program.rb, line 399 def eval(&block) instance_eval(&block) end
Adds a new instruction to the program.
@param [String, Symbol] name
@param [Array] operands
@return [Instruction]
The newly created instruction.
# File lib/ronin/asm/program.rb, line 186 def instruction(name,*operands) insn = Instruction.new(name.to_sym,operands) @instructions << insn return insn end
Generic method for generating the instruction for causing an interrupt.
@param [Integer] number
The interrupt number to call.
@abstract
# File lib/ronin/asm/program.rb, line 294 def interrupt(number) end
Adds a label to the program.
@param [Symbol, String] name
The name of the label.
@yield []
The given block will be evaluated after the label has been added.
@return [Symbol]
The label name.
# File lib/ronin/asm/program.rb, line 278 def label(name,&block) name = name.to_sym @instructions << name instance_eval(&block) return name end
Creates a operand of size 8 (bytes).
@param [MemoryOperand, Integer] op
The value of the operand.
@return [MemoryOperand, ImmediateOperand]
The new operand.
# File lib/ronin/asm/program.rb, line 256 def qword(op) case op when MemoryOperand MemoryOperand.new(op.base,op.offset,op.index,op.scale,8) else ImmediateOperand.new(op,8) end end
Accesses a register.
@param [String, Symbol] name
The name of the register.
@return [Register]
The register.
@raise [ArgumentError]
The register could not be found.
# File lib/ronin/asm/program.rb, line 161 def register(name) name = name.to_sym unless register?(name) raise(ArgumentError,"unknown register: #{name}") end unless @allocated_registers.include?(name) # mark the register as being used, when it was first accessed @allocated_registers << name end return @registers[name] end
Determines if a register exists.
@param [Symbol] name
The name of the register.
@return [Boolean]
Specifies whether the register exists.
# File lib/ronin/asm/program.rb, line 145 def register?(name) @registers.has_key?(name.to_sym) end
Generic method for clearing a register.
@param [Symbol] name
The name of the reigster.
@abstract
# File lib/ronin/asm/program.rb, line 335 def register_clear(name) end
Generic method for loading a register.
@param [Symbol] name
The name of the reigster.
@abstract
# File lib/ronin/asm/program.rb, line 371 def register_load(name) end
Generic method for saving a register.
@param [Symbol] name
The name of the reigster.
@abstract
# File lib/ronin/asm/program.rb, line 360 def register_save(name) end
Generic method for setting a register.
@param [Symbol] name
The name of the reigster.
@param [Register, Immediate, Integer] value
The new value for the register.
@abstract
# File lib/ronin/asm/program.rb, line 349 def register_set(name,value) end
Generic method for popping off the stack.
@param [Symbol] name
The name of the reigster.
@abstract
# File lib/ronin/asm/program.rb, line 324 def stack_pop(name) end
Generic method for pushing onto the stack.
@param [Register, Integer] value
The value to push.
@abstract
# File lib/ronin/asm/program.rb, line 313 def stack_push(value) end
Generic method for generating the instruction for invoking a syscall.
@abstract
# File lib/ronin/asm/program.rb, line 302 def syscall end
Converts the program to Assembly Source Code.
@param [Symbol] syntax
The syntax to compile the program to.
# File lib/ronin/asm/program.rb, line 409 def to_asm(syntax=:intel) SYNTAX[syntax].emit_program(self) end
@see to_s
# File lib/ronin/asm/program.rb, line 416 def to_s to_asm end
Creates a operand of size 2 (bytes).
@param [MemoryOperand, Integer] op
The value of the operand.
@return [MemoryOperand, ImmediateOperand]
The new operand value.
# File lib/ronin/asm/program.rb, line 220 def word(op) case op when MemoryOperand MemoryOperand.new(op.base,op.offset,op.index,op.scale,2) else ImmediateOperand.new(op,2) end end
Protected Instance Methods
Allows adding unknown instructions to the program.
@param [Symbol] name
The name of the instruction.
@param [Array] arguments
Additional operands.
# File lib/ronin/asm/program.rb, line 487 def method_missing(name,*arguments,&block) if (block && arguments.empty?) label(name,&block) elsif block.nil? if (arguments.empty? && register?(name)) register(name) else instruction(name,*arguments) end else super(name,*arguments,&block) end end