From 65abef7782c65f355cba69486e917711613f2acb Mon Sep 17 00:00:00 2001 From: david942j Date: Sat, 18 Feb 2017 22:30:47 +0800 Subject: [PATCH] x86 emulator --- lib/one_gadget/emulators/amd64.rb | 6 ++++++ lib/one_gadget/emulators/i386.rb | 2 +- lib/one_gadget/emulators/x86.rb | 25 +++++++++++++++++++++---- spec/emulators/i386_spec.rb | 17 +++++++++++++++++ 4 files changed, 45 insertions(+), 5 deletions(-) diff --git a/lib/one_gadget/emulators/amd64.rb b/lib/one_gadget/emulators/amd64.rb index fac32cc..e9adb00 100644 --- a/lib/one_gadget/emulators/amd64.rb +++ b/lib/one_gadget/emulators/amd64.rb @@ -4,6 +4,12 @@ module OneGadget module Emulators # Emulator of amd64 instruction set. class Amd64 < X86 + class << self + def stack_pointer + 'rsp' + end + end + REGISTERS = %w(rax rbx rcx rdx rdi rsi rbp rsp rip) + 7.upto(15).map { |i| "r#{i}" } # Instantiate a {Amd64} object. diff --git a/lib/one_gadget/emulators/i386.rb b/lib/one_gadget/emulators/i386.rb index 6f2d83f..f42f630 100644 --- a/lib/one_gadget/emulators/i386.rb +++ b/lib/one_gadget/emulators/i386.rb @@ -4,7 +4,6 @@ module OneGadget module Emulators # Emulator of amd64 instruction set. class I386 < X86 - REGISTERS = %w(eax ebx ecx edx edi esi ebp esp eip).freeze class << self def bits 32 @@ -15,6 +14,7 @@ module OneGadget end end + REGISTERS = %w(eax ebx ecx edx edi esi ebp esp eip).freeze # Instantiate a {I386} object. def initialize super(REGISTERS) diff --git a/lib/one_gadget/emulators/x86.rb b/lib/one_gadget/emulators/x86.rb index aaaf45a..7bad570 100644 --- a/lib/one_gadget/emulators/x86.rb +++ b/lib/one_gadget/emulators/x86.rb @@ -50,9 +50,22 @@ module OneGadget private + def register?(reg) + @registers.include?(reg) + end + def inst_mov(tar, src) src = OneGadget::Emulators::Lambda.parse(src, predefined: @registers) - @registers[tar] = src + if register?(tar) + @registers[tar] = src + else + # Just ignore strange case... + return unless tar.include?(self.class.stack_pointer) + tar = OneGadget::Emulators::Lambda.parse(tar, predefined: @registers) + return if tar.deref_count != 1 # should not happened + tar.ref! + @stack[tar.evaluate(eval_dict)] = src + end end def inst_lea(tar, src) @@ -64,9 +77,7 @@ module OneGadget def inst_push(val) val = OneGadget::Emulators::Lambda.parse(val, predefined: @registers) @registers[self.class.stack_pointer] -= bytes - dict = {} - dict[self.class.stack_pointer] = 0 - cur_top = @registers[self.class.stack_pointer].evaluate(dict) + cur_top = @registers[self.class.stack_pointer].evaluate(eval_dict) raise ArgumentError, "Corrupted stack pointer: #{cur_top}" unless cur_top.is_a?(Integer) @stack[cur_top] = val end @@ -84,6 +95,12 @@ module OneGadget def bytes self.class.bits / 8 end + + def eval_dict + dict = {} + dict[self.class.stack_pointer] = 0 + dict + end end end end diff --git a/spec/emulators/i386_spec.rb b/spec/emulators/i386_spec.rb index 3f2896e..7621ef9 100644 --- a/spec/emulators/i386_spec.rb +++ b/spec/emulators/i386_spec.rb @@ -24,6 +24,7 @@ describe OneGadget::Emulators::I386 do expect(@processor.stack[0].to_s).to eq 'esi-0x55f61' expect(@processor.stack[4].to_s).to eq 'esp+0x34' expect(@processor.stack[8].to_s).to eq '[[esi-0xb8]]' + # The defualt value of stack is a lambda expect(@processor.stack[3].to_s).to eq '[esp+0x3]' end @@ -57,5 +58,21 @@ describe OneGadget::Emulators::I386 do expect(@processor.stack[-0x3c].to_s).to eq '1337' expect(@processor.stack[-0x4].to_s).to eq '1' end + + it 'libc-2.19' do + gadget = <<-'EOS' + 64c60: mov DWORD PTR [esp+0x8],eax + 64c64: lea eax,[ebx-0x4956f] + 64c6a: mov DWORD PTR [esp+0x4],eax + 64c6e: lea eax,[ebx-0x49574] + 64c74: mov DWORD PTR [esp],eax + 64c77: call b5170 + EOS + gadget.lines.each { |s| @processor.process(s) } + expect(@processor.registers['esp'].to_s).to eq 'esp' + expect(@processor.stack[0].to_s).to eq 'ebx-0x49574' + expect(@processor.stack[4].to_s).to eq 'ebx-0x4956f' + expect(@processor.stack[8].to_s).to eq 'eax' + end end end