diff --git a/CMakeLists.txt b/CMakeLists.txt index 2f454c4..f859feb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -10,7 +10,10 @@ project(Zydis VERSION 2.0) # Features option(ZYDIS_FEATURE_DECODER - "Enable instruction decoding and formtting functionality" + "Enable instruction decoding functionality" + ON) +option(ZYDIS_FEATURE_FORMATTER + "Enable instruction formatting functionality" ON) #option(ZYDIS_FEATURE_ENCODER # "Enable instruction encoding functionality" @@ -80,24 +83,18 @@ if (NOT ZYDIS_FEATURE_ENCODER AND NOT ZYDIS_FEATURE_DECODER) ) endif () -if (ZYDIS_FEATURE_EVEX) - target_compile_definitions("Zydis" PUBLIC "ZYDIS_ENABLE_FEATURE_EVEX") +if (NOT ZYDIS_FEATURE_DECODER) + target_compile_definitions("Zydis" PUBLIC "ZYDIS_DISABLE_DECODER") endif () -if (ZYDIS_FEATURE_MVEX) - target_compile_definitions("Zydis" PUBLIC "ZYDIS_ENABLE_FEATURE_MVEX") +if (NOT ZYDIS_FEATURE_FORMATTER) + target_compile_definitions("Zydis" PUBLIC "ZYDIS_DISABLE_FORMATTER") endif () -if (ZYDIS_FEATURE_FLAGS) - target_compile_definitions("Zydis" PUBLIC "ZYDIS_ENABLE_FEATURE_FLAGS") +if (NOT ZYDIS_FEATURE_EVEX) + target_compile_definitions("Zydis" PUBLIC "ZYDIS_DISABLE_EVEX") endif () -if (ZYDIS_FEATURE_CPUID) - target_compile_definitions("Zydis" PUBLIC "ZYDIS_ENABLE_FEATURE_CPUID") +if (NOT ZYDIS_FEATURE_MVEX) + target_compile_definitions("Zydis" PUBLIC "ZYDIS_DISABLE_MVEX") endif () -if (ZYDIS_FEATURE_DECODER) - target_compile_definitions("Zydis" PUBLIC "ZYDIS_ENABLE_FEATURE_DECODER") -endif () -#if (ZYDIS_FEATURE_ENCODER) -# target_compile_definitions("Zydis" PUBLIC "ZYDIS_ENABLE_FEATURE_ENCODER") -#endif () target_sources("Zydis" PUBLIC @@ -134,16 +131,6 @@ if (ZYDIS_FEATURE_DECODER) "src/FormatHelper.c") endif () -#if (ZYDIS_FEATURE_ENCODER) -# target_sources("Zydis" -# PUBLIC -# "${CMAKE_CURRENT_LIST_DIR}/include/Zydis/Encoder.h" -# PRIVATE -# "src/EncoderData.h" -# "src/Encoder.c" -# "src/EncoderData.c") -#endif () - if (BUILD_SHARED_LIBS AND WIN32) target_sources("Zydis" PRIVATE "src/VersionInfo.rc") endif () diff --git a/README.md b/README.md index 2622719..95ddeb9 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ -# Zyan Disassembler Engine (Zydis) -[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT) [![Gitter](https://badges.gitter.im/zyantific/zyan-disassembler-engine.svg)](https://gitter.im/zyantific/zyan-disassembler-engine?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=body_badge) +![zydis logo](https://mainframe.pw/u/P94JAqY9XSDdPedv.svg?x) +[![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://opensource.org/licenses/MIT) [![Gitter](https://badges.gitter.im/zyantific/zyan-disassembler-engine.svg)](https://gitter.im/zyantific/zyan-disassembler-engine?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=body_badge) [![Build status](https://ci.appveyor.com/api/projects/status/2tad27q0b9v6qtga/branch/master?svg=true)](https://ci.appveyor.com/project/athre0z/zydis/branch/master) Fast and lightweight x86/x86-64 disassembler library. @@ -116,6 +116,7 @@ make - Intel (for open-sourcing XED, allowing for automatic comparision of our tables against theirs, improving both) - LLVM (for providing pretty solid instruction data as well) - Christian Ludloff (http://sandpile.org, insanely helpful) +- [LekoArts](https://www.lekoarts.de/) (for creating the project logo) - Our [contributors on GitHub](https://github.com/zyantific/zydis/graphs/contributors) ## License diff --git a/assets/PinTestTool/ZydisTestTool.cpp b/assets/PinTestTool/ZydisTestTool.cpp deleted file mode 100755 index 07fc9b9..0000000 --- a/assets/PinTestTool/ZydisTestTool.cpp +++ /dev/null @@ -1,286 +0,0 @@ -/** - * - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include "pin.H" -#include "xed-interface.h" - -#include -#include -#include -#include -#include - -/* ========================================================================== */ -/* TLS struct */ -/* ========================================================================== */ - -struct ThreadData -{ - CONTEXT ctx; - ZydisInstructionDecoder decoder; - - ThreadData() - { - ZydisDecoderInitInstructionDecoderEx( - &decoder, ZYDIS_DISASSEMBLER_MODE_64BIT, NULL, 0 - ); - } -}; - -/* ========================================================================== */ -/* Global variables */ -/* ========================================================================== */ - -TLS_KEY tls_key; -std::ostream* out = &cerr; - -PIN_LOCK unique_iforms_lock; -std::set unique_iforms; - -/* ========================================================================== */ -/* Tables */ -/* ========================================================================== */ - -struct RegMapping -{ - REG pin; - ZydisRegister zy; -}; - -RegMapping reg_mapping[] = { - // 64-bit GP register - {REG_RAX, ZYDIS_REGISTER_RAX}, - {REG_RBX, ZYDIS_REGISTER_RBX}, - {REG_RCX, ZYDIS_REGISTER_RCX}, - {REG_RDX, ZYDIS_REGISTER_RDX}, - {REG_RSP, ZYDIS_REGISTER_RSP}, - {REG_RBP, ZYDIS_REGISTER_RBP}, - {REG_RSI, ZYDIS_REGISTER_RSI}, - {REG_RDI, ZYDIS_REGISTER_RDI}, - {REG_R8, ZYDIS_REGISTER_R8 }, - {REG_R9, ZYDIS_REGISTER_R9 }, - {REG_R10, ZYDIS_REGISTER_R10}, - {REG_R11, ZYDIS_REGISTER_R11}, - {REG_R12, ZYDIS_REGISTER_R12}, - {REG_R13, ZYDIS_REGISTER_R13}, - {REG_R14, ZYDIS_REGISTER_R14}, - {REG_R15, ZYDIS_REGISTER_R15}, - - // Segment registers - {REG_SEG_ES, ZYDIS_REGISTER_ES}, - {REG_SEG_SS, ZYDIS_REGISTER_SS}, - {REG_SEG_SS, ZYDIS_REGISTER_SS}, - {REG_SEG_CS, ZYDIS_REGISTER_CS}, - {REG_SEG_DS, ZYDIS_REGISTER_DS}, - {REG_SEG_FS, ZYDIS_REGISTER_FS}, - {REG_SEG_GS, ZYDIS_REGISTER_GS}, - - // Mask registers - {REG_K0, ZYDIS_REGISTER_K0}, - {REG_K1, ZYDIS_REGISTER_K1}, - {REG_K2, ZYDIS_REGISTER_K2}, - {REG_K3, ZYDIS_REGISTER_K3}, - {REG_K4, ZYDIS_REGISTER_K4}, - {REG_K5, ZYDIS_REGISTER_K5}, - {REG_K6, ZYDIS_REGISTER_K6}, - {REG_K7, ZYDIS_REGISTER_K7}, - - // TODO: XMM, YMM, ZMM, ST, TR - - // Special registers - {REG_MXCSR, ZYDIS_REGISTER_MXCSR}, -}; - -/* ========================================================================== */ -/* Command line switches */ -/* ========================================================================== */ - -KNOB knob_out_file( - KNOB_MODE_WRITEONCE, "pintool", "o", "", "Output file name" -); - -KNOB know_unique_iform( - KNOB_MODE_WRITEONCE, "pintool", "unique_iform", "0", - "Only instrument one instruction per iform" -); - -KNOB omit_op_checks( - KNOB_MODE_WRITEONCE, "pintool", "omit_op_checks", "0", - "Skip verification of operand write assumptions" -); - -KNOB omit_flag_checks( - KNOB_MODE_WRITEONCE, "pintool", "omit_flag_checks", "1", - "Skip verification of flag write assumptions" -); - -/* ========================================================================== */ -/* Instrumentation callbacks */ -/* ========================================================================== */ - -VOID PIN_FAST_ANALYSIS_CALL pre_ins_cb(THREADID tid, const CONTEXT* ctx) -{ - ThreadData *tls = static_cast(PIN_GetThreadData(tls_key, tid)); - PIN_SaveContext(ctx, &tls->ctx); -} - -VOID PIN_FAST_ANALYSIS_CALL post_ins_cb(THREADID tid, const CONTEXT* post_ctx) -{ - ThreadData *tls = static_cast(PIN_GetThreadData(tls_key, tid)); - - // Get IPs. - ADDRINT pre_ip = PIN_GetContextReg(&tls->ctx, REG_INST_PTR); - ADDRINT post_ip = PIN_GetContextReg(post_ctx, REG_INST_PTR); - - // If the IP didn't change, we're probably dealing with a rep. - // Skip instruction until last execution where fallthrough kicks in. - ADDRINT ip_diff = post_ip - pre_ip; - if (!ip_diff) return; - - // Disassemble previously executed instruction. - ZydisMemoryInput input; - ZydisInputInitMemoryInput(&input, (void*)pre_ip, 15); - ZydisDecoderSetInput(&tls->decoder, (ZydisCustomInput*)&input); - - ZydisInstructionInfo insn_info; - ZydisStatus decode_status = ZydisDecoderDecodeNextInstruction( - &tls->decoder, &insn_info - ); - - // Can we decode it? - if (!ZYDIS_SUCCESS(decode_status)) { - *out << "Decoding failure" << endl; - goto error; - } - - // Does the length look like what we expected? - if (insn_info.length != ip_diff) { - *out << "Instruction length mismatch (expected " - << dec << ip_diff << ", got " << (int)insn_info.length - << ')' << endl; - goto error; - } - - // Analyze operand effects. - if (!omit_op_checks) { - for (const RegMapping* map = reg_mapping - ; map < reg_mapping + sizeof reg_mapping / sizeof reg_mapping[0] - ; ++map) { - - ADDRINT pre_reg_val = PIN_GetContextReg(&tls->ctx, map->pin); - ADDRINT post_reg_val = PIN_GetContextReg(post_ctx, map->pin); - - // Did the instruction touch this register? - if (pre_reg_val != post_reg_val) { - *out << "Reg value changed (" - << ZydisRegisterGetString(map->zy) - << ")!" << endl; - } - } - } - - // Analyze flag effects. - if (!omit_flag_checks) { - ADDRINT prev_flags = PIN_GetContextReg(&tls->ctx, REG_GFLAGS); - ADDRINT new_flags = PIN_GetContextReg(post_ctx, REG_GFLAGS); - ADDRINT changed_flags = prev_flags ^ new_flags; - if (changed_flags) { - // TODO: implement once flag infos are available. - } - } - - return; - -error: - // Always print raw bytes on error. - *out << "Raw bytes: "; - for (size_t i = 0; i < 15; ++i) { - *out << setfill('0') << setw(2) << hex - << (int)((uint8_t*)pre_ip)[i] << ' '; - } - *out << endl; -} - -VOID instruction(INS ins, VOID *v) -{ - if (!INS_HasFallThrough(ins)) return; - - xed_decoded_inst_t* xed = INS_XedDec(ins); - xed_iform_enum_t iform = xed_decoded_inst_get_iform_enum(xed); - - if (know_unique_iform.Value()) { - PIN_GetLock(&unique_iforms_lock, 0); - if (unique_iforms.find(iform) != unique_iforms.end()) { - PIN_ReleaseLock(&unique_iforms_lock); - return; - } - unique_iforms.insert(iform); - *out << iform << endl; - PIN_ReleaseLock(&unique_iforms_lock); - } - - INS_InsertCall( - ins, IPOINT_BEFORE, (AFUNPTR)&pre_ins_cb, - IARG_FAST_ANALYSIS_CALL, IARG_THREAD_ID, IARG_CONST_CONTEXT, - IARG_END - ); - INS_InsertCall( - ins, IPOINT_AFTER, (AFUNPTR)&post_ins_cb, - IARG_FAST_ANALYSIS_CALL, IARG_THREAD_ID, IARG_CONST_CONTEXT, - IARG_END - ); -} - -VOID thread_start(THREADID tid, CONTEXT *ctx, INT32 flags, VOID* v) -{ - ThreadData* tls = new ThreadData; - PIN_SetThreadData(tls_key, tls, tid); -} - -int main(int argc, char *argv[]) -{ - if (PIN_Init(argc, argv)) { - cerr << KNOB_BASE::StringKnobSummary() << endl; - return 1; - } - - // Open output file. - string file_name = knob_out_file.Value(); - if (!file_name.empty()) { - out = new std::ofstream(file_name.c_str()); - } - - // Init TLS. - tls_key = PIN_CreateThreadDataKey(0); - PIN_InitLock(&unique_iforms_lock); - - // Register hooks. - PIN_AddThreadStartFunction(&thread_start, NULL); - INS_AddInstrumentFunction(&instruction, NULL); - - // Start the program, never returns. - PIN_StartProgram(); - - return 0; -} - -/* ========================================================================== */ diff --git a/assets/PinTestTool/makefile b/assets/PinTestTool/makefile deleted file mode 100644 index da26698..0000000 --- a/assets/PinTestTool/makefile +++ /dev/null @@ -1,21 +0,0 @@ -############################################################## -# -# DO NOT EDIT THIS FILE! -# -############################################################## - -# If the tool is built out of the kit, PIN_ROOT must be specified in the make invocation and point to the kit root. -ifdef PIN_ROOT -CONFIG_ROOT := $(PIN_ROOT)/source/tools/Config -else -CONFIG_ROOT := ../Config -endif -include $(CONFIG_ROOT)/makefile.config -include makefile.rules -include $(TOOLS_ROOT)/Config/makefile.default.rules - -############################################################## -# -# DO NOT EDIT THIS FILE! -# -############################################################## diff --git a/assets/PinTestTool/makefile.rules b/assets/PinTestTool/makefile.rules deleted file mode 100644 index 4a1ba92..0000000 --- a/assets/PinTestTool/makefile.rules +++ /dev/null @@ -1,89 +0,0 @@ -############################################################## -# -# This file includes all the test targets as well as all the -# non-default build rules and test recipes. -# -############################################################## - - -############################################################## -# -# Test targets -# -############################################################## - -###### Place all generic definitions here ###### - -# This defines tests which run tools of the same name. This is simply for convenience to avoid -# defining the test name twice (once in TOOL_ROOTS and again in TEST_ROOTS). -# Tests defined here should not be defined in TOOL_ROOTS and TEST_ROOTS. -TEST_TOOL_ROOTS := ZydisTestTool - -OBJECT_ROOTS += \ - zydis/src/Decoder \ - zydis/src/Formatter \ - zydis/src/Input \ - zydis/src/InstructionDetails \ - zydis/src/InstructionTable \ - zydis/src/Mnemonic \ - zydis/src/Register \ - zydis/src/Utils \ - zydis/src/Zydis - -# This defines the tests to be run that were not already defined in TEST_TOOL_ROOTS. -TEST_ROOTS := - -# This defines the tools which will be run during the the tests, and were not already defined in -# TEST_TOOL_ROOTS. -TOOL_ROOTS := - -# This defines the static analysis tools which will be run during the the tests. They should not -# be defined in TEST_TOOL_ROOTS. If a test with the same name exists, it should be defined in -# TEST_ROOTS. -# Note: Static analysis tools are in fact executables linked with the Pin Static Analysis Library. -# This library provides a subset of the Pin APIs which allows the tool to perform static analysis -# of an application or dll. Pin itself is not used when this tool runs. -SA_TOOL_ROOTS := - -# This defines all the applications that will be run during the tests. -APP_ROOTS := - -# This defines any additional object files that need to be compiled. -OBJECT_ROOTS := - -# This defines any additional dlls (shared objects), other than the pintools, that need to be compiled. -DLL_ROOTS := - -# This defines any static libraries (archives), that need to be built. -LIB_ROOTS := - -###### Define the sanity subset ###### - -# This defines the list of tests that should run in sanity. It should include all the tests listed in -# TEST_TOOL_ROOTS and TEST_ROOTS excluding only unstable tests. -SANITY_SUBSET := $(TEST_TOOL_ROOTS) $(TEST_ROOTS) - - -############################################################## -# -# Test recipes -# -############################################################## - -# This section contains recipes for tests other than the default. -# See makefile.default.rules for the default test rules. -# All tests in this section should adhere to the naming convention: .test - - -############################################################## -# -# Build rules -# -############################################################## - -ADDITIONAL_INCLUDES := -Izydis/include -I. -TOOL_CFLAGS += $(ADDITIONAL_INCLUDES) -TOOL_CXXFLAGS += $(ADDITIONAL_INCLUDES) - -$(OBJDIR)ZydisTestTool$(PINTOOL_SUFFIX): $(OBJDIR)ZydisTestTool$(OBJ_SUFFIX) $(OBJDIR)zydis/src/Decoder$(OBJ_SUFFIX) $(OBJDIR)zydis/src/Formatter$(OBJ_SUFFIX) $(OBJDIR)zydis/src/Input$(OBJ_SUFFIX) $(OBJDIR)zydis/src/InstructionDetails$(OBJ_SUFFIX) $(OBJDIR)zydis/src/InstructionTable$(OBJ_SUFFIX) $(OBJDIR)zydis/src/Mnemonic$(OBJ_SUFFIX) $(OBJDIR)zydis/src/Register$(OBJ_SUFFIX) $(OBJDIR)zydis/src/Utils$(OBJ_SUFFIX) $(OBJDIR)zydis/src/Zydis$(OBJ_SUFFIX) - $(LINKER) $(TOOL_LDFLAGS) $(LINK_EXE)$@ $^ $(TOOL_LPATHS) $(TOOL_LIBS) diff --git a/assets/PinTestTool/ZydisExportConfig.h b/assets/ZydisExportConfigSample.h similarity index 100% rename from assets/PinTestTool/ZydisExportConfig.h rename to assets/ZydisExportConfigSample.h diff --git a/src/Decoder.c b/src/Decoder.c index aab7c3f..c7da321 100644 --- a/src/Decoder.c +++ b/src/Decoder.c @@ -470,10 +470,10 @@ static ZydisStatus ZydisDecodeVEX(ZydisDecoderContext* context, } // Map 0 is only valid for some KNC instructions -#ifdef ZYDIS_ENABLE_FEATURE_MVEX - if (instruction->raw.vex.m_mmmm > 0x03) -#else +#ifdef ZYDIS_DISABLE_MVEX if ((instruction->raw.vex.m_mmmm == 0) || (instruction->raw.vex.m_mmmm > 0x03)) +#else + if (instruction->raw.vex.m_mmmm > 0x03) #endif { // Invalid according to the intel documentation diff --git a/src/Zydis.c b/src/Zydis.c index cb260dd..a7a5713 100644 --- a/src/Zydis.c +++ b/src/Zydis.c @@ -40,33 +40,32 @@ ZydisBool ZydisIsFeatureEnabled(ZydisFeature feature) switch (feature) { case ZYDIS_FEATURE_EVEX: -#ifdef ZYDIS_ENABLE_FEATURE_EVEX +#ifndef ZYDIS_DISABLE_EVEX return ZYDIS_TRUE; #else return ZYDIS_FALSE; #endif case ZYDIS_FEATURE_MVEX: -#ifdef ZYDIS_ENABLE_FEATURE_MVEX +#ifndef ZYDIS_DISABLE_MVEX return ZYDIS_TRUE; #else return ZYDIS_FALSE; #endif case ZYDIS_FEATURE_FLAGS: -#ifdef ZYDIS_ENABLE_FEATURE_FLAGS +#ifndef ZYDIS_DISABLE_FLAGS return ZYDIS_TRUE; #else return ZYDIS_FALSE; #endif case ZYDIS_FEATURE_CPUID: -#ifdef ZYDIS_ENABLE_FEATURE_CPUID +#ifndef ZYDIS_DISABLE_CPUID return ZYDIS_TRUE; #else return ZYDIS_FALSE; #endif default: - break; + return ZYDIS_FALSE; } - return ZYDIS_FALSE; } /* ============================================================================================== */