summaryrefslogtreecommitdiff
path: root/emulate
diff options
context:
space:
mode:
Diffstat (limited to 'emulate')
-rw-r--r--emulate/cpustate.hpp34
-rw-r--r--emulate/emulator.hpp97
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 <iostream>
#include <array>
#include <bitset>
+#include <iomanip>
#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 <fstream>
#include <iomanip>
+#include <limits>
+
+template <typename T>
+ struct SignedCounterpart {};
+
+ template <>
+ struct SignedCounterpart<uint32_t> {
+ typedef int32_t type;
+ };
+
+ template <>
+ struct SignedCounterpart<uint16_t> {
+ typedef int16_t type;
+ };
+
+ template <>
+ struct SignedCounterpart<uint8_t> {
+ typedef int8_t type;
+};
class Emulator {
public:
@@ -70,7 +89,18 @@ public:
};
template <typename Ret>
- struct binary_op : public boost::static_visitor<Ret> {
+ struct op : public boost::static_visitor<Ret> {
+ CpuState& cpu;
+
+ op(CpuState& cpu)
+ : cpu(cpu)
+ {}
+ };
+
+ template <typename Ret>
+ struct binary_op : public op<Ret> {
+ using op<Ret>::op;
+
template <typename T, typename U>
Ret operator()(T&, U const&) const {
throw IncompatibleArguments();
@@ -79,6 +109,7 @@ public:
struct and_ : public binary_op<void> {
using binary_op::operator();
+ using binary_op<void>::binary_op;
template<typename T>
void operator()(T& lh, T const& rh) const {
@@ -88,6 +119,7 @@ public:
struct mov : public binary_op<void> {
using binary_op::operator();
+ using binary_op<void>::binary_op;
template<typename T>
void operator()(T& lh, T const& rh) const {
@@ -95,12 +127,57 @@ public:
}
};
- struct sub : public binary_op<void> {
+ struct sub : public binary_op<void> {
using binary_op::operator();
+ using binary_op<void>::binary_op;
template<typename T>
void operator()(T& lh, T const& rh) const {
+ typedef typename SignedCounterpart<T>::type S;
+ auto& slh = reinterpret_cast<S&>(lh);
+ auto const& srh = reinterpret_cast<S const&>(rh);
+
+ cpu.of() = ((srh < 0) && (slh > std::numeric_limits<S>::max() + srh)) || ((rh > 0) && (slh < std::numeric_limits<S>::min() + srh));
+ cpu.af() = !(lh & 8) && (rh & 8);
+ cpu.cf() = !(static_cast<T>(std::numeric_limits<S>::min()) & lh) && (static_cast<T>(std::numeric_limits<S>::min()) & rh);
+
lh -= rh;
+
+ cpu.sf() = static_cast<T>(std::numeric_limits<S>::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<void> {
+ using binary_op::operator();
+ using binary_op<void>::binary_op;
+
+ template <typename T>
+ void operator()(T& lh, T const& rh) const {
+ lh >>= rh;
+ }
+ };
+
+ struct cmp : public binary_op<void> {
+ using binary_op::operator();
+ using binary_op<void>::binary_op;
+
+ template<typename T>
+ void operator()(T& lh, T const& rh) const {
+ typedef typename SignedCounterpart<T>::type S;
+ auto& slh = reinterpret_cast<S&>(lh);
+ auto const& srh = reinterpret_cast<S const&>(rh);
+
+ cpu.of() = ((srh < 0) && (slh > std::numeric_limits<S>::max() + srh)) || ((rh > 0) && (slh < std::numeric_limits<S>::min() + srh));
+ cpu.af() = !(lh & 8) && (rh & 8);
+ cpu.cf() = !(static_cast<T>(std::numeric_limits<S>::min()) & lh) && (static_cast<T>(std::numeric_limits<S>::min()) & rh);
+
+ T result = lh - rh;
+
+ cpu.sf() = static_cast<T>(std::numeric_limits<S>::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<sub>(inst);
}
+ void handle_I_SHR(_DInst inst) {
+ handle_binary<shr>(inst);
+ }
+
+ void handle_I_CMP(_DInst inst) {
+ handle_binary<cmp>(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);
}