Last active
August 29, 2015 16:17
-
-
Save masami256/ff2920be7ea5d92d538a to your computer and use it in GitHub Desktop.
自作エミュレータで学ぶx86アーキテクチャ emu2.3のruby版
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env ruby | |
| require 'pp' | |
| class Emulator | |
| @@EAX = 0 | |
| @@ECX = 1 | |
| @@EDX = 2 | |
| @@EBX = 3 | |
| @@ESP = 4 | |
| @@EBP = 5 | |
| @@ESI = 6 | |
| @@EDI = 7 | |
| @@REGISTER_COUNT = 8 | |
| def initialize(size: 10240, eip: 0, esp: 0x7c00) | |
| @registers = Array.new(@@REGISTER_COUNT, 0) | |
| @eflags = 0 | |
| @memory = Array.new(size, 0) | |
| @eip = eip | |
| @registers[@@ESP] = esp | |
| init_instructions | |
| @register_names = [ | |
| "eax", | |
| "ecx", | |
| "edx", | |
| "ebx", | |
| "esp", | |
| "ebp", | |
| "esi", | |
| "edi", | |
| ] | |
| end | |
| def read_binary_data_to_memory(data, size: 0x200) | |
| @memory = data[0..size] | |
| end | |
| def run | |
| while @eip < @memory.length | |
| code = get_code8(0) | |
| if @instructions[code].nil? | |
| puts("[*]Instruction #{code} is not implemtend") | |
| return | |
| end | |
| printf("EIP = 0x%08x, Code = 0x%02x\n", @eip, code) | |
| self.send(@instructions[code]) | |
| if @eip == 0x00 | |
| puts("[+]End of program") | |
| return | |
| end | |
| end | |
| end | |
| def dump_registers | |
| @@REGISTER_COUNT.times do |i| | |
| printf("%s = 0x%08x\n", @register_names[i], @registers[i]) | |
| end | |
| printf("EIP = 0x%08x\n", @eip) | |
| end | |
| private | |
| def mov_r32_imm32 | |
| reg = get_code8(0) - 0xb8 | |
| value = get_code32(1) | |
| @registers[reg] = value | |
| @eip += 5 | |
| end | |
| def short_jump | |
| diff = get_code8(1) | |
| @eip += (diff + 2) | |
| end | |
| def init_instructions | |
| @instructions = Array.new(256, nil) | |
| 8.times do |i| | |
| @instructions[0xb8 + i] = "mov_r32_imm32" | |
| end | |
| @instructions[0xeb] = "short_jump" | |
| end | |
| def get_code8(index) | |
| return @memory[@eip + index].unpack("C")[0] | |
| end | |
| def get_code32(index) | |
| ret = 0 | |
| 4.times do |i| | |
| ret |= get_code8(index + i) >> (i * 8) | |
| end | |
| return ret | |
| end | |
| end | |
| class Utility | |
| def self.read_bin_file(filepath) | |
| st = File::Stat.new(filepath) | |
| puts("[+]read #{filepath} size #{st.size}") | |
| f = File.open(filepath) | |
| return f.read(st.size) | |
| end | |
| end | |
| if __FILE__ == $0 | |
| if ARGV.length != 1 | |
| puts("usage: #{$0} file") | |
| exit(-1) | |
| end | |
| test_file = ARGV[0] | |
| excutable_file_data = Utility::read_bin_file(test_file) | |
| emurator = Emulator.new | |
| emurator.read_binary_data_to_memory(excutable_file_data) | |
| emurator.run | |
| emurator.dump_registers | |
| end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment