Class: OneGadget::Emulators::X86
- Defined in:
- lib/one_gadget/emulators/x86.rb
Overview
Super class for amd64 and i386 processor.
Constant Summary collapse
- JCC =
x86 conditional-jump mnemonics mapped to shared Conditional::RELATION predicates (x86's adapter table, as ArmFamily::COND is for arm/aarch64).
{ 'je' => :eq, 'jz' => :eq, 'jne' => :ne, 'jnz' => :ne, 'jb' => :ult, 'jc' => :ult, 'jnae' => :ult, 'jae' => :uge, 'jnb' => :uge, 'jnc' => :uge, 'ja' => :ugt, 'jnbe' => :ugt, 'jbe' => :ule, 'jna' => :ule, 'jl' => :slt, 'jnge' => :slt, 'jge' => :sge, 'jnl' => :sge, 'jg' => :sgt, 'jnle' => :sgt, 'jle' => :sle, 'jng' => :sle, 'js' => :slt, 'jns' => :sge }.freeze
- COMPARES =
x86 flag-setting compare mnemonics mapped to the ALU op whose result their flags reflect (see Conditional::COMPARE_OPS).
testis a bitwise AND,cmpa subtraction. { 'cmp' => :sub, 'test' => :and }.freeze
- SEGMENT_OPERAND =
A segment-prefixed operand reads thread-local storage, which isn't modelled (nor is its counterpart on the other arches -- aarch64's
mrs tpidr_el0and arm'smrc p15are unsupported instructions, so those paths already abort). Every gadget observed behind one testserrno == ENOEXECon glibc'sexecvpepath -- a value the caller would have to have arranged beforehand, since the gadget is entered after theexecvethat would set it -- so modelling this only produces gadgets that all but never apply. Worth revisiting if a libc is found reaching a terminal call under a condition that commonly holds, e.g.errno != <some error>. /\b(?:fs|gs|ds|es|ss|cs):/
Constants inherited from Processor
Processor::ADDRESS_TYPES, Processor::CLOBBERED, Processor::NULLABLE_REQUIREMENTS, Processor::POINTER_REQUIREMENTS, Processor::TERMINAL_CALL_RE
Constants included from Conditional
Conditional::COMPARE_OPS, Conditional::NEGATE, Conditional::RELATION
Instance Attribute Summary
Attributes inherited from Processor
#bp, #pc, #refused_line, #registers, #sp
Instance Method Summary collapse
-
#initialize(registers, sp, bp, pc) ⇒ X86
constructor
Constructor for a x86 processor.
-
#instructions ⇒ Array<Instruction>
Supported instruction set.
-
#process!(cmd) ⇒ Boolean
Process one command.
Methods inherited from Processor
#address_deref0?, #argument, bits, #bp_based_stack, #closed_fds, #constraint_key, #constraints, #drop_implied_nonzero, #drop_restated_null, #get_corresponding_stack, instruction_table, line_memo, #parse, #process, #reach_terminal_call, #render_constraint, #resolve_address, #setup_frame_pointer, #sp_based_stack, #terminal_call?
Methods included from Conditional
#branch_on_bit, #branch_on_compare, #branch_on_zero, #comparisons_on, #handle_compare, #mnemonic, #operand_str, #record_compare, #resolve_pending_branch, #satisfiable?, #value_str
Constructor Details
#initialize(registers, sp, bp, pc) ⇒ X86
Constructor for a x86 processor.
13 14 15 16 17 |
# File 'lib/one_gadget/emulators/x86.rb', line 13 def initialize(registers, sp, bp, pc) super(registers, sp) @pc = pc setup_frame_pointer(bp) end |
Instance Method Details
#instructions ⇒ Array<Instruction>
Supported instruction set.
67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 |
# File 'lib/one_gadget/emulators/x86.rb', line 67 def instructions [ Instruction.new('add', 2), Instruction.new('and', 2), Instruction.new('call', 1), Instruction.new('endbr32', -1), Instruction.new('endbr64', -1), Instruction.new('jmp', 1), Instruction.new('lea', 2), Instruction.new('mov', 2), Instruction.new('movsxd', 2), Instruction.new('nop', -1), Instruction.new('push', 1), Instruction.new('sub', 2), Instruction.new('xchg', 2), Instruction.new('xor', 2), Instruction.new('movq', 2), Instruction.new('movaps', 2), Instruction.new('movhps', 2), Instruction.new('punpcklqdq', 2) ] end |
#process!(cmd) ⇒ Boolean
Process one command. Will raise exceptions when encounter unhandled instruction.
25 26 27 28 29 30 31 32 33 34 35 |
# File 'lib/one_gadget/emulators/x86.rb', line 25 def process!(cmd) cmd = concretize_rip(cmd) resolve_pending_branch(cmd) mnem = mnemonic(cmd) return handle_compare(COMPARES[mnem], cmd) if COMPARES.key?(mnem) return handle_branch(mnem, cmd) != :fail if branch_mnem?(mnem) inst, args = parse(cmd) sym = :"inst_#{inst.inst}" __send__(sym, *args) != :fail end |