Initial version 2.0 release

This commit is contained in:
flobernd 2016-05-25 21:25:48 +02:00
parent f377f7b559
commit 7c9a6db6af
53 changed files with 284281 additions and 32941 deletions

227
.gitignore vendored
View File

@ -1,183 +1,78 @@
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
# User-specific files # Created by https://www.gitignore.io/api/c,c++,cmake
*.suo
*.user
*.sln.docstates
# Build results ### C ###
[Dd]ebug/ # Object files
[Dd]ebugPublic/ *.o
[Rr]elease/ *.ko
[Rr]eleases/
x64/
x86/
build/
bld/
[Bb]in/
[Oo]bj/
# Roslyn cache directories
*.ide/
# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*
#NUNIT
*.VisualState.xml
TestResult.xml
# Build Results of an ATL Project
[Dd]ebugPS/
[Rr]eleasePS/
dlldata.c
*_i.c
*_p.c
*_i.h
*.ilk
*.meta
*.obj *.obj
*.elf
# Precompiled Headers
*.gch
*.pch *.pch
*.pdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*.log
*.vspscc
*.vssscc
.builds
*.pidb
*.svclog
*.scc
# Chutzpah Test files # Libraries
_Chutzpah* *.lib
*.a
*.la
*.lo
# Visual C++ cache files # Shared objects (inc. Windows DLLs)
ipch/ *.dll
*.aps *.so
*.ncb *.so.*
*.opensdf *.dylib
*.sdf
*.cachefile
# Visual Studio profiler # Executables
*.psess *.exe
*.vsp *.out
*.vspx *.app
*.i*86
*.x86_64
*.hex
# TFS 2012 Local Workspace # Debug files
$tf/ *.dSYM/
*.su
# Guidance Automation Toolkit
*.gpState
# ReSharper is a .NET coding add-in ### C++ ###
_ReSharper*/ # Compiled Object files
*.[Rr]e[Ss]harper *.slo
*.DotSettings.user *.lo
*.o
*.obj
# JustCode is a .NET coding addin-in # Precompiled Headers
.JustCode *.gch
*.pch
# TeamCity is a build add-in # Compiled Dynamic libraries
_TeamCity* *.so
*.dylib
*.dll
# DotCover is a Code Coverage Tool # Fortran module files
*.dotCover *.mod
# NCrunch # Compiled Static libraries
_NCrunch_* *.lai
.*crunch*.local.xml *.la
*.a
*.lib
# MightyMoose # Executables
*.mm.* *.exe
AutoTest.Net/ *.out
*.app
# Web workbench (sass)
.sass-cache/
# Installshield output folder ### CMake ###
[Ee]xpress/ CMakeCache.txt
CMakeFiles
# DocProject is a documentation generator add-in CMakeScripts
DocProject/buildhelp/ Makefile
DocProject/Help/*.HxT cmake_install.cmake
DocProject/Help/*.HxC install_manifest.txt
DocProject/Help/*.hhc CTestTestfile.cmake
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html
# Click-Once directory
publish/
# Publish Web Output
*.[Pp]ublish.xml
*.azurePubxml
# TODO: Comment the next line if you want to checkin your web deploy settings
# but database connection strings (with potential passwords) will be unencrypted
*.pubxml
*.publishproj
# NuGet Packages
*.nupkg
# The packages folder can be ignored because of Package Restore
**/packages/*
# except build/, which is used as an MSBuild target.
!**/packages/build/
# If using the old MSBuild-Integrated Package Restore, uncomment this:
#!**/packages/repositories.config
# Windows Azure Build Output
csx/
*.build.csdef
# Windows Store app package directory
AppPackages/
# Others
sql/
*.Cache
ClientBin/
[Ss]tyle[Cc]op.*
~$*
*~
*.dbmdl
*.dbproj.schemaview
*.pfx
*.publishsettings
node_modules/
# RIA/Silverlight projects
Generated_Code/
# Backup & report files from converting an old project file
# to a newer Visual Studio version. Backup files are not needed,
# because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm
# SQL Server files
*.mdf
*.ldf
# Business Intelligence projects
*.rdl.data
*.bim.layout
*.bim_*.settings
# Microsoft Fakes
FakesAssemblies/

View File

@ -1,29 +0,0 @@
language: cpp
compiler: clang
script: make
branches:
only:
- master
before_install:
# Install clang 3.6
- echo "yes" | sudo add-apt-repository 'deb http://ppa.launchpad.net/ubuntu-toolchain-r/test/ubuntu precise main'
- echo "yes" | sudo add-apt-repository 'deb http://llvm.org/apt/precise/ llvm-toolchain-precise-3.6 main'
- wget --no-check-certificate -O - http://llvm.org/apt/llvm-snapshot.gpg.key | sudo apt-key add -;
- sudo apt-get update
- sudo apt-get install -qq --allow-unauthenticated llvm-3.6 llvm-3.6-dev clang-3.6 libstdc++-4.8-dev lib32stdc++6
- export CXX="clang++-3.6" CC="clang-3.6"
# Install cmake 3.2
- wget --no-check-certificate https://www.cmake.org/files/v3.2/cmake-3.2.2-Linux-i386.sh
- chmod a+x cmake-3.2.2-Linux-i386.sh
- sudo ./cmake-3.2.2-Linux-i386.sh --skip-license --prefix=/usr
before_script:
- mkdir build
- cd build
- cmake ..
script:
- make

View File

@ -2,21 +2,21 @@ cmake_minimum_required(VERSION 2.8.12)
include(GenerateExportHeader) include(GenerateExportHeader)
project(Zydis) project(Zydis)
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
option(BUILD_SHARED_LIBS "Build shared libraries rather than static ones" FALSE) option(BUILD_SHARED_LIBS "Build shared libraries rather than static ones" FALSE)
option(FORCE_SHARED_CRT option(FORCE_SHARED_CRT
"Forces shared linkage against the CRT even when building a static library" "Forces shared linkage against the CRT even when building a static library"
FALSE) FALSE)
option(BUILD_EXAMPLES "Build examples" TRUE) option(BUILD_EXAMPLES "Build examples" TRUE)
option(BUILD_C_BINDINGS "Build C bindings" TRUE) option(BUILD_TOOLS "Build tools")
if (NOT CONFIGURED_ONCE) if (NOT CONFIGURED_ONCE)
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" OR if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" OR
"${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
set(compiler_specific "-Werror") set(compiler_specific "-std=c99 -pedantic -Wextra -Werror")
set(compiler_specific_cxx "-std=c++14")
elseif (MSVC) elseif (MSVC)
set(compiler_specific "/WX /W4 /D_CRT_SECURE_NO_WARNINGS /GR-") set(compiler_specific "/WX /W4 /D_CRT_SECURE_NO_WARNINGS /TC")
endif () endif ()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${compiler_specific} ${compiler_specific_cxx}" set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${compiler_specific} ${compiler_specific_cxx}"
@ -28,46 +28,41 @@ endif ()
# CMake always orders MSVC to build with a shared CRT. Hack CMake variables in order # CMake always orders MSVC to build with a shared CRT. Hack CMake variables in order
# to generate with a statically linked CRT when we build as a static library. # to generate with a statically linked CRT when we build as a static library.
if (MSVC AND NOT FORCE_SHARED_CRT) if (MSVC AND NOT FORCE_SHARED_CRT)
set(manipulated_vars foreach(flag_var
CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE
CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_RELWITHDEBINFO)
CMAKE_CXX_FLAGS_RELEASE if(${flag_var} MATCHES "/MD")
CMAKE_CXX_FLAGS_RELWITHDEBINFO string(REGEX REPLACE "/MD" "/MT" ${flag_var} "${${flag_var}}")
CMAKE_C_FLAGS_DEBUG endif(${flag_var} MATCHES "/MD")
CMAKE_C_FLAGS_MINSIZEREL endforeach(flag_var)
CMAKE_C_FLAGS_RELEASE
CMAKE_C_FLAGS_RELWITHDEBINFO)
foreach (cur_var ${manipulated_vars})
string(REPLACE "/MD" "/MT" ${cur_var} "${${cur_var}}")
endforeach ()
endif () endif ()
# Library # Library
set(headers set(headers
"Zydis/Zydis.hpp" "include/Zydis/Decoder.h"
"Zydis/ZydisInstructionDecoder.hpp" "include/Zydis/Defines.h"
"Zydis/ZydisInstructionFormatter.hpp" "include/Zydis/Formatter.h"
"Zydis/ZydisOpcodeTable.hpp" "include/Zydis/Input.h"
"Zydis/ZydisSymbolResolver.hpp" "include/Zydis/InstructionInfo.h"
"Zydis/ZydisTypes.hpp" "include/Zydis/Mnemonic.h"
"Zydis/ZydisUtils.hpp") "include/Zydis/Register.h"
"include/Zydis/Status.h"
"include/Zydis/SymbolResolver.h"
"include/Zydis/Utils.h"
"include/Zydis/Zydis.h"
"include/Zydis/Internal/InstructionTable.h")
set(sources set(sources
"Zydis/ZydisInstructionDecoder.cpp" "src/Decoder.c"
"Zydis/ZydisInstructionFormatter.cpp" "src/Formatter.c"
"Zydis/ZydisOpcodeTable.cpp" "src/Input.c"
"Zydis/ZydisSymbolResolver.cpp" "src/InstructionTable.c"
"Zydis/ZydisUtils.cpp") "src/Mnemonic.c"
"src/Register.c"
"src/Utils.c"
"src/Zydis.c")
if (BUILD_SHARED_LIBS AND WIN32) if (BUILD_SHARED_LIBS AND WIN32)
set(sources ${sources} set(sources ${sources} "src/VersionInfo.rc")
"Zydis/VersionInfo.rc")
endif ()
if (BUILD_C_BINDINGS)
set(headers ${headers}
"Zydis/ZydisAPI.h")
set(sources ${sources}
"Zydis/ZydisAPI.cpp")
endif () endif ()
add_library("Zydis" ${headers} ${sources}) add_library("Zydis" ${headers} ${sources})
@ -80,17 +75,25 @@ include_directories(${PROJECT_BINARY_DIR})
# Examples # Examples
if (BUILD_EXAMPLES) if (BUILD_EXAMPLES)
include_directories("Zydis") include_directories("include")
add_executable("ZydisTest" "examples/ZydisTest.c")
add_executable("SimpleDemo_CPP" "Examples/CPP/SimpleDemo/SimpleDemo.cpp") target_link_libraries("ZydisTest" "Zydis")
target_link_libraries("SimpleDemo_CPP" "Zydis") set_target_properties ("ZydisTest" PROPERTIES
add_executable("CustomDataSource_CPP" "Examples/CPP/CustomDataSource/CustomDataSource.cpp") FOLDER "Examples"
target_link_libraries("CustomDataSource_CPP" "Zydis") )
add_executable("ZydisPE" "examples/ZydisPE.c")
if (BUILD_C_BINDINGS) target_link_libraries("ZydisPE" "Zydis")
add_executable("SimpleDemo_C" "Examples/C/SimpleDemo/SimpleDemo.c") set_target_properties ("ZydisPE" PROPERTIES
target_link_libraries("SimpleDemo_C" "Zydis") FOLDER "Examples"
endif () )
endif () endif ()
set(CONFIGURED_ONCE TRUE CACHE INTERNAL "CMake has configured at least once.") # Tools
if (BUILD_TOOLS)
include_directories("include")
add_executable("ZydisDisasm" "tools/ZydisDisasm.c")
target_link_libraries("ZydisDisasm" "Zydis")
set_target_properties ("ZydisDisasm" PROPERTIES
FOLDER "Tools"
)
endif ()

File diff suppressed because it is too large Load Diff

View File

@ -1,199 +0,0 @@
/***************************************************************************************************
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 <ZydisAPI.h>
#include <stdio.h>
#include <stdint.h>
#include <inttypes.h>
void PrintZydisError()
{
puts("Zydis error: ");
switch (ZydisGetLastError())
{
case ZYDIS_ERROR_SUCCESS:
puts("success");
break;
case ZYDIS_ERROR_UNKNOWN:
puts("unknown error");
break;
case ZYDIS_ERROR_NOT_ENOUGH_MEMORY:
puts("not enough memory");
break;
case ZYDIS_ERROR_INVALID_PARAMETER:
puts("invalid parameter");
break;
}
}
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
};
ZydisInstructionInfo info;
ZydisInstructionDecoderContext* decoder = NULL;
ZydisInstructionFormatterContext* formatter = NULL;
ZydisInputContext* input32 = NULL;
ZydisInputContext* input64 = NULL;
// Create decoder and formatter instances
decoder = ZydisCreateInstructionDecoder();
if (!decoder)
{
goto ZydisError;
}
formatter = ZydisCreateIntelInstructionFormatter();
if (!formatter)
{
goto FreeZydisDecoder;
}
// Create memory data sources
input32 = ZydisCreateMemoryInput(&data32[0], sizeof(data32));
if (!input32)
{
goto FreeZydisFormatter;
}
input64 = ZydisCreateMemoryInput(&data64[0], sizeof(data64));
if (!input64)
{
goto FreeZydisInput32;
}
// Set decoder properties
ZydisSetDisassemblerMode(decoder, ZYDIS_DM_M32BIT);
ZydisSetDataSource(decoder, input32);
ZydisSetInstructionPointer(decoder, 0x77091852);
// Decode and format all instructions
puts("32 bit test ...\n\n");
while (ZydisDecodeInstruction(decoder, &info))
{
printf("%08X ", (uint32_t)(info.instrAddress & 0xFFFFFFFF));
if (info.flags & ZYDIS_IF_ERROR_MASK)
{
printf("db %02X\n", info.data[0]);
}
else
{
const char* instructionText;
if (!ZydisFormatInstruction(formatter, &info, &instructionText))
{
goto FreeZydisInput64;
}
printf("%s\n", instructionText);
}
}
// Check if an error occured in ZydisDecodeInstruction or the end of the input was reached.
if (ZydisGetLastError() != ZYDIS_ERROR_SUCCESS)
{
goto FreeZydisInput64;
}
puts("\n");
// Set decoder properties
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))
{
printf("%016"PRIX64" ", info.instrAddress);
if (info.flags & ZYDIS_IF_ERROR_MASK)
{
printf("db %02X", info.data[0]);
}
else
{
const char* instructionText;
if (!ZydisFormatInstruction(formatter, &info, &instructionText))
{
goto FreeZydisInput64;
}
printf("%s\n", instructionText);
}
}
// Check if an error occured in ZydisDecodeInstruction or the end of the input was reached.
if (ZydisGetLastError() != ZYDIS_ERROR_SUCCESS)
{
goto FreeZydisInput64;
}
// Cleanup code
FreeZydisInput64:
ZydisFreeInput(input64);
FreeZydisInput32:
ZydisFreeInput(input32);
FreeZydisFormatter:
ZydisFreeInstructionFormatter(formatter);
FreeZydisDecoder:
ZydisFreeInstructionDecoder(decoder);
ZydisError:
if (ZydisGetLastError() != ZYDIS_ERROR_SUCCESS)
{
PrintZydisError();
getchar();
return 1;
}
getchar();
return 0;
}

View File

@ -1,169 +0,0 @@
/***************************************************************************************************
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 <stdint.h>
#include <iostream>
#include <iomanip>
#include <vector>
#include <string>
#include <sstream>
#include <Zydis.hpp>
class ZydisStdinInput : public Zydis::BaseInput
{
private:
std::vector<uint8_t> m_buffer;
uint32_t m_position = 0;
uint64_t m_globalPosition = 0;
private:
void gatherInput();
protected:
uint8_t internalInputPeek() override;
uint8_t internalInputNext() override;
public:
bool isEndOfInput() const override;
uint64_t getPosition() const override;
bool setPosition(uint64_t position) override;
};
void ZydisStdinInput::gatherInput()
{
if (m_position != m_buffer.size())
{
return;
}
std::vector<uint8_t> buffer;
bool valid;
do
{
valid = true;
buffer.clear();
std::string input;
std::getline(std::cin, input);
if (input.empty())
{
valid = false;
continue;
}
std::istringstream ss(input);
uint32_t x;
do
{
ss >> std::hex >> x;
if (ss.fail())
{
std::cout << std::endl << "# Error: Invalid hex input." << std::endl << std::endl;
ss.ignore();
valid = false;
break;
}
if (buffer.size() == buffer.capacity())
{
buffer.reserve(buffer.capacity() + 512);
}
if (x > 255)
{
std::cout << std::endl << "# Warning: 0x"
<< std::hex << std::setw(8) << std::setfill('0') << std::uppercase << x
<< " converted to uint8_t. Possible data loss." << std::endl << std::endl;
}
buffer.resize(buffer.size() + 1);
buffer[buffer.size() - 1] = static_cast<uint8_t>(x);
} while (!ss.eof());
} while (!valid);
m_buffer = buffer;
m_position = 0;
}
uint8_t ZydisStdinInput::internalInputPeek()
{
gatherInput();
return m_buffer[m_position];
}
uint8_t ZydisStdinInput::internalInputNext()
{
gatherInput();
m_globalPosition++;
return m_buffer[m_position++];
}
bool ZydisStdinInput::isEndOfInput() const
{
return false;
}
uint64_t ZydisStdinInput::getPosition() const
{
return m_globalPosition;
}
bool ZydisStdinInput::setPosition(uint64_t position)
{
if (position > m_globalPosition)
{
return false;
}
int64_t delta = m_globalPosition - position;
if (delta > m_position)
{
return false;
}
m_position = m_position - static_cast<int32_t>(delta);
m_globalPosition = position;
return true;
}
int main()
{
Zydis::InstructionInfo info;
Zydis::InstructionDecoder decoder;
Zydis::IntelInstructionFormatter formatter;
ZydisStdinInput input;
decoder.setDisassemblerMode(Zydis::DisassemblerMode::M32BIT);
decoder.setDataSource(&input);
decoder.setInstructionPointer(0x00000000);
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) << static_cast<int>(info.data[0]) << std::endl;
} else
{
std::cout << formatter.formatInstruction(info) << std::endl;
}
}
return 0;
}

View File

@ -1,109 +0,0 @@
/***************************************************************************************************
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 <stdint.h>
#include <iostream>
#include <iomanip>
#include <Zydis.hpp>
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) << static_cast<int>(info.data[0]) << std::endl;
} 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) << static_cast<int>(info.data[0]) << std::endl;
} else
{
std::cout << formatter.formatInstruction(info) << std::endl;
}
}
std::cin.get();
return 0;
}

View File

@ -1,156 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{EFA075B8-AFB9-4E06-99AD-BD58F50A9500}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>OptableGenerator</RootNamespace>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v120</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v120</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v120</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v120</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
<IncludePath>..\VerteronDisassemblerEngine\;$(IncludePath)</IncludePath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental>
<IncludePath>..\VerteronDisassemblerEngine\;$(IncludePath)</IncludePath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
<IncludePath>..\VerteronDisassemblerEngine\;$(IncludePath)</IncludePath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
<IncludePath>..\VerteronDisassemblerEngine\;$(IncludePath)</IncludePath>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<PrecompiledHeader>
</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>
</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level3</WarningLevel>
<PrecompiledHeader>
</PrecompiledHeader>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="Main.cpp" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\VerteronDisassemblerEngine\VerteronDisassemblerEngine.vcxproj">
<Project>{f5c6f0a7-f75d-42bd-a8ab-a2d1d5f67099}</Project>
</ProjectReference>
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@ -1,6 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<ClCompile Include="Main.cpp" />
</ItemGroup>
</Project>

View File

@ -1,72 +0,0 @@
/**
* pugixml parser - version 1.4
* --------------------------------------------------------
* Copyright (C) 2006-2014, by Arseny Kapoulkine (arseny.kapoulkine@gmail.com)
* Report bugs and download new versions at http://pugixml.org/
*
* This library is distributed under the MIT License. See notice at the end
* of this file.
*
* This work is based on the pugxml parser, which is:
* Copyright (C) 2003, by Kristen Wegner (kristen@tima.net)
*/
#ifndef HEADER_PUGICONFIG_HPP
#define HEADER_PUGICONFIG_HPP
// Uncomment this to enable wchar_t mode
// #define PUGIXML_WCHAR_MODE
// Uncomment this to disable XPath
// #define PUGIXML_NO_XPATH
// Uncomment this to disable STL
// #define PUGIXML_NO_STL
// Uncomment this to disable exceptions
// #define PUGIXML_NO_EXCEPTIONS
// Set this to control attributes for public classes/functions, i.e.:
// #define PUGIXML_API __declspec(dllexport) // to export all public symbols from DLL
// #define PUGIXML_CLASS __declspec(dllimport) // to import all classes from DLL
// #define PUGIXML_FUNCTION __fastcall // to set calling conventions to all public functions to fastcall
// In absence of PUGIXML_CLASS/PUGIXML_FUNCTION definitions PUGIXML_API is used instead
// Tune these constants to adjust memory-related behavior
// #define PUGIXML_MEMORY_PAGE_SIZE 32768
// #define PUGIXML_MEMORY_OUTPUT_STACK 10240
// #define PUGIXML_MEMORY_XPATH_PAGE_SIZE 4096
// Uncomment this to switch to header-only version
// #define PUGIXML_HEADER_ONLY
// #include "pugixml.cpp"
// Uncomment this to enable long long support
// #define PUGIXML_HAS_LONG_LONG
#endif
/**
* Copyright (c) 2006-2014 Arseny Kapoulkine
*
* 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.
*/

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,30 +1,28 @@
Zyan Disassembler Engine (Zydis) [![Build Status](https://travis-ci.org/zyantific/zyan-disassembler-engine.svg?branch=master)](https://travis-ci.org/zyantific/zyan-disassembler-engine) Zyan Disassembler Engine (Zydis)
================================ ================================
Fast and lightweight x86/x86-64 disassembler library. Fast and lightweight x86/x86-64 disassembler library.
## Features ## ## Features ##
- Supports all x86 and x86-64 (AMD64) General purpose and System instructions. - Supports all x86 and x86-64 (AMD64) general-purpose and system instructions.
- Supported ISA extensions: - Supported ISA extensions:
- MMX, FPU (x87), AMD 3DNow - FPU (x87), MMX
- SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, AES, - SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, SSE4A, AESNI
- AMD-V, INTEL-VMX, SMX - AVX, AVX2, AVX512BW, AVX512CD, AVX512DQ, AVX512ER, AVX512F, AVX512PF, AVX512VL
- ADX, BMI1, BMI2, FMA, FMA4
- ..
- Optimized for high performance - Optimized for high performance
- Very small overhead compared to other common disassembler libraries (about 60KiB) - Very small overhead compared to other common disassembler libraries
- Abstract formatter and symbol-resolver classes for custom syntax implementations.
- Intel syntax is implemented by default
- Complete doxygen documentation - Complete doxygen documentation
## Quick Example ## ## Quick Example ##
The following example program uses Zydis to disassemble a given memory buffer and prints the output to the console. The following example program uses Zydis to disassemble a given memory buffer and prints the output to the console.
```c++ ```C
#include <iostream> #include <stdio.h>
#include <iomanip> #include <Zydis/Zydis.h>
#include <stdint.h>
#include <Zydis.hpp>
int main() int main()
{ {
@ -35,29 +33,30 @@ int main()
0x88, 0xFC, 0xDA, 0x02, 0x00 0x88, 0xFC, 0xDA, 0x02, 0x00
}; };
Zydis::MemoryInput input(&data[0], sizeof(data)); ZydisMemoryInput input;
Zydis::InstructionInfo info; ZydisInputInitMemoryInput(&input, &data, sizeof(data));
Zydis::InstructionDecoder decoder;
decoder.setDisassemblerMode(Zydis::DisassemblerMode::M32BIT);
decoder.setDataSource(&input);
decoder.setInstructionPointer(0x00400000);
Zydis::IntelInstructionFormatter formatter;
while (decoder.decodeInstruction(info)) ZydisInstructionDecoder decoder;
ZydisDecoderInitInstructionDecoderEx(&decoder, ZYDIS_DISASSEMBLER_MODE_64BIT,
(ZydisCustomInput*)&input, ZYDIS_DECODER_FLAG_SKIP_DATA);
ZydisDecoderSetInstructionPointer(&decoder, 0x007FFFFFFF400000);
ZydisInstructionFormatter formatter;
ZydisFormatterInitInstructionFormatterEx(&formatter,
ZYDIS_FORMATTER_STYLE_INTEL, ZYDIS_FORMATTER_FLAG_ALWAYS_DISPLAY_MEMORY_SEGMENT);
ZydisInstructionInfo info;
char buffer[256];
while (ZYDIS_SUCCESS(ZydisDecoderDecodeNextInstruction(&decoder, &info)))
{ {
std::cout << std::hex << std::setw(8) << std::setfill('0') printf("%016llX ", info.instrAddress);
<< std::uppercase << info.instrAddress << " "; if (info.flags & ZYDIS_IFLAG_ERROR_MASK)
if (info.flags & Zydis::IF_ERROR_MASK)
{ {
std::cout << "db " << std::setw(2) printf(" db %02x\n", info.data[0]);
<< static_cast<int>(info.data[0]) continue;
<< std::endl;
}
else
{
std::cout << formatter.formatInstruction(info) << std::endl;
} }
ZydisFormatterFormatInstruction(&formatter, &info, &buffer[0], sizeof(buffer));
printf(" %s\n", &buffer[0]);
} }
} }
``` ```
@ -67,23 +66,19 @@ int main()
The above example program generates the following output: The above example program generates the following output:
``` ```
00400000 push ecx 007FFFFFFF400000 push rcx
00400001 lea eax, [ebp-01] 007FFFFFFF400001 lea eax, dword ptr ss:[rbp-0x01]
00400004 push eax 007FFFFFFF400004 push rax
00400005 push dword ptr [ebp+0C] 007FFFFFFF400005 push qword ptr ss:[rbp+0x0C]
00400008 push dword ptr [ebp+08] 007FFFFFFF400008 push qword ptr ss:[rbp+0x08]
0040000B call dword ptr [7648A5A0] 007FFFFFFF40000B call qword ptr ds:[0x008000007588A5B1]
00400011 test eax, eax 007FFFFFFF400011 test eax, eax
00400013 js 0042DB15 007FFFFFFF400013 js 0x007FFFFFFF42DB15
``` ```
## Compilation ## ## Compilation ##
Zydis builds cleanly on most platforms without any external dependencies. You can use CMake to generate project files for your favorite C++14 compiler. Zydis builds cleanly on most platforms without any external dependencies. You can use CMake to generate project files for your favorite C99 compiler.
## Documentation ##
[The HTML Doxygen documentation](https://www.zyantific.com/doc/zydis/index.html) is automatically built from master every 12 hours.
## License ## ## License ##

View File

@ -1,100 +0,0 @@
/***************************************************************************************************
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.
***************************************************************************************************/
/**
* @file
* @brief C++ API include file.
*/
/**
* @mainpage Zyan Disassembler Engine (Zydis)
*
* Zydis is a fast and lightweight x86/x86-64 disassembler library.
*
* @section Features
* - Supports all x86 and x86-64 (AMD64) General purpose and System instructions.
* - Supported ISA extensions:
* - MMX, FPU (x87), AMD 3DNow
* - SSE, SSE2, SSE3, SSSE3, SSE4.1, SSE4.2, AES,
* - AMD-V, INTEL-VMX, SMX
* - Optimized for high performance
* - Very small overhead compared to other common disassembler libraries (about 60KiB)
* - Abstract formatter and symbol-resolver classes for custom syntax implementations.
* - Intel syntax is implemented by default
* - Complete doxygen documentation
*
* @section Quick Example
* The following example program uses Zydis to disassemble a given memory buffer and prints the
* output to the console.
*
* @code
* #include <tchar.h>
* #include <iostream>
* #include <stdint.h>
* #include "Zydis.hpp"
*
* int _tmain(int argc, _TCHAR* argv[])
* {
* uint8_t data[] =
* {
* 0x90, 0xE9, 0x00, 0x00, 0x00, 0x00, 0xC3
* };
* Zydis::MemoryInput input(&data[0], sizeof(data));
* Zydis::InstructionInfo info;
* Zydis::InstructionDecoder decoder;
* decoder.setDisassemblerMode(Zydis::DisassemblerMode::M32BIT);
* decoder.setDataSource(&input);
* decoder.setInstructionPointer(0);
* Zydis::IntelInstructionFormatter formatter;
* while (decoder.decodeInstruction(info))
* {
* std::cout << formatter.formatInstruction(info) << std::endl;
* }
* }
* @endcode
*
* @section Compilation
* Zydis builds cleanly on most platforms without any external dependencies. You can use CMake
* to generate project files for your favorite C++14 compiler.
*
* @section License
* Zyan Disassembler Engine is licensed under the MIT License. Dependencies are under their
* respective licenses.
*/
#ifndef _ZYDIS_HPP_
#define _ZYDIS_HPP_
#include "ZydisInstructionDecoder.hpp"
#include "ZydisInstructionFormatter.hpp"
#include "ZydisSymbolResolver.hpp"
#include "ZydisUtils.hpp"
#endif /*_ZYDIS_HPP_ */

View File

@ -1,653 +0,0 @@
/***************************************************************************************************
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 "ZydisAPI.h"
#include "ZydisInstructionDecoder.hpp"
#include "ZydisInstructionFormatter.hpp"
/* Static Checks ================================================================================ */
static_assert(
sizeof(ZydisOperandInfo) == sizeof(Zydis::OperandInfo),
"struct size mismatch");
static_assert(
sizeof(ZydisInstructionInfo) == sizeof(Zydis::InstructionInfo),
"struct size mismatch");
/* Error Handling =============================================================================== */
static uint32_t g_zydisLastError = ZYDIS_ERROR_SUCCESS;
uint32_t ZydisGetLastError()
{
return g_zydisLastError;
}
void ZydisSetLastError(uint32_t errorCode)
{
g_zydisLastError = errorCode;
}
/* Conversion Helper ============================================================================ */
typedef enum _ZydisClassType
{
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 <typename ZydisClassT>
class ZydisClassEx final
{
private:
using FullClassT = ZydisClassEx<ZydisClassT>;
public:
uint32_t type;
uint32_t align;
std::conditional_t<std::is_abstract<ZydisClassT>::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<!std::is_abstract<ZydisClassTT>::value, int> = 0,
typename... InstanceCtorArgsT>
ZydisClassEx(uint32_t classType, InstanceCtorArgsT... args)
: type(classType)
, align(0)
, 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<ZydisClassT*>(&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<FullClassT*>(
reinterpret_cast<uintptr_t>(instance)
- sizeof(std::declval<FullClassT>().type)
- sizeof(std::declval<FullClassT>().align));
}
};
#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 <typename ContextClassT, typename ZydisClassT, typename... ZydisClassCtorArgsT>
ContextClassT* ZydisCreateContext(uint32_t classType, ZydisClassCtorArgsT... args)
{
auto instanceEx = new (std::nothrow) ZydisClassEx<ZydisClassT>(classType, args...);
if (!instanceEx)
{
ZydisSetLastError(ZYDIS_ERROR_NOT_ENOUGH_MEMORY);
return nullptr;
}
// Return the original instance as context.
return reinterpret_cast<ContextClassT*>(instanceEx->getInstance());
}
/**
* @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 <typename ContextClassT, typename ZydisClassT>
ZydisClassT* ZydisRetrieveInstance(uint32_t expectedType, const ContextClassT* context)
{
auto instanceEx = ZydisClassEx<ZydisClassT>::fromInstance(
reinterpret_cast<ZydisClassT*>(const_cast<ContextClassT*>(context)));
if ((instanceEx->getClassType() & expectedType) != expectedType)
{
ZydisSetLastError(ZYDIS_ERROR_INVALID_PARAMETER);
return nullptr;
}
// The context points to the same address as the instance. We just need to cast it.
return reinterpret_cast<ZydisClassT*>(const_cast<ContextClassT*>(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 <typename ContextClassT, typename ZydisClassT>
bool ZydisFreeContext(uint32_t expectedType, const ContextClassT* context)
{
auto instanceEx = ZydisClassEx<ZydisClassT>::fromInstance(
reinterpret_cast<ZydisClassT*>(const_cast<ContextClassT*>(context)));
if ((instanceEx->getClassType() & expectedType) != expectedType)
{
ZydisSetLastError(ZYDIS_ERROR_INVALID_PARAMETER);
return false;
}
delete instanceEx;
return true;
}
/* Input ======================================================================================== */
/**
* @brief Helper class for custom input implementations.
*/
class ZydisCustomInput : public Zydis::BaseInput
{
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<ZydisInputContext, ZydisCustomInput>(ZYDIS_CONTEXT_INPUT_CUSTOM,
userData, cbPeek, cbNext, cbIsEndOfInput, cbGetPosition, cbSetPosition, cbDestructor);
}
ZydisInputContext* ZydisCreateMemoryInput(const void* buffer, size_t bufferLen)
{
return ZydisCreateContext<ZydisInputContext, Zydis::MemoryInput>(
ZYDIS_CONTEXT_INPUT_MEMORY, buffer, bufferLen);
}
bool ZydisIsEndOfInput(const ZydisInputContext* input, bool* isEndOfInput)
{
Zydis::BaseInput* instance =
ZydisRetrieveInstance<ZydisInputContext, Zydis::BaseInput>(ZYDIS_CONTEXT_INPUT, input);
if (!instance)
{
return false;
}
*isEndOfInput = instance->isEndOfInput();
return true;
}
bool ZydisGetInputPosition(const ZydisInputContext* input, uint64_t* position)
{
Zydis::BaseInput* instance =
ZydisRetrieveInstance<ZydisInputContext, Zydis::BaseInput>(ZYDIS_CONTEXT_INPUT, input);
if (!instance)
{
return false;
}
*position = instance->getPosition();
return true;
}
bool ZydisSetInputPosition(const ZydisInputContext* input, uint64_t position)
{
Zydis::BaseInput* instance =
ZydisRetrieveInstance<ZydisInputContext, Zydis::BaseInput>(ZYDIS_CONTEXT_INPUT, input);
if (!instance)
{
return false;
}
ZydisSetLastError(ZYDIS_ERROR_SUCCESS);
return instance->setPosition(position);
}
bool ZydisFreeInput(const ZydisInputContext* input)
{
return ZydisFreeContext<ZydisInputContext, Zydis::BaseInput>(ZYDIS_CONTEXT_INPUT, input);
}
/* InstructionDecoder =========================================================================== */
ZydisInstructionDecoderContext* ZydisCreateInstructionDecoder()
{
return ZydisCreateContext<ZydisInstructionDecoderContext, Zydis::InstructionDecoder>(
ZYDIS_CONTEXT_INSTRUCTIONDECODER);
}
ZydisInstructionDecoderContext* ZydisCreateInstructionDecoderEx(
const ZydisInputContext* input, ZydisDisassemblerMode disassemblerMode,
ZydisInstructionSetVendor preferredVendor, uint64_t instructionPointer)
{
Zydis::BaseInput* object =
ZydisRetrieveInstance<ZydisInputContext, Zydis::BaseInput>(ZYDIS_CONTEXT_INPUT, input);
if (!object)
{
return nullptr;
}
return ZydisCreateContext<ZydisInstructionDecoderContext, Zydis::InstructionDecoder>(
ZYDIS_CONTEXT_INSTRUCTIONDECODER, object,
static_cast<Zydis::DisassemblerMode>(disassemblerMode),
static_cast<Zydis::InstructionSetVendor>(preferredVendor), instructionPointer);
}
bool ZydisDecodeInstruction(const ZydisInstructionDecoderContext* decoder,
ZydisInstructionInfo* info)
{
Zydis::InstructionDecoder* instance =
ZydisRetrieveInstance<ZydisInstructionDecoderContext,
Zydis::InstructionDecoder>(ZYDIS_CONTEXT_INSTRUCTIONDECODER, decoder);
if (!instance)
{
return false;
}
ZydisSetLastError(ZYDIS_ERROR_SUCCESS);
return instance->decodeInstruction(*reinterpret_cast<Zydis::InstructionInfo*>(info));
}
bool ZydisGetDataSource(const ZydisInstructionDecoderContext* decoder,
ZydisInputContext** input)
{
Zydis::InstructionDecoder* instance =
ZydisRetrieveInstance<ZydisInstructionDecoderContext,
Zydis::InstructionDecoder>(ZYDIS_CONTEXT_INSTRUCTIONDECODER, decoder);
if (!instance)
{
return false;
}
*input = reinterpret_cast<ZydisInputContext*>(instance->getDataSource());
if (!input)
{
return false;
}
return true;
}
bool ZydisSetDataSource(const ZydisInstructionDecoderContext* decoder,
ZydisInputContext* input)
{
Zydis::InstructionDecoder* instance =
ZydisRetrieveInstance<ZydisInstructionDecoderContext,
Zydis::InstructionDecoder>(ZYDIS_CONTEXT_INSTRUCTIONDECODER, decoder);
if (!instance)
{
return false;
}
Zydis::BaseInput* object =
ZydisRetrieveInstance<ZydisInputContext, Zydis::BaseInput>(ZYDIS_CONTEXT_INPUT, input);
if (!object)
{
return false;
}
instance->setDataSource(object);
return true;
}
bool ZydisGetDisassemblerMode(const ZydisInstructionDecoderContext* decoder,
ZydisDisassemblerMode* disassemblerMode)
{
Zydis::InstructionDecoder* instance =
ZydisRetrieveInstance<ZydisInstructionDecoderContext,
Zydis::InstructionDecoder>(ZYDIS_CONTEXT_INSTRUCTIONDECODER, decoder);
if (!instance)
{
return false;
}
*disassemblerMode = static_cast<ZydisDisassemblerMode>(instance->getDisassemblerMode());
return true;
}
bool ZydisSetDisassemblerMode(const ZydisInstructionDecoderContext* decoder,
ZydisDisassemblerMode disassemblerMode)
{
Zydis::InstructionDecoder* instance =
ZydisRetrieveInstance<ZydisInstructionDecoderContext,
Zydis::InstructionDecoder>(ZYDIS_CONTEXT_INSTRUCTIONDECODER, decoder);
if (!instance)
{
return false;
}
instance->setDisassemblerMode(static_cast<Zydis::DisassemblerMode>(disassemblerMode));
return true;
}
bool ZydisGetPreferredVendor(const ZydisInstructionDecoderContext* decoder,
ZydisInstructionSetVendor* preferredVendor)
{
Zydis::InstructionDecoder* instance =
ZydisRetrieveInstance<ZydisInstructionDecoderContext,
Zydis::InstructionDecoder>(ZYDIS_CONTEXT_INSTRUCTIONDECODER, decoder);
if (!instance)
{
return false;
}
*preferredVendor = static_cast<ZydisInstructionSetVendor>(instance->getPreferredVendor());
return true;
}
bool ZydisSetPreferredVendor(const ZydisInstructionDecoderContext* decoder,
ZydisInstructionSetVendor preferredVendor)
{
Zydis::InstructionDecoder* instance =
ZydisRetrieveInstance<ZydisInstructionDecoderContext,
Zydis::InstructionDecoder>(ZYDIS_CONTEXT_INSTRUCTIONDECODER, decoder);
if (!instance)
{
return false;
}
instance->setPreferredVendor(static_cast<Zydis::InstructionSetVendor>(preferredVendor));
return true;
}
bool ZydisGetInstructionPointer(const ZydisInstructionDecoderContext* decoder,
uint64_t* instructionPointer)
{
Zydis::InstructionDecoder* instance =
ZydisRetrieveInstance<ZydisInstructionDecoderContext,
Zydis::InstructionDecoder>(ZYDIS_CONTEXT_INSTRUCTIONDECODER, decoder);
if (!instance)
{
return false;
}
*instructionPointer = instance->getInstructionPointer();
return true;
}
bool ZydisSetInstructionPointer(const ZydisInstructionDecoderContext* decoder,
uint64_t instructionPointer)
{
Zydis::InstructionDecoder* instance =
ZydisRetrieveInstance<ZydisInstructionDecoderContext,
Zydis::InstructionDecoder>(ZYDIS_CONTEXT_INSTRUCTIONDECODER, decoder);
if (!instance)
{
return false;
}
instance->setInstructionPointer(instructionPointer);
return true;
}
bool ZydisFreeInstructionDecoder(const ZydisInstructionDecoderContext* decoder)
{
return ZydisFreeContext<ZydisInstructionDecoderContext, Zydis::InstructionDecoder>(
ZYDIS_CONTEXT_INSTRUCTIONDECODER, decoder);
}
/* InstructionFormatter ========================================================================= */
ZydisInstructionFormatterContext* ZydisCreateCustomInstructionFormatter(/* TODO */)
{
return nullptr;
}
ZydisInstructionFormatterContext* ZydisCreateIntelInstructionFormatter()
{
return ZydisCreateContext<ZydisInstructionFormatterContext,
Zydis::IntelInstructionFormatter>(ZYDIS_CONTEXT_INSTRUCTIONFORMATTER_INTEL);
}
bool ZydisFormatInstruction(const ZydisInstructionFormatterContext* formatter,
const ZydisInstructionInfo* info, const char** instructionText)
{
Zydis::BaseInstructionFormatter* instance =
ZydisRetrieveInstance<ZydisInstructionFormatterContext,
Zydis::BaseInstructionFormatter>(ZYDIS_CONTEXT_INSTRUCTIONFORMATTER, formatter);
if (!instance)
{
return false;
}
*instructionText =
instance->formatInstruction(*reinterpret_cast<const Zydis::InstructionInfo*>(info));
return true;
}
bool ZydisGetSymbolResolver(const ZydisInstructionFormatterContext* formatter,
ZydisSymbolResolverContext** resolver)
{
Zydis::BaseInstructionFormatter* instance =
ZydisRetrieveInstance<ZydisInstructionFormatterContext,
Zydis::BaseInstructionFormatter>(ZYDIS_CONTEXT_INSTRUCTIONFORMATTER, formatter);
if (!instance)
{
return false;
}
*resolver = reinterpret_cast<ZydisSymbolResolverContext*>(instance->getSymbolResolver());
if (!resolver)
{
return false;
}
return true;
}
bool ZydisSetSymbolResolver(const ZydisInstructionFormatterContext* formatter,
ZydisSymbolResolverContext* resolver)
{
Zydis::BaseInstructionFormatter* instance =
ZydisRetrieveInstance<ZydisInstructionFormatterContext,
Zydis::BaseInstructionFormatter>(ZYDIS_CONTEXT_INSTRUCTIONFORMATTER, formatter);
if (!instance)
{
return false;
}
Zydis::BaseSymbolResolver* object =
ZydisRetrieveInstance<ZydisSymbolResolverContext,
Zydis::BaseSymbolResolver>(ZYDIS_CONTEXT_SYMBOLRESOLVER, resolver);
if (!object)
{
return false;
}
instance->setSymbolResolver(object);
return true;
}
bool ZydisFreeInstructionFormatter(const ZydisInstructionFormatterContext* formatter)
{
return ZydisFreeContext<ZydisInstructionFormatterContext, Zydis::BaseInstructionFormatter>(
ZYDIS_CONTEXT_INSTRUCTIONFORMATTER, formatter);
}
/* SymbolResolver =============================================================================== */
ZydisSymbolResolverContext* ZydisCreateCustomSymbolResolver(/*TODO*/)
{
return nullptr;
}
ZydisSymbolResolverContext* ZydisCreateExactSymbolResolver()
{
return ZydisCreateContext<ZydisSymbolResolverContext, Zydis::ExactSymbolResolver>(
ZYDIS_CONTEXT_SYMBOLRESOLVER_EXACT);
}
bool ZydisResolveSymbol(const ZydisSymbolResolverContext* resolver,
const ZydisInstructionInfo* info, uint64_t address, const char** symbol, uint64_t* offset)
{
Zydis::BaseSymbolResolver* instance =
ZydisRetrieveInstance<ZydisSymbolResolverContext,
Zydis::BaseSymbolResolver>(ZYDIS_CONTEXT_SYMBOLRESOLVER, resolver);
if (!instance)
{
return false;
}
*symbol = instance->resolveSymbol(*reinterpret_cast<const Zydis::InstructionInfo*>(info),
address, *offset);
return true;
}
bool ZydisExactSymbolResolverContainsSymbol(
const ZydisSymbolResolverContext* resolver, uint64_t address, bool* containsSymbol)
{
Zydis::ExactSymbolResolver* instance =
ZydisRetrieveInstance<ZydisSymbolResolverContext,
Zydis::ExactSymbolResolver>(ZYDIS_CONTEXT_SYMBOLRESOLVER_EXACT, resolver);
if (!instance)
{
return false;
}
*containsSymbol = instance->containsSymbol(address);
return true;
}
bool ZydisExactSymbolResolverSetSymbol(const ZydisSymbolResolverContext* resolver,
uint64_t address, const char* name)
{
Zydis::ExactSymbolResolver* instance =
ZydisRetrieveInstance<ZydisSymbolResolverContext,
Zydis::ExactSymbolResolver>(ZYDIS_CONTEXT_SYMBOLRESOLVER_EXACT, resolver);
if (!instance)
{
return false;
}
instance->setSymbol(address, name);
return true;
}
bool ZydisExactSymbolResolverRemoveSymbol(const ZydisSymbolResolverContext* resolver,
uint64_t address)
{
Zydis::ExactSymbolResolver* instance =
ZydisRetrieveInstance<ZydisSymbolResolverContext,
Zydis::ExactSymbolResolver>(ZYDIS_CONTEXT_SYMBOLRESOLVER_EXACT, resolver);
if (!instance)
{
return false;
}
instance->removeSymbol(address);
return true;
}
bool ZydisExactSymbolResolverClear(const ZydisSymbolResolverContext* resolver)
{
Zydis::ExactSymbolResolver* instance =
ZydisRetrieveInstance<ZydisSymbolResolverContext,
Zydis::ExactSymbolResolver>(ZYDIS_CONTEXT_SYMBOLRESOLVER_EXACT, resolver);
if (!instance)
{
return false;
}
instance->clear();
return true;
}
bool ZydisFreeSymbolResolver(const ZydisSymbolResolverContext* resolver)
{
return ZydisFreeContext<ZydisSymbolResolverContext, Zydis::BaseSymbolResolver>(
ZYDIS_CONTEXT_SYMBOLRESOLVER, resolver);
}
/* ============================================================================================== */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,728 +0,0 @@
/***************************************************************************************************
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.
***************************************************************************************************/
/**
* @file
* @brief Instruction decoder classes.
*/
#ifndef _ZYDIS_INSTRUCTIONDECODER_HPP_
#define _ZYDIS_INSTRUCTIONDECODER_HPP_
#include <type_traits>
#include <istream>
#include "ZydisTypes.hpp"
namespace Zydis
{
/* BaseInput ==================================================================================== */
/**
* @brief The base class for all data-source implementations.
*/
class BaseInput
{
friend class InstructionDecoder;
private:
uint8_t m_currentInput;
private:
/**
* @brief Reads the next byte from the data source. This method does NOT increase the
* current input position or the @c length field of the @c info parameter.
* @param info The instruction info.
* @return The current input byte. If the result is zero, you should always check the
* @c flags field of the @c info parameter for error flags.
* Possible error values are @c IF_ERROR_END_OF_INPUT or @c IF_ERROR_LENGTH.
*/
uint8_t inputPeek(InstructionInfo& info);
/**
* @brief Reads the next byte from the data source. This method increases the current
* input position and the @c length field of the @c info parameter.
* This method also appends the new byte to to @c data field of the @c info
* parameter.
* @param info The instruction info.
* @return The current input byte. If the result is zero, you should always check the
* @c flags field of the @c info parameter for error flags.
* Possible error values are @c IF_ERROR_END_OF_INPUT or @c IF_ERROR_LENGTH.
*/
uint8_t inputNext(InstructionInfo& info);
/**
* @brief Reads the next byte(s) from the data source. This method increases the current
* input position and the @c length field of the @c info parameter.
* This method also appends the new byte(s) to to @c data field of the @c info
* parameter.
* @param info The instruction info.
* @return The current input data. If the result is zero, you should always check the
* @c flags field of the @c info parameter for error flags.
* Possible error values are @c IF_ERROR_END_OF_INPUT or @c IF_ERROR_LENGTH.
*/
template <typename T>
T inputNext(InstructionInfo& info);
/**
* @brief Returns the current input byte. The current input byte is set everytime the
* @c inputPeek or @c inputNext method is called.
* @return The current input byte.
*/
uint8_t inputCurrent() const;
protected:
/**
* @brief Override this method in your custom data source implementations.
* Reads the next byte from the data source. This method increases the current
* input position by one.
* @return The current input byte.
*/
virtual uint8_t internalInputPeek() = 0;
/**
* @brief Override this method in your custom data source implementations.
* Reads the next byte from the data source. This method does NOT increase the
* current input position.
* @return The current input byte.
*/
virtual uint8_t internalInputNext() = 0;
protected:
/**
* @brief Default constructor.
*/
BaseInput() { };
public:
/**
* @brief Destructor.
*/
virtual ~BaseInput() { };
public:
/**
* @brief Override this method in your custom data source implementations.
* Signals, if the end of the data source is reached.
* @return True if end of input, false if not.
*/
virtual bool isEndOfInput() const = 0;
/**
* @brief Override this method in your custom data source implementations.
* Returns the current input position.
* @return The current input position.
*/
virtual uint64_t getPosition() const = 0;
/**
* @brief Override this method in your custom data source implementations.
* Sets a new input position.
* @param position The new input position.
* @return Returns false, if the new position exceeds the maximum input length.
*/
virtual bool setPosition(uint64_t position) = 0;
};
inline uint8_t BaseInput::inputPeek(InstructionInfo& info)
{
if (info.length == 15)
{
info.flags |= IF_ERROR_LENGTH;
return 0;
}
if (isEndOfInput())
{
info.flags |= IF_ERROR_END_OF_INPUT;
return 0;
}
m_currentInput = internalInputPeek();
return m_currentInput;
}
inline uint8_t BaseInput::inputNext(InstructionInfo& info)
{
if (info.length == 15)
{
info.flags |= IF_ERROR_LENGTH;
return 0;
}
if (isEndOfInput())
{
info.flags |= IF_ERROR_END_OF_INPUT;
return 0;
}
m_currentInput = internalInputNext();
info.data[info.length] = m_currentInput;
info.length++;
return m_currentInput;
}
template <typename T>
inline T BaseInput::inputNext(InstructionInfo& info)
{
static_assert(std::is_integral<T>::value, "integral type required");
T result = 0;
for (unsigned i = 0; i < (sizeof(T) / sizeof(uint8_t)); ++i)
{
T b = inputNext(info);
if (!b && (info.flags & IF_ERROR_MASK))
{
return 0;
}
result |= (b << (i * 8));
}
return result;
}
inline uint8_t BaseInput::inputCurrent() const
{
return m_currentInput;
}
/* MemoryInput ================================================================================== */
/**
* @brief A memory-buffer based data source for the @c InstructionDecoder class.
*/
class MemoryInput : public BaseInput
{
private:
const void* m_inputBuffer;
uint64_t m_inputBufferLen;
uint64_t m_inputBufferPos;
protected:
/**
* @brief Reads the next byte from the data source. This method increases the current
* input position by one.
* @return The current input byte.
*/
uint8_t internalInputPeek() override;
/**
* @brief Reads the next byte from the data source. This method does NOT increase the
* current input position.
* @return The current input byte.
*/
uint8_t internalInputNext() override;
public:
/**
* @brief Constructor.
* @param buffer The input buffer.
* @param bufferLen The length of the input buffer.
*/
MemoryInput(const void* buffer, size_t bufferLen)
: m_inputBuffer(buffer)
, m_inputBufferLen(bufferLen)
, m_inputBufferPos(0) { };
public:
/**
* @brief Signals, if the end of the data source is reached.
* @return True if end of input, false if not.
*/
bool isEndOfInput() const override;
/**
* @brief Returns the current input position.
* @return The current input position.
*/
uint64_t getPosition() const override;
/**
* @brief Sets a new input position.
* @param position The new input position.
* @return Returns false, if the new position exceeds the maximum input length.
*/
bool setPosition(uint64_t position) override;
};
inline uint8_t MemoryInput::internalInputPeek()
{
return *(static_cast<const uint8_t*>(m_inputBuffer) + m_inputBufferPos);
}
inline uint8_t MemoryInput::internalInputNext()
{
++m_inputBufferPos;
return *(static_cast<const uint8_t*>(m_inputBuffer) + m_inputBufferPos - 1);
}
inline bool MemoryInput::isEndOfInput() const
{
return (m_inputBufferPos >= m_inputBufferLen);
}
inline uint64_t MemoryInput::getPosition() const
{
return m_inputBufferPos;
}
inline bool MemoryInput::setPosition(uint64_t position)
{
m_inputBufferPos = position;
return isEndOfInput();
}
/* StreamInput ================================================================================== */
/**
* @brief A stream based data source for the @c InstructionDecoder class.
*/
class StreamInput : public BaseInput
{
private:
std::istream* m_inputStream;
protected:
/**
* @brief Reads the next byte from the data source. This method increases the current
* input position by one.
* @return The current input byte.
*/
uint8_t internalInputPeek() override;
/**
* @brief Reads the next byte from the data source. This method does NOT increase the
* current input position.
* @return The current input byte.
*/
uint8_t internalInputNext() override;
public:
/**
* @brief Constructor.
* @param stream The input stream.
*/
explicit StreamInput(std::istream* stream)
: m_inputStream(stream) { };
public:
/**
* @brief Signals, if the end of the data source is reached.
* @return True if end of input, false if not.
*/
bool isEndOfInput() const override;
/**
* @brief Returns the current input position.
* @return The current input position.
*/
uint64_t getPosition() const override;
/**
* @brief Sets a new input position.
* @param position The new input position.
* @return Returns false, if the new position exceeds the maximum input length.
*/
bool setPosition(uint64_t position) override;
};
inline uint8_t StreamInput::internalInputPeek()
{
if (!m_inputStream)
{
return 0;
}
return static_cast<uint8_t>(m_inputStream->peek());
}
inline uint8_t StreamInput::internalInputNext()
{
if (!m_inputStream)
{
return 0;
}
return static_cast<uint8_t>(m_inputStream->get());
}
inline bool StreamInput::isEndOfInput() const
{
if (!m_inputStream)
{
return true;
}
// We use good() instead of eof() to make sure the decoding will fail, if an stream internal
// error occured.
return !m_inputStream->good();
}
inline uint64_t StreamInput::getPosition() const
{
if (!m_inputStream)
{
return 0;
}
return m_inputStream->tellg();
}
inline bool StreamInput::setPosition(uint64_t position)
{
if (!m_inputStream)
{
return false;
}
m_inputStream->seekg(position);
return isEndOfInput();
}
/* Enums ======================================================================================== */
/**
* @brief Values that represent a disassembler mode.
*/
enum class DisassemblerMode : uint8_t
{
M16BIT,
M32BIT,
M64BIT
};
/**
* @brief Values that represent an instruction-set vendor.
*/
enum class InstructionSetVendor : uint8_t
{
ANY,
INTEL,
AMD
};
/* InstructionDecoder =========================================================================== */
/**
* @brief The @c InstructionDecoder class decodes x86/x86-64 assembly instructions from a
* given data source.
*/
class InstructionDecoder
{
private:
enum class RegisterClass : uint8_t
{
GENERAL_PURPOSE,
MMX,
CONTROL,
DEBUG,
SEGMENT,
XMM
};
private:
BaseInput* m_input;
DisassemblerMode m_disassemblerMode;
InstructionSetVendor m_preferredVendor;
uint64_t m_instructionPointer;
private:
/**
* @brief Reads the next byte from the data source. This method does NOT increase the
* current input position or the @c length field of the @c info parameter.
* @param info The instruction info.
* @return The current input byte. If the result is zero, you should always check the
* @c flags field of the @c info parameter for error flags.
* Possible error values are @c IF_ERROR_END_OF_INPUT or @c IF_ERROR_LENGTH.
*/
uint8_t inputPeek(InstructionInfo& info);
/**
* @brief Reads the next byte from the data source. This method increases the current
* input position and the @c length field of the @info parameter.
* This method also appends the new byte to to @c data field of the @c info
* parameter.
* @param info The instruction info.
* @return The current input byte. If the result is zero, you should always check the
* @c flags field of the @c info parameter for error flags.
* Possible error values are @c IF_ERROR_END_OF_INPUT or @c IF_ERROR_LENGTH.
*/
uint8_t inputNext(InstructionInfo& info);
/**
* @brief Reads the next byte(s) from the data source. This method increases the current
* input position and the @c length field of the @info parameter.
* This method also appends the new byte(s) to to @c data field of the @c info
* parameter.
* @param info The instruction info.
* @return The current input data. If the result is zero, you should always check the
* @c flags field of the @c info parameter for error flags.
* Possible error values are @c IF_ERROR_END_OF_INPUT or @c IF_ERROR_LENGTH.
*/
template <typename T>
T inputNext(InstructionInfo& info);
/**
* @brief Returns the current input byte. The current input byte is set everytime the
* @c inputPeek or @c inputNext method is called.
* @return The current input byte.
*/
uint8_t inputCurrent() const;
private:
/**
* @brief Decodes a register operand.
* @param info The instruction info.
* @param operand The @c OperandInfo struct that receives the decoded data.
* @param registerClass The register class to use.
* @param registerId The register id.
* @param operandSize The defined size of the operand.
* @return True if it succeeds, false if it fails.
*/
bool decodeRegisterOperand(InstructionInfo& info, OperandInfo& operand,
RegisterClass registerClass, uint8_t registerId, DefinedOperandSize operandSize) const;
/**
* @brief Decodes a register/memory operand.
* @param info The instruction info.
* @param operand The @c OperandInfo struct that receives the decoded data.
* @param registerClass The register class to use.
* @param operandSize The defined size of the operand.
* @return True if it succeeds, false if it fails.
*/
bool decodeRegisterMemoryOperand(InstructionInfo& info, OperandInfo& operand,
RegisterClass registerClass, DefinedOperandSize operandSize);
/**
* @brief Decodes an immediate operand.
* @param info The instruction info.
* @param operand The @c OperandInfo struct that receives the decoded data.
* @param operandSize The defined size of the operand.
* @return True if it succeeds, false if it fails.
*/
bool decodeImmediate(InstructionInfo& info, OperandInfo& operand,
DefinedOperandSize operandSize);
/**
* @brief Decodes a displacement operand.
* @param info The instruction info.
* @param operand The @c OperandInfo struct that receives the decoded data.
* @param size The size of the displacement data.
* @return True if it succeeds, false if it fails.
*/
bool decodeDisplacement(InstructionInfo& info, OperandInfo& operand, uint8_t size);
private:
/**
* @brief Decodes the modrm field of the instruction. This method reads an additional
* input byte.
* @param The @c InstructionInfo struct that receives the decoded data.
* @return True if it succeeds, false if it fails.
*/
bool decodeModrm(InstructionInfo& info);
/**
* @brief Decodes the sib field of the instruction. This method reads an additional
* input byte.
* @param info The @c InstructionInfo struct that receives the decoded data.
* @return True if it succeeds, false if it fails.
*/
bool decodeSIB(InstructionInfo& info);
/**
* @brief Decodes vex prefix of the instruction. This method takes the current input byte
* to determine the vex prefix type and reads one or two additional input bytes
* on demand.
* @param info The @c InstructionInfo struct that receives the decoded data.
* @return True if it succeeds, false if it fails.
*/
bool decodeVex(InstructionInfo& info);
private:
/**
* @brief Returns the effective operand size.
* @param info The instruction info.
* @param operandSize The defined operand size.
* @return The effective operand size.
*/
uint16_t getEffectiveOperandSize(const InstructionInfo& info,
DefinedOperandSize operandSize) const;
/**
* @brief Decodes all instruction operands.
* @param info The @c InstructionInfo struct that receives the decoded data.
* @return True if it succeeds, false if it fails.
*/
bool decodeOperands(InstructionInfo& info);
/**
* @brief Decodes the specified instruction operand.
* @param info The instruction info.
* @param operand The @c OperandInfo struct that receives the decoded data.
* @param operandType The defined type of the operand.
* @param operandSize The defined size of the operand.
* @return True if it succeeds, false if it fails.
*/
bool decodeOperand(InstructionInfo& info, OperandInfo& operand,
DefinedOperandType operandType, DefinedOperandSize operandSize);
private:
/**
* @brief Resolves the effective operand and address mode of the instruction.
* This method requires a non-null value in the @c instrDefinition field of the
* @c info struct.
* @param info The @c InstructionInfo struct that receives the effective operand and
* address mode.
*/
void resolveOperandAndAddressMode(InstructionInfo& info) const;
/**
* @brief Calculates the effective REX/VEX.w, r, x, b, l values.
* This method requires a non-null value in the @c instrDefinition field of the
* @c info struct.
* @param info The @c InstructionInfo struct that receives the effective operand and
* address mode.
*/
void calculateEffectiveRexVexValues(InstructionInfo& info) const;
private:
/**
* @brief Collects and decodes optional instruction prefixes.
* @param info The @c InstructionInfo struct that receives the decoded data.
* @return True if it succeeds, false if it fails.
*/
bool decodePrefixes(InstructionInfo& info);
/**
* @brief Collects and decodes the instruction opcodes using the opcode tree.
* @param info The @c InstructionInfo struct that receives the decoded data.
* @return True if it succeeds, false if it fails.
*/
bool decodeOpcode(InstructionInfo& info);
public:
/**
* @brief Default constructor.
*/
InstructionDecoder();
/**
* @brief Constructor.
* @param input A reference to the input data source.
* @param disassemblerMode The disasasembler mode.
* @param preferredVendor The preferred instruction-set vendor.
* @param instructionPointer The initial instruction pointer.
*/
explicit InstructionDecoder(BaseInput* input,
DisassemblerMode disassemblerMode = DisassemblerMode::M32BIT,
InstructionSetVendor preferredVendor = InstructionSetVendor::ANY,
uint64_t instructionPointer = 0);
public:
/**
* @brief Decodes the next instruction from the input data source.
* @param info The @c InstructionInfo struct that receives the information about the
* decoded instruction.
* @return This method returns false, if the current position has exceeded the maximum input
* length.
* In all other cases (valid and invalid instructions) the return value is true.
*/
bool decodeInstruction(InstructionInfo& info);
public:
/**
* @brief Returns a pointer to the current data source.
* @return A pointer to the current data source.
*/
BaseInput* getDataSource() const;
/**
* @brief Sets a new data source.
* @param input A reference to the new input data source.
*/
void setDataSource(BaseInput* input);
/**
* @brief Returns the current disassembler mode.
* @return The current disassembler mode.
*/
DisassemblerMode getDisassemblerMode() const;
/**
* @brief Sets the current disassembler mode.
* @param disassemblerMode The new disassembler mode.
*/
void setDisassemblerMode(DisassemblerMode disassemblerMode);
/**
* @brief Returns the preferred instruction-set vendor.
* @return The preferred instruction-set vendor.
*/
InstructionSetVendor getPreferredVendor() const;
/**
* @brief Sets the preferred instruction-set vendor.
* @param preferredVendor The new preferred instruction-set vendor.
*/
void setPreferredVendor(InstructionSetVendor preferredVendor);
/**
* @brief Returns the current instruction pointer.
* @return The current instruction pointer.
*/
uint64_t getInstructionPointer() const;
/**
* @brief Sets a new instruction pointer.
* @param instructionPointer The new instruction pointer.
*/
void setInstructionPointer(uint64_t instructionPointer);
};
inline uint8_t InstructionDecoder::inputPeek(InstructionInfo& info)
{
if (!m_input)
{
info.flags |= IF_ERROR_END_OF_INPUT;
return 0;
}
return m_input->inputPeek(info);
}
inline uint8_t InstructionDecoder::inputNext(InstructionInfo& info)
{
if (!m_input)
{
info.flags |= IF_ERROR_END_OF_INPUT;
return 0;
}
return m_input->inputNext(info);
}
template <typename T>
inline T InstructionDecoder::inputNext(InstructionInfo& info)
{
if (!m_input)
{
info.flags |= IF_ERROR_END_OF_INPUT;
return 0;
}
return m_input->inputNext<T>(info);
}
inline uint8_t InstructionDecoder::inputCurrent() const
{
if (!m_input)
{
return 0;
}
return m_input->inputCurrent();
}
inline BaseInput *InstructionDecoder::getDataSource() const
{
return m_input;
}
inline void InstructionDecoder::setDataSource(BaseInput* input)
{
m_input = input;
}
inline DisassemblerMode InstructionDecoder::getDisassemblerMode() const
{
return m_disassemblerMode;
}
inline void InstructionDecoder::setDisassemblerMode(DisassemblerMode disassemblerMode)
{
m_disassemblerMode = disassemblerMode;
}
inline InstructionSetVendor InstructionDecoder::getPreferredVendor() const
{
return m_preferredVendor;
}
inline void InstructionDecoder::setPreferredVendor(InstructionSetVendor preferredVendor)
{
m_preferredVendor = preferredVendor;
}
inline uint64_t InstructionDecoder::getInstructionPointer() const
{
return m_instructionPointer;
}
inline void InstructionDecoder::setInstructionPointer(uint64_t instructionPointer)
{
m_instructionPointer = instructionPointer;
}
/* ============================================================================================== */
}
#endif /* _ZYDIS_INSTRUCTIONDECODER_HPP_ */

View File

@ -1,602 +0,0 @@
/***************************************************************************************************
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 "ZydisInstructionFormatter.hpp"
#include "ZydisUtils.hpp"
#include <cstdarg>
#include <cctype>
#include <cstdio>
#include <cstring>
namespace Zydis
{
/* BaseInstructionFormatter ================================================================ */
const char* BaseInstructionFormatter::m_registerStrings[] =
{
/* 8 bit general purpose registers */
"al", "cl", "dl", "bl",
"ah", "ch", "dh", "bh",
"spl", "bpl", "sil", "dil",
"r8b", "r9b", "r10b", "r11b",
"r12b", "r13b", "r14b", "r15b",
/* 16 bit general purpose registers */
"ax", "cx", "dx", "bx",
"sp", "bp", "si", "di",
"r8w", "r9w", "r10w", "r11w",
"r12w", "r13w", "r14w", "r15w",
/* 32 bit general purpose registers */
"eax", "ecx", "edx", "ebx",
"esp", "ebp", "esi", "edi",
"r8d", "r9d", "r10d", "r11d",
"r12d", "r13d", "r14d", "r15d",
/* 64 bit general purpose registers */
"rax", "rcx", "rdx", "rbx",
"rsp", "rbp", "rsi", "rdi",
"r8", "r9", "r10", "r11",
"r12", "r13", "r14", "r15",
/* segment registers */
"es", "cs", "ss",
"ds", "fs", "gs",
/* control registers */
"cr0", "cr1", "cr2", "cr3",
"cr4", "cr5", "cr6", "cr7",
"cr8", "cr9", "cr10", "cr11",
"cr12", "cr13", "cr14", "cr15",
/* debug registers */
"dr0", "dr1", "dr2", "dr3",
"dr4", "dr5", "dr6", "dr7",
"dr8", "dr9", "dr10", "dr11",
"dr12", "dr13", "dr14", "dr15",
/* mmx registers */
"mm0", "mm1", "mm2", "mm3",
"mm4", "mm5", "mm6", "mm7",
/* x87 registers */
"st0", "st1", "st2", "st3",
"st4", "st5", "st6", "st7",
/* extended multimedia registers */
"xmm0", "xmm1", "xmm2", "xmm3",
"xmm4", "xmm5", "xmm6", "xmm7",
"xmm8", "xmm9", "xmm10", "xmm11",
"xmm12", "xmm13", "xmm14", "xmm15",
/* 256 bit multimedia registers */
"ymm0", "ymm1", "ymm2", "ymm3",
"ymm4", "ymm5", "ymm6", "ymm7",
"ymm8", "ymm9", "ymm10", "ymm11",
"ymm12", "ymm13", "ymm14", "ymm15",
/* instruction pointer register */
"rip"
};
void BaseInstructionFormatter::internalFormatInstruction(const InstructionInfo& /*info*/)
{
// Nothing to do here
}
BaseInstructionFormatter::BaseInstructionFormatter()
: m_symbolResolver(nullptr)
, m_outputStringLen(0)
, m_outputUppercase(false)
{
}
BaseInstructionFormatter::BaseInstructionFormatter(
BaseSymbolResolver *symbolResolver)
: m_symbolResolver(symbolResolver)
, m_outputStringLen(0)
, m_outputUppercase(false)
{
}
const char* BaseInstructionFormatter::formatInstruction(const InstructionInfo& info)
{
// Clears the internal string buffer
outputClear();
// Calls the virtual format method that actually formats the instruction
internalFormatInstruction(info);
if (m_outputBuffer.size() == 0)
{
// The basic instruction formatter only returns the instruction menmonic.
return Internal::GetInstructionMnemonicString(info.mnemonic);
}
// Return the formatted instruction string
return outputString();
}
BaseInstructionFormatter::~BaseInstructionFormatter()
{
}
void BaseInstructionFormatter::outputClear()
{
m_outputStringLen = 0;
}
char const *BaseInstructionFormatter::outputString()
{
return& m_outputBuffer[0];
}
void BaseInstructionFormatter::outputAppend(char const* text)
{
// Get the string length including the null-terminator char
size_t strLen = strlen(text) + 1;
// Get the buffer size
size_t bufLen = m_outputBuffer.size();
// Decrease the offset by one, to exclude already existing null-terminator chars in the
// output buffer
size_t offset = (m_outputStringLen) ? m_outputStringLen - 1 : 0;
// Resize capacity of the output buffer on demand and add some extra space to improve the
// performance
if (bufLen <= (m_outputStringLen + strLen))
{
m_outputBuffer.resize(bufLen + strLen + 512);
}
// Write the text to the output buffer
memcpy(&m_outputBuffer[offset], text, strLen);
// Increase the string length
m_outputStringLen = offset + strLen;
// Convert to uppercase
if (m_outputUppercase)
{
for (size_t i = offset; i < m_outputStringLen - 1; ++i)
{
m_outputBuffer[i] = static_cast<char>(toupper(m_outputBuffer[i]));
}
}
}
void BaseInstructionFormatter::outputAppendFormatted(char const* format, ...)
{
va_list arguments;
va_start(arguments, format);
// Get the buffer size
size_t bufLen = m_outputBuffer.size();
// Decrease the offset by one, to exclude already existing null-terminator chars in the
// output buffer
size_t offset = (m_outputStringLen) ? m_outputStringLen - 1 : 0;
// Resize the output buffer on demand and add some extra space to improve the performance
if ((bufLen - m_outputStringLen) < 256)
{
bufLen = bufLen + 512;
m_outputBuffer.resize(bufLen);
}
int strLen = 0;
do
{
// If the formatted text did not fit in the output buffer, resize it, and try again
if (strLen < 0)
{
m_outputBuffer.resize(bufLen + 512);
return outputAppendFormatted(format, arguments);
}
// Write the formatted text to the output buffer
assert((bufLen - offset) > 0);
strLen = std::vsnprintf(&m_outputBuffer[offset], bufLen - offset, format, arguments);
} while (strLen < 0);
// Increase the string length
m_outputStringLen = offset + strLen + 1;
// Convert to uppercase
if (m_outputUppercase)
{
for (size_t i = offset; i < m_outputStringLen - 1; ++i)
{
m_outputBuffer[i] = static_cast<char>(toupper(m_outputBuffer[i]));
}
}
va_end(arguments);
}
void BaseInstructionFormatter::outputAppendAddress(const InstructionInfo& info,
uint64_t address, bool resolveSymbols)
{
uint64_t offset = 0;
const char *name = nullptr;
if (resolveSymbols)
{
name = resolveSymbol(info, address, offset);
}
if (name)
{
if (offset)
{
outputAppendFormatted("%s+%.2llX", name, offset);
} else
{
outputAppend(name);
}
} else
{
if (info.flags & IF_DISASSEMBLER_MODE_16)
{
outputAppendFormatted("%.4X", address);
} else if (info.flags & IF_DISASSEMBLER_MODE_32)
{
outputAppendFormatted("%.8lX", address);
} else if (info.flags & IF_DISASSEMBLER_MODE_64)
{
outputAppendFormatted("%.16llX", address);
} else
{
assert(0);
}
}
}
void BaseInstructionFormatter::outputAppendImmediate(const InstructionInfo& info,
const OperandInfo& operand, bool resolveSymbols)
{
assert(operand.type == OperandType::IMMEDIATE);
uint64_t value = 0;
if (operand.signed_lval&& (operand.size != info.operand_mode))
{
if (operand.size == 8)
{
value = static_cast<int64_t>(operand.lval.sbyte);
} else
{
assert(operand.size == 32);
value = static_cast<int64_t>(operand.lval.sdword);
}
if (info.operand_mode < 64)
{
value = value& ((1ull << info.operand_mode) - 1ull);
}
} else
{
switch (operand.size)
{
case 8:
value = operand.lval.ubyte;
break;
case 16:
value = operand.lval.uword;
break;
case 32:
value = operand.lval.udword;
break;
case 64:
value = operand.lval.uqword;
break;
default:
assert(0);
}
}
uint64_t offset = 0;
const char* name = nullptr;
if (resolveSymbols)
{
name = resolveSymbol(info, value, offset);
}
if (name)
{
if (offset)
{
outputAppendFormatted("%s+%.2llX", name, offset);
} else
{
outputAppend(name);
}
} else
{
outputAppendFormatted("%.2llX", value);
}
}
void BaseInstructionFormatter::outputAppendDisplacement(const OperandInfo& operand)
{
assert(operand.offset > 0);
if ((operand.base == Register::NONE) && (operand.index == Register::NONE))
{
// Assume the displacement value is unsigned
assert(operand.scale == 0);
assert(operand.offset != 8);
uint64_t value = 0;
switch (operand.offset)
{
case 16:
value = operand.lval.uword;
break;
case 32:
value = operand.lval.udword;
break;
case 64:
value = operand.lval.uqword;
break;
default:
assert(0);
}
outputAppendFormatted("%.2llX", value);
} else
{
// The displacement value might be negative
assert(operand.offset != 64);
int64_t value = 0;
switch (operand.offset)
{
case 8:
value = operand.lval.sbyte;
break;
case 16:
value = operand.lval.sword;
break;
case 32:
value = operand.lval.sdword;
break;
default:
assert(0);
}
if (value < 0)
{
outputAppendFormatted("-%.2lX", -value);
} else
{
outputAppendFormatted("%s%.2lX", (operand.base != Register::NONE ||
operand.index != Register::NONE) ? "+" : "", value);
}
}
}
/* IntelInstructionFormatter =============================================================== */
void IntelInstructionFormatter::outputAppendOperandCast(const OperandInfo& operand)
{
switch(operand.size)
{
case 8:
outputAppend("byte ptr " );
break;
case 16:
outputAppend("word ptr " );
break;
case 32:
outputAppend("dword ptr ");
break;
case 64:
outputAppend("qword ptr ");
break;
case 80:
outputAppend("tword ptr ");
break;
case 128:
outputAppend("oword ptr ");
break;
case 256:
outputAppend("yword ptr ");
break;
default:
break;
}
}
void IntelInstructionFormatter::formatOperand(const InstructionInfo& info,
const OperandInfo& operand)
{
switch (operand.type)
{
case OperandType::REGISTER:
outputAppend(registerToString(operand.base));
break;
case OperandType::MEMORY:
if (info.flags & IF_PREFIX_SEGMENT)
{
outputAppendFormatted("%s:", registerToString(info.segment));
}
outputAppend("[");
if (operand.base == Register::RIP)
{
// TODO: Add option
outputAppendAddress(info, CalcAbsoluteTarget(info, operand), true);
} else
{
if (operand.base != Register::NONE)
{
outputAppend(registerToString(operand.base));
}
if (operand.index != Register::NONE)
{
outputAppendFormatted("%s%s", operand.base != Register::NONE ? "+" : "",
registerToString(operand.index));
if (operand.scale)
{
outputAppendFormatted("*%d", operand.scale);
}
}
if (operand.offset)
{
outputAppendDisplacement(operand);
}
}
outputAppend("]");
break;
case OperandType::POINTER:
// TODO: resolve symbols
switch (operand.size)
{
case 32:
outputAppendFormatted("word %.4X:%.4X", operand.lval.ptr.seg,
operand.lval.ptr.off& 0xFFFF);
break;
case 48:
outputAppendFormatted("dword %.4X:%.8lX", operand.lval.ptr.seg, operand.lval.ptr.off);
break;
default:
assert(0);
}
break;
case OperandType::IMMEDIATE:
{
outputAppendImmediate(info, operand, true);
}
break;
case OperandType::REL_IMMEDIATE:
{
if (operand.size == 8)
{
outputAppend("short ");
}
outputAppendAddress(info, CalcAbsoluteTarget(info, operand), true);
}
break;
case OperandType::CONSTANT:
outputAppendFormatted("%.2X", operand.lval.udword);
break;
default:
assert(0);
break;
}
}
void IntelInstructionFormatter::internalFormatInstruction(const InstructionInfo& info)
{
// Append string prefixes
if (info.flags & IF_PREFIX_LOCK)
{
outputAppend("lock ");
}
if (info.flags & IF_PREFIX_REP)
{
outputAppend("rep ");
} else if (info.flags & IF_PREFIX_REPNE)
{
outputAppend("repne ");
}
// Append the instruction mnemonic
outputAppend(Internal::GetInstructionMnemonicString(info.mnemonic));
// Append the first operand
if (info.operand[0].type != OperandType::NONE)
{
outputAppend(" ");
bool cast = false;
if (info.operand[0].type == OperandType::MEMORY)
{
if (info.operand[1].type == OperandType::IMMEDIATE ||
info.operand[1].type == OperandType::CONSTANT ||
info.operand[1].type == OperandType::NONE ||
(info.operand[0].size != info.operand[1].size))
{
cast = true;
} else if (info.operand[1].type == OperandType::REGISTER &&
info.operand[1].base == Register::CL)
{
switch (info.mnemonic)
{
case InstructionMnemonic::RCL:
case InstructionMnemonic::ROL:
case InstructionMnemonic::ROR:
case InstructionMnemonic::RCR:
case InstructionMnemonic::SHL:
case InstructionMnemonic::SHR:
case InstructionMnemonic::SAR:
cast = true;
break;
default:
break;
}
}
}
if (cast)
{
outputAppendOperandCast(info.operand[0]);
}
formatOperand(info, info.operand[0]);
}
// Append the second operand
if (info.operand[1].type != OperandType::NONE)
{
outputAppend(", ");
bool cast = false;
if (info.operand[1].type == OperandType::MEMORY &&
info.operand[0].size != info.operand[1].size &&
((info.operand[0].type != OperandType::REGISTER) ||
((info.operand[0].base != Register::ES) &&
(info.operand[0].base != Register::CS) &&
(info.operand[0].base != Register::SS) &&
(info.operand[0].base != Register::DS) &&
(info.operand[0].base != Register::FS) &&
(info.operand[0].base != Register::GS))))
{
cast = true;
}
if (cast)
{
outputAppendOperandCast(info.operand[1]);
}
formatOperand(info, info.operand[1]);
}
// Append the third operand
if (info.operand[2].type != OperandType::NONE)
{
outputAppend(", ");
bool cast = false;
if (info.operand[2].type == OperandType::MEMORY &&
(info.operand[2].size != info.operand[1].size))
{
cast = true;
}
if (cast)
{
outputAppendOperandCast(info.operand[2]);
}
formatOperand(info, info.operand[2]);
}
// Append the fourth operand
if (info.operand[3].type != OperandType::NONE)
{
outputAppend(", ");
formatOperand(info, info.operand[3]);
}
}
IntelInstructionFormatter::IntelInstructionFormatter()
: BaseInstructionFormatter()
{
}
IntelInstructionFormatter::IntelInstructionFormatter(
BaseSymbolResolver *symbolResolver)
: BaseInstructionFormatter(symbolResolver)
{
}
IntelInstructionFormatter::~IntelInstructionFormatter()
{
}
/* ============================================================================================== */
}

View File

@ -1,250 +0,0 @@
/***************************************************************************************************
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.
***************************************************************************************************/
/**
* @file
* @brief Instruction formatting classes.
*/
#ifndef _ZYDIS_INSTRUCTIONFORMATTER_HPP_
#define _ZYDIS_INSTRUCTIONFORMATTER_HPP_
#include <vector>
#include "ZydisTypes.hpp"
#include "ZydisSymbolResolver.hpp"
namespace Zydis
{
/* BaseInstructionFormatter ===================================================================== */
/**
* @brief Base class for all instruction formatter implementations.
*/
class BaseInstructionFormatter
{
private:
static const char* m_registerStrings[];
BaseSymbolResolver* m_symbolResolver;
std::vector<char> m_outputBuffer;
size_t m_outputStringLen;
bool m_outputUppercase;
protected:
/**
* @brief Clears the output string buffer.
*/
void outputClear();
/**
* @brief Returns the content of the output string buffer.
* @return Pointer to the content of the ouput string buffer.
*/
const char* outputString();
/**
* @brief Appends text to the ouput string buffer.
* @param text The text.
*/
void outputAppend(const char* text);
/**
* @brief Appends formatted text to the output string buffer.
* @param format The format string.
*/
void outputAppendFormatted(const char* format, ...);
/**
* @brief Changes automatic conversion of characters to uppercase.
* @param uppercase Set true to enable automatic uppercase conversion.
*/
void outputSetUppercase(bool uppercase);
/**
* @brief Appends a formatted address to the output string buffer.
* @param info The instruction info.
* @param address The address.
* @param resolveSymbols If this parameter is true, the method will try to display a
* smybol name instead of the numeric value.
*/
void outputAppendAddress(const InstructionInfo& info, uint64_t address,
bool resolveSymbols = true);
/**
* @brief Appends a formatted immediate value to the output string buffer.
* @param info The instruction info.
* @param operand The immediate operand.
* @param resolveSymbols If this parameter is true, the method will try to display a
* smybol name instead of the numeric value.
*/
void outputAppendImmediate(const InstructionInfo& info, const OperandInfo& operand,
bool resolveSymbols = false);
/**
* @brief Appends a formatted memory displacement value to the output string buffer.
* @param operand The memory operand.
*/
void outputAppendDisplacement(const OperandInfo& operand);
protected:
/**
* @brief Returns the string representation of a given register.
* @param reg The register.
* @return The string representation of the given register.
*/
const char *registerToString(Register reg) const;
/**
* @brief Resolves a symbol.
* @param info The instruction info.
* @param address The address.
* @param offset Reference to an unsigned 64 bit integer that receives an offset
* relative to the base address of the symbol.
* @return The name of the symbol, if the symbol was found, @c NULL if not.
*/
const char* resolveSymbol(const InstructionInfo& info, uint64_t address,
uint64_t& offset) const;
protected:
/**
* @brief Override this method to implement a custom disassembly syntax. Use the
* @c outputAppend and @c outputAppendFormatted methods to fill the internal
* string buffer.
* @param info The instruction info.
*/
virtual void internalFormatInstruction(const InstructionInfo& info);
/**
* @brief Default constructor.
*/
BaseInstructionFormatter();
/**
* @brief Constructor.
* @param symbolResolver Pointer to a symbol resolver instance or @c NULL, if no smybol
* resolver should be used.
*/
explicit BaseInstructionFormatter(BaseSymbolResolver* symbolResolver);
public:
/**
* @brief Destructor.
*/
virtual ~BaseInstructionFormatter();
public:
/**
* @brief Formats a decoded instruction.
* @param info The instruction info.
* @return Pointer to the formatted instruction string.
*/
const char* formatInstruction(const InstructionInfo& info);
public:
/**
* @brief Returns a pointer to the current symbol resolver.
* @return Pointer to the current symbol resolver or @c NULL, if no symbol resolver is used.
*/
BaseSymbolResolver* getSymbolResolver() const;
/**
* @brief Sets a new symbol resolver.
* @param symbolResolver Pointer to a symbol resolver instance or @c NULL, if no smybol
* resolver should be used.
*/
void setSymbolResolver(BaseSymbolResolver* symbolResolver);
};
inline void BaseInstructionFormatter::outputSetUppercase(bool uppercase)
{
m_outputUppercase = uppercase;
}
inline char const* BaseInstructionFormatter::registerToString(Register reg) const
{
if (reg == Register::NONE)
{
return "error";
}
return m_registerStrings[static_cast<uint16_t>(reg) - 1];
}
inline char const* BaseInstructionFormatter::resolveSymbol(const InstructionInfo& info,
uint64_t address, uint64_t& offset) const
{
if (m_symbolResolver)
{
return m_symbolResolver->resolveSymbol(info, address, offset);
}
return nullptr;
}
inline BaseSymbolResolver* BaseInstructionFormatter::getSymbolResolver() const
{
return m_symbolResolver;
}
inline void BaseInstructionFormatter::setSymbolResolver(
BaseSymbolResolver* symbolResolver)
{
m_symbolResolver = symbolResolver;
}
/* IntelInstructionFormatter ==================================================================== */
/**
* @brief Intel syntax instruction formatter.
*/
class IntelInstructionFormatter : public BaseInstructionFormatter
{
private:
/**
* @brief Appends an operand cast to the output string buffer.
* @param operand The operand.
*/
void outputAppendOperandCast(const OperandInfo& operand);
/**
* @brief Formats the specified operand and appends the resulting string to the output
* buffer.
* @param info The instruction info.
* @param operand The operand.
*/
void formatOperand(const InstructionInfo& info, const OperandInfo& operand);
protected:
/**
* @brief Fills the internal string buffer with an intel style formatted instruction string.
* @param info The instruction info.
*/
void internalFormatInstruction(const InstructionInfo& info) override;
public:
/**
* @brief Default constructor.
*/
IntelInstructionFormatter();
/**
* @brief Constructor.
* @param symbolResolver Pointer to a symbol resolver instance or @c NULL, if no smybol
* resolver should be used.
*/
explicit IntelInstructionFormatter(BaseSymbolResolver* symbolResolver);
/**
* @brief Destructor.
*/
~IntelInstructionFormatter() override;
};
/* ============================================================================================== */
}
#endif /* _ZYDIS_INSTRUCTIONFORMATTER_HPP_ */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,91 +0,0 @@
/***************************************************************************************************
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 "ZydisSymbolResolver.hpp"
namespace Zydis
{
/* BaseSymbolResolver ====================================================================== */
BaseSymbolResolver::~BaseSymbolResolver()
{
}
const char* BaseSymbolResolver::resolveSymbol(const InstructionInfo& /*info*/,
uint64_t /*address*/, uint64_t& /*offset*/)
{
return nullptr;
}
/* ExactSymbolResolver ===================================================================== */
ExactSymbolResolver::~ExactSymbolResolver()
{
}
const char* ExactSymbolResolver::resolveSymbol(const InstructionInfo& /*info*/,
uint64_t address, uint64_t& offset)
{
std::unordered_map<uint64_t, std::string>::const_iterator iterator = m_symbolMap.find(address);
if (iterator != m_symbolMap.cend())
{
offset = 0;
return iterator->second.c_str();
}
return nullptr;
}
bool ExactSymbolResolver::containsSymbol(uint64_t address) const
{
std::unordered_map<uint64_t, std::string>::const_iterator iterator = m_symbolMap.find(address);
return (iterator != m_symbolMap.end());
}
void ExactSymbolResolver::setSymbol(uint64_t address, const char *name)
{
m_symbolMap[address].assign(name);
}
void ExactSymbolResolver::removeSymbol(uint64_t address)
{
m_symbolMap.erase(address);
}
void ExactSymbolResolver::clear()
{
m_symbolMap.clear();
}
/* ============================================================================================== */
}

View File

@ -1,125 +0,0 @@
/***************************************************************************************************
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.
***************************************************************************************************/
/**
* @file
* @brief Classes for symbol resolving in the disassembly.
*/
#ifndef _ZYDIS_SYMBOLRESOLVER_HPP_
#define _ZYDIS_SYMBOLRESOLVER_HPP_
#include <string>
#include <unordered_map>
#include "ZydisTypes.hpp"
namespace Zydis
{
/* BaseSymbolResolver =========================================================================== */
/**
* @brief Base class for all symbol resolver implementations.
*/
class BaseSymbolResolver
{
public:
/**
* @brief Destructor.
*/
virtual ~BaseSymbolResolver();
public:
/**
* @brief Resolves a symbol.
* @param info The instruction info.
* @param address The address.
* @param offset Reference to an unsigned 64 bit integer that receives an offset
* relative to the base address of the symbol.
* @return The name of the symbol, if the symbol was found, @c NULL if not.
*/
virtual const char* resolveSymbol(const InstructionInfo& info, uint64_t address,
uint64_t& offset);
};
/* ExactSymbolResolver ========================================================================== */
/**
* @brief Simple symbol resolver that only matches exact addresses.
*/
class ExactSymbolResolver : public BaseSymbolResolver
{
private:
std::unordered_map<uint64_t, std::string> m_symbolMap;
public:
/**
* @brief Destructor.
*/
~ExactSymbolResolver() override;
public:
/**
* @brief Resolves a symbol.
* @param info The instruction info.
* @param address The address.
* @param offset Reference to an unsigned 64 bit integer that receives an offset
* relative to the base address of the symbol.
* @return The name of the symbol, if the symbol was found, @c NULL if not.
*/
const char* resolveSymbol(const InstructionInfo& info, uint64_t address,
uint64_t& offset) override;
public:
/**
* @brief Query if the given address is a known symbol.
* @param address The address.
* @return True if the address is known, false if not.
*/
bool containsSymbol(uint64_t address) const;
/**
* @brief Adds or changes a symbol.
* @param address The address.
* @param name The symbol name.
*/
void setSymbol(uint64_t address, const char* name);
/**
* @brief Removes the symbol described by address. This will invalidate all char pointers
* to the specific symbol name.
* @param address The address.
*/
void removeSymbol(uint64_t address);
/**
* @brief Clears the symbol tree.
*/
void clear();
};
/* ============================================================================================== */
}
#endif /* _ZYDIS_SYMBOLRESOLVER_HPP_ */

View File

@ -1,543 +0,0 @@
/***************************************************************************************************
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.
***************************************************************************************************/
#ifndef _ZYDIS_TYPES_HPP_
#define _ZYDIS_TYPES_HPP_
#include <stdint.h>
#include "ZydisOpcodeTable.hpp"
namespace Zydis
{
/* InstructionFlags ============================================================================= */
/**
* @brief Values that represent additional flags of a decoded instruction.
*/
enum InstructionFlags : uint32_t
{
IF_NONE = 0x00000000,
/**
* @brief The instruction was decoded in 16 bit disassembler mode.
*/
IF_DISASSEMBLER_MODE_16 = 0x00000001,
/**
* @brief The instruction was decoded in 32 bit disassembler mode.
*/
IF_DISASSEMBLER_MODE_32 = 0x00000002,
/**
* @brief The instruction was decoded in 64 bit disassembler mode.
*/
IF_DISASSEMBLER_MODE_64 = 0x00000004,
/**
* @brief The instruction has a segment prefix (0x26, 0x2E, 0x36, 0x3E, 0x64, 0x65).
*/
IF_PREFIX_SEGMENT = 0x00000008,
/**
* @brief The instruction has a lock prefix (0xF0).
*/
IF_PREFIX_LOCK = 0x00000010,
/**
* @brief The instruction has a repne prefix (0xF2).
*/
IF_PREFIX_REPNE = 0x00000020,
/**
* @brief The instruction has a rep prefix (0xF3).
*/
IF_PREFIX_REP = 0x00000040,
/**
* @brief The instruction has an operand size prefix (0x66).
*/
IF_PREFIX_OPERAND_SIZE = 0x00000080,
/**
* @brief The instruction has an address size prefix (0x67).
*/
IF_PREFIX_ADDRESS_SIZE = 0x00000100,
/**
* @brief The instruction has a rex prefix (0x40 - 0x4F).
*/
IF_PREFIX_REX = 0x00000200,
/**
* @brief The instruction has a vex prefix (0xC4 or 0xC5).
*/
IF_PREFIX_VEX = 0x00000400,
/**
* @brief The instruction has a modrm byte.
*/
IF_MODRM = 0x00000800,
/**
* @brief The instruction has a sib byte.
*/
IF_SIB = 0x00001000,
/**
* @brief The instruction has an operand with a relative address.
*/
IF_RELATIVE = 0x00002000,
/**
* @brief An error occured while decoding the instruction.
*/
IF_ERROR_MASK = 0xFFF00000,
/**
* @brief End of input reached while decoding the instruction.
*/
IF_ERROR_END_OF_INPUT = 0x00100000,
/**
* @brief The instruction length has exceeded the maximum of 15 bytes.
*/
IF_ERROR_LENGTH = 0x00200000,
/**
* @brief The instruction is invalid.
*/
IF_ERROR_INVALID = 0x00400000,
/**
* @brief The instruction is invalid in 64 bit mode.
*/
IF_ERROR_INVALID_64 = 0x00800000,
/**
* @brief An error occured while decoding the instruction operands.
*/
IF_ERROR_OPERAND = 0x01000000
};
/* Register ===================================================================================== */
/**
* @brief Values that represent a cpu register.
*/
enum class Register : uint16_t
{
NONE,
/* 8 bit general purpose registers */
AL, CL, DL, BL,
AH, CH, DH, BH,
SPL, BPL, SIL, DIL,
R8B, R9B, R10B, R11B,
R12B, R13B, R14B, R15B,
/* 16 bit general purpose registers */
AX, CX, DX, BX,
SP, BP, SI, DI,
R8W, R9W, R10W, R11W,
R12W, R13W, R14W, R15W,
/* 32 bit general purpose registers */
EAX, ECX, EDX, EBX,
ESP, EBP, ESI, EDI,
R8D, R9D, R10D, R11D,
R12D, R13D, R14D, R15D,
/* 64 bit general purpose registers */
RAX, RCX, RDX, RBX,
RSP, RBP, RSI, RDI,
R8, R9, R10, R11,
R12, R13, R14, R15,
/* segment registers */
ES, CS, SS,
DS, FS, GS,
/* control registers */
CR0, CR1, CR2, CR3,
CR4, CR5, CR6, CR7,
CR8, CR9, CR10, CR11,
CR12, CR13, CR14, CR15,
/* debug registers */
DR0, DR1, DR2, DR3,
DR4, DR5, DR6, DR7,
DR8, DR9, DR10, DR11,
DR12, DR13, DR14, DR15,
/* mmx registers */
MM0, MM1, MM2, MM3,
MM4, MM5, MM6, MM7,
/* x87 registers */
ST0, ST1, ST2, ST3,
ST4, ST5, ST6, ST7,
/* extended multimedia registers */
XMM0, XMM1, XMM2, XMM3,
XMM4, XMM5, XMM6, XMM7,
XMM8, XMM9, XMM10, XMM11,
XMM12, XMM13, XMM14, XMM15,
/* 256 bit multimedia registers */
YMM0, YMM1, YMM2, YMM3,
YMM4, YMM5, YMM6, YMM7,
YMM8, YMM9, YMM10, YMM11,
YMM12, YMM13, YMM14, YMM15,
/* instruction pointer register */
RIP
};
/* OperandType ================================================================================== */
/**
* @brief Values that represent the type of a decoded operand.
*/
enum class OperandType : uint8_t
{
/**
* @brief The operand is not used.
*/
NONE,
/**
* @brief The operand is a register operand.
*/
REGISTER,
/**
* @brief The operand is a memory operand.
*/
MEMORY,
/**
* @brief The operand is a pointer operand.
*/
POINTER,
/**
* @brief The operand is an immediate operand.
*/
IMMEDIATE,
/**
* @brief The operand is a relative immediate operand.
*/
REL_IMMEDIATE,
/**
* @brief The operand is a constant value.
*/
CONSTANT
};
/* ZydisOperandAccessMode ============================================================================ */
/**
* @brief Values that represent the operand access mode.
*/
enum class OperandAccessMode : uint8_t
{
NA,
/**
* @brief The operand is accessed in read-only mode.
*/
READ,
/**
* @brief The operand is accessed in write mode.
*/
WRITE,
/**
* @brief The operand is accessed in read-write mode.
*/
READWRITE
};
/* OperandInfo ================================================================================== */
/**
* @brief This struct holds information about a decoded operand.
*/
struct OperandInfo
{
/**
* @brief The type of the operand.
*/
OperandType type;
/**
* @brief The size of the operand.
*/
uint16_t size;
/**
* @brief The operand access mode.
*/
OperandAccessMode access_mode;
/**
* @brief The base register.
*/
Register base;
/**
* @brief The index register.
*/
Register index;
/**
* @brief The scale factor.
*/
uint8_t scale;
/**
* @brief The lvalue offset. If the @c offset is zero and the operand @c type is not
* @c CONSTANT, no lvalue is present.
*/
uint8_t offset;
/**
* @brief Signals, if the lval is signed.
*/
bool signed_lval;
/**
* @brief The lvalue.
*/
union {
int8_t sbyte;
uint8_t ubyte;
int16_t sword;
uint16_t uword;
int32_t sdword;
uint32_t udword;
int64_t sqword;
uint64_t uqword;
struct {
uint16_t seg;
uint32_t off;
} ptr;
} lval;
};
/* InstructionInfo ============================================================================== */
/**
* @brief This struct holds information about a decoded instruction.
*/
struct InstructionInfo
{
/**
* @brief The instruction flags.
*/
uint32_t flags;
/**
* @brief The instruction mnemonic.
*/
InstructionMnemonic mnemonic;
/**
* @brief The total length of the instruction.
*/
uint8_t length;
/**
* @brief Contains all bytes of the instruction.
*/
uint8_t data[15];
/**
* @brief The length of the instruction opcodes.
*/
uint8_t opcode_length;
/**
* @brief The instruction opcodes.
*/
uint8_t opcode[3];
/**
* @brief The operand mode.
*/
uint8_t operand_mode;
/**
* @brief The address mode.
*/
uint8_t address_mode;
/**
* @brief The decoded operands.
*/
OperandInfo operand[4];
/**
* @brief The segment register. This value will default to @c NONE, if no segment register
* prefix is present.
*/
Register segment;
/**
* @brief The rex prefix byte.
*/
uint8_t rex;
/**
* @brief When 1, a 64-bit operand size is used. Otherwise, when 0, the default operand size
* is used.
*/
uint8_t rex_w;
/**
* @brief This 1-bit value is an extension to the MODRM.reg field.
*/
uint8_t rex_r;
/**
* @brief This 1-bit value is an extension to the SIB.index field.
*/
uint8_t rex_x;
/**
* @brief This 1-bit value is an extension to the MODRM.rm field or the SIB.base field.
*/
uint8_t rex_b;
/**
* @brief The modrm byte.
*/
uint8_t modrm;
/**
* @brief The modrm modus bits. When this field is b11, then register-direct addressing mode
* is used; otherwise register-indirect addressing mode is used.
*/
uint8_t modrm_mod;
/**
* @brief The modrm register bits. The REX.R, VEX.~R or XOP.~R field can extend this field
* with 1 most-significant bit to 4 bits total.
*/
uint8_t modrm_reg;
/**
* @brief The extended modrm register bits. If the instruction definition does not have the
* @c IDF_ACCEPTS_REXR flag set, this value defaults to the normal @c modrm_reg
* field.
*/
uint8_t modrm_reg_ext;
/**
* @brief The modrm register/memory bits. Specifies a direct or indirect register operand,
* optionally with a displacement. The REX.B, VEX.~B or XOP.~B field can extend this
* field with 1 most-significant bit to 4 bits total.
*/
uint8_t modrm_rm;
/**
* @brief The extended modrm register/memory bits. If the instruction definition does not
* have the @c IDF_ACCEPTS_REXB flag set, this value defaults to the normal
* @c modrm_rm field.
*/
uint8_t modrm_rm_ext;
/**
* @brief The sib byte.
*/
uint8_t sib;
/**
* @brief This field indicates the scaling factor of SIB.index.
*/
uint8_t sib_scale;
/**
* @brief The index register to use. The REX.X, VEX.~X or XOP.~X field can extend this field
* with 1 most-significant bit to 4 bits total.
*/
uint8_t sib_index;
/**
* @brief The extended index register. If the instruction definition does not have the
* @c IDF_ACCEPTS_REXX flag set, this value defaults to the normal @c sib_index
* field.
*/
uint8_t sib_index_ext;
/**
* @brief The base register to use. The REX.B, VEX.~B or XOP.~B field can extend this field
* with 1 most-significant bit to 4 bits total.
*/
uint8_t sib_base;
/**
* @brief The extended base register. If the instruction definition does not have the
* @c IDF_ACCEPTS_REXB flag set, this value defaults to the normal @c sib_index
* field.
*/
uint8_t sib_base_ext;
/**
* @brief The primary vex prefix byte.
*/
uint8_t vex_op;
/**
* @brief The second vex prefix byte.
*/
uint8_t vex_b1;
/**
* @brief The third vex prefix byte.
*/
uint8_t vex_b2;
/**
* @brief This 1-bit value is an 'inverted' extension to the MODRM.reg field. The inverse of
* REX.R.
*/
uint8_t vex_r;
/**
* @brief This 1-bit value is an 'inverted' extension to the SIB.index field. The inverse of
* REX.X.
*/
uint8_t vex_x;
/**
* @brief This 1-bit value is an 'inverted' extension to the MODRM.rm field or the SIB.base
* field. The inverse of REX.B.
*/
uint8_t vex_b;
/**
* @brief Specifies the opcode map to use.
* 00 = 0x0F
* 01 = 0x0F 0x38
* 02 = 0x0F 0x3A
*/
uint8_t vex_m_mmmm;
/**
* @brief For integer instructions: when 1, a 64-bit operand size is used; otherwise,
* when 0, the default operand size is used (equivalent with REX.W). For non-integer
* instructions, this bit is a general opcode extension bit.
*/
uint8_t vex_w;
/**
* @brief An additional operand for the instruction. The value of the XMM or YMM register
* is 'inverted'.
*/
uint8_t vex_vvvv;
/**
* @brief When 0, a 128-bit vector lengh is used. Otherwise, when 1, a 256-bit vector length
* is used.
*/
uint8_t vex_l;
/**
* @brief Specifies an implied mandatory prefix for the opcode.
* 00 = none
* 01 = 0x66
* 10 = 0xF3
* 11 = 0xF2
*/
uint8_t vex_pp;
/**
* @brief The effectively used REX/VEX.w value. If the instruction definition does not have
* the @c IDF_ACCEPTS_REXW flag set, this value defaults to zero.
*/
uint8_t eff_rexvex_w;
/**
* @brief The effectively used REX/VEX.r value. If the instruction definition does not have
* the @c IDF_ACCEPTS_REXR flag set, this value defaults to zero.
*/
uint8_t eff_rexvex_r;
/**
* @brief The effectively used REX/VEX.x value. If the instruction definition does not have
* the @c IDF_ACCEPTS_REXX flag set, this value defaults to zero.
*/
uint8_t eff_rexvex_x;
/**
* @brief The effectively used REX/VEX.b value. If the instruction definition does not have
* the @c IDF_ACCEPTS_REXB flag set, this value defaults to zero.
*/
uint8_t eff_rexvex_b;
/**
* @brief The effectively used VEX.l value. If the instruction definition does not have
* the @c IDF_ACCEPTS_VEXL flag set, this value defaults to zero.
*/
uint8_t eff_vex_l;
/**
* @brief The instruction definition.
*/
const InstructionDefinition* instrDefinition;
/**
* @brief The instruction address points to the current instruction (relative to the
* initial instruction pointer).
*/
uint64_t instrAddress;
/**
* @brief The instruction pointer points to the address of the next instruction (relative
* to the initial instruction pointer).
* This field is used to properly format relative instructions.
*/
uint64_t instrPointer;
};
}
#endif /* _ZYDIS_TYPES_HPP_ */

231596
assets/instructions.json Normal file

File diff suppressed because it is too large Load Diff

435
examples/ZydisPE.c Normal file
View File

@ -0,0 +1,435 @@
/***************************************************************************************************
Zyan Disassembler Engine (Zydis)
Original Author : Florian Bernd
* 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 <stddef.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <Windows.h>
#include <Zydis/Zydis.h>
/* ============================================================================================== */
/* Custom Symbol Resolving */
/* ============================================================================================== */
/**
* @brief Returns the name of the exported function at the given @c address.
*
* @param moduleHandle The module handle.
* @param address The function address.
*
* @return The name of the exported function at @c address or @c NULL.
*/
static const char* GetExportName(HMODULE moduleHandle, uintptr_t address)
{
if (!moduleHandle)
{
return NULL;
}
PIMAGE_DOS_HEADER dosHeader = (PIMAGE_DOS_HEADER)moduleHandle;
if (dosHeader->e_magic != IMAGE_DOS_SIGNATURE)
{
return NULL;
}
PIMAGE_NT_HEADERS ntHeaders = (PIMAGE_NT_HEADERS)((uint8_t*)dosHeader + dosHeader->e_lfanew);
if (ntHeaders->Signature != IMAGE_NT_SIGNATURE)
{
return NULL;
}
uintptr_t entryPoint =
(uintptr_t)((uint8_t*)moduleHandle + ntHeaders->OptionalHeader.AddressOfEntryPoint);
if (address == entryPoint)
{
return "EntryPoint";
}
if (ntHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress)
{
PIMAGE_EXPORT_DIRECTORY exportDirectory =
(PIMAGE_EXPORT_DIRECTORY)((uint8_t*)moduleHandle +
ntHeaders->OptionalHeader.DataDirectory[
IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress);
PDWORD exportAddresses =
(PDWORD)((uint8_t*)moduleHandle +exportDirectory->AddressOfFunctions);
PDWORD exportNames =
(PDWORD)((uint8_t*)moduleHandle + exportDirectory->AddressOfNames);
for (uint32_t i = 0; i < exportDirectory->NumberOfFunctions; ++i)
{
if (address == (uintptr_t)moduleHandle + exportAddresses[i])
{
return (const char*)moduleHandle + exportNames[i];
}
}
}
return NULL;
}
/**
* @brief Inserts formatted text into the @c buffer at the given @c offset and increases the
* @c offset by the length of the text.
*
* @param buffer A pointer to the target buffer.
* @param bufferLen The length of the buffer.
* @param offset A pointer to the buffer-offset.
* @param format The format string.
*
* @return A zydis status code.
*/
static ZydisStatus ZydisBufferAppendFormat(char* buffer, size_t bufferLen, size_t* offset,
const char* format, ...)
{
va_list arglist;
va_start(arglist, format);
size_t n = bufferLen - *offset;
int w = vsnprintf(&buffer[*offset], n, format, arglist);
if ((w < 0) || ((size_t)w >= n))
{
va_end(arglist);
return ZYDIS_STATUS_INSUFFICIENT_BUFFER_SIZE;
}
*offset += (size_t)w;
va_end(arglist);
return ZYDIS_STATUS_SUCCESS;
}
/**
* @brief Inserts the name of the exported function at @c address into the @c buffer at the given
* @c offset and increases the @c offset by the length of the name.
*
* @param buffer A pointer to the target buffer.
* @param bufferLen The length of the buffer.
* @param offset A pointer to the buffer-offset.
* @param moduleHandle The module handle.
* @param address The function address.
*
* @return A zydis status code.
*/
static ZydisStatus ZydisBufferAppendExport(char* buffer, size_t bufferLen, size_t* offset,
HMODULE moduleHandle, uintptr_t address)
{
const char* exportName = GetExportName(moduleHandle, address);
if (!exportName)
{
return ZYDIS_STATUS_INVALID_PARAMETER;
}
char nameBuffer[MAX_PATH];
DWORD l = GetModuleFileNameA(moduleHandle, &nameBuffer[0], MAX_PATH);
if (l == 0)
{
return ZYDIS_STATUS_INVALID_PARAMETER;
}
for (int i = l - 4; i >= 0; --i)
{
if (nameBuffer[i] == '\\')
{
memcpy(&nameBuffer[0], &nameBuffer[i + 1], l - i);
nameBuffer[l - i - 4] = 0;
break;
}
}
return ZydisBufferAppendFormat(buffer, bufferLen, offset, "%s%s", &nameBuffer[0], exportName);
}
/**
* @brief Inserts the name of the imported function at @c address into the @c buffer at the given
* @c offset and increases the @c offset by the length of the name.
*
* @param buffer A pointer to the target buffer.
* @param bufferLen The length of the buffer.
* @param offset A pointer to the buffer-offset.
* @param moduleHandle The module handle.
* @param address The function address.
*
* @return A zydis status code.
*/
static ZydisStatus ZydisBufferAppendImport(char* buffer, size_t bufferLen, size_t* offset,
HMODULE moduleHandle, uintptr_t address)
{
if (!moduleHandle)
{
return ZYDIS_STATUS_INVALID_PARAMETER;
}
PIMAGE_DOS_HEADER dosHeader = (PIMAGE_DOS_HEADER)moduleHandle;
if (dosHeader->e_magic != IMAGE_DOS_SIGNATURE)
{
return ZYDIS_STATUS_INVALID_PARAMETER;
}
PIMAGE_NT_HEADERS ntHeaders = (PIMAGE_NT_HEADERS)((uint8_t*)dosHeader + dosHeader->e_lfanew);
if (ntHeaders->Signature != IMAGE_NT_SIGNATURE)
{
return ZYDIS_STATUS_INVALID_PARAMETER;
}
if (ntHeaders->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress)
{
PIMAGE_IMPORT_DESCRIPTOR descriptor =
(PIMAGE_IMPORT_DESCRIPTOR)((uint8_t*)moduleHandle +
ntHeaders->OptionalHeader.DataDirectory[
IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);
while (descriptor->OriginalFirstThunk)
{
const char* moduleName = (char*)((uint8_t*)moduleHandle + descriptor->Name);
PIMAGE_THUNK_DATA originalThunk =
(PIMAGE_THUNK_DATA)((uint8_t*)moduleHandle + descriptor->OriginalFirstThunk);
PIMAGE_THUNK_DATA thunk =
(PIMAGE_THUNK_DATA)((uint8_t*)moduleHandle + descriptor->FirstThunk);
while (originalThunk->u1.ForwarderString)
{
if (!(originalThunk->u1.Ordinal & 0x80000000))
{
if (address == (uintptr_t)&thunk->u1.Function)
{
PIMAGE_IMPORT_BY_NAME import = (PIMAGE_IMPORT_BY_NAME)
((uint8_t*)moduleHandle + originalThunk->u1.AddressOfData);
ZydisStatus status =
ZydisBufferAppendFormat(buffer, bufferLen, offset, "%s", moduleName);
if (!ZYDIS_SUCCESS(status))
{
return status;
}
*offset -= 3;
buffer[*offset] = 0;
return ZydisBufferAppendFormat(buffer, bufferLen, offset, "%s",
import->Name);
}
}
++originalThunk;
++thunk;
}
++descriptor;
}
}
return ZYDIS_STATUS_USER + 1000;
}
/**
* @brief Defines the @c ZydisPESymbolResolver struct.
*/
typedef struct ZydisPESymbolResolver_
{
ZydisCustomSymbolResolver resolver;
HMODULE moduleHandle;
char buffer[256];
} ZydisPESymbolResolver;
/**
* @brief The custom symbol resolver callback function.
*
* @param context A pointer to the @c ZydisPESymbolResolver instance.
* @param info A pointer to the @c ZydisInstructionInfo struct.
* @param operand A pointer to the @c ZydisOperandInfo struct.
* @param address The address.
* @param offset A pointer to the memory that receives the optional symbol-offset.
*
* @return The name of the resolved symbol or @c NULL, if no symbol was found at the given
* @c address.
*/
static const char* ResolveSymbol(ZydisPESymbolResolver* context, const ZydisInstructionInfo* info,
const ZydisOperandInfo* operand, uint64_t address, int64_t* offset)
{
(void)context;
(void)info;
(void)operand;
(void)address;
*offset = 0;
size_t bufferOffset = 0;
if (ZYDIS_SUCCESS(ZydisBufferAppendExport(&context->buffer[0], sizeof(context->buffer),
&bufferOffset, context->moduleHandle, (uintptr_t)address)))
{
return &context->buffer[0];
}
if (ZYDIS_SUCCESS(ZydisBufferAppendImport(&context->buffer[0], sizeof(context->buffer),
&bufferOffset, context->moduleHandle, (uintptr_t)address)))
{
return &context->buffer[0];
}
return NULL;
}
/* ============================================================================================== */
/* Entry point */
/* ============================================================================================== */
int main(int argc, char** argv)
{
if (argc != 2)
{
fprintf(stderr, "Usage: %s <input file>\n", (argc > 0 ? argv[0] : "ZydisPE"));
return EXIT_FAILURE;
}
// Load PE file
HMODULE hModule = LoadLibraryExA(argv[1], 0, LOAD_LIBRARY_AS_DATAFILE);
if (!hModule)
{
fprintf(stderr, "Could not load PE file. Error code: %d\n", GetLastError());
return EXIT_FAILURE;
}
PIMAGE_DOS_HEADER dosHeader = (PIMAGE_DOS_HEADER)hModule;
if (dosHeader->e_magic != IMAGE_DOS_SIGNATURE)
{
fprintf(stderr, "Invalid file signature\n");
goto FatalError;
}
PIMAGE_NT_HEADERS ntHeaders = (PIMAGE_NT_HEADERS)((uint8_t*)dosHeader + dosHeader->e_lfanew);
if (ntHeaders->Signature != IMAGE_NT_SIGNATURE)
{
fprintf(stderr, "Invalid file signature\n");
goto FatalError;
}
// Determine disassembler-mode
ZydisDisassemblerMode disassemblerMode;
switch (ntHeaders->FileHeader.Machine)
{
case IMAGE_FILE_MACHINE_I386:
disassemblerMode = ZYDIS_DISASSEMBLER_MODE_32BIT;
break;
case IMAGE_FILE_MACHINE_IA64:
case IMAGE_FILE_MACHINE_AMD64:
disassemblerMode = ZYDIS_DISASSEMBLER_MODE_64BIT;
break;
default:
fprintf(stderr, "Invalid assembly format\n");
goto FatalError;
}
ZydisMemoryInput input;
ZydisInstructionDecoder decoder;
if (!ZYDIS_SUCCESS(ZydisDecoderInitInstructionDecoderEx(&decoder, disassemblerMode,
(ZydisCustomInput*)&input, ZYDIS_DECODER_FLAG_SKIP_DATA)))
{
fputs("Failed to initialize instruction-decoder\n", stderr);
goto FatalError;
}
ZydisInstructionFormatter formatter;
if (!ZYDIS_SUCCESS(ZydisFormatterInitInstructionFormatterEx(&formatter,
ZYDIS_FORMATTER_STYLE_INTEL, ZYDIS_FORMATTER_FLAG_ALWAYS_DISPLAY_MEMORY_SIZE |
ZYDIS_FORMATTER_FLAG_ALWAYS_DISPLAY_MEMORY_SEGMENT)))
{
fputs("Failed to initialize instruction-formatter\n", stderr);
goto FatalError;
}
// Initialize custom symbol resolver
ZydisPESymbolResolver resolver;
resolver.resolver.resolveSymbol = (ZydisResolverResolveSymbolFunc)&ResolveSymbol;
resolver.moduleHandle = hModule;
ZydisFormatterSetSymbolResolver(&formatter, (ZydisCustomSymbolResolver*)&resolver);
LARGE_INTEGER frequency;
LARGE_INTEGER t1, t2;
QueryPerformanceFrequency(&frequency);
QueryPerformanceCounter(&t1);
// Disassemble all executable PE-sections
PIMAGE_SECTION_HEADER sectionHeader = (PIMAGE_SECTION_HEADER)((uint8_t*)ntHeaders +
sizeof(IMAGE_NT_HEADERS) - sizeof(IMAGE_OPTIONAL_HEADER) +
ntHeaders->FileHeader.SizeOfOptionalHeader);
for (int i = 0; i < ntHeaders->FileHeader.NumberOfSections; ++i)
{
if (sectionHeader->SizeOfRawData == 0)
{
continue;
}
if (!(sectionHeader->Characteristics & IMAGE_SCN_CNT_CODE))
{
continue;
}
void* data = (void*)((uint8_t*)dosHeader + sectionHeader->VirtualAddress);
if (!ZYDIS_SUCCESS(ZydisDecoderSetInstructionPointer(&decoder, (uint64_t)data)))
{
fputs("Failed to set instruction-pointer\n", stderr);
goto FatalError;
}
if (!ZYDIS_SUCCESS(ZydisInputInitMemoryInput(&input, data, sectionHeader->SizeOfRawData)))
{
fputs("Failed to initialize memory-input\n", stderr);
goto FatalError;
}
char buffer[256];
ZydisInstructionInfo info;
while (ZYDIS_SUCCESS(ZydisDecoderDecodeNextInstruction(&decoder, &info)))
{
const char* symbol = GetExportName(hModule, (uintptr_t)info.instrAddress);
if (symbol)
{
printf("\n%s:\n", symbol);
}
switch (info.mode)
{
case ZYDIS_DISASSEMBLER_MODE_16BIT:
printf("%04llX ", info.instrAddress);
break;
case ZYDIS_DISASSEMBLER_MODE_32BIT:
printf("%08llX ", info.instrAddress);
break;
case ZYDIS_DISASSEMBLER_MODE_64BIT:
printf("%016llX ", info.instrAddress);
break;
}
for (int j = 0; j < info.length; ++j)
{
printf("%02X ", info.data[j]);
}
for (int j = info.length; j < 15; ++j)
{
printf(" ");
}
if (info.flags & ZYDIS_IFLAG_ERROR_MASK)
{
printf(" db %02x\n", info.data[0]);
continue;
}
if (!ZYDIS_SUCCESS(ZydisFormatterFormatInstruction(&formatter, &info, &buffer[0],
sizeof(buffer))))
{
fputs("Failed to format decoded instruction\n", stderr);
goto FatalError;
}
printf(" %s\n", &buffer[0]);
}
++sectionHeader;
}
QueryPerformanceCounter(&t2);
double elapsedTime = (t2.QuadPart - t1.QuadPart) * 1000.0 / frequency.QuadPart;
printf("\n%f", elapsedTime);
return EXIT_SUCCESS;
FatalError:
FreeLibrary(hModule);
return EXIT_FAILURE;
}
/* ============================================================================================== */

233
include/Zydis/Decoder.h Normal file
View File

@ -0,0 +1,233 @@
/***************************************************************************************************
Zyan Disassembler Engine (Zydis)
Original Author : Florian Bernd
* 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.
***************************************************************************************************/
#ifndef ZYDIS_DECODER_H
#define ZYDIS_DECODER_H
#include <stdint.h>
#include <Zydis/Defines.h>
#include <Zydis/Status.h>
#include <Zydis/Input.h>
#include <Zydis/InstructionInfo.h>
#ifdef __cplusplus
extern "C" {
#endif
/* ============================================================================================== */
/* Enums and types */
/* ============================================================================================== */
/**
* @brief Defines the @c ZydisDecoderFlags datatype.
*/
typedef uint32_t ZydisDecoderFlags;
/**
* @brief Values that represent zydis decoder-flags.
*/
enum ZydisDecoderFlag
{
ZYDIS_DECODER_FLAG_SKIP_DATA = 0x00000001
};
/* ---------------------------------------------------------------------------------------------- */
/**
* @brief Defines the @c ZydisInstructionDecoder struct.
*/
typedef struct ZydisInstructionDecoder_
{
/**
* @brief The current disassembler-mode.
*/
ZydisDisassemblerMode disassemblerMode;
/**
* @brief A pointer to the current input data-source.
*/
ZydisCustomInput* input;
/**
* @brief Decoder flags.
*/
ZydisDecoderFlags flags;
/**
* @brief The current instruction-pointer value.
*/
uint64_t instructionPointer;
/**
* @brief Internal buffer.
*/
struct
{
uint8_t data[30];
uint8_t count;
uint8_t posRead;
uint8_t posWrite;
} buffer;
} ZydisInstructionDecoder;
/* ---------------------------------------------------------------------------------------------- */
/* ============================================================================================== */
/* Exported functions */
/* ============================================================================================== */
/**
* @brief Initializes the given @c ZydisInstructionDecoder instance.
*
* @param decoder A pointer to the @c ZydisInstructionDecoder instance.
* @param disassemblerMode The desired disassembler-mode.
* @param input A pointer to the input data-source.
*
* @return A zydis status code.
*/
ZYDIS_DLLEXTERN ZydisStatus ZydisDecoderInitInstructionDecoder(ZydisInstructionDecoder* decoder,
ZydisDisassemblerMode disassemblerMode, ZydisCustomInput* input);
/**
* @brief Initializes the given @c ZydisInstructionDecoder instance.
*
* @param decoder A pointer to the @c ZydisInstructionDecoder instance.
* @param disassemblerMode The desired disassembler-mode.
* @param input A pointer to the input data-source.
* @param flags Additional flags for the instruction-decoder.
*
* @return A zydis status code.
*/
ZYDIS_DLLEXTERN ZydisStatus ZydisDecoderInitInstructionDecoderEx(ZydisInstructionDecoder* decoder,
ZydisDisassemblerMode disassemblerMode, ZydisCustomInput* input, ZydisDecoderFlags flags);
/**
* @brief Returns the current disassembler-mode of the given @c ZydisInstructionDecoder
* instance.
*
* @param decoder A pointer to the @c ZydisInstructionDecoder instance.
* @param disassemblerMode A pointer to the memory that receives the current disassembler-mode.
*
* @return A zydis status code.
*/
ZYDIS_DLLEXTERN ZydisStatus ZydisDecoderGetDisassemblerMode(const ZydisInstructionDecoder* decoder,
ZydisDisassemblerMode* disassemblerMode);
/**
* @brief Changes the disassembler-mode of the given @c ZydisInstructionDecoder instance.
*
* @param decoder A pointer to the @c ZydisInstructionDecoder instance.
* @param disassemblerMode The new disassembler-mode.
*
* @return A zydis status code.
*/
ZYDIS_DLLEXTERN ZydisStatus ZydisDecoderSetDisassemblerMode(ZydisInstructionDecoder* decoder,
ZydisDisassemblerMode disassemblerMode);
/**
* @brief Returns the current input data-source of the given @c ZydisInstructionDecoder
* instance.
*
* @param decoder A pointer to the @c ZydisInstructionDecoder instance.
* @param input A pointer to the memory that receives the current input data-source pointer.
*
* @return A zydis status code.
*/
ZYDIS_DLLEXTERN ZydisStatus ZydisDecoderGetDecoderInput(const ZydisInstructionDecoder* decoder,
ZydisCustomInput** input);
/**
* @brief Changes the input data-source of the given @c ZydisInstructionDecoder instance.
*
* @param decoder A pointer to the @c ZydisInstructionDecoder instance.
* @param input A pointer to the new input data-source.
*
* @return A zydis status code.
*/
ZYDIS_DLLEXTERN ZydisStatus ZydisDecoderSetDecoderInput(ZydisInstructionDecoder* decoder,
ZydisCustomInput* input);
/**
* @brief Returns the current decoder-flags of the given @c ZydisInstructionDecoder instance.
*
* @param decoder A pointer to the @c ZydisInstructionDecoder instance.
* @param flags A pointer to the memory that receives the current decoder-flags.
*
* @return A zydis status code.
*/
ZYDIS_DLLEXTERN ZydisStatus ZydisDecoderGetDecoderFlags(const ZydisInstructionDecoder* decoder,
ZydisDecoderFlags* flags);
/**
* @brief Changes the decoder-flags of the given @c ZydisInstructionDecoder instance.
*
* @param decoder A pointer to the @c ZydisInstructionDecoder instance.
* @param flags The new decoder-flags.
*
* @return A zydis status code.
*/
ZYDIS_DLLEXTERN ZydisStatus ZydisDecoderSetDecoderFlags(ZydisInstructionDecoder* decoder,
ZydisDecoderFlags flags);
/**
* @brief Returns the current instruction-pointer of the given @c ZydisInstructionDecoder
* instance.
*
* @param decoder A pointer to the @c ZydisInstructionDecoder instance.
* @param instructionPointer A pointer to the memory that receives the current
* instruction-pointer.
*
* @return A zydis status code.
*/
ZYDIS_DLLEXTERN ZydisStatus ZydisDecoderGetInstructionPointer(
const ZydisInstructionDecoder* decoder, uint64_t* instructionPointer);
/**
* @brief Changes the instruction-pointer of the given @c ZydisInstructionDecoder instance.
*
* @param decoder A pointer to the @c ZydisInstructionDecoder instance.
* @param instructionPointer The new instruction-pointer value.
*
* @return A zydis status code.
*/
ZYDIS_DLLEXTERN ZydisStatus ZydisDecoderSetInstructionPointer(ZydisInstructionDecoder* decoder,
uint64_t instructionPointer);
/**
* @brief Decodes the next instruction from the decoders input data-source.
*
* @param decoder A pointer to the @c ZydisInstructionDecoder instance.
* @param info A pointer to the @c ZydisInstructionInfo struct, that receives the details
* about the decoded instruction.
*
* @return A zydis status code.
*/
ZYDIS_DLLEXTERN ZydisStatus ZydisDecoderDecodeNextInstruction(ZydisInstructionDecoder* decoder,
ZydisInstructionInfo* info);
/* ============================================================================================== */
#ifdef __cplusplus
}
#endif
#endif /* ZYDIS_DECODER_H */

136
include/Zydis/Defines.h Normal file
View File

@ -0,0 +1,136 @@
/***************************************************************************************************
Zyan Disassembler Engine (Zydis)
Original Author : Florian Bernd
* 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.
***************************************************************************************************/
#ifndef ZYDIS_DEFINES_H
#define ZYDIS_DEFINES_H
/* ============================================================================================== */
/* Compiler detection */
/* ============================================================================================== */
#if defined(__clang__)
# define ZYDIS_CLANG
# define ZYDIS_GNUC
#elif defined(__ICC) || defined(__INTEL_COMPILER)
# define ZYDIS_ICC
#elif defined(__GNUC__) || defined(__GNUG__)
# define ZYDIS_GCC
# define ZYDIS_GNUC
#elif defined(_MSC_VER)
# define ZYDIS_MSVC
#elif defined(__BORLANDC__)
# define ZYDIS_BORLAND
#else
# define ZYDIS_UNKNOWN_COMPILER
#endif
/* ============================================================================================== */
/* Platform detection */
/* ============================================================================================== */
#if defined(_WIN32)
# define ZYDIS_WINDOWS
#elif defined(__APPLE__)
# define ZYDIS_APPLE
# define ZYDIS_POSIX
#elif defined(__linux)
# define ZYDIS_LINUX
# define ZYDIS_POSIX
#elif defined(__unix)
# define ZYDIS_UNIX
# define ZYDIS_POSIX
#elif defined(__posix)
# define ZYDIS_POSIX
#else
# error "Unsupported platform detected"
#endif
/* ============================================================================================== */
/* Architecture detection */
/* ============================================================================================== */
#if defined (_M_AMD64) || defined (__x86_64__)
# define ZYDIS_X64
#elif defined (_M_IX86) || defined (__i386__)
# define ZYDIS_X86
#else
# error "Unsupported architecture detected"
#endif
/* ============================================================================================== */
/* Debug/Release detection */
/* ============================================================================================== */
#if defined(ZYDIS_MSVC) || defined(ZYDIS_BORLAND)
# ifdef _DEBUG
# define ZYDIS_DEBUG
# else
# define ZYDIS_RELEASE
# endif
#elif defined(ZYDIS_GNUC) || defined(ZYDIS_ICC)
# ifdef NDEBUG
# define ZYDIS_RELEASE
# else
# define ZYDIS_DEBUG
# endif
#else
# error "Unsupported compiler detected"
#endif
/* ============================================================================================== */
/* Misc compatibility macros */
/* ============================================================================================== */
#if defined(ZYDIS_MSVC) || defined(ZYDIS_BORLAND)
# define ZYDIS_INLINE __inline
#else
# define ZYDIS_INLINE static inline
#endif
/* ============================================================================================== */
/* Dynamic linkage macros */
/* ============================================================================================== */
#if defined(ZYDIS_MSVC) && defined(ZYDIS_DYNAMIC)
# ifdef ZYDIS_EXPORTS
# define ZYDIS_DLLEXTERN __declspec(dllexport)
# else
# define ZYDIS_DLLEXTERN __declspec(dllimport)
# endif
#else
# define ZYDIS_DLLEXTERN
#endif
/* ============================================================================================== */
/* Debugging macros */
/* ============================================================================================== */
#define ZYDIS_ASSERT(condition) assert(condition)
#define ZYDIS_UNREACHABLE assert(0)
/* ============================================================================================== */
#endif /* ZYDIS_DEFINES_H */

255
include/Zydis/Formatter.h Normal file
View File

@ -0,0 +1,255 @@
/***************************************************************************************************
Zyan Disassembler Engine (Zydis)
Original Author : Florian Bernd
* 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.
***************************************************************************************************/
#ifndef ZYDIS_FORMATTER_H
#define ZYDIS_FORMATTER_H
#include <stdint.h>
#include <Zydis/Defines.h>
#include <Zydis/Status.h>
#include <Zydis/InstructionInfo.h>
#include <Zydis/SymbolResolver.h>
#ifdef __cplusplus
extern "C" {
#endif
/* ============================================================================================== */
/* Instruction formatter */
/* ============================================================================================== */
/* ---------------------------------------------------------------------------------------------- */
/* Enums and types */
/* ---------------------------------------------------------------------------------------------- */
/**
* @brief Defines the zydis formatter-style datatype.
*/
typedef uint8_t ZydisFormatterStyle;
/**
* @brief Values that represent formatter-styles.
*/
enum ZydisFormatterStyles
{
/**
* @brief Generates intel-style disassembly.
*/
ZYDIS_FORMATTER_STYLE_INTEL
};
/**
* @brief Defines the zydis formatter-flags datatype.
*/
typedef uint8_t ZydisFormatterFlags;
/**
* @brief Values that represent formatter-flags.
*/
enum ZydisFormatterFlag
{
ZYDIS_FORMATTER_FLAG_UPPERCASE = 0x01,
ZYDIS_FORMATTER_FLAG_TAB_AFTER_MNEMONIC = 0x02,
ZYDIS_FORMATTER_FLAG_NO_SPACE_BETWEEN_OPERANDS = 0x04,
ZYDIS_FORMATTER_FLAG_ALWAYS_DISPLAY_MEMORY_SIZE = 0x08,
ZYDIS_FORMATTER_FLAG_ALWAYS_DISPLAY_MEMORY_SEGMENT = 0x10
};
/**
* @brief Defines the zydis address-format datatype.
*/
typedef uint8_t ZydisFormatterAddressFormat;
/**
* @brief Values that represent address-formats.
*/
enum ZydisFormatterAddressFormat
{
/**
* @brief Displays absolute addresses instead of relative ones.
*/
ZYDIS_FORMATTER_ADDRESS_ABSOLUTE,
/**
* @brief Uses signed hexadecimal values to display relative addresses.
*
* Examples:
* "JMP 0x20"
* "JMP -0x20"
*/
ZYDIS_FORMATTER_ADDRESS_RELATIVE_SIGNED,
/**
* @brief Uses unsigned hexadecimal values to display relative addresses.
*
* Examples:
* "JMP 0x20"
* "JMP 0xE0"
*/
ZYDIS_FORMATTER_ADDRESS_RELATIVE_UNSIGNED,
};
/**
* @brief Defines the zydis displacement-format datatype.
*/
typedef uint8_t ZydisFormatterDisplacementFormat;
/**
* @brief Values that represent displacement-formats.
*/
enum ZydisFormatterDisplacementFormats
{
/**
* @brief Formats displacements as signed hexadecimal values.
*
* Examples:
* "MOV EAX, DWORD PTR SS:[ESP+0x400]"
* "MOV EAX, DWORD PTR SS:[ESP-0x400]"
*/
ZYDIS_FORMATTER_DISP_HEX_SIGNED,
/**
* @brief Formats displacements as unsigned hexadecimal values.
*
* Examples:
* "MOV EAX, DWORD PTR SS:[ESP+0x400]"
* "MOV EAX, DWORD PTR SS:[ESP+0xFFFFFC00]"
*/
ZYDIS_FORMATTER_DISP_HEX_UNSIGNED
};
/**
* @brief Defines the zydis formatter immediate-format datatype.
*/
typedef uint8_t ZydisFormatterImmediateFormat;
/**
* @brief Values that represent formatter immediate-formats.
*/
enum ZydisFormatterImmediateFormats
{
/**
* @brief Formats immediates as signed hexadecimal values.
*
* Examples:
* "MOV EAX, 0x400"
* "MOV EAX, -0x400"
*/
ZYDIS_FORMATTER_IMM_HEX_SIGNED,
/**
* @brief Formats immediates as unsigned hexadecimal values.
*
* Examples:
* "MOV EAX, 0x400"
* "MOV EAX, 0xFFFFFC00"
*/
ZYDIS_FORMATTER_IMM_HEX_UNSIGNED
};
/**
* @brief Defines the zydis instruction-formatter struct.
*/
typedef struct ZydisInstructionFormatter_
{
ZydisFormatterStyle style;
ZydisFormatterFlags flags;
ZydisFormatterAddressFormat addressFormat;
ZydisFormatterDisplacementFormat displacementFormat;
ZydisFormatterImmediateFormat immediateFormat;
ZydisCustomSymbolResolver* symbolResolver;
} ZydisInstructionFormatter;
/* ---------------------------------------------------------------------------------------------- */
/* Exported functions */
/* ---------------------------------------------------------------------------------------------- */
/**
* @brief Initializes the given @c ZydisInstructionFormatter instance.
*
* @param formatter A pointer to the instruction-formatter instance.
* @param style The formatter style to use.
*
* @return A zydis status code.
*/
ZYDIS_DLLEXTERN ZydisStatus ZydisFormatterInitInstructionFormatter(
ZydisInstructionFormatter* formatter, ZydisFormatterStyle style);
/**
* @brief Initializes the given @c ZydisInstructionFormatter instance.
*
* @param formatter A pointer to the instruction-formatter instance.
* @param style The formatter style to use.
* @param flags Additional formatter-flags.
*
* @return A zydis status code.
*/
ZYDIS_DLLEXTERN ZydisStatus ZydisFormatterInitInstructionFormatterEx(
ZydisInstructionFormatter* formatter, ZydisFormatterStyle style, ZydisFormatterFlags flags);
/**
* @brief Returns the symbol-resolver assigned to the given instruction-formatter instance.
*
* @param formatter A pointer to the instruction-formatter instance.
* @param symbolResolver A pointer to the memory that receives the current symbol-resolver
* pointer.
*
* @return A zydis status code.
*/
ZYDIS_DLLEXTERN ZydisStatus ZydisFormatterGetSymbolResolver(
const ZydisInstructionFormatter* formatter, ZydisCustomSymbolResolver** symbolResolver);
/**
* @brief Changes the symbol-resolver of the given instruction-formatter instance.
*
* @param formatter A pointer to the instruction-formatter instance.
* @param symbolResolver A pointer to the new symbol-resolver instance.
*
* @return The ZydisStatus.
*/
ZYDIS_DLLEXTERN ZydisStatus ZydisFormatterSetSymbolResolver(
ZydisInstructionFormatter* formatter, ZydisCustomSymbolResolver* symbolResolver);
/**
* @brief Formats the given instruction and writes it into the output buffer.
*
* @param formatter A pointer to the instruction-formatter instance.
* @param info A pointer to the instruction-info struct.
* @param buffer A pointer to the output buffer.
* @param bufferLen The length of the output buffer.
*
* @return A zydis status code.
*/
ZYDIS_DLLEXTERN ZydisStatus ZydisFormatterFormatInstruction(
ZydisInstructionFormatter* formatter, const ZydisInstructionInfo* info, char* buffer,
size_t bufferLen);
/* ---------------------------------------------------------------------------------------------- */
/* ============================================================================================== */
#ifdef __cplusplus
}
#endif
#endif /* ZYDIS_FORMATTER_H */

172
include/Zydis/Input.h Normal file
View File

@ -0,0 +1,172 @@
/***************************************************************************************************
Zyan Disassembler Engine (Zydis)
Original Author : Florian Bernd
* 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.
***************************************************************************************************/
#ifndef ZYDIS_INPUT_H
#define ZYDIS_INPUT_H
#include <stdint.h>
#include <stdbool.h>
#include <stdio.h>
#include <Zydis/Defines.h>
#include <Zydis/Status.h>
#ifdef __cplusplus
extern "C" {
#endif
/* ============================================================================================== */
/* Custom input */
/* ============================================================================================== */
/* ---------------------------------------------------------------------------------------------- */
/* Enums and types */
/* ---------------------------------------------------------------------------------------------- */
/**
* @brief Defines the @c ZydisInputNextFunc function pointer used in the @c ZydisCustomInput
* struct.
*
* This function should return the byte at the current input-position and increase the position
* by one. If the input data-source has no more data available, return @c FALSE.
*/
typedef bool (*ZydisInputNextFunc)(void* context, uint8_t* data);
/* ---------------------------------------------------------------------------------------------- */
/**
* @brief Defines the zydis custom input struct.
*/
typedef struct ZydisCustomInput_
{
/**
* @brief The @c ZydisInputNextFunc callback.
*/
ZydisInputNextFunc inputNext;
} ZydisCustomInput;
/* ---------------------------------------------------------------------------------------------- */
/* ============================================================================================== */
/* Memory input */
/* ============================================================================================== */
/* ---------------------------------------------------------------------------------------------- */
/* Enums and types */
/* ---------------------------------------------------------------------------------------------- */
/**
* @brief Defines the zydis memory input struct.
*/
typedef struct ZydisMemoryInput_
{
/**
* @brief The @c ZydisCustomInput base struct.
*
* This has to be the first element in every custom input data-source struct to ensure we
* can safely downcast it.
*/
ZydisCustomInput input;
/**
* @brief A pointer to the mem buffer.
*/
const uint8_t* inputBuffer;
/**
* @brief The length of the mem buffer.
*/
uint64_t inputBufferLen;
/**
* @brief The current input position.
*/
uint64_t inputBufferPos;
} ZydisMemoryInput;
/* ---------------------------------------------------------------------------------------------- */
/* Exported functions */
/* ---------------------------------------------------------------------------------------------- */
/**
* @brief Initializes the given @c ZydisMemoryInput instance.
*
* @param input A pointer to the input data-source instance.
* @param buffer The mem buffer to use.
* @param length The length of the mem buffer.
*
* @return A zydis status code.
*/
ZYDIS_DLLEXTERN ZydisStatus ZydisInputInitMemoryInput(ZydisMemoryInput* input, const void* buffer,
uint64_t length);
/* ---------------------------------------------------------------------------------------------- */
/* ============================================================================================== */
/* File input */
/* ============================================================================================== */
/* ---------------------------------------------------------------------------------------------- */
/* Enums and types */
/* ---------------------------------------------------------------------------------------------- */
/**
* @brief Defines the zydis file input struct.
*/
typedef struct ZydisFileInput_
{
/**
* @brief The @c ZydisCustomInput base struct.
*
* This has to be the first element in every custom input data-source struct to ensure we can
* safely downcast it.
*/
ZydisCustomInput input;
/**
* @brief The input file.
*/
FILE* file;
} ZydisFileInput;
/* ---------------------------------------------------------------------------------------------- */
/* Exported functions */
/* ---------------------------------------------------------------------------------------------- */
/**
* @brief Initializes the given @c ZydisFileInput instance.
*
* @param input A pointer to the input data-source instance.
* @param file The file to use. You may freely `fseek` around after creation of the source.
*
* @return A zydis status code.
*/
ZYDIS_DLLEXTERN ZydisStatus ZydisInputInitFileInput(ZydisFileInput* input, FILE* file);
/* ---------------------------------------------------------------------------------------------- */
/* ============================================================================================== */
#ifdef __cplusplus
}
#endif
#endif /* ZYDIS_INPUT_H */

View File

@ -0,0 +1,928 @@
/***************************************************************************************************
Zyan Disassembler Engine (Zydis)
Original Author : Florian Bernd
* 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.
***************************************************************************************************/
/**
* @file
* @brief TODO
*/
#ifndef ZYDIS_INSTRUCTIONINFO_H
#define ZYDIS_INSTRUCTIONINFO_H
#include <stdint.h>
#include <stdbool.h>
#include <Zydis/Mnemonic.h>
#include <Zydis/Register.h>
#ifdef __cplusplus
extern "C" {
#endif
/* ============================================================================================== */
/* Enums and types */
/* ============================================================================================== */
/* ---------------------------------------------------------------------------------------------- */
/* Disassembler mode */
/* ---------------------------------------------------------------------------------------------- */
/**
* @brief Defines the zydis disassembler-mode datatype.
*/
typedef uint8_t ZydisDisassemblerMode;
/**
* @brief Values that represent disassembler-modes.
*/
enum ZydisDisassemblerModes
{
ZYDIS_DISASSEMBLER_MODE_16BIT = 16,
ZYDIS_DISASSEMBLER_MODE_32BIT = 32,
ZYDIS_DISASSEMBLER_MODE_64BIT = 64
};
/* ---------------------------------------------------------------------------------------------- */
/* Instruction flags */
/* ---------------------------------------------------------------------------------------------- */
/**
* @brief Defines an alias representing instruction flags.
*/
typedef uint32_t ZydisInstructionFlags;
/**
* @brief Values that represent instruction flags.
*/
enum ZydisInstructionFlag
{
/**
* @brief The instruction has one or more operand with position-relative offsets.
*/
ZYDIS_IFLAG_RELATIVE = 0x00000001,
/**
* @brief The instruction has the modrm byte.
*/
ZYDIS_IFLAG_HAS_MODRM = 0x00000002,
/**
* @brief The instruction has the sib byte.
*/
ZYDIS_IFLAG_HAS_SIB = 0x00000004,
/**
* @brief An error occured while decoding the current instruction.
*/
ZYDIS_IFLAG_ERROR_MASK = 0x7F000000,
/**
* @brief The instruction is invalid.
*/
ZYDIS_IFLAG_ERROR_INVALID = 0x01000000,
/**
* @brief The instruction length has exceeded the maximum of 15 bytes.
*/
ZYDIS_IFLAG_ERROR_INSTRUCTION_LENGTH = 0x02000000,
/**
* @brief An error occured while decoding the vex-prefix.
*/
ZYDIS_IFLAG_ERROR_MALFORMED_VEX = 0x04000000,
/**
* @brief An error occured while decoding the evex-prefix.
*/
ZYDIS_IFLAG_ERROR_MALFORMED_EVEX = 0x08000000,
/**
* @brief An error occured while decoding the xop-prefix.
*/
ZYDIS_IFLAG_ERROR_MALFORMED_XOP = 0x10000000,
/**
* @brief A rex-prefix was found while decoding a vex/evex/xop instruction.
*/
ZYDIS_IFLAG_ERROR_ILLEGAL_REX = 0x20000000,
/**
* @brief An invalid constellation was found while decoding an instruction that uses the VSIB
* addressing mode.
*/
ZYDIS_IFLAG_ERROR_INVALID_VSIB = 0x40000000,
/**
* @brief An error occured while decoding the instruction-operands.
*/
ZYDIS_IFLAG_ERROR_OPERANDS = 0x40000000
};
/* ---------------------------------------------------------------------------------------------- */
/* Prefix flags */
/* ---------------------------------------------------------------------------------------------- */
/**
* @brief Defines the zydis prefix-flags datatype.
*/
typedef uint32_t ZydisPrefixFlags;
/**
* @brief Values that represent instruction encodings.
*/
enum ZydisPrefixFlag
{
/**
* @brief The instruction has the rex-prefix (0x40 - 0x4F).
*/
ZYDIS_PREFIX_REX = 0x00000001,
/**
* @brief The instruction has the xop-prefix (0x8F).
*/
ZYDIS_PREFIX_XOP = 0x00000002,
/**
* @brief The instruction has the vex-prefix (0xC4 or 0xC5).
*/
ZYDIS_PREFIX_VEX = 0x00000004,
/**
* @brief The instruction has the evex-prefix (0x62).
*/
ZYDIS_PREFIX_EVEX = 0x00000008,
/**
* @brief The instruction has the lock-prefix (0x0F)
*/
ZYDIS_PREFIX_LOCK = 0x00000010,
/**
* @brief The instruction has the rep/repe/repz-prefix (0xF3)
*/
ZYDIS_PREFIX_REP = 0x00000020,
/**
* @brief The instruction has the rep/repe/repz-prefix (0xF3)
*/
ZYDIS_PREFIX_REPE = 0x00000020,
/**
* @brief The instruction has the rep/repe/repz-prefix (0xF3)
*/
ZYDIS_PREFIX_REPZ = 0x00000020,
/**
* @brief The instruction has the repne/repnz-prefix (0xF2)
*/
ZYDIS_PREFIX_REPNE = 0x00000040,
/**
* @brief The instruction has the repne/repnz-prefix (0xF2)
*/
ZYDIS_PREFIX_REPNZ = 0x00000040,
/**
* @brief The instruction has a segment-override prefix.
*/
ZYDIS_PREFIX_SEGMENT_MASK = 0x00001F80,
/**
* @brief The instruction has the cs segment-override prefix (0x2E).
*/
ZYDIS_PREFIX_SEGMENT_CS = 0x00000080,
/**
* @brief The instruction has the ss segment-override prefix (0x36).
*/
ZYDIS_PREFIX_SEGMENT_SS = 0x00000100,
/**
* @brief The instruction has the ds segment-override prefix (0x3E).
*/
ZYDIS_PREFIX_SEGMENT_DS = 0x00000200,
/**
* @brief The instruction has the es segment-override prefix (0x26).
*/
ZYDIS_PREFIX_SEGMENT_ES = 0x00000400,
/**
* @brief The instruction has the fs segment-override prefix (0x64).
*/
ZYDIS_PREFIX_SEGMENT_FS = 0x00000800,
/**
* @brief The instruction has the gs segment-override prefix (0x65).
*/
ZYDIS_PREFIX_SEGMENT_GS = 0x00001000,
/**
* @brief The instruction has the operand-size-override prefix (0x66).
*/
ZYDIS_PREFIX_OPERANDSIZE = 0x00002000,
/**
* @brief The instruction has the address-size-override prefix (0x67).
*/
ZYDIS_PREFIX_ADDRESSSIZE = 0x00004000,
/**
* @brief The instruction has the xacquire prefix (0xF2).
*/
ZYDIS_PREFIX_XACQUIRE = 0x00008000,
/**
* @brief The instruction has the xrelease prefix (0xF3).
*/
ZYDIS_PREFIX_XRELEASE = 0x00010000,
/**
* @brief The instruction has the branch-not-taken hint (0x2E).
*/
ZYDIS_PREFIX_BRANCH_NOT_TAKEN = 0x00020000,
/**
* @brief The instruction has the branch-taken hint (0x3E).
*/
ZYDIS_PREFIX_BRANCH_TAKEN = 0x00040000,
/**
* @brief The instruction accepts the lock-prefix.
*/
ZYDIS_PREFIX_ACCEPTS_LOCK = 0x00080000,
/**
* @brief The instruction accepts the string prefixes (rep/repe/repz/repne/repnz).
*/
ZYDIS_PREFIX_ACCEPTS_REP = 0x00100000,
/**
* @brief The instruction accepts the string prefixes (rep/repe/repz/repne/repnz).
*/
ZYDIS_PREFIX_ACCEPTS_REPE = 0x00100000,
/**
* @brief The instruction accepts the string prefixes (rep/repe/repz/repne/repnz).
*/
ZYDIS_PREFIX_ACCEPTS_REPZ = 0x00100000,
/**
* @brief The instruction accepts the string prefixes (rep/repe/repz/repne/repnz).
*/
ZYDIS_PREFIX_ACCEPTS_REPNE = 0x00100000,
/**
* @brief The instruction accepts the string prefixes (rep/repe/repz/repne/repnz).
*/
ZYDIS_PREFIX_ACCEPTS_REPNZ = 0x00100000,
/**
* @brief The instruction has multiple prefixes of the first prefix-group (0x0F, 0xF3, 0xF2).
*/
ZYDIS_PREFIX_MULTIPLE_GRP1 = 0x01000000,
/**
* @brief The instruction has multiple prefixes of the second prefix-group (0x2E, 0x36,
* 0x3E, 0x26, 0x64, 0x65).
*/
ZYDIS_PREFIX_MULTIPLE_GRP2 = 0x02000000,
/**
* @brief The instruction has multiple prefixes of the third prefix-group (0x66).
*/
ZYDIS_PREFIX_MULTIPLE_GRP3 = 0x04000000,
/**
* @brief The instruction has multiple prefixes of the fourth prefix-group (0x67).
*/
ZYDIS_PREFIX_MULTIPLE_GRP4 = 0x08000000,
};
/* ---------------------------------------------------------------------------------------------- */
/* Instruction encoding */
/* ---------------------------------------------------------------------------------------------- */
/**
* @brief Defines the zydis instruction-encoding datatype.
*/
typedef uint8_t ZydisInstructionEncoding;
/**
* @brief Values that represent instruction encodings.
*/
enum ZydisInstructionEncodings
{
ZYDIS_INSTRUCTION_ENCODING_DEFAULT = 0x00,
ZYDIS_INSTRUCTION_ENCODING_3DNOW = 0x01,
ZYDIS_INSTRUCTION_ENCODING_XOP = 0x02,
ZYDIS_INSTRUCTION_ENCODING_VEX = 0x03,
ZYDIS_INSTRUCTION_ENCODING_EVEX = 0x04
};
/* ---------------------------------------------------------------------------------------------- */
/* Opcode map */
/* ---------------------------------------------------------------------------------------------- */
/**
* @brief Defines an alias representing an opcode map.
*/
typedef uint8_t ZydisOpcodeMap;
/**
* @brief Values that represent opcode maps.
*/
enum ZydisOpcodeMaps
{
ZYDIS_OPCODE_MAP_DEFAULT = 0x00,
ZYDIS_OPCODE_MAP_0F = 0x01,
ZYDIS_OPCODE_MAP_0F38 = 0x02,
ZYDIS_OPCODE_MAP_0F3A = 0x03,
ZYDIS_OPCODE_MAP_XOP8 = 0x04,
ZYDIS_OPCODE_MAP_XOP9 = 0x05,
ZYDIS_OPCODE_MAP_XOPA = 0x06
};
/* ---------------------------------------------------------------------------------------------- */
/* Operand type */
/* ---------------------------------------------------------------------------------------------- */
/**
* @brief Defines an alias representing an operand-type.
*/
typedef uint8_t ZydisOperandType;
/**
* @brief Values that represent operand-types.
*/
enum ZydisOperandTypes
{
/**
* @brief The operand is not used.
*/
ZYDIS_OPERAND_TYPE_UNUSED,
/**
* @brief The operand is a register operand.
*/
ZYDIS_OPERAND_TYPE_REGISTER,
/**
* @brief The operand is a mem operand.
*/
ZYDIS_OPERAND_TYPE_MEMORY,
/**
* @brief The operand is a pointer operand with a segment:offset lvalue.
*/
ZYDIS_OPERAND_TYPE_POINTER,
/**
* @brief The operand is an immediate operand.
*/
ZYDIS_OPERAND_TYPE_IMMEDIATE
};
/* ---------------------------------------------------------------------------------------------- */
/* Operand encoding */
/* ---------------------------------------------------------------------------------------------- */
/**
* @brief Defines an alias representing an operand-encoding.
*/
typedef uint8_t ZydisOperandEncoding;
/**
* @brief Values that represent operand-encodings.
*/
enum ZydisOperandEncodings
{
ZYDIS_OPERAND_ENCODING_NONE,
ZYDIS_OPERAND_ENCODING_REG,
ZYDIS_OPERAND_ENCODING_RM,
ZYDIS_OPERAND_ENCODING_RM_CD2,
ZYDIS_OPERAND_ENCODING_RM_CD4,
ZYDIS_OPERAND_ENCODING_RM_CD8,
ZYDIS_OPERAND_ENCODING_RM_CD16,
ZYDIS_OPERAND_ENCODING_RM_CD32,
ZYDIS_OPERAND_ENCODING_RM_CD64,
ZYDIS_OPERAND_ENCODING_OPCODE,
ZYDIS_OPERAND_ENCODING_VVVV,
ZYDIS_OPERAND_ENCODING_AAA,
ZYDIS_OPERAND_ENCODING_IMM8,
ZYDIS_OPERAND_ENCODING_IMM16,
ZYDIS_OPERAND_ENCODING_IMM32,
ZYDIS_OPERAND_ENCODING_IMM64
};
/* ---------------------------------------------------------------------------------------------- */
/* Operand access mode */
/* ---------------------------------------------------------------------------------------------- */
/**
* @brief Defines an alias representing an operand-access mode.
*/
typedef uint8_t ZydisOperandAccess;
/**
* @brief Values that represent operand-access-modes.
*/
enum ZydisOperandAccessModes
{
/**
* @brief The operand gets read by the instruction.
*/
ZYDIS_OPERAND_ACCESS_READ,
/**
* @brief The operand gets written by the instruction.
*/
ZYDIS_OPERAND_ACCESS_WRITE,
/**
* @brief The operand gets read and written by the instruction.
*/
ZYDIS_OPERAND_ACCESS_READWRITE
};
/* ---------------------------------------------------------------------------------------------- */
/* AVX mask mode */
/* ---------------------------------------------------------------------------------------------- */
/**
* @brief Defines the @c ZydisAVXMaskMode datatype.
*/
typedef uint8_t ZydisAVXMaskMode;
/**
* @brief Values that represent zydis avx mask-modes.
*/
enum ZydisAVXMaskModes
{
ZYDIS_AVX_MASKMODE_INVALID,
/**
* @brief Merge mode. This is the default mode for all evex-instructions.
*/
ZYDIS_AVX_MASKMODE_MERGE,
/**
* @brief The zeroing mode is enabled for this instruction.
*/
ZYDIS_AVX_MASKMODE_ZERO
};
/* ---------------------------------------------------------------------------------------------- */
/* AVX broadcast type */
/* ---------------------------------------------------------------------------------------------- */
/**
* @brief Defines the @c ZydisAVXBroadcastType datatype.
*/
typedef uint8_t ZydisAVXBroadcastType;
/**
* @brief Values that represent zydis avx broadcast-types.
*/
enum ZydisAVXBroadcastTypes
{
ZYDIS_AVX_BCSTMODE_INVALID,
/**
* @brief 1to2 broadcast.
*/
ZYDIS_AVX_BCSTMODE_2,
/**
* @brief 1to4 broadcast.
*/
ZYDIS_AVX_BCSTMODE_4,
/**
* @brief 1to8 broadcast.
*/
ZYDIS_AVX_BCSTMODE_8,
/**
* @brief 1to16 broadcast.
*/
ZYDIS_AVX_BCSTMODE_16
};
/* ---------------------------------------------------------------------------------------------- */
/* AVX rounding mode */
/* ---------------------------------------------------------------------------------------------- */
/**
* @brief Defines the @c ZydisAVXRoundingMode datatype.
*/
typedef uint8_t ZydisAVXRoundingMode;
/**
* @brief Values that represent zydis avx rounding-mode.
*/
enum ZydisAVXRoundingModes // TODO: Mirror "real" values from documentation
{
ZYDIS_AVX_RNDMODE_INVALID,
/**
* @brief Round to nearest.
*/
ZYDIS_AVX_RNDMODE_RN,
/**
* @brief Round down.
*/
ZYDIS_AVX_RNDMODE_RD,
/**
* @brief Round up.
*/
ZYDIS_AVX_RNDMODE_RU,
/**
* @brief Round towards zero.
*/
ZYDIS_AVX_RNDMODE_RZ
};
/* ---------------------------------------------------------------------------------------------- */
/* Operand info */
/* ---------------------------------------------------------------------------------------------- */
/**
* @brief Defines the zydis operand info struct.
*/
typedef struct ZydisOperandInfo_
{
/**
* @brief The type of the operand.
*/
ZydisOperandType type;
/**
* @brief The logical size of the operand.
*/
uint16_t size;
/**
* @brief The operand encoding.
*/
ZydisOperandEncoding encoding;
/**
* @brief The operand access mode.
*/
ZydisOperandAccess access;
/**
* @brief Specifies the register for register-operands.
*/
ZydisRegister reg;
/**
* @brief Extended info for memory-operands.
*/
struct
{
/**
* @brief The segment register.
*/
ZydisRegister segment;
/**
* @brief The base register.
*/
ZydisRegister base;
/**
* @brief The index register.
*/
ZydisRegister index;
/**
* @brief The scale factor.
*/
uint8_t scale;
/**
* @brief Extended info for memory-operand with displacement.
*/
struct
{
/**
* @brief The physical displacement size.
*/
uint8_t size;
/**
* @brief The displacement value
*/
union
{
int8_t sbyte;
int16_t sword;
int32_t sdword;
int64_t sqword;
} value;
/**
* @brief The offset of the displacement data, relative to the beginning of the
* instruction.
*/
uint8_t dataOffset;
} disp;
} mem;
/**
* @brief Extended info for pointer operands.
*/
struct
{
uint16_t segment;
uint32_t offset;
} ptr;
/**
* @brief Extended info for immediate operands.
*/
struct
{
/**
* @brief Signals, if the immediate value is signed.
*/
bool isSigned;
/**
* @brief Signals, if the immediate value contains a relative offset.
*/
bool isRelative;
/**
* @brief The physical immediate size.
*/
uint8_t size;
/**
* @brief The immediate value.
*/
union
{
int8_t sbyte;
uint8_t ubyte;
int16_t sword;
uint16_t uword;
int32_t sdword;
uint32_t udword;
int64_t sqword;
uint64_t uqword;
} value;
/**
* @brief The offset of the immediate data, relative to the beginning of the instruction.
*/
uint8_t dataOffset;
} imm;
} ZydisOperandInfo;
/* ---------------------------------------------------------------------------------------------- */
/* Instruction info */
/* ---------------------------------------------------------------------------------------------- */
/**
* @brief Defines the zydis instruction info struct.
*/
typedef struct ZydisInstructionInfo_
{
/**
* @brief The disassembler-mode used to decode this instruction.
*/
ZydisDisassemblerMode mode;
/**
* @brief Instruction specific info- and error-flags.
*/
ZydisInstructionFlags flags;
/**
* @brief Prefix flags.
*/
ZydisPrefixFlags prefixFlags;
/**
* @brief The instruction-mnemonic.
*/
ZydisInstructionMnemonic mnemonic;
/**
* @brief The length of the decoded instruction.
*/
uint8_t length;
/**
* @brief The raw bytes of the decoded instruction.
*/
uint8_t data[15];
/**
* @brief The instruction-encoding (default, 3dnow, vex, evex, xop).
*/
ZydisInstructionEncoding encoding;
/**
* @brief The opcode-map.
*/
ZydisOpcodeMap opcodeMap;
/**
* @brief The instruction-opcode.
*/
uint8_t opcode;
/**
* @brief The number of instruction-operands.
*/
uint8_t operandCount;
/**
* @brief Detailed info for all instruction operands.
*/
ZydisOperandInfo operand[4];
/**
* @brief The operand mode (16, 32, 64).
*/
uint8_t operandMode;
/**
* @brief The address mode (16, 32, 64).
*/
uint8_t addressMode;
/**
* @brief Extended info for avx-related instructions.
*/
struct
{
/**
* @brief The AVX mask-register.
*/
ZydisRegister maskRegister;
/**
* @brief The AVX mask-mode.
*/
ZydisAVXMaskMode maskMode;
/**
* @brief The AVX broadcast-type.
*/
ZydisAVXBroadcastType broadcast;
/**
* @brief The AVX rounding-mode.
*/
ZydisAVXRoundingMode roundingMode;
/**
* @brief The AVX suppress-all-exceptions flag.
*/
bool sae;
} avx;
/**
* @brief The instruction address points at the current instruction (relative to the
* initial instruction pointer).
*/
uint64_t instrAddress;
/**
* @brief The instruction pointer points at the address of the next instruction (relative
* to the initial instruction pointer).
*
* This field is used to properly format relative instructions.
*/
uint64_t instrPointer;
/**
* @brief Extended info about different instruction-parts like modrm, sib or
* encoding-prefixes.
*/
struct
{
// TODO: uint8_t map[15];
/**
* @brief Detailed info about the rex-prefix.
*/
struct
{
/**
* @brief True if the prefix got already decoded.
*/
bool isDecoded;
/**
* @brief The raw bytes of the prefix.
*/
uint8_t data[1];
/**
* @brief 64 bit operand-size override.
*/
uint8_t w;
/**
* @brief Extension of the modrm.reg field.
*/
uint8_t r;
/**
* @brief Extension of the sib.index field.
*/
uint8_t x;
/**
* @brief Extension of the modrm.rm field, sib.base field, or opcode.reg field.
*/
uint8_t b;
} rex;
/**
* @brief Detailed info about the vex-prefix.
*/
struct
{
/**
* @brief True if the prefix got already decoded.
*/
bool isDecoded;
/**
* @brief The raw bytes of the prefix.
*/
uint8_t data[3];
uint8_t r;
uint8_t x;
uint8_t b;
uint8_t m_mmmm;
uint8_t w;
uint8_t vvvv;
uint8_t l;
uint8_t pp;
} vex;
/**
* @brief Detailed info about the evex-prefix.
*/
struct
{
/**
* @brief True if the prefix got already decoded.
*/
bool isDecoded;
/**
* @brief The raw bytes of the prefix.
*/
uint8_t data[4];
/**
* @brief TODO:
*/
uint8_t r;
/**
* @brief TODO:
*/
uint8_t x;
/**
* @brief TODO:
*/
uint8_t b;
/**
* @brief High-16 register specifier modifier.
*/
uint8_t r2;
/**
* @brief Compressed legacy escape.
*/
uint8_t mm;
/**
* @brief Osize promotion/Opcode extension.
*/
uint8_t w;
/**
* @brief NDS register specifier.
*/
uint8_t vvvv;
/**
* @brief Compressed legacy prefix.
*/
uint8_t pp;
/**
* @brief Zeroing/Merging.
*/
uint8_t z;
/**
* @brief Vector length/RC (most significant bit).
*/
uint8_t l2;
/**
* @brief Vector length/RC (least significant bit).
*/
uint8_t l;
/**
* @brief Broadcast/RC/SAE Context.
*/
uint8_t b0;
/**
* @brief High-16 NDS/VIDX register specifier.
*/
uint8_t v2;
/**
* @brief Embedded opmask register specifier.
*/
uint8_t aaa;
} evex;
/**
* @brief Detailed info about the xop-prefix.
*/
struct
{
/**
* @brief True if the prefix got already decoded.
*/
bool isDecoded;
/**
* @brief The raw bytes of the prefix.
*/
uint8_t data[3];
uint8_t r;
uint8_t x;
uint8_t b;
uint8_t m_mmmm;
uint8_t w;
uint8_t vvvv;
uint8_t l;
uint8_t pp;
} xop;
/**
* @brief Detailed info about the modrm-byte.
*/
struct
{
bool isDecoded;
uint8_t data[1];
uint8_t mod;
uint8_t reg;
uint8_t rm;
} modrm;
/**
* @brief Detailed info about the sib-byte.
*/
struct
{
bool isDecoded;
uint8_t data[1];
uint8_t scale;
uint8_t index;
uint8_t base;
} sib;
/**
* @brief Internal data.
*/
struct
{
uint8_t w;
uint8_t r;
uint8_t x;
uint8_t b;
uint8_t l;
} internal;
} details;
} ZydisInstructionInfo;
/* ---------------------------------------------------------------------------------------------- */
/* ============================================================================================== */
#ifdef __cplusplus
}
#endif
#endif /* ZYDIS_INSTRUCTIONINFO_H */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,634 @@
/***************************************************************************************************
Zyan Disassembler Engine (Zydis)
Original Author : Florian Bernd
* 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.
***************************************************************************************************/
#ifndef ZYDIS_INSTRUCTIONTABLE_H
#define ZYDIS_INSTRUCTIONTABLE_H
#include <stdint.h>
#include <assert.h>
#include <Zydis/Defines.h>
#include <Zydis/Mnemonic.h>
#include <Zydis/InstructionInfo.h>
#ifdef __cplusplus
extern "C" {
#endif
/* ============================================================================================== */
/* Enums and types */
/* ============================================================================================== */
/* ---------------------------------------------------------------------------------------------- */
/* Instruction table */
/* ---------------------------------------------------------------------------------------------- */
/**
* @brief Defines the @c ZydisInstructionTableNodeType datatype.
*/
typedef uint8_t ZydisInstructionTableNodeType;
/**
* @brief Values that represent zydis instruction table node types.
*/
enum ZydisInstructionTableNodeTypes
{
ZYDIS_NODETYPE_INVALID = 0x00,
/**
* @brief Reference to a concrete instruction definition.
*/
ZYDIS_NODETYPE_DEFINITION = 0x01,
/**
* @brief Reference to an opcode filter.
*/
ZYDIS_NODETYPE_FILTER_OPCODE = 0x02,
/**
* @brief Reference to an vex-map filter.
*/
ZYDIS_NODETYPE_FILTER_VEX = 0x03,
/**
* @brief Reference to an xop-map filter.
*/
ZYDIS_NODETYPE_FILTER_XOP = 0x04,
/**
* @brief Reference to an instruction-mode filter.
*/
ZYDIS_NODETYPE_FILTER_MODE = 0x05,
/**
* @brief Reference to a mandatory-prefix filter.
*/
ZYDIS_NODETYPE_FILTER_MANDATORYPREFIX = 0x06,
/**
* @brief Reference to a modrm.mod filter.
*/
ZYDIS_NODETYPE_FILTER_MODRMMOD = 0x07,
/**
* @brief Reference to a modrm.reg filter.
*/
ZYDIS_NODETYPE_FILTER_MODRMREG = 0x08,
/**
* @brief Reference to a modrm.rm filter.
*/
ZYDIS_NODETYPE_FILTER_MODRMRM = 0x09,
/**
* @brief Reference to an operand-size filter.
*/
ZYDIS_NODETYPE_FILTER_OPERANDSIZE = 0x0A,
/**
* @brief Reference to an address-size filter.
*/
ZYDIS_NODETYPE_FILTER_ADDRESSSIZE = 0x0B,
/**
* @brief Reference to an rex/vex/evex.w filter.
*/
ZYDIS_NODETYPE_FILTER_REXW = 0x0C,
/**
* @brief Reference to an vex/evex.l filter.
*/
ZYDIS_NODETYPE_FILTER_VEXL = 0x0D,
/**
* @brief Reference to an evex.l' filter.
*/
ZYDIS_NODETYPE_FILTER_EVEXL2 = 0x0E,
/**
* @brief Reference to an evex.b filter.
*/
ZYDIS_NODETYPE_FILTER_EVEXB = 0x0F
};
/* ---------------------------------------------------------------------------------------------- */
#pragma pack (push, 1)
/**
* @brief Defines the @c ZydisInstructionTableNode struct.
*/
typedef struct ZydisInstructionTableNode_
{
/**
* @brief The instruction table node type.
*/
ZydisInstructionTableNodeType type;
/**
* @brief The instruction table node value.
*/
uint16_t value;
} ZydisInstructionTableNode;
#pragma pack (pop)
/* ---------------------------------------------------------------------------------------------- */
/* Instruction definition */
/* ---------------------------------------------------------------------------------------------- */
/**
* @brief Defines the @c ZydisSemanticOperandType datatype.
*/
typedef uint8_t ZydisSemanticOperandType;
/**
* @brief Values that represent semantic operand types.
*/
enum ZydisSemanticOperandTypes
{
ZYDIS_SEM_OPERAND_TYPE_UNUSED,
ZYDIS_SEM_OPERAND_TYPE_GPR8,
ZYDIS_SEM_OPERAND_TYPE_GPR16,
ZYDIS_SEM_OPERAND_TYPE_GPR32,
ZYDIS_SEM_OPERAND_TYPE_GPR64,
ZYDIS_SEM_OPERAND_TYPE_FPR,
ZYDIS_SEM_OPERAND_TYPE_VR64,
ZYDIS_SEM_OPERAND_TYPE_VR128,
ZYDIS_SEM_OPERAND_TYPE_VR256,
ZYDIS_SEM_OPERAND_TYPE_VR512,
ZYDIS_SEM_OPERAND_TYPE_CR,
ZYDIS_SEM_OPERAND_TYPE_DR,
ZYDIS_SEM_OPERAND_TYPE_SREG,
ZYDIS_SEM_OPERAND_TYPE_MSKR,
ZYDIS_SEM_OPERAND_TYPE_BNDR,
ZYDIS_SEM_OPERAND_TYPE_MEM,
ZYDIS_SEM_OPERAND_TYPE_MEM8,
ZYDIS_SEM_OPERAND_TYPE_MEM16,
ZYDIS_SEM_OPERAND_TYPE_MEM32,
ZYDIS_SEM_OPERAND_TYPE_MEM64,
ZYDIS_SEM_OPERAND_TYPE_MEM80,
ZYDIS_SEM_OPERAND_TYPE_MEM128,
ZYDIS_SEM_OPERAND_TYPE_MEM256,
ZYDIS_SEM_OPERAND_TYPE_MEM512,
ZYDIS_SEM_OPERAND_TYPE_MEM32_BCST2,
ZYDIS_SEM_OPERAND_TYPE_MEM32_BCST4,
ZYDIS_SEM_OPERAND_TYPE_MEM32_BCST8,
ZYDIS_SEM_OPERAND_TYPE_MEM32_BCST16,
ZYDIS_SEM_OPERAND_TYPE_MEM64_BCST2,
ZYDIS_SEM_OPERAND_TYPE_MEM64_BCST4,
ZYDIS_SEM_OPERAND_TYPE_MEM64_BCST8,
ZYDIS_SEM_OPERAND_TYPE_MEM64_BCST16,
ZYDIS_SEM_OPERAND_TYPE_MEM32_VSIBX,
ZYDIS_SEM_OPERAND_TYPE_MEM32_VSIBY,
ZYDIS_SEM_OPERAND_TYPE_MEM32_VSIBZ,
ZYDIS_SEM_OPERAND_TYPE_MEM64_VSIBX,
ZYDIS_SEM_OPERAND_TYPE_MEM64_VSIBY,
ZYDIS_SEM_OPERAND_TYPE_MEM64_VSIBZ,
ZYDIS_SEM_OPERAND_TYPE_M1616,
ZYDIS_SEM_OPERAND_TYPE_M1632,
ZYDIS_SEM_OPERAND_TYPE_M1664,
ZYDIS_SEM_OPERAND_TYPE_MEM112,
ZYDIS_SEM_OPERAND_TYPE_MEM224,
ZYDIS_SEM_OPERAND_TYPE_IMM8,
ZYDIS_SEM_OPERAND_TYPE_IMM16,
ZYDIS_SEM_OPERAND_TYPE_IMM32,
ZYDIS_SEM_OPERAND_TYPE_IMM64,
ZYDIS_SEM_OPERAND_TYPE_IMM8U,
ZYDIS_SEM_OPERAND_TYPE_REL8,
ZYDIS_SEM_OPERAND_TYPE_REL16,
ZYDIS_SEM_OPERAND_TYPE_REL32,
ZYDIS_SEM_OPERAND_TYPE_REL64,
ZYDIS_SEM_OPERAND_TYPE_PTR1616,
ZYDIS_SEM_OPERAND_TYPE_PTR1632,
ZYDIS_SEM_OPERAND_TYPE_PTR1664,
ZYDIS_SEM_OPERAND_TYPE_MOFFS16,
ZYDIS_SEM_OPERAND_TYPE_MOFFS32,
ZYDIS_SEM_OPERAND_TYPE_MOFFS64,
ZYDIS_SEM_OPERAND_TYPE_SRCIDX8,
ZYDIS_SEM_OPERAND_TYPE_SRCIDX16,
ZYDIS_SEM_OPERAND_TYPE_SRCIDX32,
ZYDIS_SEM_OPERAND_TYPE_SRCIDX64,
ZYDIS_SEM_OPERAND_TYPE_DSTIDX8,
ZYDIS_SEM_OPERAND_TYPE_DSTIDX16,
ZYDIS_SEM_OPERAND_TYPE_DSTIDX32,
ZYDIS_SEM_OPERAND_TYPE_DSTIDX64,
ZYDIS_SEM_OPERAND_TYPE_FIXED1,
ZYDIS_SEM_OPERAND_TYPE_AL,
ZYDIS_SEM_OPERAND_TYPE_CL,
ZYDIS_SEM_OPERAND_TYPE_AX,
ZYDIS_SEM_OPERAND_TYPE_DX,
ZYDIS_SEM_OPERAND_TYPE_EAX,
ZYDIS_SEM_OPERAND_TYPE_RAX,
ZYDIS_SEM_OPERAND_TYPE_ES,
ZYDIS_SEM_OPERAND_TYPE_CS,
ZYDIS_SEM_OPERAND_TYPE_SS,
ZYDIS_SEM_OPERAND_TYPE_DS,
ZYDIS_SEM_OPERAND_TYPE_GS,
ZYDIS_SEM_OPERAND_TYPE_FS,
ZYDIS_SEM_OPERAND_TYPE_ST0
};
/* ---------------------------------------------------------------------------------------------- */
/**
* @brief Defines the @c ZydisEvexBFunctionality datatype .
*/
typedef uint8_t ZydisEvexBFunctionality;
/**
* @brief Values that represent zydis evex.b-functionalities.
*/
enum ZydisEvexBFunctionalities
{
ZYDIS_EVEXB_FUNCTIONALITY_NONE,
ZYDIS_EVEXB_FUNCTIONALITY_BC,
ZYDIS_EVEXB_FUNCTIONALITY_RC,
ZYDIS_EVEXB_FUNCTIONALITY_SAE
};
/* ---------------------------------------------------------------------------------------------- */
/**
* @brief Defines the zydis operand definition datatype.
*/
typedef uint16_t ZydisOperandDefinition;
#pragma pack (push, 1)
/**
* @brief Defines the zydis operands definition datatype.
*/
typedef struct ZydisInstructionOperands_
{
ZydisOperandDefinition operands[4];
} ZydisInstructionOperands;
/**
* @brief Defines the zydis instruction definition struct.
*/
typedef struct ZydisInstructionDefinition_
{
/**
* @brief The instruction mnemonic.
*/
ZydisInstructionMnemonic mnemonic;
/**
* @brief The instruction operand.
*/
uint16_t operands;
//ZydisOperandDefinition operands[4];
} ZydisInstructionDefinition;
#pragma pack (pop)
/* ---------------------------------------------------------------------------------------------- */
/* ============================================================================================== */
/* Data tables */
/* ============================================================================================== */
/**
* @brief Contains all opcode filters.
*
* Indexed by the numeric value of the opcode.
*/
extern const ZydisInstructionTableNode filterOpcode[][256];
/**
* @brief Contains all vex-map filters.
*
* Index values:
* 0 = LES, LDS or BOUND instruction (default encoding)
* 1 = 0F
* 2 = 0F38
* 3 = 0F3A
* 4 = 66
* 5 = 66_0F
* 6 = 66_0F38
* 7 = 66_0F3A
* 8 = F3
* 9 = F3_0F
* A = F3_0F38
* B = F3_0F3A
* C = F2
* D = F2_0F
* E = F2_0F38
* F = F2_0F3A
*/
extern const ZydisInstructionTableNode filterVEX[][16];
/**
* @brief Contains all xop-map filters.
*
* Index values:
* 0 = POP instruction (default encoding)
* 1 = xop8
* 2 = xop9
* 3 = xopA
*/
extern const ZydisInstructionTableNode filterXOP[][4];
/**
* @brief Contains all instruction-mode filters.
*
* Index values:
* 0 = 64 bit mode required
* 1 = 64 bit mode excluded
*/
extern const ZydisInstructionTableNode filterMode[][2];
/**
* @brief Contains all mandatory-prefix switch tables.
*
* Index values:
* 0 = none
* 1 = 66
* 2 = F3
* 3 = F2
*/
extern const ZydisInstructionTableNode filterMandatoryPrefix[][4];
/**
* @brief Contains all modrm.mod filters.
*
* Index values:
* 0 = [modrm_mod == !11] = memory
* 1 = [modrm_mod == 11] = register
*/
extern const ZydisInstructionTableNode filterModrmMod[][2];
/**
* @brief Contains all modrm.reg filters.
*
* Indexed by the numeric value of the modrm_reg field.
*/
extern const ZydisInstructionTableNode filterModrmReg[][8];
/**
* @brief Contains all modrm.rm filters.
*
* Indexed by the numeric value of the modrm_rm field.
*/
extern const ZydisInstructionTableNode filterModrmRm[][8];
/**
* @brief Contains all operand-size filters.
*
* Index values:
* 0 = 16bit = 0x66 prefix in 32 bit mode
* 1 = 32bit = 0x66 prefix in 16 bit mode
*/
extern const ZydisInstructionTableNode filterOperandSize[][2];
/**
* @brief Contains all address-size filters.
*
* Index values:
* 0 = 16
* 1 = 32
* 2 = 64
*/
extern const ZydisInstructionTableNode filterAddressSize[][3];
/**
* @brief Contains all rex/vex/evex.w filters.
*
* Indexed by the numeric value of the rex/vex/evex.w field.
*/
extern const ZydisInstructionTableNode filterREXW[][2];
/**
* @brief Contains all vex.l filters.
*
* Indexed by the numeric value of the vex/evex.l field.
*/
extern const ZydisInstructionTableNode filterVEXL[][2];
/**
* @brief Contains all evex.l' filters.
*
* Indexed by the numeric value of the evex.l' field.
*/
extern const ZydisInstructionTableNode filterEVEXL2[][2];
/**
* @brief Contains all evex.b filters.
*
* Indexed by the numeric value of the evex.b field.
*/
extern const ZydisInstructionTableNode filterEVEXB[][2];
/**
* @brief Contains all instruction-definitions.
*/
extern const ZydisInstructionDefinition instructionDefinitions[];
/**
* @brief Contains all instruction-operand-definitions.
*/
extern const ZydisInstructionOperands instructionOperands[];
/* ============================================================================================== */
/* Functions */
/* ============================================================================================== */
/**
* @brief Returns the type of the specified instruction table node.
*
* @param node The node.
*
* @return The type of the specified instruction table node.
*/
ZYDIS_INLINE ZydisInstructionTableNodeType ZydisInstructionTableGetNodeType(
ZydisInstructionTableNode node)
{
return node.type;
}
/**
* @brief Returns the value of the specified instruction table node.
*
* @param node The node.
*
* @return The value of the specified instruction table node.
*/
ZYDIS_INLINE uint16_t ZydisInstructionTableGetNodeValue(ZydisInstructionTableNode node)
{
return node.value;
}
/* ---------------------------------------------------------------------------------------------- */
/**
* @brief Returns the root node of the instruction table.
*
* @return The root node of the instruction table.
*/
ZYDIS_INLINE ZydisInstructionTableNode ZydisInstructionTableGetRootNode()
{
ZydisInstructionTableNode root = { ZYDIS_NODETYPE_FILTER_OPCODE, 0x00000000 };
return root;
}
/**
* @brief Returns the child node of @c parent specified by @c index.
*
* @param parent The parent node.
* @param index The index of the child node to retrieve.
*
* @return The specified child node.
*/
ZYDIS_INLINE ZydisInstructionTableNode ZydisInstructionTableGetChildNode(
ZydisInstructionTableNode parent, uint16_t index)
{
ZydisInstructionTableNodeType nodeType = ZydisInstructionTableGetNodeType(parent);
uint16_t tableIndex = ZydisInstructionTableGetNodeValue(parent);
switch (nodeType)
{
case ZYDIS_NODETYPE_FILTER_OPCODE:
ZYDIS_ASSERT(index < 256);
return filterOpcode[tableIndex][index];
case ZYDIS_NODETYPE_FILTER_VEX:
ZYDIS_ASSERT(index < 16);
return filterVEX[tableIndex][index];
case ZYDIS_NODETYPE_FILTER_XOP:
ZYDIS_ASSERT(index < 4);
return filterXOP[tableIndex][index];
case ZYDIS_NODETYPE_FILTER_MODE:
ZYDIS_ASSERT(index < 3);
return filterMode[tableIndex][index];
case ZYDIS_NODETYPE_FILTER_MANDATORYPREFIX:
ZYDIS_ASSERT(index < 4);
return filterMandatoryPrefix[tableIndex][index];
case ZYDIS_NODETYPE_FILTER_MODRMMOD:
ZYDIS_ASSERT(index < 2);
return filterModrmMod[tableIndex][index];
case ZYDIS_NODETYPE_FILTER_MODRMREG:
ZYDIS_ASSERT(index < 8);
return filterModrmReg[tableIndex][index];
case ZYDIS_NODETYPE_FILTER_MODRMRM:
ZYDIS_ASSERT(index < 8);
return filterModrmRm[tableIndex][index];
case ZYDIS_NODETYPE_FILTER_OPERANDSIZE:
ZYDIS_ASSERT(index < 2);
return filterOperandSize[tableIndex][index];
case ZYDIS_NODETYPE_FILTER_ADDRESSSIZE:
ZYDIS_ASSERT(index < 3);
return filterAddressSize[tableIndex][index];
case ZYDIS_NODETYPE_FILTER_REXW:
ZYDIS_ASSERT(index < 2);
return filterREXW[tableIndex][index];
case ZYDIS_NODETYPE_FILTER_VEXL:
ZYDIS_ASSERT(index < 2);
return filterVEXL[tableIndex][index];
case ZYDIS_NODETYPE_FILTER_EVEXL2:
ZYDIS_ASSERT(index < 2);
return filterEVEXL2[tableIndex][index];
case ZYDIS_NODETYPE_FILTER_EVEXB:
ZYDIS_ASSERT(index < 2);
return filterEVEXB[tableIndex][index];
default:
ZYDIS_UNREACHABLE;
}
ZydisInstructionTableNode node = { ZYDIS_NODETYPE_INVALID, 0x00000000 };
return node;
}
/**
* @brief Returns the instruction definition that is linked to the given @c node.
*
* @param node The instruction definition node.
*
* @return Pointer to the instruction definition.
*/
ZYDIS_INLINE const ZydisInstructionDefinition* ZydisInstructionDefinitionByNode(
ZydisInstructionTableNode node)
{
ZYDIS_ASSERT(ZydisInstructionTableGetNodeType(node) == ZYDIS_NODETYPE_DEFINITION);
return &instructionDefinitions[ZydisInstructionTableGetNodeValue(node)];
}
/* ---------------------------------------------------------------------------------------------- */
ZYDIS_INLINE ZydisInstructionMnemonic ZydisInstructionDefinitionGetMnemonic(
const ZydisInstructionDefinition* definition)
{
return (definition->mnemonic >> 4) & 0xFFF;
}
ZYDIS_INLINE const ZydisInstructionOperands* ZydisInstructionDefinitionGetOperands(
const ZydisInstructionDefinition* definition)
{
return &instructionOperands[definition->operands];
}
ZYDIS_INLINE ZydisEvexBFunctionality ZydisInstructionDefinitionGetEvexBFunctionality(
const ZydisInstructionDefinition* definition)
{
return (definition->mnemonic >> 2) & 0x03;
}
ZYDIS_INLINE bool ZydisInstructionDefinitionHasEvexAAA(const ZydisInstructionDefinition* definition)
{
return (definition->mnemonic >> 1) & 0x01;
}
ZYDIS_INLINE bool ZydisInstructionDefinitionHasEvexZ(const ZydisInstructionDefinition* definition)
{
return definition->mnemonic & 0x01;
}
/* ---------------------------------------------------------------------------------------------- */
/**
* @brief Returns the defined operand-type of the specified operand-definition.
*
* @param definition The operand definition.
*
* @return The defined operand-type of the specified operand-definition.
*/
ZYDIS_INLINE ZydisSemanticOperandType ZydisOperandDefinitionGetType(
ZydisOperandDefinition definition)
{
return ((definition >> 8) & 0xFF);
}
/**
* @brief Returns the operand-encoding of the specified operand-definition.
*
* @param definition The operand definition.
*
* @return The operand-encoding of the specified operand-definition.
*/
ZYDIS_INLINE ZydisOperandEncoding ZydisOperandDefinitionGetEncoding(
ZydisOperandDefinition definition)
{
return ((definition >> 2) & 0x3F);
}
/**
* @brief Returns the access-mode of the specified operand-definition.
*
* @param definition The operand definition.
*
* @return The access-mode of the specified operand-definition.
*/
ZYDIS_INLINE ZydisOperandAccess ZydisOperandDefinitionGetAccessMode(
ZydisOperandDefinition definition)
{
return ((definition >> 0) & 0x03);
}
/* ---------------------------------------------------------------------------------------------- */
/* ============================================================================================== */
#ifdef __cplusplus
}
#endif
#endif /* ZYDIS_INSTRUCTIONTABLE_H */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

85
include/Zydis/Mnemonic.h Normal file
View File

@ -0,0 +1,85 @@
/***************************************************************************************************
Zyan Disassembler Engine (Zydis)
Original Author : Florian Bernd
* 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.
***************************************************************************************************/
#ifndef ZYDIS_MNEMONIC_H
#define ZYDIS_MNEMONIC_H
#include <stdint.h>
#include <Zydis/Defines.h>
#include <Zydis/Status.h>
#ifdef __cplusplus
extern "C" {
#endif
/* ============================================================================================== */
/* Enums and types */
/* ============================================================================================== */
/**
* @brief Defines the @c ZydisInstructionMnemonic datatype.
*/
typedef uint16_t ZydisInstructionMnemonic;
/**
* @brief Values that represent zydis instruction-mnemonics.
*/
enum ZydisInstructionMnemonics
{
#include <Zydis/Internal/Mnemonics.inc>
};
/* ============================================================================================== */
/* Exported functions */
/* ============================================================================================== */
/**
* @brief Returns the specified instruction mnemonic string.
*
* @param mnemonic The mnemonic.
*
* @return The instruction mnemonic string or @c NULL, if an invalid mnemonic was passed.
*/
ZYDIS_DLLEXTERN const char* ZydisMnemonicGetString(ZydisInstructionMnemonic mnemonic);
/**
* @brief Replaces the string representation of the given mnemonic with a new value.
*
* @param mnemonic The mnemonic.
* @param mnemonicString The new mnemonic string. Use @c NULL to restore default value.
*
* @return A zydis status code.
*/
ZYDIS_DLLEXTERN ZydisStatus ZydisMnemonicReplaceString(ZydisInstructionMnemonic mnemonic,
const char* mnemonicString);
/* ============================================================================================== */
#ifdef __cplusplus
}
#endif
#endif /* ZYDIS_MNEMONIC_H */

394
include/Zydis/Register.h Normal file
View File

@ -0,0 +1,394 @@
/***************************************************************************************************
Zyan Disassembler Engine (Zydis)
Original Author : Florian Bernd
* 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.
***************************************************************************************************/
#ifndef ZYDIS_REGISTER_H
#define ZYDIS_REGISTER_H
#include <stdint.h>
#include <stdbool.h>
#include <Zydis/Defines.h>
#ifdef __cplusplus
extern "C" {
#endif
/* ============================================================================================== */
/* Enums and types */
/* ============================================================================================== */
/**
* @brief Defines the @c ZydisRegister datatype.
*/
typedef uint8_t ZydisRegister;
/**
* @brief Values that represent zydis registers.
*/
enum ZydisRegisters
{
ZYDIS_REGISTER_NONE,
// General purpose registers 64-bit
ZYDIS_REGISTER_RAX, ZYDIS_REGISTER_RCX, ZYDIS_REGISTER_RDX, ZYDIS_REGISTER_RBX,
ZYDIS_REGISTER_RSP, ZYDIS_REGISTER_RBP, ZYDIS_REGISTER_RSI, ZYDIS_REGISTER_RDI,
ZYDIS_REGISTER_R8, ZYDIS_REGISTER_R9, ZYDIS_REGISTER_R10, ZYDIS_REGISTER_R11,
ZYDIS_REGISTER_R12, ZYDIS_REGISTER_R13, ZYDIS_REGISTER_R14, ZYDIS_REGISTER_R15,
// General purpose registers 32-bit
ZYDIS_REGISTER_EAX, ZYDIS_REGISTER_ECX, ZYDIS_REGISTER_EDX, ZYDIS_REGISTER_EBX,
ZYDIS_REGISTER_ESP, ZYDIS_REGISTER_EBP, ZYDIS_REGISTER_ESI, ZYDIS_REGISTER_EDI,
ZYDIS_REGISTER_R8D, ZYDIS_REGISTER_r9D, ZYDIS_REGISTER_R10D, ZYDIS_REGISTER_R11D,
ZYDIS_REGISTER_R12D, ZYDIS_REGISTER_R13D, ZYDIS_REGISTER_R14D, ZYDIS_REGISTER_R15D,
// General purpose registers 16-bit
ZYDIS_REGISTER_AX, ZYDIS_REGISTER_CX, ZYDIS_REGISTER_DX, ZYDIS_REGISTER_BX,
ZYDIS_REGISTER_SP, ZYDIS_REGISTER_BP, ZYDIS_REGISTER_SI, ZYDIS_REGISTER_DI,
ZYDIS_REGISTER_R8W, ZYDIS_REGISTER_R9W, ZYDIS_REGISTER_R10W, ZYDIS_REGISTER_R11W,
ZYDIS_REGISTER_R12W, ZYDIS_REGISTER_R13W, ZYDIS_REGISTER_R14W, ZYDIS_REGISTER_R15W,
// General purpose registers 8-bit
ZYDIS_REGISTER_AL, ZYDIS_REGISTER_CL, ZYDIS_REGISTER_DL, ZYDIS_REGISTER_BL,
ZYDIS_REGISTER_AH, ZYDIS_REGISTER_CH, ZYDIS_REGISTER_DH, ZYDIS_REGISTER_BH,
ZYDIS_REGISTER_SPL, ZYDIS_REGISTER_BPL, ZYDIS_REGISTER_SIL, ZYDIS_REGISTER_DIL,
ZYDIS_REGISTER_R8B, ZYDIS_REGISTER_R9B, ZYDIS_REGISTER_R10B, ZYDIS_REGISTER_R11B,
ZYDIS_REGISTER_R12B, ZYDIS_REGISTER_R13B, ZYDIS_REGISTER_R14B, ZYDIS_REGISTER_R15B,
// Floating point legacy registers
ZYDIS_REGISTER_ST0, ZYDIS_REGISTER_ST1, ZYDIS_REGISTER_ST2, ZYDIS_REGISTER_ST3,
ZYDIS_REGISTER_ST4, ZYDIS_REGISTER_ST5, ZYDIS_REGISTER_ST6, ZYDIS_REGISTER_ST7,
// Floating point multimedia registers
ZYDIS_REGISTER_MM0, ZYDIS_REGISTER_MM1, ZYDIS_REGISTER_MM2, ZYDIS_REGISTER_MM3,
ZYDIS_REGISTER_MM4, ZYDIS_REGISTER_MM5, ZYDIS_REGISTER_MM6, ZYDIS_REGISTER_MM7,
// Floating point vector registers 512-bit
ZYDIS_REGISTER_ZMM0, ZYDIS_REGISTER_ZMM1, ZYDIS_REGISTER_ZMM2, ZYDIS_REGISTER_ZMM3,
ZYDIS_REGISTER_ZMM4, ZYDIS_REGISTER_ZMM5, ZYDIS_REGISTER_ZMM6, ZYDIS_REGISTER_ZMM7,
ZYDIS_REGISTER_ZMM8, ZYDIS_REGISTER_ZMM9, ZYDIS_REGISTER_ZMM10, ZYDIS_REGISTER_ZMM11,
ZYDIS_REGISTER_ZMM12, ZYDIS_REGISTER_ZMM13, ZYDIS_REGISTER_ZMM14, ZYDIS_REGISTER_ZMM15,
ZYDIS_REGISTER_ZMM16, ZYDIS_REGISTER_ZMM17, ZYDIS_REGISTER_ZMM18, ZYDIS_REGISTER_ZMM19,
ZYDIS_REGISTER_ZMM20, ZYDIS_REGISTER_ZMM21, ZYDIS_REGISTER_ZMM22, ZYDIS_REGISTER_ZMM23,
ZYDIS_REGISTER_ZMM24, ZYDIS_REGISTER_ZMM25, ZYDIS_REGISTER_ZMM26, ZYDIS_REGISTER_ZMM27,
ZYDIS_REGISTER_ZMM28, ZYDIS_REGISTER_ZMM29, ZYDIS_REGISTER_ZMM30, ZYDIS_REGISTER_ZMM31,
// Floating point vector registers 256-bit
ZYDIS_REGISTER_YMM0, ZYDIS_REGISTER_YMM1, ZYDIS_REGISTER_YMM2, ZYDIS_REGISTER_YMM3,
ZYDIS_REGISTER_YMM4, ZYDIS_REGISTER_YMM5, ZYDIS_REGISTER_YMM6, ZYDIS_REGISTER_YMM7,
ZYDIS_REGISTER_YMM8, ZYDIS_REGISTER_YMM9, ZYDIS_REGISTER_YMM10, ZYDIS_REGISTER_YMM11,
ZYDIS_REGISTER_YMM12, ZYDIS_REGISTER_YMM13, ZYDIS_REGISTER_YMM14, ZYDIS_REGISTER_YMM15,
ZYDIS_REGISTER_YMM16, ZYDIS_REGISTER_YMM17, ZYDIS_REGISTER_YMM18, ZYDIS_REGISTER_YMM19,
ZYDIS_REGISTER_YMM20, ZYDIS_REGISTER_YMM21, ZYDIS_REGISTER_YMM22, ZYDIS_REGISTER_YMM23,
ZYDIS_REGISTER_YMM24, ZYDIS_REGISTER_YMM25, ZYDIS_REGISTER_YMM26, ZYDIS_REGISTER_YMM27,
ZYDIS_REGISTER_YMM28, ZYDIS_REGISTER_YMM29, ZYDIS_REGISTER_YMM30, ZYDIS_REGISTER_YMM31,
// Floating point vector registers 128-bit
ZYDIS_REGISTER_XMM0, ZYDIS_REGISTER_XMM1, ZYDIS_REGISTER_XMM2, ZYDIS_REGISTER_XMM3,
ZYDIS_REGISTER_XMM4, ZYDIS_REGISTER_XMM5, ZYDIS_REGISTER_XMM6, ZYDIS_REGISTER_XMM7,
ZYDIS_REGISTER_XMM8, ZYDIS_REGISTER_XMM9, ZYDIS_REGISTER_XMM10, ZYDIS_REGISTER_XMM11,
ZYDIS_REGISTER_XMM12, ZYDIS_REGISTER_XMM13, ZYDIS_REGISTER_XMM14, ZYDIS_REGISTER_XMM15,
ZYDIS_REGISTER_XMM16, ZYDIS_REGISTER_XMM17, ZYDIS_REGISTER_XMM18, ZYDIS_REGISTER_XMM19,
ZYDIS_REGISTER_XMM20, ZYDIS_REGISTER_XMM21, ZYDIS_REGISTER_XMM22, ZYDIS_REGISTER_XMM23,
ZYDIS_REGISTER_XMM24, ZYDIS_REGISTER_XMM25, ZYDIS_REGISTER_XMM26, ZYDIS_REGISTER_XMM27,
ZYDIS_REGISTER_XMM28, ZYDIS_REGISTER_XMM29, ZYDIS_REGISTER_XMM30, ZYDIS_REGISTER_XMM31,
// Special registers
ZYDIS_REGISTER_RFLAGS, ZYDIS_REGISTER_EFLAGS, ZYDIS_REGISTER_FLAGS, ZYDIS_REGISTER_RIP,
ZYDIS_REGISTER_EIP, ZYDIS_REGISTER_IP,
// Segment registers
ZYDIS_REGISTER_ES, ZYDIS_REGISTER_SS, ZYDIS_REGISTER_CS, ZYDIS_REGISTER_DS,
ZYDIS_REGISTER_FS, ZYDIS_REGISTER_GS,
// Control registers
ZYDIS_REGISTER_CR0, ZYDIS_REGISTER_CR1, ZYDIS_REGISTER_CR2, ZYDIS_REGISTER_CR3,
ZYDIS_REGISTER_CR4, ZYDIS_REGISTER_CR5, ZYDIS_REGISTER_CR6, ZYDIS_REGISTER_CR7,
ZYDIS_REGISTER_CR8, ZYDIS_REGISTER_CR9, ZYDIS_REGISTER_CR10, ZYDIS_REGISTER_CR11,
ZYDIS_REGISTER_CR12, ZYDIS_REGISTER_CR13, ZYDIS_REGISTER_CR14, ZYDIS_REGISTER_CR15,
// Debug registers
ZYDIS_REGISTER_DR0, ZYDIS_REGISTER_DR1, ZYDIS_REGISTER_DR2, ZYDIS_REGISTER_DR3,
ZYDIS_REGISTER_DR4, ZYDIS_REGISTER_DR5, ZYDIS_REGISTER_DR6, ZYDIS_REGISTER_DR7,
ZYDIS_REGISTER_DR8, ZYDIS_REGISTER_DR9, ZYDIS_REGISTER_DR10, ZYDIS_REGISTER_DR11,
ZYDIS_REGISTER_DR12, ZYDIS_REGISTER_DR13, ZYDIS_REGISTER_DR14, ZYDIS_REGISTER_DR15,
// Mask registers
ZYDIS_REGISTER_K0, ZYDIS_REGISTER_K1, ZYDIS_REGISTER_K2, ZYDIS_REGISTER_K3,
ZYDIS_REGISTER_K4, ZYDIS_REGISTER_K5, ZYDIS_REGISTER_K6, ZYDIS_REGISTER_K7,
// Bounds registers
ZYDIS_REGISTER_BND0, ZYDIS_REGISTER_BND1, ZYDIS_REGISTER_BND2, ZYDIS_REGISTER_BND3
};
/* ---------------------------------------------------------------------------------------------- */
/**
* @brief Defines the @c ZydisRegisterClass datatype.
*/
typedef uint8_t ZydisRegisterClass;
/**
* @brief Values that represent zydis register-classes.
*/
enum ZydisRegisterClasses
{
ZYDIS_REGISTERCLASS_INVALID,
ZYDIS_REGISTERCLASS_GENERAL_PURPOSE8,
ZYDIS_REGISTERCLASS_GENERAL_PURPOSE16,
ZYDIS_REGISTERCLASS_GENERAL_PURPOSE32,
ZYDIS_REGISTERCLASS_GENERAL_PURPOSE64,
ZYDIS_REGISTERCLASS_FLOATING_POINT,
ZYDIS_REGISTERCLASS_MULTIMEDIA,
ZYDIS_REGISTERCLASS_VECTOR128,
ZYDIS_REGISTERCLASS_VECTOR256,
ZYDIS_REGISTERCLASS_VECTOR512,
ZYDIS_REGISTERCLASS_FLAGS,
ZYDIS_REGISTERCLASS_IP,
ZYDIS_REGISTERCLASS_SEGMENT,
ZYDIS_REGISTERCLASS_CONTROL,
ZYDIS_REGISTERCLASS_DEBUG,
ZYDIS_REGISTERCLASS_MASK,
ZYDIS_REGISTERCLASS_BOUNDS
};
/**
* @brief Defines the @c ZydisRegisterSize datatype.
*/
typedef uint32_t ZydisRegisterSize;
/**
* @brief Values that represent zydis register-sizes.
*/
enum ZydisRegisterSizes
{
ZYDIS_REGISTERSIZE_INVALID = 0,
ZYDIS_REGISTERSIZE_DYNAMIC = 1,
ZYDIS_REGISTERSIZE_8 = 8,
ZYDIS_REGISTERSIZE_16 = 16,
ZYDIS_REGISTERSIZE_32 = 32,
ZYDIS_REGISTERSIZE_64 = 64,
ZYDIS_REGISTERSIZE_80 = 80,
ZYDIS_REGISTERSIZE_128 = 128,
ZYDIS_REGISTERSIZE_256 = 256,
ZYDIS_REGISTERSIZE_512 = 512
};
/* ---------------------------------------------------------------------------------------------- */
/* ============================================================================================== */
/* Exported functions */
/* ============================================================================================== */
/**
* @brief Returns the register specified by the @c registerClass and the @c id.
*
* @param registerClass The register class.
* @param id The register id.
*
* @return The register specified by the @c registerClass and the @c id.
*/
ZYDIS_DLLEXTERN ZydisRegister ZydisRegisterGetById(ZydisRegisterClass registerClass, uint8_t id);
/**
* @brief Returns the specified register string.
*
* @param reg The register.
*
* @return The register string or @c NULL, if an invalid register was passed.
*/
ZYDIS_DLLEXTERN const char* ZydisRegisterGetString(ZydisRegister reg);
/**
* @brief Returns the register-class of the specified register.
*
* @param reg The register.
*
* @return The register-class of the specified register.
*/
ZYDIS_DLLEXTERN ZydisRegisterClass ZydisRegisterGetClass(ZydisRegister reg);
/**
* @brief Returns the size of the specified register.
*
* @param reg The register.
*
* @return The size of the specified register.
*/
ZYDIS_DLLEXTERN ZydisRegisterSize ZydisRegisterGetSize(ZydisRegister reg);
/**
* @brief Checks if the specified register is a general purpose register.
*
* @param reg The register.
*
* @return True, if the specified register is a general purpose register.
*/
ZYDIS_DLLEXTERN bool ZydisRegisterIsGPR(ZydisRegister reg);
/**
* @brief Checks if the specified register is a 8-bit general purpose register.
*
* @param reg The register.
*
* @return True, if the specified register is a 8-bit general purpose register.
*/
ZYDIS_DLLEXTERN bool ZydisRegisterIsGPR8(ZydisRegister reg);
/**
* @brief Checks if the specified register is a 16-bit general purpose register.
*
* @param reg The register.
*
* @return True, if the specified register is a 16-bit general purpose register.
*/
ZYDIS_DLLEXTERN bool ZydisRegisterIsGPR16(ZydisRegister reg);
/**
* @brief Checks if the specified register is a 32-bit general purpose register.
*
* @param reg The register.
*
* @return True, if the specified register is a 32-bit general purpose register.
*/
ZYDIS_DLLEXTERN bool ZydisRegisterIsGPR32(ZydisRegister reg);
/**
* @brief Checks if the specified register is a 64-bit general purpose register.
*
* @param reg The register.
*
* @return True, if the specified register is a 64-bit general purpose register.
*/
ZYDIS_DLLEXTERN bool ZydisRegisterIsGPR64(ZydisRegister reg);
/**
* @brief Checks if the specified register is a legacy floating-point register.
*
* @param reg The register.
*
* @return True, if the specified register is a legacy floating-point register.
*/
ZYDIS_DLLEXTERN bool ZydisRegisterIsFPRegister(ZydisRegister reg);
/**
* @brief Checks if the specified register is a multi-media register.
*
* @param reg The register.
*
* @return True, if the specified register is a multi-media register.
*/
ZYDIS_DLLEXTERN bool ZydisRegisterIsMMRegister(ZydisRegister reg);
/**
* @brief Checks if the specified register is a vector register.
*
* @param reg The register.
*
* @return True, if the specified register is a vector register.
*/
ZYDIS_DLLEXTERN bool ZydisRegisterIsVR(ZydisRegister reg);
/**
* @brief Checks if the specified register is a 128-bit vector register.
*
* @param reg The register.
*
* @return True, if the specified register is a 128-bit vector register.
*/
ZYDIS_DLLEXTERN bool ZydisRegisterIsVR128(ZydisRegister reg);
/**
* @brief Checks if the specified register is a 256-bit vector register.
*
* @param reg The register.
*
* @return True, if the specified register is a 256-bit vector register.
*/
ZYDIS_DLLEXTERN bool ZydisRegisterIsVR256(ZydisRegister reg);
/**
* @brief Checks if the specified register is a 512-bit vector register.
*
* @param reg The register.
*
* @return True, if the specified register is a 512-bit vector register.
*/
ZYDIS_DLLEXTERN bool ZydisRegisterIsVR512(ZydisRegister reg);
/**
* @brief Checks if the specified register is a flags register.
*
* @param reg The register.
*
* @return True, if the specified register is a flags register.
*/
ZYDIS_DLLEXTERN bool ZydisRegisterIsFlagsRegister(ZydisRegister reg);
/**
* @brief Checks if the specified register is an instruction-pointer register.
*
* @param reg The register.
*
* @return True, if the specified register is a instruction-pointer register.
*/
ZYDIS_DLLEXTERN bool ZydisRegisterIsIPRegister(ZydisRegister reg);
/**
* @brief Checks if the specified register is a segment register.
*
* @param reg The register.
*
* @return True, if the specified register is a segment register.
*/
ZYDIS_DLLEXTERN bool ZydisRegisterIsSegmentRegister(ZydisRegister reg);
/**
* @brief Checks if the specified register is a control register.
*
* @param reg The register.
*
* @return True, if the specified register is a control register.
*/
ZYDIS_DLLEXTERN bool ZydisRegisterIsCR(ZydisRegister reg);
/**
* @brief Checks if the specified register is a debug register.
*
* @param reg The register.
*
* @return True, if the specified register is a debug register.
*/
ZYDIS_DLLEXTERN bool ZydisRegisterIsDR(ZydisRegister reg);
/**
* @brief Checks if the specified register is a mask register.
*
* @param reg The register.
*
* @return True, if the specified register is a mask register.
*/
ZYDIS_DLLEXTERN bool ZydisRegisterIsMaskRegister(ZydisRegister reg);
/**
* @brief Checks if the specified register is a bound register.
*
* @param reg The register.
*
* @return True, if the specified register is a bound register.
*/
ZYDIS_DLLEXTERN bool ZydisRegisterIsBoundsRegister(ZydisRegister reg);
/* ============================================================================================== */
#ifdef __cplusplus
}
#endif
#endif /* ZYDIS_REGISTER_H */

99
include/Zydis/Status.h Normal file
View File

@ -0,0 +1,99 @@
/***************************************************************************************************
Zyan Disassembler Engine (Zydis)
Original Author : Florian Bernd
* 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.
***************************************************************************************************/
#ifndef ZYDIS_STATUS_H
#define ZYDIS_STATUS_H
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
/* ============================================================================================== */
/* Enums and types */
/* ============================================================================================== */
/**
* @brief Defines the @c ZydisStatus datatype.
*/
typedef uint32_t ZydisStatus;
/**
* @brief Values that represent a zydis status-codes.
*/
enum ZydisStatusCode
{
/**
* @brief The operation completed successfully.
*/
ZYDIS_STATUS_SUCCESS = 0x00000000,
/**
* @brief An invalid parameter was passed to a function.
*/
ZYDIS_STATUS_INVALID_PARAMETER = 0x00000001,
/**
* @brief An attempt was made to perform an invalid operation.
*/
ZYDIS_STATUS_INVALID_OPERATION = 0x00000002,
/**
* @brief An attempt was made to read data from an input data-source that has no more data
* available.
*/
ZYDIS_STATUS_NO_MORE_DATA = 0x00000003,
/**
* @brief An error occured while decoding the current instruction. Check the @c flags field
* of the @c ZydisInstructionInfo struct for further details.
*/
ZYDIS_STATUS_INVALID_INSTRUCTION = 0x00000004, // TODO: Rename
/**
* @brief A buffer passed to a function was too small to complete the requested operation.
*/
ZYDIS_STATUS_INSUFFICIENT_BUFFER_SIZE = 0x00000008,
/**
* @brief The start range of user defined status-codes.
*/
ZYDIS_STATUS_USER = 0x10000000 // TODO: Remove
};
/* ============================================================================================== */
/* Macros */
/* ============================================================================================== */
/**
* @brief Checks a zydis status code for success.
*
* @param status The status code.
*/
#define ZYDIS_SUCCESS(status) (status == ZYDIS_STATUS_SUCCESS)
/* ============================================================================================== */
#ifdef __cplusplus
}
#endif
#endif /* ZYDIS_STATUS_H */

View File

@ -0,0 +1,71 @@
/***************************************************************************************************
Zyan Disassembler Engine (Zydis)
Original Author : Florian Bernd
* 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.
***************************************************************************************************/
#ifndef ZYDIS_SYMBOLRESOLVER_H
#define ZYDIS_SYMBOLRESOLVER_H
#include <stdint.h>
#include <Zydis/InstructionInfo.h>
#ifdef __cplusplus
extern "C" {
#endif
/* ============================================================================================== */
/* Custom resolver */
/* ============================================================================================== */
/* ---------------------------------------------------------------------------------------------- */
/* Enums and types */
/* ---------------------------------------------------------------------------------------------- */
/**
* @brief Defines the @c ZydisResolverResolveSymbolFunc function pointer used in the
* @c ZydisCustomSymbolResolver struct.
*
* This function should return the name of the symbol found at the given @c address and an
* optional @c offset.
*/
typedef const char* (*ZydisResolverResolveSymbolFunc)(void* context,
const ZydisInstructionInfo* info, const ZydisOperandInfo* operand, uint64_t address,
int64_t* offset);
typedef struct ZydisCustomSymbolResolver_
{
ZydisResolverResolveSymbolFunc resolveSymbol;
} ZydisCustomSymbolResolver;
/* ---------------------------------------------------------------------------------------------- */
/* Exported functions */
/* ---------------------------------------------------------------------------------------------- */
/* ============================================================================================== */
#ifdef __cplusplus
}
#endif
#endif /* ZYDIS_SYMBOLRESOLVER_H */

67
include/Zydis/Utils.h Normal file
View File

@ -0,0 +1,67 @@
/***************************************************************************************************
Zyan Disassembler Engine (Zydis)
Original Author : Florian Bernd
* 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.
***************************************************************************************************/
#ifndef ZYDIS_UTILS_H
#define ZYDIS_UTILS_H
#include <stdint.h>
#include <Zydis/Defines.h>
#include <Zydis/Status.h>
#include <Zydis/InstructionInfo.h>
#ifdef __cplusplus
extern "C" {
#endif
/* ============================================================================================== */
/* Operand utils */
/* ============================================================================================== */
/* ---------------------------------------------------------------------------------------------- */
/* Exported functions */
/* ---------------------------------------------------------------------------------------------- */
/**
* @brief Calculates the absolute target-address of an relative instruction operand.
*
* @param info A pointer to the instruction-info struct.
* @param operand A pointer to the operand-info struct.
* @param address A pointer to the memory address that receives the absolute target-address.
*
* @return A zydis status code
*/
ZYDIS_DLLEXTERN ZydisStatus ZydisUtilsCalcAbsoluteTargetAddress(const ZydisInstructionInfo* info,
const ZydisOperandInfo* operand, uint64_t* address);
/* ---------------------------------------------------------------------------------------------- */
/* ============================================================================================== */
#ifdef __cplusplus
}
#endif
#endif /* ZYDIS_UTILS_H */

110
include/Zydis/Zydis.h Normal file
View File

@ -0,0 +1,110 @@
/***************************************************************************************************
Zyan Disassembler Engine (Zydis)
Original Author : Florian Bernd
* 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.
***************************************************************************************************/
#ifndef ZYDIS_H
#define ZYDIS_H
#include <Zydis/Status.h>
#include <Zydis/Mnemonic.h>
#include <Zydis/Register.h>
#include <Zydis/InstructionInfo.h>
#include <Zydis/Input.h>
#include <Zydis/Decoder.h>
#include <Zydis/Formatter.h>
#include <Zydis/SymbolResolver.h>
#ifdef __cplusplus
extern "C" {
#endif
/* ============================================================================================== */
/* Macros */
/* ============================================================================================== */
/* ---------------------------------------------------------------------------------------------- */
/* Constants */
/* ---------------------------------------------------------------------------------------------- */
/**
* @brief A macro that defines zydis version.
*/
#define ZYDIS_VERSION 0x0002000000000000
/* ---------------------------------------------------------------------------------------------- */
/* Helper macros */
/* ---------------------------------------------------------------------------------------------- */
/**
* @brief Extracts the major-part of the zydis version.
*
* @param version The zydis version value
*/
#define ZYDIS_VERSION_MAJOR(version) (uint16_t)((version & 0xFFFF000000000000) >> 48)
/**
* @brief Extracts the minor-part of the zydis version.
*
* @param version The zydis version value
*/
#define ZYDIS_VERSION_MINOR(version) (uint16_t)((version & 0x0000FFFF00000000) >> 32)
/**
* @brief Extracts the patch-part of the zydis version.
*
* @param version The zydis version value
*/
#define ZYDIS_VERSION_PATCH(version) (uint16_t)((version & 0x00000000FFFF0000) >> 16)
/**
* @brief Extracts the build-part of the zydis version.
*
* @param version The zydis version value
*/
#define ZYDIS_VERSION_BUILD(version) (uint16_t)(version & 0x000000000000FFFF)
/* ---------------------------------------------------------------------------------------------- */
/* ============================================================================================== */
/* Exported functions */
/* ============================================================================================== */
/**
* @brief Returns the zydis version.
*
* @return The zydis version.
*
* Use the macros provided in this file to extract the major, minor, patch and build part from the
* returned version value.
*/
ZYDIS_DLLEXTERN uint64_t ZydisGetVersion();
/* ============================================================================================== */
#ifdef __cplusplus
}
#endif
#endif /* ZYDIS_H */

2542
src/Decoder.c Normal file

File diff suppressed because it is too large Load Diff

685
src/Formatter.c Normal file
View File

@ -0,0 +1,685 @@
/***************************************************************************************************
Zyan Disassembler Engine (Zydis)
Original Author : Florian Bernd
* 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 <stdio.h>
#include <stdarg.h>
#include <stdint.h>
#include <string.h>
#include <ctype.h>
#include <assert.h>
#include <Zydis/Status.h>
#include <Zydis/Formatter.h>
#include <Zydis/SymbolResolver.h>
#include <Zydis/Utils.h>
/* ============================================================================================== */
/* Internal macros */
/* ============================================================================================== */
/* ---------------------------------------------------------------------------------------------- */
/* Helper macros */
/* ---------------------------------------------------------------------------------------------- */
#define ZYDIS_CHECK(status) \
if (status != ZYDIS_STATUS_SUCCESS) \
{ \
return status; \
}
/* ============================================================================================== */
/* Instruction formatter */
/* ============================================================================================== */
/* ---------------------------------------------------------------------------------------------- */
/* Internal functions */
/* ---------------------------------------------------------------------------------------------- */
/**
* @brief Inserts the @c text into the @c buffer at the given @c offset and increases the
* @c offset by the length of the text.
*
* @param buffer A pointer to the target buffer.
* @param bufferLen The length of the buffer.
* @param offset A pointer to the buffer-offset.
* @param text The text to insert.
* @param uppercase Set true, to convert to uppercase characters.
*
* @return A zydis status code.
*/
static ZydisStatus ZydisBufferAppend(char* buffer, size_t bufferLen, size_t* offset,
bool uppercase, const char* text)
{
ZYDIS_ASSERT(buffer);
ZYDIS_ASSERT(bufferLen != 0);
ZYDIS_ASSERT(offset);
ZYDIS_ASSERT(text);
size_t strLen = strlen(text);
if ((*offset + strLen) >= bufferLen)
{
return ZYDIS_STATUS_INSUFFICIENT_BUFFER_SIZE;
}
strncpy(&buffer[*offset], text, strLen + 1);
if (uppercase)
{
for (size_t i = *offset; i < *offset + strLen; ++i)
{
buffer[i] = (char)toupper(buffer[i]);
}
}
*offset += strLen;
return ZYDIS_STATUS_SUCCESS;
}
/**
* @brief Inserts formatted text into the @c buffer at the given @c offset and increases the
* @c offset by the length of the text.
*
* @param buffer A pointer to the target buffer.
* @param bufferLen The length of the buffer.
* @param offset A pointer to the buffer-offset.
* @param format The format string.
*
* @return A zydis status code.
*/
static ZydisStatus ZydisBufferAppendFormat(char* buffer, size_t bufferLen, size_t* offset,
bool uppercase, const char* format, ...)
{
ZYDIS_ASSERT(buffer);
ZYDIS_ASSERT(bufferLen != 0);
ZYDIS_ASSERT(offset);
ZYDIS_ASSERT(format);
va_list arglist;
va_start(arglist, format);
size_t n = bufferLen - *offset;
int w = vsnprintf(&buffer[*offset], n, format, arglist);
if ((w < 0) || ((size_t)w >= n))
{
va_end(arglist);
return ZYDIS_STATUS_INSUFFICIENT_BUFFER_SIZE;
}
if (uppercase)
{
for (size_t i = *offset; i < *offset + (size_t)w; ++i)
{
buffer[i] = (char)toupper(buffer[i]);
}
}
*offset += (size_t)w;
va_end(arglist);
return ZYDIS_STATUS_SUCCESS;
}
/* ---------------------------------------------------------------------------------------------- */
static ZydisStatus ZydisBufferAppendAbsoluteAddress(const ZydisInstructionFormatter* formatter,
char* buffer, size_t bufferLen, size_t* offset, const ZydisInstructionInfo* info,
const ZydisOperandInfo* operand)
{
ZYDIS_ASSERT(formatter);
ZYDIS_ASSERT(buffer);
ZYDIS_ASSERT(bufferLen != 0);
ZYDIS_ASSERT(offset);
ZYDIS_ASSERT(info);
ZYDIS_ASSERT(operand);
ZYDIS_ASSERT((operand->type == ZYDIS_OPERAND_TYPE_MEMORY) ||
(operand->type == ZYDIS_OPERAND_TYPE_IMMEDIATE));
uint64_t address = 0;
switch (operand->type)
{
case ZYDIS_OPERAND_TYPE_MEMORY:
ZYDIS_ASSERT(operand->mem.disp.size != 0);
if ((operand->mem.base == ZYDIS_REGISTER_EIP) || (operand->mem.base == ZYDIS_REGISTER_RIP))
{
ZYDIS_CHECK(ZydisUtilsCalcAbsoluteTargetAddress(info, operand, &address));
} else
{
ZYDIS_ASSERT(operand->mem.base == ZYDIS_REGISTER_NONE);
ZYDIS_ASSERT(operand->mem.index == ZYDIS_REGISTER_NONE);
ZYDIS_ASSERT(operand->mem.scale == 0);
address = (uint64_t)operand->mem.disp.value.sqword;
}
break;
case ZYDIS_OPERAND_TYPE_IMMEDIATE:
ZYDIS_CHECK(ZydisUtilsCalcAbsoluteTargetAddress(info, operand, &address));
break;
}
const char* symbol = NULL;
int64_t symbolOffset = 0;
if (formatter->symbolResolver)
{
symbol = formatter->symbolResolver->resolveSymbol(formatter->symbolResolver, info, operand,
address, &symbolOffset);
}
if (symbol)
{
if (symbolOffset == 0)
{
return ZydisBufferAppendFormat(buffer, bufferLen, offset, false, "%s", symbol);
}
if (symbolOffset > 0)
{
return ZydisBufferAppendFormat(
buffer, bufferLen, offset, false, "%s+0x%02llX", symbol, symbolOffset);
}
if (symbolOffset < 0)
{
return ZydisBufferAppendFormat(
buffer, bufferLen, offset, false, "%s-0x%02llX", symbol, -symbolOffset);
}
}
if (info->operandMode == 16)
{
return ZydisBufferAppendFormat(buffer, bufferLen, offset,
(formatter->flags & ZYDIS_FORMATTER_FLAG_UPPERCASE), "0x%04X", address);
}
switch (info->mode)
{
case ZYDIS_DISASSEMBLER_MODE_16BIT:
return ZydisBufferAppendFormat(buffer, bufferLen, offset,
(formatter->flags & ZYDIS_FORMATTER_FLAG_UPPERCASE), "0x%04X", address);
case ZYDIS_DISASSEMBLER_MODE_32BIT:
return ZydisBufferAppendFormat(buffer, bufferLen, offset,
(formatter->flags & ZYDIS_FORMATTER_FLAG_UPPERCASE), "0x%08lX", address);
case ZYDIS_DISASSEMBLER_MODE_64BIT:
return ZydisBufferAppendFormat(buffer, bufferLen, offset,
(formatter->flags & ZYDIS_FORMATTER_FLAG_UPPERCASE), "0x%016llX", address);
default:
return ZYDIS_STATUS_INVALID_PARAMETER;
}
}
static ZydisStatus ZydisBufferAppendImmediate(const ZydisInstructionFormatter* formatter,
char* buffer, size_t bufferLen, size_t* offset, const ZydisInstructionInfo* info,
const ZydisOperandInfo* operand)
{
ZYDIS_ASSERT(formatter);
ZYDIS_ASSERT(buffer);
ZYDIS_ASSERT(bufferLen != 0);
ZYDIS_ASSERT(offset);
ZYDIS_ASSERT(info);
ZYDIS_ASSERT(operand);
if ((formatter->addressFormat == ZYDIS_FORMATTER_ADDRESS_ABSOLUTE) &&
(operand->imm.isRelative))
{
return ZydisBufferAppendAbsoluteAddress(formatter, buffer, bufferLen, offset, info,
operand);
}
bool useSignedHex = ((operand->imm.isSigned &&
(formatter->addressFormat == ZYDIS_FORMATTER_ADDRESS_RELATIVE_SIGNED)) ||
(!operand->imm.isSigned && (formatter->immediateFormat == ZYDIS_FORMATTER_IMM_HEX_SIGNED)));
if (useSignedHex && (operand->imm.value.sqword < 0))
{
switch (operand->size)
{
case 8:
return ZydisBufferAppendFormat(buffer, bufferLen, offset,
(formatter->flags & ZYDIS_FORMATTER_FLAG_UPPERCASE), "-0x%02X",
-operand->imm.value.sbyte);
case 16:
return ZydisBufferAppendFormat(buffer, bufferLen, offset,
(formatter->flags & ZYDIS_FORMATTER_FLAG_UPPERCASE), "-0x%02X",
-operand->imm.value.sword);
case 32:
return ZydisBufferAppendFormat(buffer, bufferLen, offset,
(formatter->flags & ZYDIS_FORMATTER_FLAG_UPPERCASE), "-0x%02lX",
-operand->imm.value.sdword);
case 64:
return ZydisBufferAppendFormat(buffer, bufferLen, offset,
(formatter->flags & ZYDIS_FORMATTER_FLAG_UPPERCASE), "-0x%02llX",
-operand->imm.value.sqword);
default:
return ZYDIS_STATUS_INVALID_PARAMETER;
}
}
switch (operand->size)
{
case 8:
return ZydisBufferAppendFormat(buffer, bufferLen, offset,
(formatter->flags & ZYDIS_FORMATTER_FLAG_UPPERCASE), "0x%02X",
operand->imm.value.ubyte);
case 16:
return ZydisBufferAppendFormat(buffer, bufferLen, offset,
(formatter->flags & ZYDIS_FORMATTER_FLAG_UPPERCASE), "0x%02X",
operand->imm.value.uword);
case 32:
return ZydisBufferAppendFormat(buffer, bufferLen, offset,
(formatter->flags & ZYDIS_FORMATTER_FLAG_UPPERCASE), "0x%02lX",
operand->imm.value.udword);
case 64:
return ZydisBufferAppendFormat(buffer, bufferLen, offset,
(formatter->flags & ZYDIS_FORMATTER_FLAG_UPPERCASE), "0x%02llX",
operand->imm.value.uqword);
default:
return ZYDIS_STATUS_INVALID_PARAMETER;
}
}
/* ---------------------------------------------------------------------------------------------- */
static ZydisStatus ZydisBufferAppendOperandIntelMemory(const ZydisInstructionFormatter* formatter,
char* buffer, size_t bufferLen, size_t* offset, const ZydisInstructionInfo* info,
const ZydisOperandInfo* operand, uint16_t typecast)
{
if (typecast)
{
char* str = "";
switch (typecast)
{
case 8:
str = "byte ptr ";
break;
case 16:
str = "word ptr ";
break;
case 32:
str = "dword ptr ";
break;
case 48:
str = "fword ptr ";
break;
case 64:
str = "qword ptr ";
break;
case 80:
str = "tbyte ptr ";
break;
case 128:
str = "xmmword ptr ";
break;
case 256:
str = "ymmword ptr ";
break;
case 512:
str = "zmmword ptr ";
break;
}
ZYDIS_CHECK(ZydisBufferAppend(
buffer, bufferLen, offset, (formatter->flags & ZYDIS_FORMATTER_FLAG_UPPERCASE), str));
}
if (operand->mem.segment != ZYDIS_REGISTER_NONE)
{
if ((formatter->flags & ZYDIS_FORMATTER_FLAG_ALWAYS_DISPLAY_MEMORY_SEGMENT) ||
(((operand->mem.segment != ZYDIS_REGISTER_DS) ||
(info->prefixFlags & ZYDIS_PREFIX_SEGMENT_DS)) &&
((operand->mem.segment != ZYDIS_REGISTER_SS) ||
(info->prefixFlags & ZYDIS_PREFIX_SEGMENT_SS))))
{
ZYDIS_CHECK(ZydisBufferAppendFormat(buffer, bufferLen, offset,
(formatter->flags & ZYDIS_FORMATTER_FLAG_UPPERCASE), "%s:",
ZydisRegisterGetString(operand->mem.segment)));
}
}
ZYDIS_CHECK(ZydisBufferAppend(
buffer, bufferLen, offset, (formatter->flags & ZYDIS_FORMATTER_FLAG_UPPERCASE), "["));
if ((operand->mem.disp.size != 0) && ((operand->mem.base == ZYDIS_REGISTER_NONE) ||
(operand->mem.base == ZYDIS_REGISTER_EIP) || (operand->mem.base == ZYDIS_REGISTER_RIP)) &&
(operand->mem.index == ZYDIS_REGISTER_NONE) && (operand->mem.scale == 0))
{
ZYDIS_CHECK(ZydisBufferAppendAbsoluteAddress(formatter, buffer, bufferLen, offset, info,
operand));
} else
{
if (operand->mem.base != ZYDIS_REGISTER_NONE)
{
ZYDIS_CHECK(ZydisBufferAppend(buffer, bufferLen, offset,
(formatter->flags & ZYDIS_FORMATTER_FLAG_UPPERCASE),
ZydisRegisterGetString(operand->mem.base)));
}
if (operand->mem.index != ZYDIS_REGISTER_NONE)
{
const char* c = (operand->mem.base != ZYDIS_REGISTER_NONE) ? "+" : "";
ZYDIS_CHECK(ZydisBufferAppendFormat(buffer, bufferLen, offset,
(formatter->flags & ZYDIS_FORMATTER_FLAG_UPPERCASE), "%s%s", c,
ZydisRegisterGetString(operand->mem.index)));
if (operand->mem.scale)
{
ZYDIS_CHECK(ZydisBufferAppendFormat(buffer, bufferLen, offset,
(formatter->flags & ZYDIS_FORMATTER_FLAG_UPPERCASE), "*%d",
operand->mem.scale));
}
}
if ((operand->mem.disp.size) && ((operand->mem.disp.value.sqword) ||
((operand->mem.base == ZYDIS_REGISTER_NONE) &&
(operand->mem.index == ZYDIS_REGISTER_NONE))))
{
if ((operand->mem.disp.value.sqword < 0) && (
(operand->mem.base != ZYDIS_REGISTER_NONE) ||
(operand->mem.index != ZYDIS_REGISTER_NONE)))
{
ZYDIS_CHECK(
ZydisBufferAppendFormat(buffer, bufferLen, offset,
(formatter->flags & ZYDIS_FORMATTER_FLAG_UPPERCASE), "-0x%02llX",
-operand->mem.disp.value.sqword));
} else
{
const char* sign =
((operand->mem.base == ZYDIS_REGISTER_NONE) &&
(operand->mem.index == ZYDIS_REGISTER_NONE)) ? "" : "+";
ZYDIS_CHECK(
ZydisBufferAppendFormat(buffer, bufferLen, offset,
(formatter->flags & ZYDIS_FORMATTER_FLAG_UPPERCASE), "%s0x%02llX",
sign, operand->mem.disp.value.sqword));
}
}
}
return ZydisBufferAppend(
buffer, bufferLen, offset, (formatter->flags & ZYDIS_FORMATTER_FLAG_UPPERCASE), "]");
}
/* ---------------------------------------------------------------------------------------------- */
/* Intel style */
/* ---------------------------------------------------------------------------------------------- */
static ZydisStatus ZydisBufferAppendOperandIntel(const ZydisInstructionFormatter* formatter,
char* buffer, size_t bufferLen, size_t* offset, const ZydisInstructionInfo* info,
const ZydisOperandInfo* operand, uint16_t typecast)
{
switch (operand->type)
{
case ZYDIS_OPERAND_TYPE_REGISTER:
{
const char* reg = ZydisRegisterGetString(operand->reg);
if (!reg)
{
reg = "invalid";
}
return ZydisBufferAppend(
buffer, bufferLen, offset, (formatter->flags & ZYDIS_FORMATTER_FLAG_UPPERCASE), reg);
}
case ZYDIS_OPERAND_TYPE_MEMORY:
return ZydisBufferAppendOperandIntelMemory(formatter, buffer, bufferLen, offset, info,
operand, typecast);
case ZYDIS_OPERAND_TYPE_POINTER:
return ZydisBufferAppendFormat(buffer, bufferLen, offset,
(formatter->flags & ZYDIS_FORMATTER_FLAG_UPPERCASE), "0x%02X:0x%02lX",
operand->ptr.segment, operand->ptr.offset);
case ZYDIS_OPERAND_TYPE_IMMEDIATE:
return ZydisBufferAppendImmediate(formatter, buffer, bufferLen, offset, info, operand);
}
return ZYDIS_STATUS_INVALID_PARAMETER;
}
static ZydisStatus ZydisFormatterFormatInstructionIntel(ZydisInstructionFormatter* formatter,
const ZydisInstructionInfo* info, char* buffer, size_t bufferLen)
{
size_t offset = 0;
if ((info->prefixFlags & ZYDIS_PREFIX_ACCEPTS_REPNE) &&
(info->prefixFlags & ZYDIS_PREFIX_REPNE))
{
ZYDIS_CHECK(ZydisBufferAppend(buffer, bufferLen, &offset,
(formatter->flags & ZYDIS_FORMATTER_FLAG_UPPERCASE), "repne "));
}
if ((info->prefixFlags & ZYDIS_PREFIX_ACCEPTS_REP) && (info->prefixFlags & ZYDIS_PREFIX_REP))
{
ZYDIS_CHECK(ZydisBufferAppend(buffer, bufferLen, &offset,
(formatter->flags & ZYDIS_FORMATTER_FLAG_UPPERCASE), "rep "));
}
if ((info->prefixFlags & ZYDIS_PREFIX_ACCEPTS_LOCK) && (info->prefixFlags & ZYDIS_PREFIX_LOCK))
{
ZYDIS_CHECK(ZydisBufferAppend(buffer, bufferLen, &offset,
(formatter->flags & ZYDIS_FORMATTER_FLAG_UPPERCASE), "lock "));
}
if (info->prefixFlags & ZYDIS_PREFIX_XACQUIRE)
{
ZYDIS_CHECK(ZydisBufferAppend(buffer, bufferLen, &offset,
(formatter->flags & ZYDIS_FORMATTER_FLAG_UPPERCASE), "xacquire "));
} else if (info->prefixFlags & ZYDIS_PREFIX_XRELEASE)
{
ZYDIS_CHECK(ZydisBufferAppend(buffer, bufferLen, &offset,
(formatter->flags & ZYDIS_FORMATTER_FLAG_UPPERCASE), "xrelease "));
}
const char* mnemonic = ZydisMnemonicGetString(info->mnemonic);
if (!mnemonic)
{
mnemonic = "invalid";
}
ZYDIS_CHECK(ZydisBufferAppend(buffer, bufferLen, &offset,
(formatter->flags & ZYDIS_FORMATTER_FLAG_UPPERCASE), mnemonic));
uint16_t typecast = 0;
for (int i = 0; i < 4; ++i)
{
if (info->operand[i].type == ZYDIS_OPERAND_TYPE_UNUSED)
{
break;
}
if (i == 0)
{
if (formatter->flags & ZYDIS_FORMATTER_FLAG_TAB_AFTER_MNEMONIC)
{
ZYDIS_CHECK(ZydisBufferAppend(buffer, bufferLen, &offset,
(formatter->flags & ZYDIS_FORMATTER_FLAG_UPPERCASE), "\t"));
} else
{
ZYDIS_CHECK(ZydisBufferAppend(buffer, bufferLen, &offset,
(formatter->flags & ZYDIS_FORMATTER_FLAG_UPPERCASE), " "));
}
} else
{
if (formatter->flags & ZYDIS_FORMATTER_FLAG_NO_SPACE_BETWEEN_OPERANDS)
{
ZYDIS_CHECK(ZydisBufferAppend(buffer, bufferLen, &offset,
(formatter->flags & ZYDIS_FORMATTER_FLAG_UPPERCASE), ","));
} else
{
ZYDIS_CHECK(ZydisBufferAppend(buffer, bufferLen, &offset,
(formatter->flags & ZYDIS_FORMATTER_FLAG_UPPERCASE), ", "));
}
}
if (formatter->flags & ZYDIS_FORMATTER_FLAG_ALWAYS_DISPLAY_MEMORY_SIZE)
{
if (info->operand[i].type == ZYDIS_OPERAND_TYPE_MEMORY)
{
typecast = info->operand[i].size;
}
} else if (info->operand[i].type == ZYDIS_OPERAND_TYPE_MEMORY)
{
switch (i)
{
case 0:
typecast = ((info->operand[1].type == ZYDIS_OPERAND_TYPE_UNUSED) ||
(info->operand[1].type == ZYDIS_OPERAND_TYPE_IMMEDIATE) ||
(info->operand[0].size != info->operand[1].size)) ? info->operand[0].size : 0;
if (!typecast && (info->operand[1].type == ZYDIS_OPERAND_TYPE_REGISTER) &&
(info->operand[1].reg == ZYDIS_REGISTER_CL))
{
switch (info->mnemonic)
{
case ZYDIS_MNEMONIC_RCL:
case ZYDIS_MNEMONIC_ROL:
case ZYDIS_MNEMONIC_ROR:
case ZYDIS_MNEMONIC_RCR:
case ZYDIS_MNEMONIC_SHL:
case ZYDIS_MNEMONIC_SHR:
case ZYDIS_MNEMONIC_SAR:
typecast = info->operand[0].size;
}
}
break;
case 1:
case 2:
typecast = (info->operand[i - 1].size != info->operand[i].size) ?
info->operand[i - 1].size : 0;
break;
}
}
ZYDIS_CHECK(ZydisBufferAppendOperandIntel(formatter, buffer, bufferLen, &offset, info,
&info->operand[i], typecast));
if (info->encoding == ZYDIS_INSTRUCTION_ENCODING_EVEX)
{
if (i == 0)
{
if (info->avx.maskRegister)
{
ZYDIS_CHECK(ZydisBufferAppendFormat(buffer, bufferLen, &offset,
(formatter->flags & ZYDIS_FORMATTER_FLAG_UPPERCASE), " {%s}",
ZydisRegisterGetString(info->avx.maskRegister)));
}
if (info->avx.maskMode == ZYDIS_AVX_MASKMODE_ZERO)
{
ZYDIS_CHECK(ZydisBufferAppend(buffer, bufferLen, &offset,
(formatter->flags & ZYDIS_FORMATTER_FLAG_UPPERCASE), " {z}"));
}
} else
{
if (info->operand[i].type == ZYDIS_OPERAND_TYPE_MEMORY)
{
switch (info->avx.broadcast)
{
case ZYDIS_AVX_BCSTMODE_2:
ZYDIS_CHECK(ZydisBufferAppend(buffer, bufferLen, &offset,
(formatter->flags & ZYDIS_FORMATTER_FLAG_UPPERCASE), " {1to2}"));
break;
case ZYDIS_AVX_BCSTMODE_4:
ZYDIS_CHECK(ZydisBufferAppend(buffer, bufferLen, &offset,
(formatter->flags & ZYDIS_FORMATTER_FLAG_UPPERCASE), " {1to4}"));
break;
case ZYDIS_AVX_BCSTMODE_8:
ZYDIS_CHECK(ZydisBufferAppend(buffer, bufferLen, &offset,
(formatter->flags & ZYDIS_FORMATTER_FLAG_UPPERCASE), " {1to8}"));
break;
case ZYDIS_AVX_BCSTMODE_16:
ZYDIS_CHECK(ZydisBufferAppend(buffer, bufferLen, &offset,
(formatter->flags & ZYDIS_FORMATTER_FLAG_UPPERCASE), " {1to16}"));
break;
}
}
if ((i == (info->operandCount - 1)) || ((i != (info->operandCount - 1)) &&
(info->operand[i + 1].type == ZYDIS_OPERAND_TYPE_IMMEDIATE)))
{
switch (info->avx.roundingMode)
{
case ZYDIS_AVX_RNDMODE_INVALID:
if (info->avx.sae)
{
ZYDIS_CHECK(ZydisBufferAppend(buffer, bufferLen, &offset,
(formatter->flags & ZYDIS_FORMATTER_FLAG_UPPERCASE), " {sae}"));
}
break;
case ZYDIS_AVX_RNDMODE_RN:
ZYDIS_CHECK(ZydisBufferAppend(buffer, bufferLen, &offset,
(formatter->flags & ZYDIS_FORMATTER_FLAG_UPPERCASE), " {rn-sae}"));
break;
case ZYDIS_AVX_RNDMODE_RD:
ZYDIS_CHECK(ZydisBufferAppend(buffer, bufferLen, &offset,
(formatter->flags & ZYDIS_FORMATTER_FLAG_UPPERCASE), " {rd-sae}"));
break;
case ZYDIS_AVX_RNDMODE_RU:
ZYDIS_CHECK(ZydisBufferAppend(buffer, bufferLen, &offset,
(formatter->flags & ZYDIS_FORMATTER_FLAG_UPPERCASE), " {ru-sae}"));
break;
case ZYDIS_AVX_RNDMODE_RZ:
ZYDIS_CHECK(ZydisBufferAppend(buffer, bufferLen, &offset,
(formatter->flags & ZYDIS_FORMATTER_FLAG_UPPERCASE), " {rz-sae}"));
break;
default:
return ZYDIS_STATUS_INVALID_PARAMETER;
}
}
}
}
}
return ZYDIS_STATUS_SUCCESS;
}
/* ---------------------------------------------------------------------------------------------- */
/* Exported functions */
/* ---------------------------------------------------------------------------------------------- */
ZydisStatus ZydisFormatterInitInstructionFormatter(ZydisInstructionFormatter* formatter,
ZydisFormatterStyle style)
{
return ZydisFormatterInitInstructionFormatterEx(formatter, style, 0);
}
ZydisStatus ZydisFormatterInitInstructionFormatterEx(
ZydisInstructionFormatter* formatter, ZydisFormatterStyle style, ZydisFormatterFlags flags)
{
if (!formatter || (style != ZYDIS_FORMATTER_STYLE_INTEL))
{
return ZYDIS_STATUS_INVALID_PARAMETER;
}
formatter->style = style;
formatter->flags = flags;
formatter->addressFormat = ZYDIS_FORMATTER_ADDRESS_ABSOLUTE;
formatter->displacementFormat = ZYDIS_FORMATTER_DISP_HEX_SIGNED;
formatter->immediateFormat = ZYDIS_FORMATTER_IMM_HEX_UNSIGNED;
formatter->symbolResolver = NULL;
return ZYDIS_STATUS_SUCCESS;
}
ZydisStatus ZydisFormatterGetSymbolResolver(const ZydisInstructionFormatter* formatter,
ZydisCustomSymbolResolver** symbolResolver)
{
if (!formatter || !symbolResolver)
{
return ZYDIS_STATUS_INVALID_PARAMETER;
}
*symbolResolver = formatter->symbolResolver;
return ZYDIS_STATUS_SUCCESS;
}
ZydisStatus ZydisFormatterSetSymbolResolver(ZydisInstructionFormatter* formatter,
ZydisCustomSymbolResolver* symbolResolver)
{
if (!formatter)
{
return ZYDIS_STATUS_INVALID_PARAMETER;
}
formatter->symbolResolver = symbolResolver;
return ZYDIS_STATUS_SUCCESS;
}
ZydisStatus ZydisFormatterFormatInstruction(ZydisInstructionFormatter* formatter,
const ZydisInstructionInfo* info, char* buffer, size_t bufferLen)
{
if (!formatter || !info || !buffer || (bufferLen == 0))
{
return ZYDIS_STATUS_INVALID_PARAMETER;
}
switch (formatter->style)
{
case ZYDIS_FORMATTER_STYLE_INTEL:
return ZydisFormatterFormatInstructionIntel(formatter, info, buffer, bufferLen);
default:
return ZYDIS_STATUS_INVALID_PARAMETER;
}
}
/* ---------------------------------------------------------------------------------------------- */
/* ============================================================================================== */

100
src/Input.c Normal file
View File

@ -0,0 +1,100 @@
/***************************************************************************************************
Zyan Disassembler Engine (Zydis)
Original Author : Florian Bernd
* 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 <assert.h>
#include <Zydis/Status.h>
#include <Zydis/Input.h>
/* ============================================================================================== */
/* Memory input */
/* ============================================================================================== */
/* ---------------------------------------------------------------------------------------------- */
/* Internal functions */
/* ---------------------------------------------------------------------------------------------- */
static bool ZydisMemoryInputNext(ZydisMemoryInput* context, uint8_t* data)
{
if (context->inputBufferPos >= context->inputBufferLen)
{
return false;
}
*data = context->inputBuffer[context->inputBufferPos++];
return true;
}
/* ---------------------------------------------------------------------------------------------- */
/* Exported functions */
/* ---------------------------------------------------------------------------------------------- */
ZydisStatus ZydisInputInitMemoryInput(ZydisMemoryInput* input, const void* buffer, uint64_t length)
{
if (!input || !buffer || (length == 0))
{
return ZYDIS_STATUS_INVALID_PARAMETER;
}
input->input.inputNext = (ZydisInputNextFunc)&ZydisMemoryInputNext;
input->inputBuffer = (uint8_t*)buffer;
input->inputBufferLen = length;
input->inputBufferPos = 0;
return ZYDIS_STATUS_SUCCESS;
}
/* ---------------------------------------------------------------------------------------------- */
/* ============================================================================================== */
/* File input */
/* ============================================================================================== */
/* ---------------------------------------------------------------------------------------------- */
/* Internal functions */
/* ---------------------------------------------------------------------------------------------- */
static bool ZydisFileInputNext(ZydisFileInput* context, uint8_t* data)
{
int c = fgetc(context->file);
*data = (uint8_t)c;
return (c != EOF);
}
/* ---------------------------------------------------------------------------------------------- */
/* Exported functions */
/* ---------------------------------------------------------------------------------------------- */
ZydisStatus ZydisInputInitFileInput(ZydisFileInput* input, FILE* file)
{
if (!file)
{
return ZYDIS_STATUS_INVALID_PARAMETER;
}
input->input.inputNext = (ZydisInputNextFunc)&ZydisFileInputNext;
input->file = file;
return ZYDIS_STATUS_SUCCESS;
}
/* ---------------------------------------------------------------------------------------------- */
/* ============================================================================================== */

View File

@ -1,14 +1,8 @@
/************************************************************************************************** /***************************************************************************************************
Verteron Disassembler Engine Zyan Disassembler Engine (Zydis)
Version 1.0
Remarks : Freeware, Copyright must be included
Original Author : Florian Bernd Original Author : Florian Bernd
Modifications :
Last change : 29. October 2014
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal
@ -16,10 +10,10 @@
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is * copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions: * furnished to do so, subject to the following conditions:
* *
* The above copyright notice and this permission notice shall be included in all * The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software. * copies or substantial portions of the Software.
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@ -28,13 +22,33 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE. * SOFTWARE.
**************************************************************************************************/ ***************************************************************************************************/
#include <tchar.h>
#include "PugiXML/pugixml.hpp"
#include "VXDisassemblerTypes.h"
int _tmain(int argc, _TCHAR* argv[]) #include <Zydis/Internal/InstructionTable.h>
{
// TODO: #define ZYDIS_INVALID { ZYDIS_NODETYPE_INVALID, 0x00000000 }
return 0; #define ZYDIS_FILTER(type, id) { type, id }
} #define ZYDIS_DEFINITION(id) { ZYDIS_NODETYPE_DEFINITION, id }
#include <Zydis/Internal/InstructionTable.inc>
#undef ZYDIS_INVALID
#undef ZYDIS_FILTER
#undef ZYDIS_DEFINITION
#define ZYDIS_MAKE_OPERAND(type, encoding, access) \
(((uint16_t)type) << 8) | ((((uint16_t)encoding) & 0x3F) << 2) | (access & 0x03)
#define ZYDIS_MAKE_AVX512INFO(hasEvexB, hasEvexAAA, hasEvexZ) \
((((uint8_t)hasEvexB & 0x03) << 2) | (((uint8_t)hasEvexAAA & 0x01) << 1) | (hasEvexZ & 0x01))
//#define ZYDIS_MAKE_DEFINITION(mnemonic, op1, op2, op3, op4, avx512info) \
// { (((uint16_t)mnemonic & 0xFFF) << 4) | (avx512info & 0xF), { op1, op2, op3, op4 } }
#define ZYDIS_MAKE_DEFINITION(mnemonic, operandsId, avx512info) \
{ (((uint16_t)mnemonic & 0xFFF) << 4) | (avx512info & 0xF), operandsId }
#include <Zydis/Internal/InstructionDefinitions.inc>
#undef ZYDIS_MAKE_OPERAND
#undef ZYDIS_MAKE_AVX512INFO
#undef ZYDIS_MAKE_DEFINITION

View File

@ -1,12 +1,8 @@
/*************************************************************************************************** /***************************************************************************************************
Zyan Disassembler Engine Zyan Disassembler Engine (Zydis)
Version 1.0
Remarks : Freeware, Copyright must be included
Original Author : Florian Bernd Original Author : Florian Bernd
Modifications : Joel Höner
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal
@ -28,46 +24,38 @@
***************************************************************************************************/ ***************************************************************************************************/
#include "ZydisUtils.hpp" #include <stddef.h>
#include <cassert> #include <Zydis/Defines.h>
#include <Zydis/Mnemonic.h>
namespace Zydis /* ============================================================================================== */
{ /* Mnemonic strings */
/* ============================================================================================== */
uint64_t CalcAbsoluteTarget(const InstructionInfo& info, const OperandInfo& operand) static const char* mnemonicStrings[] =
{ {
assert((operand.type == OperandType::REL_IMMEDIATE) || #include <Zydis/Internal/MnemonicStrings.inc>
((operand.type == OperandType::MEMORY) && (operand.base == Register::RIP))); };
uint64_t truncMask = 0xFFFFFFFFFFFFFFFFull; /* ============================================================================================== */
if (!(info.flags & IF_DISASSEMBLER_MODE_64)) /* Exported functions */
/* ============================================================================================== */
const char* ZydisMnemonicGetString(ZydisInstructionMnemonic mnemonic)
{
if (mnemonic > (sizeof(mnemonicStrings) / sizeof(mnemonicStrings[0])) - 1)
{ {
truncMask >>= (64 - info.operand_mode); return NULL;
} }
uint16_t size = operand.size; return mnemonicStrings[mnemonic];
if ((operand.type == OperandType::MEMORY) && (operand.base == Register::RIP))
{
size = operand.offset;
}
switch (size)
{
case 8:
return (info.instrPointer + operand.lval.sbyte) & truncMask;
case 16:
{
uint32_t delta = operand.lval.sword & truncMask;
if ((info.instrPointer + delta) > 0xFFFF)
{
return (info.instrPointer& 0xF0000) + ((info.instrPointer + delta) & 0xFFFF);
}
return info.instrPointer + delta;
}
case 32:
return (info.instrPointer + operand.lval.sdword) & truncMask;
default:
assert(0);
}
return 0;
} }
} ZydisStatus ZydisMnemonicReplaceString(ZydisInstructionMnemonic mnemonic,
const char* mnemonicString)
{
(void)mnemonic;
(void)mnemonicString;
return ZYDIS_STATUS_INVALID_OPERATION;
}
/* ============================================================================================== */

435
src/Register.c Normal file
View File

@ -0,0 +1,435 @@
/***************************************************************************************************
Zyan Disassembler Engine (Zydis)
Original Author : Florian Bernd
* 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 <stddef.h>
#include <stdbool.h>
#include <Zydis/Register.h>
/* ============================================================================================== */
/* Register strings */
/* ============================================================================================== */
const char* registerStrings[] =
{
"none",
// General purpose registers 64-bit
"rax", "rcx", "rdx", "rbx",
"rsp", "rbp", "rsi", "rdi",
"r8", "r9", "r10", "r11",
"r12", "r13", "r14", "r15",
// General purpose registers 32-bit
"eax", "ecx", "edx", "ebx",
"esp", "ebp", "esi", "edi",
"r8d", "r9d", "r10d", "r11d",
"r12d", "r13d", "r14d", "r15d",
// General purpose registers 16-bit
"ax", "cx", "dx", "bx",
"sp", "bp", "si", "di",
"r8w", "r9w", "r10w", "r11w",
"r12w", "r13w", "r14w", "r15w",
// General purpose registers 8-bit
"al", "cl", "dl", "bl",
"ah", "ch", "dh", "bh",
"spl", "bpl", "sil", "dil",
"r8b", "r9b", "r10b", "r11b",
"r12b", "r13b", "r14b", "r15b",
// Floating point legacy registers
"st0", "st1", "st2", "st3",
"st4", "st5", "st6", "st7",
// Floating point multimedia registers
"mm0", "mm1", "mm2", "mm3",
"mm4", "mm5", "mm6", "mm7",
// Floating point vector registers 512-bit
"zmm0", "zmm1", "zmm2", "zmm3",
"zmm4", "zmm5", "zmm6", "zmm7",
"zmm8", "zmm9", "zmm10", "zmm11",
"zmm12", "zmm13", "zmm14", "zmm15",
"zmm16", "zmm17", "zmm18", "zmm19",
"zmm20", "zmm21", "zmm22", "zmm23",
"zmm24", "zmm25", "zmm26", "zmm27",
"zmm28", "zmm29", "zmm30", "zmm31",
// Floating point vector registers 256-bit
"ymm0", "ymm1", "ymm2", "ymm3",
"ymm4", "ymm5", "ymm6", "ymm7",
"ymm8", "ymm9", "ymm10", "ymm11",
"ymm12", "ymm13", "ymm14", "ymm15",
"ymm16", "ymm17", "ymm18", "ymm19",
"ymm20", "ymm21", "ymm22", "ymm23",
"ymm24", "ymm25", "ymm26", "ymm27",
"ymm28", "ymm29", "ymm30", "ymm31",
// Floating point vector registers 128-bit
"xmm0", "xmm1", "xmm2", "xmm3",
"xmm4", "xmm5", "xmm6", "xmm7",
"xmm8", "xmm9", "xmm10", "xmm11",
"xmm12", "xmm13", "xmm14", "xmm15",
"xmm16", "xmm17", "xmm18", "xmm19",
"xmm20", "xmm21", "xmm22", "xmm23",
"xmm24", "xmm25", "xmm26", "xmm27",
"xmm28", "xmm29", "xmm30", "xmm31",
// Special registers
"rflags", "eflags", "flags", "rip",
"eip", "ip",
// Segment registers
"es", "ss", "cs", "ds",
"fs", "gs",
// Control registers
"cr0", "cr1", "cr2", "cr3",
"cr4", "cr5", "cr6", "cr7",
"cr8", "cr9", "cr10", "cr11",
"cr12", "cr13", "cr14", "cr15",
// Debug registers
"dr0", "dr1", "dr2", "dr3",
"dr4", "dr5", "dr6", "dr7",
"dr8", "dr9", "dr10", "dr11",
"dr12", "dr13", "dr14", "dr15",
// Mask registers
"k0", "k1", "k2", "k3",
"k4", "k5", "k6", "k7",
// Bounds registers
"bnd0", "bnd1", "bnd2", "bnd3"
};
/* ============================================================================================== */
/* Exported functions */
/* ============================================================================================== */
ZydisRegister ZydisRegisterGetById(ZydisRegisterClass registerClass, uint8_t id)
{
switch (registerClass)
{
case ZYDIS_REGISTERCLASS_GENERAL_PURPOSE8:
if (id > 19)
{
return ZYDIS_REGISTER_NONE;
}
return ZYDIS_REGISTER_AL + id;
case ZYDIS_REGISTERCLASS_GENERAL_PURPOSE16:
if (id > 15)
{
return ZYDIS_REGISTER_NONE;
}
return ZYDIS_REGISTER_AX + id;
case ZYDIS_REGISTERCLASS_GENERAL_PURPOSE32:
if (id > 15)
{
return ZYDIS_REGISTER_NONE;
}
return ZYDIS_REGISTER_EAX + id;
case ZYDIS_REGISTERCLASS_GENERAL_PURPOSE64:
if (id > 15)
{
return ZYDIS_REGISTER_NONE;
}
return ZYDIS_REGISTER_RAX + id;
case ZYDIS_REGISTERCLASS_FLOATING_POINT:
if (id > 7)
{
return ZYDIS_REGISTER_NONE;
}
return ZYDIS_REGISTER_ST0 + id;
case ZYDIS_REGISTERCLASS_MULTIMEDIA:
if (id > 7)
{
return ZYDIS_REGISTER_NONE;
}
return ZYDIS_REGISTER_MM0 + id;
case ZYDIS_REGISTERCLASS_VECTOR128:
if (id > 31)
{
return ZYDIS_REGISTER_NONE;
}
return ZYDIS_REGISTER_XMM0 + id;
case ZYDIS_REGISTERCLASS_VECTOR256:
if (id > 31)
{
return ZYDIS_REGISTER_NONE;
}
return ZYDIS_REGISTER_YMM0 + id;
case ZYDIS_REGISTERCLASS_VECTOR512:
if (id > 31)
{
return ZYDIS_REGISTER_NONE;
}
return ZYDIS_REGISTER_ZMM0 + id;
case ZYDIS_REGISTERCLASS_SEGMENT:
if (id > 5)
{
return ZYDIS_REGISTER_NONE;
}
return ZYDIS_REGISTER_ES + id;
case ZYDIS_REGISTERCLASS_CONTROL:
if (id > 15)
{
return ZYDIS_REGISTER_NONE;
}
return ZYDIS_REGISTER_CR0 + id;
case ZYDIS_REGISTERCLASS_DEBUG:
if (id > 15)
{
return ZYDIS_REGISTER_NONE;
}
return ZYDIS_REGISTER_DR0 + id;
case ZYDIS_REGISTERCLASS_MASK:
if (id > 7)
{
return ZYDIS_REGISTER_NONE;
}
return ZYDIS_REGISTER_K0 + id;
case ZYDIS_REGISTERCLASS_BOUNDS:
if (id > 3)
{
return ZYDIS_REGISTER_NONE;
}
return ZYDIS_REGISTER_BND0 + id;
case ZYDIS_REGISTERCLASS_FLAGS:
case ZYDIS_REGISTERCLASS_IP:
// These registers are unique
break;
}
return ZYDIS_REGISTER_NONE;
}
const char* ZydisRegisterGetString(ZydisRegister reg)
{
if ((reg == 0) || (reg > (sizeof(registerStrings) / sizeof(registerStrings[0])) - 1))
{
return NULL;
}
return registerStrings[reg];
}
ZydisRegisterClass ZydisRegisterGetClass(ZydisRegister reg)
{
if ((reg >= ZYDIS_REGISTER_RAX) && (reg <= ZYDIS_REGISTER_R15))
{
return ZYDIS_REGISTERCLASS_GENERAL_PURPOSE64;
}
if ((reg >= ZYDIS_REGISTER_EAX) && (reg <= ZYDIS_REGISTER_R15D))
{
return ZYDIS_REGISTERCLASS_GENERAL_PURPOSE32;
}
if ((reg >= ZYDIS_REGISTER_AX) && (reg <= ZYDIS_REGISTER_R15W))
{
return ZYDIS_REGISTERCLASS_GENERAL_PURPOSE16;
}
if ((reg >= ZYDIS_REGISTER_AL) && (reg <= ZYDIS_REGISTER_R15B))
{
return ZYDIS_REGISTERCLASS_GENERAL_PURPOSE8;
}
if ((reg >= ZYDIS_REGISTER_ST0) && (reg <= ZYDIS_REGISTER_ST7))
{
return ZYDIS_REGISTERCLASS_FLOATING_POINT;
}
if ((reg >= ZYDIS_REGISTER_ZMM0) && (reg <= ZYDIS_REGISTER_ZMM31))
{
return ZYDIS_REGISTERCLASS_VECTOR512;
}
if ((reg >= ZYDIS_REGISTER_YMM0) && (reg <= ZYDIS_REGISTER_YMM31))
{
return ZYDIS_REGISTERCLASS_VECTOR256;
}
if ((reg >= ZYDIS_REGISTER_XMM0) && (reg <= ZYDIS_REGISTER_XMM31))
{
return ZYDIS_REGISTERCLASS_VECTOR128;
}
if ((reg >= ZYDIS_REGISTER_RFLAGS) && (reg <= ZYDIS_REGISTER_FLAGS))
{
return ZYDIS_REGISTERCLASS_FLAGS;
}
if ((reg >= ZYDIS_REGISTER_RIP) && (reg <= ZYDIS_REGISTER_IP))
{
return ZYDIS_REGISTERCLASS_IP;
}
if ((reg >= ZYDIS_REGISTER_ES) && (reg <= ZYDIS_REGISTER_GS))
{
return ZYDIS_REGISTERCLASS_SEGMENT;
}
if ((reg >= ZYDIS_REGISTER_CR0) && (reg <= ZYDIS_REGISTER_CR15))
{
return ZYDIS_REGISTERCLASS_CONTROL;
}
if ((reg >= ZYDIS_REGISTER_DR0) && (reg <= ZYDIS_REGISTER_DR15))
{
return ZYDIS_REGISTERCLASS_DEBUG;
}
if ((reg >= ZYDIS_REGISTER_K0) && (reg <= ZYDIS_REGISTER_K7))
{
return ZYDIS_REGISTERCLASS_MASK;
}
if ((reg >= ZYDIS_REGISTER_BND0) && (reg <= ZYDIS_REGISTER_BND3))
{
return ZYDIS_REGISTERCLASS_BOUNDS;
}
return ZYDIS_REGISTERCLASS_INVALID;
}
ZydisRegisterSize ZydisRegisterGetSize(ZydisRegister reg)
{
ZydisRegisterClass registerClass = ZydisRegisterGetClass(reg);
switch (registerClass)
{
case ZYDIS_REGISTERCLASS_GENERAL_PURPOSE8:
return ZYDIS_REGISTERSIZE_8;
case ZYDIS_REGISTERCLASS_GENERAL_PURPOSE16:
return ZYDIS_REGISTERSIZE_16;
case ZYDIS_REGISTERCLASS_GENERAL_PURPOSE32:
return ZYDIS_REGISTERSIZE_32;
case ZYDIS_REGISTERCLASS_GENERAL_PURPOSE64:
return ZYDIS_REGISTERSIZE_64;
case ZYDIS_REGISTERCLASS_FLOATING_POINT:
return ZYDIS_REGISTERSIZE_80;
case ZYDIS_REGISTERCLASS_MULTIMEDIA:
return ZYDIS_REGISTERSIZE_64;
case ZYDIS_REGISTERCLASS_VECTOR128:
return ZYDIS_REGISTERSIZE_128;
case ZYDIS_REGISTERCLASS_VECTOR256:
return ZYDIS_REGISTERSIZE_256;
case ZYDIS_REGISTERCLASS_VECTOR512:
return ZYDIS_REGISTERSIZE_512;
case ZYDIS_REGISTERCLASS_FLAGS:
return ZYDIS_REGISTERSIZE_DYNAMIC;
case ZYDIS_REGISTERCLASS_IP:
return ZYDIS_REGISTERSIZE_DYNAMIC;
case ZYDIS_REGISTERCLASS_SEGMENT:
return ZYDIS_REGISTERSIZE_16;
case ZYDIS_REGISTERCLASS_CONTROL:
return ZYDIS_REGISTERSIZE_DYNAMIC;
case ZYDIS_REGISTERCLASS_DEBUG:
return ZYDIS_REGISTERSIZE_DYNAMIC;
case ZYDIS_REGISTERCLASS_MASK:
return ZYDIS_REGISTERSIZE_64;
case ZYDIS_REGISTERCLASS_BOUNDS:
return ZYDIS_REGISTERSIZE_128;
}
return ZYDIS_REGISTERSIZE_INVALID;
}
bool ZydisRegisterIsGPR(ZydisRegister reg)
{
switch (ZydisRegisterGetClass(reg))
{
case ZYDIS_REGISTERCLASS_GENERAL_PURPOSE64:
case ZYDIS_REGISTERCLASS_GENERAL_PURPOSE32:
case ZYDIS_REGISTERCLASS_GENERAL_PURPOSE16:
case ZYDIS_REGISTERCLASS_GENERAL_PURPOSE8:
return true;
}
return false;
}
bool ZydisRegisterIsGPR8(ZydisRegister reg)
{
return (ZydisRegisterGetClass(reg) == ZYDIS_REGISTERCLASS_GENERAL_PURPOSE8);
}
bool ZydisRegisterIsGPR16(ZydisRegister reg)
{
return (ZydisRegisterGetClass(reg) == ZYDIS_REGISTERCLASS_GENERAL_PURPOSE16);
}
bool ZydisRegisterIsGPR32(ZydisRegister reg)
{
return (ZydisRegisterGetClass(reg) == ZYDIS_REGISTERCLASS_GENERAL_PURPOSE32);
}
bool ZydisRegisterIsGPR64(ZydisRegister reg)
{
return (ZydisRegisterGetClass(reg) == ZYDIS_REGISTERCLASS_GENERAL_PURPOSE64);
}
bool ZydisRegisterIsFPRegister(ZydisRegister reg)
{
return (ZydisRegisterGetClass(reg) == ZYDIS_REGISTERCLASS_FLOATING_POINT);
}
bool ZydisRegisterIsMMRegister(ZydisRegister reg)
{
return (ZydisRegisterGetClass(reg) == ZYDIS_REGISTERCLASS_MULTIMEDIA);
}
bool ZydisRegisterIsVR(ZydisRegister reg)
{
switch (ZydisRegisterGetClass(reg))
{
case ZYDIS_REGISTERCLASS_VECTOR512:
case ZYDIS_REGISTERCLASS_VECTOR256:
case ZYDIS_REGISTERCLASS_VECTOR128:
return true;
}
return false;
}
bool ZydisRegisterIsVR128(ZydisRegister reg)
{
return (ZydisRegisterGetClass(reg) == ZYDIS_REGISTERCLASS_VECTOR128);
}
bool ZydisRegisterIsVR256(ZydisRegister reg)
{
return (ZydisRegisterGetClass(reg) == ZYDIS_REGISTERCLASS_VECTOR256);
}
bool ZydisRegisterIsVR512(ZydisRegister reg)
{
return (ZydisRegisterGetClass(reg) == ZYDIS_REGISTERCLASS_VECTOR512);
}
bool ZydisRegisterIsFlagsRegister(ZydisRegister reg)
{
return (ZydisRegisterGetClass(reg) == ZYDIS_REGISTERCLASS_FLAGS);
}
bool ZydisRegisterIsIPRegister(ZydisRegister reg)
{
return (ZydisRegisterGetClass(reg) == ZYDIS_REGISTERCLASS_IP);
}
bool ZydisRegisterIsSegmentRegister(ZydisRegister reg)
{
return (ZydisRegisterGetClass(reg) == ZYDIS_REGISTERCLASS_SEGMENT);
}
bool ZydisRegisterIsCR(ZydisRegister reg)
{
return (ZydisRegisterGetClass(reg) == ZYDIS_REGISTERCLASS_CONTROL);
}
bool ZydisRegisterIsDR(ZydisRegister reg)
{
return (ZydisRegisterGetClass(reg) == ZYDIS_REGISTERCLASS_DEBUG);
}
bool ZydisRegisterIsMaskRegister(ZydisRegister reg)
{
return (ZydisRegisterGetClass(reg) == ZYDIS_REGISTERCLASS_MASK);
}
bool ZydisRegisterIsBoundsRegister(ZydisRegister reg)
{
return (ZydisRegisterGetClass(reg) == ZYDIS_REGISTERCLASS_BOUNDS);
}
/* ============================================================================================== */

88
src/Utils.c Normal file
View File

@ -0,0 +1,88 @@
/***************************************************************************************************
Zyan Disassembler Engine (Zydis)
Original Author : Florian Bernd
* 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 <stdint.h>
#include <Zydis/Utils.h>
/* ============================================================================================== */
/* Operand utils */
/* ============================================================================================== */
/* ---------------------------------------------------------------------------------------------- */
/* Exported functions */
/* ---------------------------------------------------------------------------------------------- */
ZydisStatus ZydisUtilsCalcAbsoluteTargetAddress(const ZydisInstructionInfo* info,
const ZydisOperandInfo* operand, uint64_t* address)
{
if (!info || !operand || !address)
{
return ZYDIS_STATUS_INVALID_PARAMETER;
}
switch (operand->type)
{
case ZYDIS_OPERAND_TYPE_MEMORY:
if (operand->mem.disp.size == 0)
{
return ZYDIS_STATUS_INVALID_PARAMETER;
}
if (operand->mem.base == ZYDIS_REGISTER_EIP)
{
*address = (uint64_t)((uint32_t)info->instrPointer + operand->mem.disp.value.sdword);
return ZYDIS_STATUS_SUCCESS;
}
if (operand->mem.base == ZYDIS_REGISTER_RIP)
{
*address = (uint64_t)(info->instrPointer + operand->mem.disp.value.sqword);
return ZYDIS_STATUS_SUCCESS;
}
break;
case ZYDIS_OPERAND_TYPE_IMMEDIATE:
if (operand->imm.isSigned || operand->imm.isRelative)
{
*address = (uint64_t)((int64_t)info->instrPointer + operand->imm.value.sqword);
switch (info->operandMode)
{
case 16:
*address = (uint16_t)*address;
break;
case 32:
if (info->mode != ZYDIS_DISASSEMBLER_MODE_64BIT)
{
*address = (uint32_t)*address;
}
break;
}
return ZYDIS_STATUS_SUCCESS;
}
break;
}
return ZYDIS_STATUS_INVALID_PARAMETER;
}
/* ---------------------------------------------------------------------------------------------- */
/* ============================================================================================== */

View File

@ -1,12 +1,8 @@
/*************************************************************************************************** /***************************************************************************************************
Zyan Disassembler Engine Zyan Disassembler Engine (Zydis)
Version 1.0
Remarks : Freeware, Copyright must be included
Original Author : Florian Bernd Original Author : Florian Bernd
Modifications : Joel Höner
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal
@ -28,28 +24,15 @@
***************************************************************************************************/ ***************************************************************************************************/
/** #include <Zydis/Zydis.h>
* @file
* @brief Utility functions.
*/
#ifndef _ZYDIS_UTILS_HPP_ /* ============================================================================================== */
#define _ZYDIS_UTILS_HPP_ /* Exported functions */
/* ============================================================================================== */
#include <stdint.h> uint64_t ZydisGetVersion()
#include "ZydisTypes.hpp"
namespace Zydis
{ {
return ZYDIS_VERSION;
/**
* @brief Calculates the absolute target address of a relative instruction operand.
* @param info The instruction info.
* @param operand The operand.
* @return The absolute target address.
*/
uint64_t CalcAbsoluteTarget(const InstructionInfo& info, const OperandInfo& operand);
} }
#endif /* _ZYDIS_UTILS_HPP_ */ /* ============================================================================================== */

92
tools/ZydisDisasm.c Normal file
View File

@ -0,0 +1,92 @@
/***************************************************************************************************
Zyan Disassembler Engine (Zydis)
Original Author : Florian Bernd, 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 <stddef.h>
#include <stdint.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <Zydis/Zydis.h>
/* ============================================================================================== */
/* Entry point */
/* ============================================================================================== */
int main(int argc, char** argv)
{
if (argc != 2)
{
fprintf(stderr, "Usage: %s <input file>\n", (argc > 0 ? argv[0] : "ZydisDisasm"));
return EXIT_FAILURE;
}
FILE* file = fopen(argv[1], "rb");
if (!file)
{
fprintf(stderr, "Can not open file: %s\n", strerror(errno));
return EXIT_FAILURE;
}
ZydisFileInput input;
if (!ZYDIS_SUCCESS(ZydisInputInitFileInput(&input, file)))
{
fputs("Failed to initialize file-input\n", stderr);
return EXIT_FAILURE;
}
ZydisInstructionFormatter formatter;
if (!ZYDIS_SUCCESS(ZydisFormatterInitInstructionFormatterEx(&formatter,
ZYDIS_FORMATTER_STYLE_INTEL, ZYDIS_FORMATTER_FLAG_ALWAYS_DISPLAY_MEMORY_SEGMENT)))
{
fputs("Failed to initialized instruction-formatter\n", stderr);
return EXIT_FAILURE;
}
ZydisInstructionDecoder decoder;
if (!ZYDIS_SUCCESS(ZydisDecoderInitInstructionDecoderEx(&decoder, ZYDIS_DISASSEMBLER_MODE_64BIT,
(ZydisCustomInput*)&input, ZYDIS_DECODER_FLAG_SKIP_DATA)))
{
fputs("Failed to initialize instruction-decoder\n", stderr);
return EXIT_FAILURE;
}
char buffer[256];
ZydisInstructionInfo info;
while (ZYDIS_SUCCESS(ZydisDecoderDecodeNextInstruction(&decoder, &info)))
{
if (info.flags & ZYDIS_IFLAG_ERROR_MASK)
{
printf("db %02X\n", info.data[0]);
continue;
}
ZydisFormatterFormatInstruction(&formatter, &info, buffer, sizeof(buffer));
printf("%s\n", &buffer[0]);
}
}
/* ============================================================================================== */