From 0588b1ad00078daeda76a810b9ba6c68f97206a2 Mon Sep 17 00:00:00 2001 From: Dennis Brentjes Date: Tue, 4 Oct 2016 22:15:25 +0200 Subject: Adds shr and cmp (with flags), and adds flags for sub. --- emulate/cpustate.hpp | 34 +++++++++++++++++- emulate/emulator.hpp | 97 ++++++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 127 insertions(+), 4 deletions(-) diff --git a/emulate/cpustate.hpp b/emulate/cpustate.hpp index fb9c377..6b80551 100644 --- a/emulate/cpustate.hpp +++ b/emulate/cpustate.hpp @@ -3,6 +3,7 @@ #include #include #include +#include #define REGISTER1( NAME ) \ private: \ @@ -74,4 +75,35 @@ struct CpuState { #undef REGISTER1 #undef REGISTER2 -#undef EFLAGS \ No newline at end of file +#undef EFLAGS + +std::ostream& operator<<(std::ostream& os, CpuState& cpu) { + os << "EIP: 0x" << std::hex << std::setw(8) << std::setfill('0') << cpu.eip() << std::endl + << "EAX: 0x" << std::hex << std::setw(8) << std::setfill('0') << cpu.eax() << std::endl + << "EBX: 0x" << std::hex << std::setw(8) << std::setfill('0') << cpu.ebx() << std::endl + << "ECX: 0x" << std::hex << std::setw(8) << std::setfill('0') << cpu.ecx() << std::endl + << "EDX: 0x" << std::hex << std::setw(8) << std::setfill('0') << cpu.edx() << std::endl + << "ESP: 0x" << std::hex << std::setw(8) << std::setfill('0') << cpu.esp() << std::endl + << "EBP: 0x" << std::hex << std::setw(8) << std::setfill('0') << cpu.ebp() << std::endl + << "ESI: 0x" << std::hex << std::setw(8) << std::setfill('0') << cpu.esi() << std::endl + << "EDI: 0x" << std::hex << std::setw(8) << std::setfill('0') << cpu.edi() << std::endl + << "cf \tpf \taf \tzf \tsf \ttf \tintf \tdf \tof \tnt \trf \tvm \tac \tvif \tvip \tid" << std::endl + << cpu.cf() << "\t" + << cpu.pf() << "\t" + << cpu.af() << "\t" + << cpu.zf() << "\t" + << cpu.sf() << "\t" + << cpu.tf() << "\t" + << cpu.intf() << "\t" + << cpu.df() << "\t" + << cpu.of() << "\t" + << cpu.nt() << "\t" + << cpu.rf() << "\t" + << cpu.vm() << "\t" + << cpu.ac() << "\t" + << cpu.vif() << "\t" + << cpu.vip() << "\t" + << cpu.id() << "\t" + << std::endl; + return os; +} diff --git a/emulate/emulator.hpp b/emulate/emulator.hpp index 9bb5735..69c2f46 100644 --- a/emulate/emulator.hpp +++ b/emulate/emulator.hpp @@ -11,6 +11,25 @@ #include #include +#include + +template + struct SignedCounterpart {}; + + template <> + struct SignedCounterpart { + typedef int32_t type; + }; + + template <> + struct SignedCounterpart { + typedef int16_t type; + }; + + template <> + struct SignedCounterpart { + typedef int8_t type; +}; class Emulator { public: @@ -70,7 +89,18 @@ public: }; template - struct binary_op : public boost::static_visitor { + struct op : public boost::static_visitor { + CpuState& cpu; + + op(CpuState& cpu) + : cpu(cpu) + {} + }; + + template + struct binary_op : public op { + using op::op; + template Ret operator()(T&, U const&) const { throw IncompatibleArguments(); @@ -79,6 +109,7 @@ public: struct and_ : public binary_op { using binary_op::operator(); + using binary_op::binary_op; template void operator()(T& lh, T const& rh) const { @@ -88,6 +119,7 @@ public: struct mov : public binary_op { using binary_op::operator(); + using binary_op::binary_op; template void operator()(T& lh, T const& rh) const { @@ -95,12 +127,57 @@ public: } }; - struct sub : public binary_op { + struct sub : public binary_op { using binary_op::operator(); + using binary_op::binary_op; template void operator()(T& lh, T const& rh) const { + typedef typename SignedCounterpart::type S; + auto& slh = reinterpret_cast(lh); + auto const& srh = reinterpret_cast(rh); + + cpu.of() = ((srh < 0) && (slh > std::numeric_limits::max() + srh)) || ((rh > 0) && (slh < std::numeric_limits::min() + srh)); + cpu.af() = !(lh & 8) && (rh & 8); + cpu.cf() = !(static_cast(std::numeric_limits::min()) & lh) && (static_cast(std::numeric_limits::min()) & rh); + lh -= rh; + + cpu.sf() = static_cast(std::numeric_limits::min()) & lh; + cpu.zf() = lh == 0; + cpu.pf() = ((lh & 1) + (lh >> 1 & 1) + (lh >> 2 & 1) + (lh >> 3 & 1) + (lh >> 4 & 1) + (lh >> 5 & 1) + (lh >> 6 & 1) + (lh >> 7 & 1) % 2) + 1; + } + }; + + struct shr : public binary_op { + using binary_op::operator(); + using binary_op::binary_op; + + template + void operator()(T& lh, T const& rh) const { + lh >>= rh; + } + }; + + struct cmp : public binary_op { + using binary_op::operator(); + using binary_op::binary_op; + + template + void operator()(T& lh, T const& rh) const { + typedef typename SignedCounterpart::type S; + auto& slh = reinterpret_cast(lh); + auto const& srh = reinterpret_cast(rh); + + cpu.of() = ((srh < 0) && (slh > std::numeric_limits::max() + srh)) || ((rh > 0) && (slh < std::numeric_limits::min() + srh)); + cpu.af() = !(lh & 8) && (rh & 8); + cpu.cf() = !(static_cast(std::numeric_limits::min()) & lh) && (static_cast(std::numeric_limits::min()) & rh); + + T result = lh - rh; + + cpu.sf() = static_cast(std::numeric_limits::min()) & result; + cpu.zf() = result == 0; + cpu.pf() = ((result & 1) + (result >> 1 & 1) + (result >> 2 & 1) + (result >> 3 & 1) + (result >> 4 & 1) + (result >> 5 & 1) + (result >> 6 & 1) + (result >> 7 & 1) % 2) + 1; } }; @@ -171,7 +248,7 @@ public: } } - boost::apply_visitor(O(), *dest, src); + boost::apply_visitor(O(cpu), *dest, src); } void handle_I_JMP(_DInst inst) { @@ -200,6 +277,14 @@ public: handle_binary(inst); } + void handle_I_SHR(_DInst inst) { + handle_binary(inst); + } + + void handle_I_CMP(_DInst inst) { + handle_binary(inst); + } + void handle_I_INT(_DInst inst) { _Operand int_op = inst.ops[0]; @@ -232,6 +317,8 @@ public: REGISTER_HANDLER(I_MOV); REGISTER_HANDLER(I_SUB); REGISTER_HANDLER(I_INT); + REGISTER_HANDLER(I_SHR); + REGISTER_HANDLER(I_CMP); #undef REGISTER_HANDLER @@ -243,6 +330,9 @@ public: REGISTER_GETTER(R_AX , ax ); REGISTER_GETTER(R_EAX, eax); REGISTER_GETTER(R_EBX, ebx); + REGISTER_GETTER(R_ECX, ecx); + REGISTER_GETTER(R_ESI, esi); + REGISTER_GETTER(R_EDI, edi); #undef REGISTER_GETTER @@ -307,6 +397,7 @@ void emulate(std::string file_path) { _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; + std::cout << emulator.cpu << std::endl; emulator.handle_instruction(decinst); } -- cgit v1.2.3-70-g09d2