Fix #861: Add Debug registers for x86

This commit is contained in:
Jonathan Salwan 2020-04-01 14:53:09 +02:00
parent ff421129f3
commit c1fe0d2eda
7 changed files with 133 additions and 8 deletions

View file

@ -1 +1 @@
1454
1455

View file

@ -142,6 +142,12 @@ namespace triton {
std::memcpy(this->fs, other.fs, sizeof(this->fs));
std::memcpy(this->gs, other.gs, sizeof(this->gs));
std::memcpy(this->ss, other.ss, sizeof(this->ss));
std::memcpy(this->dr0, other.dr0, sizeof(this->dr0));
std::memcpy(this->dr1, other.dr1, sizeof(this->dr1));
std::memcpy(this->dr2, other.dr2, sizeof(this->dr2));
std::memcpy(this->dr3, other.dr3, sizeof(this->dr3));
std::memcpy(this->dr6, other.dr6, sizeof(this->dr6));
std::memcpy(this->dr7, other.dr7, sizeof(this->dr7));
}
@ -231,6 +237,12 @@ namespace triton {
std::memset(this->fs, 0x00, sizeof(this->fs));
std::memset(this->gs, 0x00, sizeof(this->gs));
std::memset(this->ss, 0x00, sizeof(this->ss));
std::memset(this->dr0, 0x00, sizeof(this->dr0));
std::memset(this->dr1, 0x00, sizeof(this->dr1));
std::memset(this->dr2, 0x00, sizeof(this->dr2));
std::memset(this->dr3, 0x00, sizeof(this->dr3));
std::memset(this->dr6, 0x00, sizeof(this->dr6));
std::memset(this->dr7, 0x00, sizeof(this->dr7));
}
@ -258,6 +270,7 @@ namespace triton {
this->isAVX256(regId) ||
this->isAVX512(regId) ||
this->isControl(regId) ||
this->isDebug(regId) ||
this->isSegment(regId)
);
}
@ -298,6 +311,11 @@ namespace triton {
}
bool x8664Cpu::isDebug(triton::arch::register_e regId) const {
return ((regId >= triton::arch::ID_REG_X86_DR0 && regId <= triton::arch::ID_REG_X86_DR7) ? true : false);
}
bool x8664Cpu::isSegment(triton::arch::register_e regId) const {
return ((regId >= triton::arch::ID_REG_X86_CS && regId <= triton::arch::ID_REG_X86_SS) ? true : false);
}
@ -358,6 +376,10 @@ namespace triton {
else if (this->isControl(regId))
ret.insert(&reg);
/* Add Debug */
else if (this->isDebug(regId))
ret.insert(&reg);
/* Add Segment */
else if (this->isSegment(regId))
ret.insert(&reg);
@ -736,6 +758,13 @@ namespace triton {
case triton::arch::ID_REG_X86_CR14: return (*((triton::uint64*)(this->cr14)));
case triton::arch::ID_REG_X86_CR15: return (*((triton::uint64*)(this->cr15)));
case triton::arch::ID_REG_X86_DR0: return (*((triton::uint64*)(this->dr0)));
case triton::arch::ID_REG_X86_DR1: return (*((triton::uint64*)(this->dr1)));
case triton::arch::ID_REG_X86_DR2: return (*((triton::uint64*)(this->dr2)));
case triton::arch::ID_REG_X86_DR3: return (*((triton::uint64*)(this->dr3)));
case triton::arch::ID_REG_X86_DR6: return (*((triton::uint64*)(this->dr6)));
case triton::arch::ID_REG_X86_DR7: return (*((triton::uint64*)(this->dr7)));
case triton::arch::ID_REG_X86_IE: return (((*((triton::uint64*)(this->mxcsr))) >> 0) & 1);
case triton::arch::ID_REG_X86_DE: return (((*((triton::uint64*)(this->mxcsr))) >> 1) & 1);
case triton::arch::ID_REG_X86_ZE: return (((*((triton::uint64*)(this->mxcsr))) >> 2) & 1);
@ -1182,12 +1211,19 @@ namespace triton {
case triton::arch::ID_REG_X86_CR14: (*((triton::uint64*)(this->cr14))) = value.convert_to<triton::uint64>(); break;
case triton::arch::ID_REG_X86_CR15: (*((triton::uint64*)(this->cr15))) = value.convert_to<triton::uint64>(); break;
case triton::arch::ID_REG_X86_CS: (*((triton::uint64*)(this->cs))) = value.convert_to<triton::uint64>(); break;
case triton::arch::ID_REG_X86_DS: (*((triton::uint64*)(this->ds))) = value.convert_to<triton::uint64>(); break;
case triton::arch::ID_REG_X86_ES: (*((triton::uint64*)(this->es))) = value.convert_to<triton::uint64>(); break;
case triton::arch::ID_REG_X86_FS: (*((triton::uint64*)(this->fs))) = value.convert_to<triton::uint64>(); break;
case triton::arch::ID_REG_X86_GS: (*((triton::uint64*)(this->gs))) = value.convert_to<triton::uint64>(); break;
case triton::arch::ID_REG_X86_SS: (*((triton::uint64*)(this->ss))) = value.convert_to<triton::uint64>(); break;
case triton::arch::ID_REG_X86_DR0: (*((triton::uint64*)(this->dr0))) = value.convert_to<triton::uint64>(); break;
case triton::arch::ID_REG_X86_DR1: (*((triton::uint64*)(this->dr1))) = value.convert_to<triton::uint64>(); break;
case triton::arch::ID_REG_X86_DR2: (*((triton::uint64*)(this->dr2))) = value.convert_to<triton::uint64>(); break;
case triton::arch::ID_REG_X86_DR3: (*((triton::uint64*)(this->dr3))) = value.convert_to<triton::uint64>(); break;
case triton::arch::ID_REG_X86_DR6: (*((triton::uint64*)(this->dr6))) = value.convert_to<triton::uint64>(); break;
case triton::arch::ID_REG_X86_DR7: (*((triton::uint64*)(this->dr7))) = value.convert_to<triton::uint64>(); break;
case triton::arch::ID_REG_X86_CS: (*((triton::uint64*)(this->cs))) = value.convert_to<triton::uint64>(); break;
case triton::arch::ID_REG_X86_DS: (*((triton::uint64*)(this->ds))) = value.convert_to<triton::uint64>(); break;
case triton::arch::ID_REG_X86_ES: (*((triton::uint64*)(this->es))) = value.convert_to<triton::uint64>(); break;
case triton::arch::ID_REG_X86_FS: (*((triton::uint64*)(this->fs))) = value.convert_to<triton::uint64>(); break;
case triton::arch::ID_REG_X86_GS: (*((triton::uint64*)(this->gs))) = value.convert_to<triton::uint64>(); break;
case triton::arch::ID_REG_X86_SS: (*((triton::uint64*)(this->ss))) = value.convert_to<triton::uint64>(); break;
default:
throw triton::exceptions::Cpu("x8664Cpu:setConcreteRegisterValue(): Invalid register.");

View file

@ -110,6 +110,12 @@ namespace triton {
std::memcpy(this->fs, other.fs, sizeof(this->fs));
std::memcpy(this->gs, other.gs, sizeof(this->gs));
std::memcpy(this->ss, other.ss, sizeof(this->ss));
std::memcpy(this->dr0, other.dr0, sizeof(this->dr0));
std::memcpy(this->dr1, other.dr1, sizeof(this->dr1));
std::memcpy(this->dr2, other.dr2, sizeof(this->dr2));
std::memcpy(this->dr3, other.dr3, sizeof(this->dr3));
std::memcpy(this->dr6, other.dr6, sizeof(this->dr6));
std::memcpy(this->dr7, other.dr7, sizeof(this->dr7));
}
@ -167,6 +173,12 @@ namespace triton {
std::memset(this->fs, 0x00, sizeof(this->fs));
std::memset(this->gs, 0x00, sizeof(this->gs));
std::memset(this->ss, 0x00, sizeof(this->ss));
std::memset(this->dr0, 0x00, sizeof(this->dr0));
std::memset(this->dr1, 0x00, sizeof(this->dr1));
std::memset(this->dr2, 0x00, sizeof(this->dr2));
std::memset(this->dr3, 0x00, sizeof(this->dr3));
std::memset(this->dr6, 0x00, sizeof(this->dr6));
std::memset(this->dr7, 0x00, sizeof(this->dr7));
}
@ -193,6 +205,7 @@ namespace triton {
this->isSSE(regId) ||
this->isAVX256(regId) ||
this->isControl(regId) ||
this->isDebug(regId) ||
this->isSegment(regId)
);
}
@ -228,6 +241,11 @@ namespace triton {
}
bool x86Cpu::isDebug(triton::arch::register_e regId) const {
return ((regId >= triton::arch::ID_REG_X86_DR0 && regId <= triton::arch::ID_REG_X86_DR7) ? true : false);
}
bool x86Cpu::isSegment(triton::arch::register_e regId) const {
return ((regId >= triton::arch::ID_REG_X86_CS && regId <= triton::arch::ID_REG_X86_SS) ? true : false);
}
@ -285,6 +303,10 @@ namespace triton {
else if (this->isControl(regId))
ret.insert(&reg);
/* Add Debug */
else if (this->isDebug(regId))
ret.insert(&reg);
/* Add Segment */
else if (this->isSegment(regId))
ret.insert(&reg);
@ -565,6 +587,13 @@ namespace triton {
case triton::arch::ID_REG_X86_CR14: return (*((triton::uint32*)(this->cr14)));
case triton::arch::ID_REG_X86_CR15: return (*((triton::uint32*)(this->cr15)));
case triton::arch::ID_REG_X86_DR0: return (*((triton::uint32*)(this->dr0)));
case triton::arch::ID_REG_X86_DR1: return (*((triton::uint32*)(this->dr1)));
case triton::arch::ID_REG_X86_DR2: return (*((triton::uint32*)(this->dr2)));
case triton::arch::ID_REG_X86_DR3: return (*((triton::uint32*)(this->dr3)));
case triton::arch::ID_REG_X86_DR6: return (*((triton::uint32*)(this->dr6)));
case triton::arch::ID_REG_X86_DR7: return (*((triton::uint32*)(this->dr7)));
case triton::arch::ID_REG_X86_IE: return (((*((triton::uint32*)(this->mxcsr))) >> 0) & 1);
case triton::arch::ID_REG_X86_DE: return (((*((triton::uint32*)(this->mxcsr))) >> 1) & 1);
case triton::arch::ID_REG_X86_ZE: return (((*((triton::uint32*)(this->mxcsr))) >> 2) & 1);
@ -913,6 +942,13 @@ namespace triton {
case triton::arch::ID_REG_X86_CR14: (*((triton::uint32*)(this->cr14))) = value.convert_to<triton::uint32>(); break;
case triton::arch::ID_REG_X86_CR15: (*((triton::uint32*)(this->cr15))) = value.convert_to<triton::uint32>(); break;
case triton::arch::ID_REG_X86_DR0: (*((triton::uint32*)(this->dr0))) = value.convert_to<triton::uint32>(); break;
case triton::arch::ID_REG_X86_DR1: (*((triton::uint32*)(this->dr1))) = value.convert_to<triton::uint32>(); break;
case triton::arch::ID_REG_X86_DR2: (*((triton::uint32*)(this->dr2))) = value.convert_to<triton::uint32>(); break;
case triton::arch::ID_REG_X86_DR3: (*((triton::uint32*)(this->dr3))) = value.convert_to<triton::uint32>(); break;
case triton::arch::ID_REG_X86_DR6: (*((triton::uint32*)(this->dr6))) = value.convert_to<triton::uint32>(); break;
case triton::arch::ID_REG_X86_DR7: (*((triton::uint32*)(this->dr7))) = value.convert_to<triton::uint32>(); break;
case triton::arch::ID_REG_X86_CS: (*((triton::uint32*)(this->cs))) = value.convert_to<triton::uint32>(); break;
case triton::arch::ID_REG_X86_DS: (*((triton::uint32*)(this->ds))) = value.convert_to<triton::uint32>(); break;
case triton::arch::ID_REG_X86_ES: (*((triton::uint32*)(this->es))) = value.convert_to<triton::uint32>(); break;

View file

@ -199,6 +199,14 @@ REG_SPEC(CR13, cr13, QWORD_SIZE_BIT-1, 0, CR13, DWORD_SIZE_BIT-1, 0, CR13, true)
REG_SPEC(CR14, cr14, QWORD_SIZE_BIT-1, 0, CR14, DWORD_SIZE_BIT-1, 0, CR14, true) // cr14
REG_SPEC(CR15, cr15, QWORD_SIZE_BIT-1, 0, CR15, DWORD_SIZE_BIT-1, 0, CR15, true) // cr15
/* Debug */
REG_SPEC(DR0, dr0, QWORD_SIZE_BIT-1, 0, DR0, DWORD_SIZE_BIT-1, 0, DR0, true) // dr0
REG_SPEC(DR1, dr1, QWORD_SIZE_BIT-1, 0, DR1, DWORD_SIZE_BIT-1, 0, DR1, true) // dr1
REG_SPEC(DR2, dr2, QWORD_SIZE_BIT-1, 0, DR2, DWORD_SIZE_BIT-1, 0, DR2, true) // dr2
REG_SPEC(DR3, dr3, QWORD_SIZE_BIT-1, 0, DR3, DWORD_SIZE_BIT-1, 0, DR3, true) // dr3
REG_SPEC(DR6, dr6, QWORD_SIZE_BIT-1, 0, DR6, DWORD_SIZE_BIT-1, 0, DR6, true) // dr6
REG_SPEC(DR7, dr7, QWORD_SIZE_BIT-1, 0, DR7, DWORD_SIZE_BIT-1, 0, DR7, true) // dr7
/* Flags ID used in the Taint and Symbolic Engines */
REG_SPEC_NO_CAPSTONE(AC, ac, 0, 0, AC, 0, 0, AC, true) // ac
REG_SPEC_NO_CAPSTONE(AF, af, 0, 0, AF, 0, 0, AF, true) // af

View file

@ -239,6 +239,18 @@ namespace triton {
triton::uint8 gs[QWORD_SIZE];
//! Concrete value of SS
triton::uint8 ss[QWORD_SIZE];
//! Concrete value of dr0
triton::uint8 dr0[QWORD_SIZE];
//! Condete value of dr1
triton::uint8 dr1[QWORD_SIZE];
//! Condete value of dr2
triton::uint8 dr2[QWORD_SIZE];
//! Condete value of dr3
triton::uint8 dr3[QWORD_SIZE];
//! Condete value of dr6
triton::uint8 dr6[QWORD_SIZE];
//! Condete value of dr7
triton::uint8 dr7[QWORD_SIZE];
public:
//! Constructor.
@ -271,6 +283,9 @@ namespace triton {
//! Returns true if regId is a control (cr) register.
TRITON_EXPORT bool isControl(triton::arch::register_e regId) const;
//! Returns true if regId is a debug (dr) register.
TRITON_EXPORT bool isDebug(triton::arch::register_e regId) const;
//! Returns true if regId is a Segment.
TRITON_EXPORT bool isSegment(triton::arch::register_e regId) const;

View file

@ -175,6 +175,18 @@ namespace triton {
triton::uint8 gs[DWORD_SIZE];
//! Concrete value of SS
triton::uint8 ss[DWORD_SIZE];
//! Concrete value of dr0
triton::uint8 dr0[DWORD_SIZE];
//! Condete value of dr1
triton::uint8 dr1[DWORD_SIZE];
//! Condete value of dr2
triton::uint8 dr2[DWORD_SIZE];
//! Condete value of dr3
triton::uint8 dr3[DWORD_SIZE];
//! Condete value of dr6
triton::uint8 dr6[DWORD_SIZE];
//! Condete value of dr7
triton::uint8 dr7[DWORD_SIZE];
public:
//! Constructor.
@ -204,6 +216,9 @@ namespace triton {
//! Returns true if regId is a control (cr) register.
TRITON_EXPORT bool isControl(triton::arch::register_e regId) const;
//! Returns true if regId is a debug (dr) register.
TRITON_EXPORT bool isDebug(triton::arch::register_e regId) const;
//! Returns true if regId is a Segment.
TRITON_EXPORT bool isSegment(triton::arch::register_e regId) const;

View file

@ -120,7 +120,16 @@ class TestRegisterValues(unittest.TestCase):
self.ctx = TritonContext()
self.ctx.setArchitecture(ARCH.X86_64)
def test_set_concrete_value(self):
def set_concrete_value(self, ctx):
for reg in ctx.getParentRegisters():
i = random.randrange(0, 0xffffffffffffffff) & reg.getBitvector().getMaxValue()
self.assertEqual(ctx.getConcreteRegisterValue(reg), 0)
ctx.setConcreteRegisterValue(reg, i)
self.assertEqual(ctx.getConcreteRegisterValue(reg), i)
ctx.setConcreteRegisterValue(reg, 0)
self.assertEqual(ctx.getConcreteRegisterValue(reg), 0)
def test_set_concrete_value1(self):
"""Check register value modification."""
for reg in (REG.X86_64.AH, REG.X86_64.AL):
# OK
@ -135,6 +144,12 @@ class TestRegisterValues(unittest.TestCase):
with self.assertRaises(Exception):
self.ctx.setConcreteRegisterValue(reg, 2)
def test_set_concrete_value2(self):
ctx1 = TritonContext(ARCH.X86_64)
ctx2 = TritonContext(ARCH.X86)
self.set_concrete_value(ctx1)
self.set_concrete_value(ctx2)
def test_overlap(self):
"""Check register overlapping."""
self.assertTrue(self.ctx.registers.ax.isOverlapWith(self.ctx.registers.eax), "overlap with upper")