Skip to content

Commit

Permalink
Added DF_FILL_EFLAGS feature
Browse files Browse the repository at this point in the history
  • Loading branch information
gdabah committed Apr 21, 2020
1 parent 5f0e70c commit 589ecbb
Show file tree
Hide file tree
Showing 9 changed files with 107 additions and 40 deletions.
8 changes: 1 addition & 7 deletions examples/tests/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,7 @@ int main(int argc, char **argv)

unsigned char rawData[] = {

0x68, 0, 0, 0, 0,
0x9b,
0xdf, 0xe0,
0x66, 0xa1, 0xcc, 0xb0, 0x97, 0x7c,
0xC7, 0xC1, 0x08, 0x00, 0x00, 0x00,
0xc7, 0xf8, 0xaa, 0xaa, 0xaa, 0xaa,
0x48, 0xC7, 0xC0, 0x00, 0x00, 0x00, 0x00
0x33, 0xc0
} ;
res = distorm_decode(offset, (const unsigned char*)rawData, sizeof(rawData), Decode64Bits, decodedInstructions, MAX_INSTRUCTIONS, &decodedInstructionsCount);
for (int i = 0; i < decodedInstructionsCount; i++) {
Expand Down
6 changes: 3 additions & 3 deletions examples/tests/tests.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -14,21 +14,21 @@
<ProjectGuid>{C35D3921-227A-432A-BB5D-90ECEBAB08B2}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>tests</RootNamespace>
<WindowsTargetPlatformVersion>10.0.17763.0</WindowsTargetPlatformVersion>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>v141</PlatformToolset>
<PlatformToolset>v142</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
<PlatformToolset>v141</PlatformToolset>
<PlatformToolset>v142</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
Expand Down
4 changes: 4 additions & 0 deletions examples/win32/disasm.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -27,18 +27,22 @@
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v142</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v142</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v142</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<CharacterSet>MultiByte</CharacterSet>
<PlatformToolset>v142</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
Expand Down
5 changes: 3 additions & 2 deletions include/distorm.h
Original file line number Diff line number Diff line change
Expand Up @@ -252,7 +252,7 @@ typedef struct {
uint8_t dispSize;
/* Meta defines the instruction set class, and the flow control flags. Use META macros. */
uint16_t meta;
/* The CPU flags that the instruction operates upon. */
/* The CPU flags that the instruction operates upon, set only with DF_FILL_EFLAGS enabled, otherwise 0. */
uint16_t modifiedFlagsMask, testedFlagsMask, undefinedFlagsMask;
} _DInst;

Expand Down Expand Up @@ -390,7 +390,8 @@ typedef struct {
#define DF_STOP_ON_PRIVILEGED 0x800
/* The decoder will not synchronize to the next byte after the previosuly decoded instruction, instead it will start decoding at the next byte. */
#define DF_SINGLE_BYTE_STEP 0x1000

/* The decoder will fill in the eflags fields for the decoded instruction. */
#define DF_FILL_EFLAGS 0x2000
/* The decoder will stop and return to the caller when any flow control instruction was decoded. */
#define DF_STOP_ON_FLOW_CONTROL (DF_STOP_ON_CALL | DF_STOP_ON_RET | DF_STOP_ON_SYS | DF_STOP_ON_UNC_BRANCH | DF_STOP_ON_CND_BRANCH | DF_STOP_ON_INT | DF_STOP_ON_CMOV | DF_STOP_ON_HLT)

Expand Down
14 changes: 5 additions & 9 deletions make/win32/cdistorm.vcxproj
Original file line number Diff line number Diff line change
Expand Up @@ -23,34 +23,34 @@
<ProjectGuid>{15051CE1-AB10-4239-973D-01B84F2AD0A9}</ProjectGuid>
<RootNamespace>distorm</RootNamespace>
<Keyword>Win32Proj</Keyword>
<WindowsTargetPlatformVersion>10.0.17763.0</WindowsTargetPlatformVersion>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='dll|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseOfAtl>false</UseOfAtl>
<CharacterSet>NotSet</CharacterSet>
<UseOfMfc>false</UseOfMfc>
<PlatformToolset>v141</PlatformToolset>
<PlatformToolset>v142</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='clib|Win32'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseOfAtl>false</UseOfAtl>
<CharacterSet>NotSet</CharacterSet>
<PlatformToolset>v141</PlatformToolset>
<PlatformToolset>v142</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='dll|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseOfAtl>false</UseOfAtl>
<CharacterSet>NotSet</CharacterSet>
<UseOfMfc>false</UseOfMfc>
<PlatformToolset>v141</PlatformToolset>
<PlatformToolset>v142</PlatformToolset>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='clib|x64'" Label="Configuration">
<ConfigurationType>StaticLibrary</ConfigurationType>
<UseOfAtl>false</UseOfAtl>
<CharacterSet>NotSet</CharacterSet>
<PlatformToolset>v141</PlatformToolset>
<PlatformToolset>v142</PlatformToolset>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
Expand Down Expand Up @@ -109,7 +109,6 @@
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;NDEBUG;DISTORM_STATIC;SUPPORT_64BIT_OFFSET;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling>
<MinimalRebuild>true</MinimalRebuild>
<ExceptionHandling>false</ExceptionHandling>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<FunctionLevelLinking>true</FunctionLevelLinking>
Expand Down Expand Up @@ -138,7 +137,6 @@
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;NDEBUG;DISTORM_STATIC;SUPPORT_64BIT_OFFSET;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling>
<MinimalRebuild>true</MinimalRebuild>
<ExceptionHandling>false</ExceptionHandling>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<FunctionLevelLinking>true</FunctionLevelLinking>
Expand All @@ -164,7 +162,6 @@
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;NDEBUG;DISTORM_DYNAMIC;SUPPORT_64BIT_OFFSET;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling>
<MinimalRebuild>true</MinimalRebuild>
<ExceptionHandling>false</ExceptionHandling>
<FunctionLevelLinking>true</FunctionLevelLinking>
<PrecompiledHeader>
Expand Down Expand Up @@ -193,7 +190,6 @@
<AdditionalIncludeDirectories>%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;NDEBUG;DISTORM_DYNAMIC;SUPPORT_64BIT_OFFSET;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling>
<MinimalRebuild>true</MinimalRebuild>
<ExceptionHandling>false</ExceptionHandling>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<FunctionLevelLinking>true</FunctionLevelLinking>
Expand Down
23 changes: 19 additions & 4 deletions python/distorm3/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ class _DInst (Structure):
('addr', _OffsetType),
('flags', c_uint16), # -1 if invalid. See C headers for more info
('unusedPrefixesMask', c_uint16),
('usedRegistersMask', c_uint32), # used registers mask.
('usedRegistersMask', c_uint32), # used registers mask
('opcode', c_uint16), # look up in opcode table
('ops', _Operand*4),
('size', c_ubyte),
Expand All @@ -171,9 +171,9 @@ class _DInst (Structure):
('scale', c_ubyte), # ignore for values 0, 1 (other valid values - 2,4,8)
('dispSize', c_ubyte),
('meta', c_uint16), # meta flags - instruction set class, etc. See C headers again...
('modifiedFlagsMask', c_uint16), # CPU modified (output) flags by instruction.
('testedFlagsMask', c_uint16), # CPU tested (input) flags by instruction.
('undefinedFlagsMask', c_uint16) # CPU undefined flags by instruction.
('modifiedFlagsMask', c_uint16), # CPU modified (output) flags by instruction only set with DF_FILL_EFLAGS
('testedFlagsMask', c_uint16), # CPU tested (input) flags by instruction only set with DF_FILL_EFLAGS
('undefinedFlagsMask', c_uint16) # CPU undefined flags by instruction only set with DF_FILL_EFLAGS
]

#==============================================================================
Expand Down Expand Up @@ -206,6 +206,16 @@ class _DInst (Structure):
"FLAG_RIP_RELATIVE"
]

# CPU flags that instructions modify, test or undefine (are EFLAGS compatible!).
D_CF = 1 # Carry #
D_PF = 4 # Parity #
D_AF = 0x10 # Auxiliary #
D_ZF = 0x40 # Zero #
D_SF = 0x80 # Sign #
D_IF = 0x200 # Interrupt #
D_DF = 0x400 # Direction #
D_OF = 0x800 # Overflow #

# Instruction could not be disassembled. Special-case handling
FLAG_NOT_DECODABLE = 0xFFFF # -1 in uint16
# Some features
Expand All @@ -224,6 +234,7 @@ class _DInst (Structure):
DF_STOP_ON_HLT = 0x400
DF_STOP_ON_PRIVILEGED = 0x800
DF_SINGLE_BYTE_STEP = 0x1000
DF_FILL_EFLAGS = 0x2000
DF_STOP_ON_FLOW_CONTROL = (DF_STOP_ON_CALL | DF_STOP_ON_RET | DF_STOP_ON_SYS | \
DF_STOP_ON_UNC_BRANCH | DF_STOP_ON_CND_BRANCH | DF_STOP_ON_INT | DF_STOP_ON_CMOV | \
DF_STOP_ON_HLT)
Expand Down Expand Up @@ -575,6 +586,10 @@ def __init__(self, di, instructionBytes, dt):
self.meta = di.meta
self.instructionClass = _getISC(metas)
self.flowControl = _getFC(metas)
# copy eflags
self.modifiedFlags = di.modifiedFlagsMask
self.undefinedFlags = di.undefinedFlagsMask
self.testedFlags = di.testedFlagsMask

def _extractOperand(self, di, operand):
# a single operand can be up to: reg1 + reg2*scale + constant
Expand Down
62 changes: 55 additions & 7 deletions python/test_distorm3.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,14 +54,14 @@ def test_dummy(self):
self.fail("dummy")

class InstBin(Test):
def __init__(self, bin, mode, features):
def __init__(self, bin, mode, features, address):
Test.__init__(self)
try:
bin = bin.decode("hex")
except:
bin = bytes.fromhex(bin)
#fbin[mode].write(bin)
self.insts = distorm3.Decompose(0, bin, mode, features)
self.insts = distorm3.Decompose(address, bin, mode, features)
self.inst = self.insts[0]
def check_valid(self, instsNo = 1):
self.assertNotEqual(self.inst.rawFlags, 65535)
Expand Down Expand Up @@ -141,14 +141,14 @@ def I16(instText, instNo = 0, features = 0):
def I32(instText, features = 0):
return Inst(instText, distorm3.Decode32Bits, 0, features)

def IB32(bin, features = 0):
return InstBin(bin, distorm3.Decode32Bits, features)
def IB32(bin, features = 0, address = 0):
return InstBin(bin, distorm3.Decode32Bits, features, address)

def I64(instText, features = 0):
return Inst(instText, distorm3.Decode64Bits, 0, features)

def IB64(bin, features = 0):
return InstBin(bin, distorm3.Decode64Bits, features)
def IB64(bin, features = 0, address = 0):
return InstBin(bin, distorm3.Decode64Bits, features, address)

def ABS64(x):
return x
Expand Down Expand Up @@ -1607,6 +1607,19 @@ def test_drop_prefixes(self):
def test_zzz_must_be_last_drop_prefixes(self):
# Drop prefixes when the last byte in stream is a prefix.
IB32("66")
def test_undefined_byte00(self):
# This is a regression test for the decomposer wrapper
a = ""
insts = IB32("c300").insts
for i in insts:
a += str(i)
insts = IB32("33c0" * 2000 + "90", 0, 0x4000).insts
self.assertEqual(insts[-1].mnemonic, "NOP")
self.assertEqual(insts[-1].instructionBytes, b"\x90")
self.assertEqual(insts[-1].address, 0x4000 + 2000 * 2)
self.assertEqual(insts[1000].mnemonic, "XOR")
self.assertEqual(insts[1000].instructionBytes, b"\x33\xc0")
self.assertEqual(insts[1000].address, 0x4000 + 1000 * 2)

class TestFeatures(unittest.TestCase):
def test_addr16(self):
Expand Down Expand Up @@ -1637,7 +1650,14 @@ def test_fc(self):
a = I32("nop\nxor eax, eax\n" + j + "\ninc eax", distorm3.DF_RETURN_FC_ONLY | distorm3.DF_STOP_ON_FLOW_CONTROL)
self.assertEqual(len(a.insts), 1)
def test_filter(self):
pass
a = IB32("33c0907e00" * 5, distorm3.DF_RETURN_FC_ONLY).insts
self.assertEqual(len(a), 5)
self.assertEqual(a[0].mnemonic[0], "J")
self.assertEqual(a[0].address, 3)
self.assertEqual(a[1].address, 8)
self.assertEqual(a[2].address, 13)
self.assertEqual(a[3].address, 18)
self.assertEqual(a[4].address, 23)
def test_stop_on_privileged(self):
a = I32("nop\niret\nret", distorm3.DF_STOP_ON_PRIVILEGED)
self.assertEqual(len(a.insts), 2)
Expand All @@ -1663,6 +1683,34 @@ def test_step_byte(self):
self.assertEqual(a[5].address, 5)
self.assertEqual(a[5].mnemonic, "DEC")
self.assertEqual(a[5].size, 1)
def test_eflags_on(self):
a = IB32("33c04890", distorm3.DF_FILL_EFLAGS).insts
# XOR
self.assertEqual(a[0].modifiedFlags, distorm3.D_SF | distorm3.D_ZF | distorm3.D_PF)
self.assertEqual(a[0].testedFlags, 0)
self.assertEqual(a[0].undefinedFlags, distorm3.D_AF)
# INC
self.assertEqual(a[1].modifiedFlags, distorm3.D_OF | distorm3.D_SF | distorm3.D_ZF | distorm3.D_AF | distorm3.D_PF)
self.assertEqual(a[1].testedFlags, 0)
self.assertEqual(a[1].undefinedFlags, 0)
# NOP
self.assertEqual(a[2].modifiedFlags, 0)
self.assertEqual(a[2].testedFlags, 0)
self.assertEqual(a[2].undefinedFlags, 0)
def test_eflags_off(self):
a = IB32("33c04890").insts
# XOR
self.assertEqual(a[0].modifiedFlags, 0)
self.assertEqual(a[0].testedFlags, 0)
self.assertEqual(a[0].undefinedFlags, 0)
# INC
self.assertEqual(a[1].modifiedFlags, 0)
self.assertEqual(a[1].testedFlags, 0)
self.assertEqual(a[1].undefinedFlags, 0)
# NOP
self.assertEqual(a[2].modifiedFlags, 0)
self.assertEqual(a[2].testedFlags, 0)
self.assertEqual(a[2].undefinedFlags, 0)

def GetNewSuite(className):
suite = unittest.TestSuite()
Expand Down
23 changes: 16 additions & 7 deletions src/decoder.c
Original file line number Diff line number Diff line change
Expand Up @@ -66,11 +66,17 @@ static _DecodeType decode_get_effective_op_size(_DecodeType dt, _iflags decodedP
return dt;
}

/* A helper macro to convert from diStorm's CPU flags to EFLAGS. */
/*
* A helper macro to convert from diStorm's CPU flags to EFLAGS.
* Copy eflags from compact version (8 bits) to eflags compatible (16 bits).
* From D_COMPACT_IF to D_IF, bit index 1 to 9.
* From D_COMPACT_DF to D_DF, bit index 3 to 10.
* From D_COMPACT_OF to D_OF, bit index 5 to 11.
*/
#define CONVERT_FLAGS_TO_EFLAGS(dst, src, field) dst->field = ((src->field & D_COMPACT_SAME_FLAGS) | \
((src->field & D_COMPACT_IF) ? D_IF : 0) | \
((src->field & D_COMPACT_DF) ? D_DF : 0) | \
((src->field & D_COMPACT_OF) ? D_OF : 0));
((src->field & D_COMPACT_IF) << (9 - 1)) | \
((src->field & D_COMPACT_DF) << (10 - 3)) | \
((src->field & D_COMPACT_OF) << (11 - 5)));

static _DecodeResult decode_inst(_CodeInfo* ci, _PrefixState* ps, _DInst* di)
{
Expand Down Expand Up @@ -377,9 +383,11 @@ static _DecodeResult decode_inst(_CodeInfo* ci, _PrefixState* ps, _DInst* di)
if (di->base != R_NONE) di->usedRegistersMask |= _REGISTERTORCLASS[di->base];

/* Copy CPU affected flags. */
CONVERT_FLAGS_TO_EFLAGS(di, isi, modifiedFlagsMask);
CONVERT_FLAGS_TO_EFLAGS(di, isi, testedFlagsMask);
CONVERT_FLAGS_TO_EFLAGS(di, isi, undefinedFlagsMask);
if (ci->features & DF_FILL_EFLAGS) {
if (isi->modifiedFlagsMask) CONVERT_FLAGS_TO_EFLAGS(di, isi, modifiedFlagsMask);
if (isi->testedFlagsMask) CONVERT_FLAGS_TO_EFLAGS(di, isi, testedFlagsMask);
if (isi->undefinedFlagsMask) CONVERT_FLAGS_TO_EFLAGS(di, isi, undefinedFlagsMask);
}

/* Calculate the size of the instruction we've just decoded. */
di->size = (uint8_t)((ci->code - startCode) & 0xff);
Expand Down Expand Up @@ -456,6 +464,7 @@ _DecodeResult decode_internal(_CodeInfo* _ci, int supportOldIntr, _DInst result[
/* No entries are used yet. */
*usedInstructionsCount = 0;
ci.dt = _ci->dt;
ci.features = _ci->features;
_ci->nextOffset = codeOffset;

/* Decode instructions as long as we have what to decode/enough room in entries. */
Expand Down
2 changes: 1 addition & 1 deletion src/insts.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ This library is licensed under the BSD license. See the file COPYING.


/*
* GENERATED BY disOps at Tue Apr 21 15:58:20 2020
* GENERATED BY disOps at Tue Apr 21 19:11:41 2020
*/

_InstInfo II_MOVSXD = /*II*/ {0x1d4, 10027};
Expand Down

0 comments on commit 589ecbb

Please sign in to comment.