summaryrefslogtreecommitdiff
path: root/emulate/emulator.hpp
diff options
context:
space:
mode:
authorDennis Brentjes <d.brentjes@gmail.com>2016-09-19 17:38:23 +0200
committerDennis Brentjes <d.brentjes@gmail.com>2016-10-04 22:18:23 +0200
commitc29ae7a65c636b8d1fa37c6589278dcdee97658f (patch)
treea0ad6583a1f954a179349e0b27d58d7c945c59b5 /emulate/emulator.hpp
parentabd5cfdd4a6c8e9979b2deb3c48304fb3d63a44c (diff)
downloadopenwar-c29ae7a65c636b8d1fa37c6589278dcdee97658f.tar.gz
openwar-c29ae7a65c636b8d1fa37c6589278dcdee97658f.tar.bz2
openwar-c29ae7a65c636b8d1fa37c6589278dcdee97658f.zip
Started working on a x86 emulator.
Diffstat (limited to 'emulate/emulator.hpp')
-rw-r--r--emulate/emulator.hpp113
1 files changed, 113 insertions, 0 deletions
diff --git a/emulate/emulator.hpp b/emulate/emulator.hpp
new file mode 100644
index 0000000..e894042
--- /dev/null
+++ b/emulate/emulator.hpp
@@ -0,0 +1,113 @@
+#pragma once
+
+#include "cpustate.hpp"
+
+#include "le_parse_util.hpp"
+
+#include <distorm.h>
+#include <mnemonics.h>
+
+#include <fstream>
+#include <iomanip>
+
+class Emulator {
+public:
+ CpuState cpu;
+
+ std::map<int, std::function<void(_DInst)>> opcode_handlers;
+
+
+
+ void handle_I_JMP(_DInst inst) {
+ if(inst.ops[0].type == O_PC || inst.ops[0].type == O_PTR || inst.ops[0].type == O_DISP) {
+ binparse::Offset32 target = binparse::Offset32(INSTRUCTION_GET_TARGET(&inst));
+ cpu.eip() = target;
+ } else if (inst.ops[0].type == O_SMEM) {
+ throw UnhandledInstruction();
+ } else {
+ throw UnrecognizedInstruction();
+ }
+ }
+ void handle_I_STI(_DInst) {
+ cpu.intf() = 1;
+ }
+
+ void handle_I_AND(_DInst inst) {
+ std::cout << inst.ops[0].size << std::endl;
+ //get_op(0, inst) &= get_op(1, inst);
+ }
+
+public:
+ Emulator(binparse::Offset32 init_eip, binparse::Offset32 init_esp)
+ : cpu()
+ {
+ cpu.eip() = init_eip;
+ cpu.esp() = init_esp;
+
+ #define REGISTER_HANDLER(OPCODE) opcode_handlers[OPCODE] = std::bind(&Emulator::handle_##OPCODE, this, std::placeholders::_1)
+
+ REGISTER_HANDLER(I_JMP);
+ REGISTER_HANDLER(I_STI);
+ REGISTER_HANDLER(I_AND);
+
+ #undef REGISTER_HANDLER
+ }
+
+ struct UnhandledInstruction : public std::runtime_error {
+ UnhandledInstruction()
+ : std::runtime_error("Encountered unhandled instruction")
+ {}
+ };
+
+ struct UnrecognizedInstruction : public std::runtime_error {
+ UnrecognizedInstruction()
+ : std::runtime_error("Encountered unhandled instruction")
+ {}
+ };
+
+ void handle_instruction(_DInst inst) {
+ opcode_handlers.at(inst.opcode)(inst);
+ }
+
+};
+
+void emulate(std::string file_path) {
+ std::ifstream file_stream(file_path, std::ios::binary);
+ file_stream.unsetf(std::ios::skipws);
+ auto file = le::parse_file(file_stream);
+ auto binary = load_binary(file);
+
+ _CodeInfo ci;
+ _DecodeType dt = Decode32Bits;
+
+ auto code_object = file.object_table.entries.at(file.le_header.EIP_object);
+ auto initial_eip = code_object.reloc_base_address + file.le_header.EIP;
+
+ auto data_object = file.object_table.entries.at(file.le_header.ESP_object);
+ auto initial_esp = data_object.reloc_base_address + file.le_header.ESP;
+
+ Emulator emulator(initial_eip, initial_esp);
+
+ unsigned int decodedInstructionsCount;
+
+ bool run = true;
+ while(run) {
+ ci.code = binary.data() + emulator.cpu.eip();
+ ci.nextOffset = emulator.cpu.eip();
+ ci.codeLen = binary.size() - emulator.cpu.eip();
+ ci.codeOffset = emulator.cpu.eip();
+ ci.dt = dt;
+ ci.features = DF_NONE;
+
+ _DInst decinst;
+ distorm_decompose(&ci, &decinst, 1, &decodedInstructionsCount);
+
+ emulator.cpu.eip() += decinst.size;
+
+ _DecodedInst inst;
+ distorm_format64(&ci, &decinst, &inst);
+ std::cout << "CurrentInstruction: " << std::hex << std::setw(8) << std::setfill('0') << inst.offset << ":\t" << inst.mnemonic.p << " " << inst.operands.p << std::endl;
+
+ emulator.handle_instruction(decinst);
+ }
+}