From 7caec91207e00ac41b21b48965abcf796bfaf797 Mon Sep 17 00:00:00 2001 From: flobernd Date: Tue, 19 May 2015 21:45:53 +0200 Subject: [PATCH] Improved C-bindings again * Implemented API for custom data souces * Internal changes --- CMakeLists.txt | 25 +- Examples/C/SimpleDemo/SimpleDemo.c | 11 +- Examples/CPP/SimpleDemo/SimpleDemo.cpp | 109 +++++++ README.md | 3 +- Zydis/ZydisAPI.cpp | 379 ++++++++++++++++++------- Zydis/ZydisAPI.h | 71 +++-- 6 files changed, 437 insertions(+), 161 deletions(-) create mode 100644 Examples/CPP/SimpleDemo/SimpleDemo.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 8496c59..934e304 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -44,10 +44,10 @@ endif () # Library set(headers - "Zydis/Zydis.hpp" - "Zydis/ZydisInstructionDecoder.hpp" + "Zydis/Zydis.hpp" + "Zydis/ZydisInstructionDecoder.hpp" "Zydis/ZydisInstructionFormatter.hpp" - "Zydis/ZydisOpcodeTable.hpp" + "Zydis/ZydisOpcodeTable.hpp" "Zydis/ZydisSymbolResolver.hpp" "Zydis/ZydisTypes.hpp" "Zydis/ZydisUtils.hpp") @@ -57,12 +57,12 @@ set(sources "Zydis/ZydisOpcodeTable.cpp" "Zydis/ZydisSymbolResolver.cpp" "Zydis/ZydisUtils.cpp") - + if (BUILD_C_BINDINGS) - set(headers ${headers} - "Zydis/ZydisAPI.h") - set(sources ${sources} - "Zydis/ZydisAPI.cpp") + set(headers ${headers} + "Zydis/ZydisAPI.h") + set(sources ${sources} + "Zydis/ZydisAPI.cpp") endif () add_library("Zydis" ${headers} ${sources}) @@ -76,8 +76,13 @@ include_directories(${PROJECT_BINARY_DIR}) if (BUILD_EXAMPLES) include_directories("Zydis") - add_executable("C_SimpleDemo" "Examples/C/SimpleDemo/SimpleDemo.c") - target_link_libraries("C_SimpleDemo" "Zydis") + add_executable("SimpleDemo_CPP" "Examples/CPP/SimpleDemo/SimpleDemo.cpp") + target_link_libraries("SimpleDemo_CPP" "Zydis") + + if (BUILD_C_BINDINGS) + add_executable("SimpleDemo_C" "Examples/C/SimpleDemo/SimpleDemo.c") + target_link_libraries("SimpleDemo_C" "Zydis") + endif () endif () set(CONFIGURED_ONCE TRUE CACHE INTERNAL "CMake has configured at least once.") diff --git a/Examples/C/SimpleDemo/SimpleDemo.c b/Examples/C/SimpleDemo/SimpleDemo.c index 700e260..1484985 100644 --- a/Examples/C/SimpleDemo/SimpleDemo.c +++ b/Examples/C/SimpleDemo/SimpleDemo.c @@ -92,24 +92,24 @@ int main() decoder = ZydisCreateInstructionDecoder(); if (!decoder) { - goto FreeZydisDecoder; + goto ZydisError; } formatter = ZydisCreateIntelInstructionFormatter(); if (!formatter) { - goto FreeZydisFormatter; + goto FreeZydisDecoder; } // Create memory data sources input32 = ZydisCreateMemoryInput(&data32[0], sizeof(data32)); if (!input32) { - goto FreeZydisInput32; + goto FreeZydisFormatter; } input64 = ZydisCreateMemoryInput(&data64[0], sizeof(data64)); if (!input64) { - goto FreeZydisInput64; + goto FreeZydisInput32; } // Set decoder properties @@ -148,6 +148,8 @@ int main() ZydisSetDisassemblerMode(decoder, ZYDIS_DM_M64BIT); ZydisSetDataSource(decoder, input64); ZydisSetInstructionPointer(decoder, 0x00007FFA39A81930ull); + + // Decode and format all instructions puts("64 bit test ...\n\n"); while (ZydisDecodeInstruction(decoder, &info)) { @@ -181,6 +183,7 @@ FreeZydisFormatter: ZydisFreeInstructionFormatter(formatter); FreeZydisDecoder: ZydisFreeInstructionDecoder(decoder); +ZydisError: if (ZydisGetLastError() != ZYDIS_ERROR_SUCCESS) { diff --git a/Examples/CPP/SimpleDemo/SimpleDemo.cpp b/Examples/CPP/SimpleDemo/SimpleDemo.cpp new file mode 100644 index 0000000..2bf03fb --- /dev/null +++ b/Examples/CPP/SimpleDemo/SimpleDemo.cpp @@ -0,0 +1,109 @@ +/*************************************************************************************************** + + Zyan Disassembler Engine + Version 1.0 + + Remarks : Freeware, Copyright must be included + + Original Author : Florian Bernd + Modifications : Joel Höner + + * 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 +#include +#include +#include + +int main() +{ + uint8_t data32[] = + { + 0x8B, 0xFF, 0x55, 0x8B, 0xEC, 0x6A, 0xFE, 0x68, 0xD8, 0x18, 0x09, 0x77, 0x68, 0x85, 0xD2, + 0x09, 0x77, 0x64, 0xA1, 0x00, 0x00, 0x00, 0x00, 0x50, 0x83, 0xEC, 0x14, 0x53, 0x56, 0x57, + 0xA1, 0x68, 0xEE, 0x13, 0x77, 0x31, 0x45, 0xF8, 0x33, 0xC5, 0x50, 0x8D, 0x45, 0xF0, 0x64, + 0xA3, 0x00, 0x00, 0x00, 0x00, 0x89, 0x65, 0xE8, 0xC7, 0x45, 0xFC, 0x00, 0x00, 0x00, 0x00, + 0x8B, 0x5D, 0x08, 0xF6, 0xC3, 0x04, 0x0F, 0x85, 0x57, 0x74, 0x00, 0x00, 0x53, 0x6A, 0x00, + 0xFF, 0x35, 0xA0, 0xE3, 0x13, 0x77, 0xFF, 0x15, 0x00, 0x10, 0x14, 0x77, 0x85, 0xC0, 0x0F, + 0x84, 0xC6, 0x48, 0x04, 0x00, 0xC7, 0x45, 0x08, 0x00, 0x00, 0x00, 0x00, 0xC7, 0x45, 0xFC, + 0xFE, 0xFF, 0xFF, 0xFF, 0x33, 0xC0, 0x8B, 0x4D, 0xF0, 0x64, 0x89, 0x0D, 0x00, 0x00, 0x00, + 0x00, 0x59, 0x5F, 0x5E, 0x5B, 0x8B, 0xE5, 0x5D, 0xC2, 0x04, 0x00 + }; + uint8_t data64[] = + { + 0x48, 0x89, 0x5C, 0x24, 0x10, 0x48, 0x89, 0x74, 0x24, 0x18, 0x89, 0x4C, 0x24, 0x08, 0x57, + 0x41, 0x54, 0x41, 0x55, 0x41, 0x56, 0x41, 0x57, 0x48, 0x83, 0xEC, 0x40, 0x4C, 0x8B, 0xF2, + 0x8B, 0xD9, 0x48, 0xC7, 0x44, 0x24, 0x20, 0x00, 0x00, 0x00, 0x00, 0x33, 0xF6, 0x48, 0x89, + 0x74, 0x24, 0x30, 0x45, 0x33, 0xFF, 0xF7, 0xC1, 0x8D, 0xF0, 0xFF, 0xFF, 0x0F, 0x85, 0xAA, + 0x53, 0x08, 0x00, 0xF6, 0xC1, 0x40, 0x8B, 0xFE, 0x41, 0xBD, 0x08, 0x00, 0x00, 0x00, 0x41, + 0x0F, 0x45, 0xFD, 0xF6, 0xC1, 0x02, 0x48, 0x8B, 0x0D, 0x10, 0xD4, 0x0E, 0x00, 0x0F, 0x85, + 0x40, 0xE1, 0x01, 0x00, 0x8B, 0x15, 0x4C, 0xD5, 0x0E, 0x00, 0x81, 0xC2, 0x00, 0x00, 0x14, + 0x00, 0x0B, 0xD7, 0x4D, 0x8B, 0xC6, 0xFF, 0x15, 0x3B, 0x2F, 0x10, 0x00, 0x48, 0x8B, 0xD8, + 0x48, 0x85, 0xC0, 0x0F, 0x84, 0x93, 0x78, 0x0A, 0x00, 0x48, 0x8B, 0xC3, 0x48, 0x8B, 0x5C, + 0x24, 0x78, 0x48, 0x8B, 0xB4, 0x24, 0x80, 0x00, 0x00, 0x00, 0x48, 0x83, 0xC4, 0x40, 0x41, + 0x5F, 0x41, 0x5E, 0x41, 0x5D, 0x41, 0x5C, 0x5F, 0xC3 + }; + + Zydis::InstructionInfo info; + Zydis::InstructionDecoder decoder; + Zydis::IntelInstructionFormatter formatter; + Zydis::MemoryInput input32(&data32[0], sizeof(data32)); + Zydis::MemoryInput input64(&data64[0], sizeof(data64)); + + decoder.setDisassemblerMode(Zydis::DisassemblerMode::M32BIT); + decoder.setDataSource(&input32); + decoder.setInstructionPointer(0x77091852); + std::cout << "32 bit test ..." << std::endl << std::endl; + while (decoder.decodeInstruction(info)) + { + std::cout << std::hex << std::setw(8) << std::setfill('0') << std::uppercase + << info.instrAddress << " "; + if (info.flags & Zydis::IF_ERROR_MASK) + { + std::cout << "db " << std::setw(2) << info.data[0]; + } else + { + std::cout << formatter.formatInstruction(info) << std::endl; + } + } + + std::cout << std::endl; + + decoder.setDisassemblerMode(Zydis::DisassemblerMode::M64BIT); + decoder.setDataSource(&input64); + decoder.setInstructionPointer(0x00007FFA39A81930ull); + std::cout << "64 bit test ..." << std::endl << std::endl; + while (decoder.decodeInstruction(info)) + { + std::cout << std::hex << std::setw(16) << std::setfill('0') << std::uppercase + << info.instrAddress << " "; + if (info.flags & Zydis::IF_ERROR_MASK) + { + std::cout << "db " << std::setw(2) << info.data[0]; + } else + { + std::cout << formatter.formatInstruction(info) << std::endl; + } + } + + std::cin.get(); + return 0; +} \ No newline at end of file diff --git a/README.md b/README.md index a8677ba..d6bf326 100644 --- a/README.md +++ b/README.md @@ -48,8 +48,7 @@ int _tmain(int argc, _TCHAR* argv[]) ## Compilation ## -- While Zydis supports other compilers in theory, compilation has not been tested with any compiler other than MSVC12 (Visual Studio 2013) -- Multi-compiler support might be added in the future +Zydis builds cleanly on most platforms without any external dependencies. You can use CMake to generate project files for your favorite C++14 compiler. ## License ## Zyan Disassembler Engine is licensed under the MIT License. Dependencies are under their respective licenses. diff --git a/Zydis/ZydisAPI.cpp b/Zydis/ZydisAPI.cpp index 9673beb..e26dc26 100644 --- a/Zydis/ZydisAPI.cpp +++ b/Zydis/ZydisAPI.cpp @@ -32,6 +32,8 @@ #include "ZydisInstructionDecoder.hpp" #include "ZydisInstructionFormatter.hpp" +/* Static Checks ================================================================================ */ + static_assert( sizeof(ZydisOperandInfo) == sizeof(Zydis::OperandInfo), "struct size mismatch"); @@ -56,81 +58,229 @@ void ZydisSetLastError(uint32_t errorCode) /* Conversion Helper ============================================================================ */ -template -ContextT* ZydisCreateContextInplace(uint8_t contextType, InstanceCtorArgsT... args) +typedef enum _ZydisClassType { - ContextT* context = new (std::nothrow) ContextT; - if (!context) + ZYDIS_CONTEXT_INPUT = 0x00000080, + ZYDIS_CONTEXT_INPUT_CUSTOM = ZYDIS_CONTEXT_INPUT | 0x00000001, + ZYDIS_CONTEXT_INPUT_MEMORY = ZYDIS_CONTEXT_INPUT | 0x00000002, + ZYDIS_CONTEXT_INSTRUCTIONDECODER = 0x00000040, + ZYDIS_CONTEXT_INSTRUCTIONFORMATTER = 0x00000020, + ZYDIS_CONTEXT_INSTRUCTIONFORMATTER_CUSTOM = ZYDIS_CONTEXT_INSTRUCTIONFORMATTER | 0x00000001, + ZYDIS_CONTEXT_INSTRUCTIONFORMATTER_INTEL = ZYDIS_CONTEXT_INSTRUCTIONFORMATTER | 0x00000002, + ZYDIS_CONTEXT_SYMBOLRESOLVER = 0x00000010, + ZYDIS_CONTEXT_SYMBOLRESOLVER_CUSTOM = ZYDIS_CONTEXT_SYMBOLRESOLVER | 0x00000001, + ZYDIS_CONTEXT_SYMBOLRESOLVER_EXACT = ZYDIS_CONTEXT_SYMBOLRESOLVER | 0x00000002 +} ZydisClassType; + +/** + * @brief This helper class extends a zydis class with a type field. It is used by the C-bindings + * to check type correctness for input parameters. + * @param ZydisClassT The zydis class type. + */ +#pragma pack(push, 1) +template +class ZydisClassEx final +{ +private: + using FullClassT = ZydisClassEx; +public: + uint32_t type; + std::conditional_t::value, char, ZydisClassT> instance; +public: + /** + * @brief Constructor + * @param InstanceCtorArgsT The argument types for the constructor of the zydis class. + * @param classType The type of the zydis class. + * @param args... The arguments for the constructor of the zydis class. + */ + template< + typename ZydisClassTT=ZydisClassT, + std::enable_if_t::value, int> = 0, + typename... InstanceCtorArgsT> + ZydisClassEx(uint32_t classType, InstanceCtorArgsT... args) + : type(classType) + , instance(args...) { }; +public: + /** + * @brief Returns the class type. + * @return The assigned class type. + */ + uint32_t getClassType() const + { + return type; + } + /** + * @brief Returns the zydis class instance. + * @return Pointer to the zydis class instance. + */ + ZydisClassT* getInstance() + { + return reinterpret_cast(&instance); + } +public: + /** + * @brief Casts the given instance to @c ZydisClassEx. + * @param instance The zydis class instance. + * @return Pointer to the @c ZydisClassEx instance. + */ + static FullClassT* fromInstance(ZydisClassT* instance) + { + return reinterpret_cast( + reinterpret_cast(instance) - offsetof(FullClassT, instance)); + } +}; +#pragma pack(pop) + +/** + * @brief Creates a context by constructing a new wrapped zydis class instance. + * @param ContextClassT The context class. + * @param ZydisClassT The zydis class type. + * @param ZydisClassCtorArgsT The argument types for the constructor of the zydis class. + * @param classType The type of the zydis class. + * @param args... The arguments for the constructor of the zydis class. + */ +template +ContextClassT* ZydisCreateContext(uint32_t classType, ZydisClassCtorArgsT... args) +{ + auto instanceEx = new (std::nothrow) ZydisClassEx(classType, args...); + if (!instanceEx) { ZydisSetLastError(ZYDIS_ERROR_NOT_ENOUGH_MEMORY); return nullptr; } - context->type = contextType; - context->object = new (std::nothrow) InstanceT(args...); - if (!context->object) - { - delete context; - ZydisSetLastError(ZYDIS_ERROR_NOT_ENOUGH_MEMORY); - return nullptr; - } - return context; + // Return the original instance as context. + return reinterpret_cast(instanceEx->getInstance()); } -template -ContextT* ZydisCreateContext(uint8_t contextType, InstanceT* instance) +/** + * @brief Retrieves the zydis class instance of the given context. + * @param ContextClassT The context class. + * @param ZydisClassT The zydis class type. + * @param expectedType The expected type of the zydis class. + */ +template +ZydisClassT* ZydisRetrieveInstance(uint32_t expectedType, const ContextClassT* context) { - ContextT* context = new (std::nothrow) ContextT; - if (!context) - { - ZydisSetLastError(ZYDIS_ERROR_NOT_ENOUGH_MEMORY); - return nullptr; - } - context->type = contextType; - context->object = instance; - return context; -} - -template -bool ZydisFreeContext(const ContextT* context, uint8_t expectedType) -{ - InstanceT* instance = ZydisCast(context, expectedType); - if (!instance) - { - return false; - } - delete instance; - delete context; - return true; -} - -template -InstanceT* ZydisCast(const ContextT* input, uint8_t expectedType) -{ - if (!input || !input->object || ((input->type & expectedType) != expectedType)) + auto instanceEx = ZydisClassEx::fromInstance( + reinterpret_cast(const_cast(context))); + if ((instanceEx->getClassType() & expectedType) != expectedType) { ZydisSetLastError(ZYDIS_ERROR_INVALID_PARAMETER); return nullptr; } - return reinterpret_cast(input->object); + // The context points to the same address as the instance. We just need to cast it. + return reinterpret_cast(const_cast(context)); +} + +/** + * @brief Creates a context by constructing a new wrapped zydis instance. + * @param ContextClassT The context class. + * @param ZydisClassT The zydis class type. + * @param expectedType The expected type of the zydis class. + */ +template +bool ZydisFreeContext(uint32_t expectedType, const ContextClassT* context) +{ + auto instanceEx = ZydisClassEx::fromInstance( + reinterpret_cast(const_cast(context))); + if ((instanceEx->getClassType() & expectedType) != expectedType) + { + ZydisSetLastError(ZYDIS_ERROR_INVALID_PARAMETER); + return false; + } + delete instanceEx; + return true; } /* Input ======================================================================================== */ -ZydisInputContext* ZydisCreateCustomInput(/* TODO */) +/** + * @brief Helper class for custom input implementations. + */ +class ZydisCustomInput : public Zydis::BaseInput { - return nullptr; +private: + void* m_userData; + ZydisCustomDestructorT m_cbDestructor; + ZydisCustomInputPeekT m_cbPeek; + ZydisCustomInputNextT m_cbNext; + ZydisCustomInputIsEndOfInputT m_cbIsEndOfInput; + ZydisCustomInputGetPositionT m_cbGetPosition; + ZydisCustomInputSetPositionT m_cbSetPosition; +protected: + uint8_t internalInputPeek() override + { + return m_cbPeek(m_userData); + } + + uint8_t internalInputNext() override + { + return m_cbNext(m_userData); + } +public: + ZydisCustomInput(void* userData, + ZydisCustomInputPeekT cbPeek, ZydisCustomInputNextT cbNext, + ZydisCustomInputIsEndOfInputT cbIsEndOfInput, ZydisCustomInputGetPositionT cbGetPosition, + ZydisCustomInputSetPositionT cbSetPosition, ZydisCustomDestructorT cbDestructor) + : m_userData(userData) + , m_cbDestructor(cbDestructor) + , m_cbPeek(cbPeek) + , m_cbNext(cbNext) + , m_cbIsEndOfInput(cbIsEndOfInput) + , m_cbGetPosition(cbGetPosition) + , m_cbSetPosition(cbSetPosition) + { + + } + + ~ZydisCustomInput() override + { + if (m_cbDestructor) + { + m_cbDestructor(m_userData); + } + } +public: + bool isEndOfInput() const override + { + return m_cbIsEndOfInput(m_userData); + } + + uint64_t getPosition() const override + { + return m_cbGetPosition(m_userData); + } + + bool setPosition(uint64_t position) override + { + return m_cbSetPosition(m_userData, position); + } +}; + +ZydisInputContext* ZydisCreateCustomInput(void* userData, + ZydisCustomInputPeekT cbPeek, ZydisCustomInputNextT cbNext, + ZydisCustomInputIsEndOfInputT cbIsEndOfInput, ZydisCustomInputGetPositionT cbGetPosition, + ZydisCustomInputSetPositionT cbSetPosition, ZydisCustomDestructorT cbDestructor) +{ + if (!cbPeek || !cbNext || !cbIsEndOfInput || !cbGetPosition || !cbSetPosition) + { + ZydisSetLastError(ZYDIS_ERROR_INVALID_PARAMETER); + return nullptr; + } + return ZydisCreateContext(ZYDIS_CONTEXT_INPUT_CUSTOM, + userData, cbPeek, cbNext, cbIsEndOfInput, cbGetPosition, cbSetPosition, cbDestructor); } ZydisInputContext* ZydisCreateMemoryInput(const void* buffer, size_t bufferLen) { - return ZydisCreateContextInplace( - ZYDIS_CONTEXT_INPUT | ZYDIS_CONTEXT_INPUT_MEMORY, buffer, bufferLen); + return ZydisCreateContext( + ZYDIS_CONTEXT_INPUT_MEMORY, buffer, bufferLen); } bool ZydisIsEndOfInput(const ZydisInputContext* input, bool* isEndOfInput) { Zydis::BaseInput* instance = - ZydisCast(input, ZYDIS_CONTEXT_INPUT); + ZydisRetrieveInstance(ZYDIS_CONTEXT_INPUT, input); if (!instance) { return false; @@ -142,7 +292,7 @@ bool ZydisIsEndOfInput(const ZydisInputContext* input, bool* isEndOfInput) bool ZydisGetInputPosition(const ZydisInputContext* input, uint64_t* position) { Zydis::BaseInput* instance = - ZydisCast(input, ZYDIS_CONTEXT_INPUT); + ZydisRetrieveInstance(ZYDIS_CONTEXT_INPUT, input); if (!instance) { return false; @@ -154,7 +304,7 @@ bool ZydisGetInputPosition(const ZydisInputContext* input, uint64_t* position) bool ZydisSetInputPosition(const ZydisInputContext* input, uint64_t position) { Zydis::BaseInput* instance = - ZydisCast(input, ZYDIS_CONTEXT_INPUT); + ZydisRetrieveInstance(ZYDIS_CONTEXT_INPUT, input); if (!instance) { return false; @@ -165,23 +315,39 @@ bool ZydisSetInputPosition(const ZydisInputContext* input, uint64_t position) bool ZydisFreeInput(const ZydisInputContext* input) { - return ZydisFreeContext(input, ZYDIS_CONTEXT_INPUT); + return ZydisFreeContext(ZYDIS_CONTEXT_INPUT, input); } /* InstructionDecoder =========================================================================== */ ZydisInstructionDecoderContext* ZydisCreateInstructionDecoder() { - return ZydisCreateContextInplace( + return ZydisCreateContext( ZYDIS_CONTEXT_INSTRUCTIONDECODER); } +ZydisInstructionDecoderContext* ZydisCreateInstructionDecoderEx( + const ZydisInputContext* input, ZydisDisassemblerMode disassemblerMode, + ZydisInstructionSetVendor preferredVendor, uint64_t instructionPointer) +{ + Zydis::BaseInput* object = + ZydisRetrieveInstance(ZYDIS_CONTEXT_INPUT, input); + if (!object) + { + return nullptr; + } + return ZydisCreateContext( + ZYDIS_CONTEXT_INSTRUCTIONDECODER, object, + static_cast(disassemblerMode), + static_cast(preferredVendor), instructionPointer); +} + bool ZydisDecodeInstruction(const ZydisInstructionDecoderContext* decoder, ZydisInstructionInfo* info) { Zydis::InstructionDecoder* instance = - ZydisCast(decoder, ZYDIS_CONTEXT_INSTRUCTIONDECODER); + ZydisRetrieveInstance(ZYDIS_CONTEXT_INSTRUCTIONDECODER, decoder); if (!instance) { return false; @@ -194,14 +360,13 @@ bool ZydisGetDataSource(const ZydisInstructionDecoderContext* decoder, ZydisInputContext** input) { Zydis::InstructionDecoder* instance = - ZydisCast(decoder, ZYDIS_CONTEXT_INSTRUCTIONDECODER); + ZydisRetrieveInstance(ZYDIS_CONTEXT_INSTRUCTIONDECODER, decoder); if (!instance) { return false; } - *input = ZydisCreateContext(ZYDIS_CONTEXT_INPUT, instance->getDataSource()); + *input = reinterpret_cast(instance->getDataSource()); if (!input) { return false; @@ -213,14 +378,14 @@ bool ZydisSetDataSource(const ZydisInstructionDecoderContext* decoder, ZydisInputContext* input) { Zydis::InstructionDecoder* instance = - ZydisCast(decoder, ZYDIS_CONTEXT_INSTRUCTIONDECODER); + ZydisRetrieveInstance(ZYDIS_CONTEXT_INSTRUCTIONDECODER, decoder); if (!instance) { return false; } Zydis::BaseInput* object = - ZydisCast(input, ZYDIS_CONTEXT_INPUT); + ZydisRetrieveInstance(ZYDIS_CONTEXT_INPUT, input); if (!object) { return false; @@ -233,8 +398,8 @@ bool ZydisGetDisassemblerMode(const ZydisInstructionDecoderContext* decoder, ZydisDisassemblerMode* disassemblerMode) { Zydis::InstructionDecoder* instance = - ZydisCast(decoder, ZYDIS_CONTEXT_INSTRUCTIONDECODER); + ZydisRetrieveInstance(ZYDIS_CONTEXT_INSTRUCTIONDECODER, decoder); if (!instance) { return false; @@ -247,8 +412,8 @@ bool ZydisSetDisassemblerMode(const ZydisInstructionDecoderContext* decoder, ZydisDisassemblerMode disassemblerMode) { Zydis::InstructionDecoder* instance = - ZydisCast(decoder, ZYDIS_CONTEXT_INSTRUCTIONDECODER); + ZydisRetrieveInstance(ZYDIS_CONTEXT_INSTRUCTIONDECODER, decoder); if (!instance) { return false; @@ -261,8 +426,8 @@ bool ZydisGetPreferredVendor(const ZydisInstructionDecoderContext* decoder, ZydisInstructionSetVendor* preferredVendor) { Zydis::InstructionDecoder* instance = - ZydisCast(decoder, ZYDIS_CONTEXT_INSTRUCTIONDECODER); + ZydisRetrieveInstance(ZYDIS_CONTEXT_INSTRUCTIONDECODER, decoder); if (!instance) { return false; @@ -275,8 +440,8 @@ bool ZydisSetPreferredVendor(const ZydisInstructionDecoderContext* decoder, ZydisInstructionSetVendor preferredVendor) { Zydis::InstructionDecoder* instance = - ZydisCast(decoder, ZYDIS_CONTEXT_INSTRUCTIONDECODER); + ZydisRetrieveInstance(ZYDIS_CONTEXT_INSTRUCTIONDECODER, decoder); if (!instance) { return false; @@ -289,8 +454,8 @@ bool ZydisSetPreferredVendor(const ZydisInstructionDecoderContext* decoder, uint64_t* instructionPointer) { Zydis::InstructionDecoder* instance = - ZydisCast(decoder, ZYDIS_CONTEXT_INSTRUCTIONDECODER); + ZydisRetrieveInstance(ZYDIS_CONTEXT_INSTRUCTIONDECODER, decoder); if (!instance) { return false; @@ -303,8 +468,8 @@ bool ZydisSetInstructionPointer(const ZydisInstructionDecoderContext* decoder, uint64_t instructionPointer) { Zydis::InstructionDecoder* instance = - ZydisCast(decoder, ZYDIS_CONTEXT_INSTRUCTIONDECODER); + ZydisRetrieveInstance(ZYDIS_CONTEXT_INSTRUCTIONDECODER, decoder); if (!instance) { return false; @@ -315,9 +480,8 @@ bool ZydisSetInstructionPointer(const ZydisInstructionDecoderContext* decoder, bool ZydisFreeInstructionDecoder(const ZydisInstructionDecoderContext* decoder) { - return ZydisFreeContext< - ZydisInstructionDecoderContext, Zydis::InstructionDecoder>( - decoder, ZYDIS_CONTEXT_INSTRUCTIONDECODER); + return ZydisFreeContext( + ZYDIS_CONTEXT_INSTRUCTIONDECODER, decoder); } /* InstructionFormatter ========================================================================= */ @@ -329,17 +493,16 @@ ZydisInstructionFormatterContext* ZydisCreateCustomInstructionFormatter(/* TODO ZydisInstructionFormatterContext* ZydisCreateIntelInstructionFormatter() { - return ZydisCreateContextInplace( - ZYDIS_CONTEXT_INSTRUCTIONFORMATTER | ZYDIS_CONTEXT_INSTRUCTIONFORMATTER_INTEL); + return ZydisCreateContext(ZYDIS_CONTEXT_INSTRUCTIONFORMATTER_INTEL); } bool ZydisFormatInstruction(const ZydisInstructionFormatterContext* formatter, const ZydisInstructionInfo* info, const char** instructionText) { - Zydis::IntelInstructionFormatter* instance = - ZydisCast(formatter, ZYDIS_CONTEXT_INSTRUCTIONFORMATTER); + Zydis::BaseInstructionFormatter* instance = + ZydisRetrieveInstance(ZYDIS_CONTEXT_INSTRUCTIONFORMATTER, formatter); if (!instance) { return false; @@ -352,15 +515,14 @@ bool ZydisFormatInstruction(const ZydisInstructionFormatterContext* formatter, bool ZydisGetSymbolResolver(const ZydisInstructionFormatterContext* formatter, ZydisSymbolResolverContext** resolver) { - Zydis::IntelInstructionFormatter* instance = - ZydisCast(formatter, ZYDIS_CONTEXT_INSTRUCTIONFORMATTER); + Zydis::BaseInstructionFormatter* instance = + ZydisRetrieveInstance(ZYDIS_CONTEXT_INSTRUCTIONFORMATTER, formatter); if (!instance) { return false; } - *resolver = ZydisCreateContext(ZYDIS_CONTEXT_SYMBOLRESOLVER, instance->getSymbolResolver()); + *resolver = reinterpret_cast(instance->getSymbolResolver()); if (!resolver) { return false; @@ -371,16 +533,16 @@ bool ZydisGetSymbolResolver(const ZydisInstructionFormatterContext* formatter, bool ZydisSetSymbolResolver(const ZydisInstructionFormatterContext* formatter, ZydisSymbolResolverContext* resolver) { - Zydis::IntelInstructionFormatter* instance = - ZydisCast(formatter, ZYDIS_CONTEXT_INSTRUCTIONFORMATTER); + Zydis::BaseInstructionFormatter* instance = + ZydisRetrieveInstance(ZYDIS_CONTEXT_INSTRUCTIONFORMATTER, formatter); if (!instance) { return false; } Zydis::BaseSymbolResolver* object = - ZydisCast(resolver, ZYDIS_CONTEXT_SYMBOLRESOLVER); + ZydisRetrieveInstance(ZYDIS_CONTEXT_SYMBOLRESOLVER, resolver); if (!object) { return false; @@ -391,9 +553,8 @@ bool ZydisSetSymbolResolver(const ZydisInstructionFormatterContext* formatter, bool ZydisFreeInstructionFormatter(const ZydisInstructionFormatterContext* formatter) { - return ZydisFreeContext< - ZydisInstructionFormatterContext, Zydis::BaseInstructionFormatter>( - formatter, ZYDIS_CONTEXT_INSTRUCTIONFORMATTER); + return ZydisFreeContext( + ZYDIS_CONTEXT_INSTRUCTIONFORMATTER, formatter); } /* SymbolResolver =============================================================================== */ @@ -405,16 +566,16 @@ ZydisSymbolResolverContext* ZydisCreateCustomSymbolResolver(/*TODO*/) ZydisSymbolResolverContext* ZydisCreateExactSymbolResolver() { - return ZydisCreateContextInplace( - ZYDIS_CONTEXT_SYMBOLRESOLVER | ZYDIS_CONTEXT_SYMBOLRESOLVER_EXACT); + return ZydisCreateContext( + ZYDIS_CONTEXT_SYMBOLRESOLVER_EXACT); } bool ZydisResolveSymbol(const ZydisSymbolResolverContext* resolver, const ZydisInstructionInfo* info, uint64_t address, const char** symbol, uint64_t* offset) { Zydis::BaseSymbolResolver* instance = - ZydisCast(resolver, ZYDIS_CONTEXT_SYMBOLRESOLVER); + ZydisRetrieveInstance(ZYDIS_CONTEXT_SYMBOLRESOLVER, resolver); if (!instance) { return false; @@ -428,8 +589,8 @@ bool ZydisExactSymbolResolverContainsSymbol( const ZydisSymbolResolverContext* resolver, uint64_t address, bool* containsSymbol) { Zydis::ExactSymbolResolver* instance = - ZydisCast(resolver, ZYDIS_CONTEXT_SYMBOLRESOLVER_EXACT); + ZydisRetrieveInstance(ZYDIS_CONTEXT_SYMBOLRESOLVER_EXACT, resolver); if (!instance) { return false; @@ -442,8 +603,8 @@ bool ZydisExactSymbolResolverSetSymbol(const ZydisSymbolResolverContext* resolve uint64_t address, const char* name) { Zydis::ExactSymbolResolver* instance = - ZydisCast(resolver, ZYDIS_CONTEXT_SYMBOLRESOLVER_EXACT); + ZydisRetrieveInstance(ZYDIS_CONTEXT_SYMBOLRESOLVER_EXACT, resolver); if (!instance) { return false; @@ -456,8 +617,8 @@ bool ZydisExactSymbolResolverRemoveSymbol(const ZydisSymbolResolverContext* reso uint64_t address) { Zydis::ExactSymbolResolver* instance = - ZydisCast(resolver, ZYDIS_CONTEXT_SYMBOLRESOLVER_EXACT); + ZydisRetrieveInstance(ZYDIS_CONTEXT_SYMBOLRESOLVER_EXACT, resolver); if (!instance) { return false; @@ -469,8 +630,8 @@ bool ZydisExactSymbolResolverRemoveSymbol(const ZydisSymbolResolverContext* reso bool ZydisExactSymbolResolverClear(const ZydisSymbolResolverContext* resolver) { Zydis::ExactSymbolResolver* instance = - ZydisCast(resolver, ZYDIS_CONTEXT_SYMBOLRESOLVER_EXACT); + ZydisRetrieveInstance(ZYDIS_CONTEXT_SYMBOLRESOLVER_EXACT, resolver); if (!instance) { return false; @@ -482,7 +643,7 @@ bool ZydisExactSymbolResolverClear(const ZydisSymbolResolverContext* resolver) bool ZydisFreeSymbolResolver(const ZydisSymbolResolverContext* resolver) { return ZydisFreeContext( - resolver, ZYDIS_CONTEXT_SYMBOLRESOLVER); + ZYDIS_CONTEXT_SYMBOLRESOLVER, resolver); } /* ============================================================================================== */ \ No newline at end of file diff --git a/Zydis/ZydisAPI.h b/Zydis/ZydisAPI.h index 78c36c2..a5a8b29 100644 --- a/Zydis/ZydisAPI.h +++ b/Zydis/ZydisAPI.h @@ -42,7 +42,7 @@ extern "C" { #endif -/* Types ======================================================================================== */ +/* Zydis Types ================================================================================== */ /** * @brief Values that represent additional flags of a decoded instruction. @@ -543,45 +543,37 @@ typedef struct _ZydisInstructionInfo uint64_t instrPointer; } ZydisInstructionInfo; -/* Context Types ================================================================================ */ +/* Context Declarations ========================================================================= */ -typedef enum _ZydisContextType -{ - ZYDIS_CONTEXT_INPUT = 0x0080, - ZYDIS_CONTEXT_INPUT_CUSTOM = ZYDIS_CONTEXT_INPUT | 0x0001, - ZYDIS_CONTEXT_INPUT_MEMORY = ZYDIS_CONTEXT_INPUT | 0x0002, - ZYDIS_CONTEXT_INSTRUCTIONDECODER = 0x0040, - ZYDIS_CONTEXT_INSTRUCTIONFORMATTER = 0x0020, - ZYDIS_CONTEXT_INSTRUCTIONFORMATTER_CUSTOM = ZYDIS_CONTEXT_INSTRUCTIONFORMATTER | 0x0001, - ZYDIS_CONTEXT_INSTRUCTIONFORMATTER_INTEL = ZYDIS_CONTEXT_INSTRUCTIONFORMATTER | 0x0002, - ZYDIS_CONTEXT_SYMBOLRESOLVER = 0x0010, - ZYDIS_CONTEXT_SYMBOLRESOLVER_CUSTOM = ZYDIS_CONTEXT_SYMBOLRESOLVER | 0x0001, - ZYDIS_CONTEXT_SYMBOLRESOLVER_EXACT = ZYDIS_CONTEXT_SYMBOLRESOLVER | 0x0002 -} ZydisContextType; +typedef struct _ZydisInputContext { int dummy; } ZydisInputContext; -typedef struct _ZydisInputContext -{ - uint8_t type; - void* object; -} ZydisInputContext; +typedef struct _ZydisInstructionDecoderContext { int dummy; } ZydisInstructionDecoderContext; -typedef struct _ZydisInstructionDecoderContext -{ - uint8_t type; - void* object; -} ZydisInstructionDecoderContext; +typedef struct _ZydisInstructionFormatterContext { int dummy; } ZydisInstructionFormatterContext; -typedef struct _ZydisInstructionFormatterContext -{ - uint8_t type; - void* object; -} ZydisInstructionFormatterContext; +typedef struct _ZydisSymbolResolverContext { int dummy; } ZydisSymbolResolverContext; -typedef struct _ZydisSymbolResolverContext -{ - uint8_t type; - void* object; -} ZydisSymbolResolverContext; +/* Callback Declarations ======================================================================== */ + +/* General -------------------------------------------------------------------------------------- */ + +typedef void (*ZydisCustomDestructorT)(void* userData); + +/* Input ---------------------------------------------------------------------------------------- */ + +typedef uint8_t (*ZydisCustomInputPeekT)(void* userData); +typedef uint8_t (*ZydisCustomInputNextT)(void* userData); +typedef bool (*ZydisCustomInputIsEndOfInputT)(void* userData); +typedef uint64_t (*ZydisCustomInputGetPositionT)(void* userData); +typedef bool (*ZydisCustomInputSetPositionT)(void* userData, uint64_t position); + +/* InstructionFormatter ------------------------------------------------------------------------- */ + +// TODO: + +/* SymbolResolver ------------------------------------------------------------------------------- */ + +// TODO: /* Error Handling =============================================================================== */ @@ -597,7 +589,10 @@ ZYDIS_EXPORT uint32_t ZydisGetLastError(); /* Input ======================================================================================== */ -ZYDIS_EXPORT ZydisInputContext* ZydisCreateCustomInput(/* TODO */); +ZYDIS_EXPORT ZydisInputContext* ZydisCreateCustomInput(void* userData, + ZydisCustomInputPeekT cbPeek, ZydisCustomInputNextT cbNext, + ZydisCustomInputIsEndOfInputT cbIsEndOfInput, ZydisCustomInputGetPositionT cbGetPosition, + ZydisCustomInputSetPositionT cbSetPosition, ZydisCustomDestructorT cbDestructor); ZYDIS_EXPORT ZydisInputContext* ZydisCreateMemoryInput(const void* buffer, size_t bufferLen); @@ -633,6 +628,10 @@ typedef enum _ZydisInstructionSetVendor /* : uint8_t */ ZYDIS_EXPORT ZydisInstructionDecoderContext* ZydisCreateInstructionDecoder(); +ZYDIS_EXPORT ZydisInstructionDecoderContext* ZydisCreateInstructionDecoderEx( + const ZydisInputContext* input, ZydisDisassemblerMode disassemblerMode, + ZydisInstructionSetVendor preferredVendor, uint64_t instructionPointer); + ZYDIS_EXPORT bool ZydisDecodeInstruction(const ZydisInstructionDecoderContext* decoder, ZydisInstructionInfo* info);