Hmm, this is preperation for something... I wonder what it might be ;)

This commit is contained in:
Luke Usher 2016-10-06 08:51:00 +01:00
parent 27e86ff74a
commit 0f7ddacfd4
33 changed files with 33324 additions and 30 deletions

View File

@ -68,7 +68,7 @@
<ClCompile>
<Optimization>MaxSpeed</Optimization>
<InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
<AdditionalIncludeDirectories>..\..\import\OpenXDK;..\..\src;..\..\src\Common;..\..\src\Common\Win32;..\..\import\OpenXDK\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>..\..\import\OpenXDK;..\..\import\zydis\Zydis;..\..\src;..\..\src\Common;..\..\src\Common\Win32;..\..\import\OpenXDK\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_USRDLL;CXBXKRNL_EXPORTS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<StringPooling>true</StringPooling>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
@ -82,7 +82,7 @@
<AdditionalIncludeDirectories>Include\Win32\CxbxKrnl;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ResourceCompile>
<Link>
<AdditionalDependencies>Shlwapi.lib;legacy_stdio_definitions.lib;dxerr8.lib;xinput.lib;ws2_32.lib;dsound.lib;winmm.lib;ddraw.lib;d3dx8.lib;d3d8.lib;dinput8.lib;dxguid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>Shlwapi.lib;Zydis.lib;legacy_stdio_definitions.lib;dxerr8.lib;xinput.lib;ws2_32.lib;dsound.lib;winmm.lib;ddraw.lib;d3dx8.lib;d3d8.lib;dinput8.lib;dxguid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies)</AdditionalDependencies>
<SuppressStartupBanner>true</SuppressStartupBanner>
<IgnoreSpecificDefaultLibraries>libci.lib;%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries>
<RandomizedBaseAddress>false</RandomizedBaseAddress>
@ -91,6 +91,7 @@
<TargetMachine>MachineX86</TargetMachine>
<ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
<LargeAddressAware>false</LargeAddressAware>
<AdditionalLibraryDirectories>..\..\import\zydis\Build\$(Configuration)\</AdditionalLibraryDirectories>
</Link>
<Bscmake>
<SuppressStartupBanner>true</SuppressStartupBanner>
@ -112,7 +113,7 @@
</Midl>
<ClCompile>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>..\..\src\Common;..\..\import\OpenXDK\include;..\..\src;..\..\src\Common\Win32;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>..\..\src\Common;..\..\import\zydis\Zydis;..\..\import\OpenXDK\include;..\..\src;..\..\src\Common\Win32;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_USRDLL;CXBXKRNL_EXPORTS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>true</MinimalRebuild>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
@ -127,7 +128,7 @@
<AdditionalIncludeDirectories>Include\Win32\CxbxKrnl;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ResourceCompile>
<Link>
<AdditionalDependencies>Shlwapi.lib;legacy_stdio_definitions.lib;dxerr8.lib;xinput.lib;ws2_32.lib;dsound.lib;winmm.lib;ddraw.lib;d3dx8.lib;d3d8.lib;dinput8.lib;dxguid.lib;odbc32.lib;odbccp32.lib;dbghelp.lib;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalDependencies>Shlwapi.lib;Zydis.lib;legacy_stdio_definitions.lib;dxerr8.lib;xinput.lib;ws2_32.lib;dsound.lib;winmm.lib;ddraw.lib;d3dx8.lib;d3d8.lib;dinput8.lib;dxguid.lib;odbc32.lib;odbccp32.lib;dbghelp.lib;%(AdditionalDependencies)</AdditionalDependencies>
<SuppressStartupBanner>true</SuppressStartupBanner>
<IgnoreSpecificDefaultLibraries>libci.lib;%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries>
<GenerateDebugInformation>true</GenerateDebugInformation>
@ -139,6 +140,7 @@
<TargetMachine>MachineX86</TargetMachine>
<ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
<LargeAddressAware>false</LargeAddressAware>
<AdditionalLibraryDirectories>..\..\import\zydis\Build\$(Configuration)\</AdditionalLibraryDirectories>
</Link>
<Bscmake>
<SuppressStartupBanner>true</SuppressStartupBanner>
@ -164,6 +166,7 @@
<ClInclude Include="..\..\src\CxbxKrnl\EmuFS.h" />
<ClInclude Include="..\..\src\CxbxKrnl\EmuNtDll.h" />
<ClInclude Include="..\..\src\CxbxKrnl\EmuShared.h" />
<ClInclude Include="..\..\src\CxbxKrnl\EmuX86.h" />
<ClInclude Include="..\..\src\CxbxKrnl\EmuXactEng.h" />
<ClInclude Include="..\..\src\CxbxKrnl\EmuXapi.h" />
<ClInclude Include="..\..\src\CxbxKrnl\EmuXG.h" />
@ -480,6 +483,7 @@
<AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<ClCompile Include="..\..\src\CxbxKrnl\EmuX86.cpp" />
<ClCompile Include="..\..\src\CxbxKrnl\EmuXactEng.cpp" />
<ClCompile Include="..\..\src\CxbxKrnl\EmuXapi.cpp">
<AdditionalIncludeDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>

183
import/zydis/.gitignore vendored Normal file
View File

@ -0,0 +1,183 @@
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
# User-specific files
*.suo
*.user
*.sln.docstates
# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
[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
*.pch
*.pdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*.log
*.vspscc
*.vssscc
.builds
*.pidb
*.svclog
*.scc
# Chutzpah Test files
_Chutzpah*
# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opensdf
*.sdf
*.cachefile
# Visual Studio profiler
*.psess
*.vsp
*.vspx
# TFS 2012 Local Workspace
$tf/
# Guidance Automation Toolkit
*.gpState
# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
*.DotSettings.user
# JustCode is a .NET coding addin-in
.JustCode
# TeamCity is a build add-in
_TeamCity*
# DotCover is a Code Coverage Tool
*.dotCover
# NCrunch
_NCrunch_*
.*crunch*.local.xml
# MightyMoose
*.mm.*
AutoTest.Net/
# Web workbench (sass)
.sass-cache/
# Installshield output folder
[Ee]xpress/
# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
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/

29
import/zydis/.travis.yml Normal file
View File

@ -0,0 +1,29 @@
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

@ -0,0 +1,96 @@
cmake_minimum_required(VERSION 2.8.12)
include(GenerateExportHeader)
project(Zydis)
option(BUILD_SHARED_LIBS "Build shared libraries rather than static ones" FALSE)
option(FORCE_SHARED_CRT
"Forces shared linkage against the CRT even when building a static library"
FALSE)
option(BUILD_EXAMPLES "Build examples" TRUE)
option(BUILD_C_BINDINGS "Build C bindings" TRUE)
if (NOT CONFIGURED_ONCE)
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" OR
"${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
set(compiler_specific "-Werror")
set(compiler_specific_cxx "-std=c++14")
elseif (MSVC)
set(compiler_specific "/WX /W4 /D_CRT_SECURE_NO_WARNINGS /GR-")
endif ()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${compiler_specific} ${compiler_specific_cxx}"
CACHE STRING "Flags used by the compiler during all build types." FORCE)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${compiler_specific}"
CACHE STRING "Flags used by the compiler during all build types." FORCE)
endif ()
# 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.
if (MSVC AND NOT FORCE_SHARED_CRT)
set(manipulated_vars
CMAKE_CXX_FLAGS_DEBUG
CMAKE_CXX_FLAGS_MINSIZEREL
CMAKE_CXX_FLAGS_RELEASE
CMAKE_CXX_FLAGS_RELWITHDEBINFO
CMAKE_C_FLAGS_DEBUG
CMAKE_C_FLAGS_MINSIZEREL
CMAKE_C_FLAGS_RELEASE
CMAKE_C_FLAGS_RELWITHDEBINFO)
foreach (cur_var ${manipulated_vars})
string(REPLACE "/MD" "/MT" ${cur_var} "${${cur_var}}")
endforeach ()
endif ()
# Library
set(headers
"Zydis/Zydis.hpp"
"Zydis/ZydisInstructionDecoder.hpp"
"Zydis/ZydisInstructionFormatter.hpp"
"Zydis/ZydisOpcodeTable.hpp"
"Zydis/ZydisSymbolResolver.hpp"
"Zydis/ZydisTypes.hpp"
"Zydis/ZydisUtils.hpp")
set(sources
"Zydis/ZydisInstructionDecoder.cpp"
"Zydis/ZydisInstructionFormatter.cpp"
"Zydis/ZydisOpcodeTable.cpp"
"Zydis/ZydisSymbolResolver.cpp"
"Zydis/ZydisUtils.cpp")
if (BUILD_SHARED_LIBS AND WIN32)
set(sources ${sources}
"Zydis/VersionInfo.rc")
endif ()
if (BUILD_C_BINDINGS)
set(headers ${headers}
"Zydis/ZydisAPI.h")
set(sources ${sources}
"Zydis/ZydisAPI.cpp")
endif ()
add_library("Zydis" ${headers} ${sources})
set_target_properties("Zydis" PROPERTIES COMPILE_DEFINITIONS "Zydis_EXPORTS")
generate_export_header(
"Zydis"
BASE_NAME "ZYDIS"
EXPORT_FILE_NAME "ZydisExportConfig.h")
include_directories(${PROJECT_BINARY_DIR})
# Examples
if (BUILD_EXAMPLES)
include_directories("Zydis")
add_executable("SimpleDemo_CPP" "Examples/CPP/SimpleDemo/SimpleDemo.cpp")
target_link_libraries("SimpleDemo_CPP" "Zydis")
add_executable("CustomDataSource_CPP" "Examples/CPP/CustomDataSource/CustomDataSource.cpp")
target_link_libraries("CustomDataSource_CPP" "Zydis")
if (BUILD_C_BINDINGS)
add_executable("SimpleDemo_C" "Examples/C/SimpleDemo/SimpleDemo.c")
target_link_libraries("SimpleDemo_C" "Zydis")
endif ()
endif ()
set(CONFIGURED_ONCE TRUE CACHE INTERNAL "CMake has configured at least once.")

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,199 @@
/***************************************************************************************************
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

@ -0,0 +1,169 @@
/***************************************************************************************************
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

@ -0,0 +1,109 @@
/***************************************************************************************************
Zyan Disassembler Engine
Version 1.0
Remarks : Freeware, Copyright must be included
Original Author : Florian Bernd
Modifications : Joel Höner
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
***************************************************************************************************/
#include <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;
}

22
import/zydis/LICENSE Normal file
View File

@ -0,0 +1,22 @@
The MIT License (MIT)
Copyright (c) 2014 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.

View File

@ -0,0 +1,40 @@
/**************************************************************************************************
Verteron Disassembler Engine
Version 1.0
Remarks : Freeware, Copyright must be included
Original Author : Florian Bernd
Modifications :
Last change : 29. October 2014
* 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 <tchar.h>
#include "PugiXML/pugixml.hpp"
#include "VXDisassemblerTypes.h"
int _tmain(int argc, _TCHAR* argv[])
{
// TODO:
return 0;
}

View File

@ -0,0 +1,156 @@
<?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

@ -0,0 +1,72 @@
/**
* 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

90
import/zydis/README.md Normal file
View File

@ -0,0 +1,90 @@
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)
================================
Fast and lightweight x86/x86-64 disassembler library.
## 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
## Quick Example ##
The following example program uses Zydis to disassemble a given memory buffer and prints the output to the console.
```c++
#include <iostream>
#include <iomanip>
#include <stdint.h>
#include <Zydis.hpp>
int main()
{
uint8_t data[] =
{
0x51, 0x8D, 0x45, 0xFF, 0x50, 0xFF, 0x75, 0x0C, 0xFF, 0x75,
0x08, 0xFF, 0x15, 0xA0, 0xA5, 0x48, 0x76, 0x85, 0xC0, 0x0F,
0x88, 0xFC, 0xDA, 0x02, 0x00
};
Zydis::MemoryInput input(&data[0], sizeof(data));
Zydis::InstructionInfo info;
Zydis::InstructionDecoder decoder;
decoder.setDisassemblerMode(Zydis::DisassemblerMode::M32BIT);
decoder.setDataSource(&input);
decoder.setInstructionPointer(0x00400000);
Zydis::IntelInstructionFormatter formatter;
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;
}
}
}
```
## Sample Output ##
The above example program generates the following output:
```
00400000 push ecx
00400001 lea eax, [ebp-01]
00400004 push eax
00400005 push dword ptr [ebp+0C]
00400008 push dword ptr [ebp+08]
0040000B call dword ptr [7648A5A0]
00400011 test eax, eax
00400013 js 0042DB15
```
## 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.
## Documentation ##
[The HTML Doxygen documentation](https://www.zyantific.com/doc/zydis/index.html) is automatically built from master every 12 hours.
## License ##
Zyan Disassembler Engine is licensed under the MIT License. Dependencies are under their respective licenses.

Binary file not shown.

View File

@ -0,0 +1,100 @@
/***************************************************************************************************
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

@ -0,0 +1,653 @@
/***************************************************************************************************
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

@ -0,0 +1,728 @@
/***************************************************************************************************
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

@ -0,0 +1,602 @@
/***************************************************************************************************
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

@ -0,0 +1,250 @@
/***************************************************************************************************
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

@ -0,0 +1,91 @@
/***************************************************************************************************
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

@ -0,0 +1,125 @@
/***************************************************************************************************
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

@ -0,0 +1,543 @@
/***************************************************************************************************
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_ */

View File

@ -0,0 +1,73 @@
/***************************************************************************************************
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 "ZydisUtils.hpp"
#include <cassert>
namespace Zydis
{
uint64_t CalcAbsoluteTarget(const InstructionInfo& info, const OperandInfo& operand)
{
assert((operand.type == OperandType::REL_IMMEDIATE) ||
((operand.type == OperandType::MEMORY) && (operand.base == Register::RIP)));
uint64_t truncMask = 0xFFFFFFFFFFFFFFFFull;
if (!(info.flags & IF_DISASSEMBLER_MODE_64))
{
truncMask >>= (64 - info.operand_mode);
}
uint16_t size = operand.size;
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;
}
}

View File

@ -0,0 +1,55 @@
/***************************************************************************************************
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 Utility functions.
*/
#ifndef _ZYDIS_UTILS_HPP_
#define _ZYDIS_UTILS_HPP_
#include <stdint.h>
#include "ZydisTypes.hpp"
namespace Zydis
{
/**
* @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_ */

View File

@ -43,6 +43,7 @@ namespace xboxkrnl
#include "CxbxKrnl.h"
#define COMPILE_MULTIMON_STUBS
#include "Emu.h"
#include "EmuX86.h"
#include "EmuFS.h"
#include "EmuAlloc.h"
@ -144,38 +145,35 @@ extern int EmuException(LPEXCEPTION_POINTERS e)
{
g_bEmuException = true;
// print debug information
{
if(e->ExceptionRecord->ExceptionCode == 0x80000003)
printf("EmuMain (0x%X): Recieved Breakpoint Exception (int 3)\n", GetCurrentThreadId());
else
printf("EmuMain (0x%X): Recieved Exception (Code := 0x%.08X)\n", GetCurrentThreadId(), e->ExceptionRecord->ExceptionCode);
printf("\n"
" EIP := 0x%.08X EFL := 0x%.08X\n"
" EAX := 0x%.08X EBX := 0x%.08X ECX := 0x%.08X EDX := 0x%.08X\n"
" ESI := 0x%.08X EDI := 0x%.08X ESP := 0x%.08X EBP := 0x%.08X\n"
" CR2 := 0x%.08X\n"
"\n",
e->ContextRecord->Eip, e->ContextRecord->EFlags,
e->ContextRecord->Eax, e->ContextRecord->Ebx, e->ContextRecord->Ecx, e->ContextRecord->Edx,
e->ContextRecord->Esi, e->ContextRecord->Edi, e->ContextRecord->Esp, e->ContextRecord->Ebp,
e->ContextRecord->Dr2);
#ifdef _DEBUG
CONTEXT Context = *(e->ContextRecord);
EmuPrintStackTrace(&Context);
#endif
}
fflush(stdout);
// notify user
{
char buffer[256];
if(e->ExceptionRecord->ExceptionCode == 0x80000003)
{
// print debug information
{
printf("EmuMain (0x%X): Recieved Breakpoint Exception (int 3)\n", GetCurrentThreadId());
printf("\n"
" EIP := 0x%.08X EFL := 0x%.08X\n"
" EAX := 0x%.08X EBX := 0x%.08X ECX := 0x%.08X EDX := 0x%.08X\n"
" ESI := 0x%.08X EDI := 0x%.08X ESP := 0x%.08X EBP := 0x%.08X\n"
" CR2 := 0x%.08X\n"
"\n",
e->ContextRecord->Eip, e->ContextRecord->EFlags,
e->ContextRecord->Eax, e->ContextRecord->Ebx, e->ContextRecord->Ecx, e->ContextRecord->Edx,
e->ContextRecord->Esi, e->ContextRecord->Edi, e->ContextRecord->Esp, e->ContextRecord->Ebp,
e->ContextRecord->Dr2);
#ifdef _DEBUG
CONTEXT Context = *(e->ContextRecord);
EmuPrintStackTrace(&Context);
#endif
}
fflush(stdout);
sprintf(buffer,
"Recieved Breakpoint Exception (int 3) @ EIP := 0x%.08X\n"
"\n"
@ -209,6 +207,37 @@ extern int EmuException(LPEXCEPTION_POINTERS e)
}
else
{
// Pass the exception to our X86 implementation, to try and execute the failing instruction
if (EmuX86_DecodeException(e))
{
g_bEmuException = false;
return EXCEPTION_CONTINUE_EXECUTION;
}
// print debug information
{
printf("EmuMain (0x%X): Recieved Exception (Code := 0x%.08X)\n", GetCurrentThreadId(), e->ExceptionRecord->ExceptionCode);
printf("\n"
" EIP := 0x%.08X EFL := 0x%.08X\n"
" EAX := 0x%.08X EBX := 0x%.08X ECX := 0x%.08X EDX := 0x%.08X\n"
" ESI := 0x%.08X EDI := 0x%.08X ESP := 0x%.08X EBP := 0x%.08X\n"
" CR2 := 0x%.08X\n"
"\n",
e->ContextRecord->Eip, e->ContextRecord->EFlags,
e->ContextRecord->Eax, e->ContextRecord->Ebx, e->ContextRecord->Ecx, e->ContextRecord->Edx,
e->ContextRecord->Esi, e->ContextRecord->Edi, e->ContextRecord->Esp, e->ContextRecord->Ebp,
e->ContextRecord->Dr2);
#ifdef _DEBUG
CONTEXT Context = *(e->ContextRecord);
EmuPrintStackTrace(&Context);
#endif
}
fflush(stdout);
sprintf(buffer,
"Recieved Exception Code 0x%.08X @ EIP := 0x%.08X\n"
"\n"

73
src/CxbxKrnl/EmuX86.cpp Normal file
View File

@ -0,0 +1,73 @@
// ******************************************************************
// *
// * .,-::::: .,:: .::::::::. .,:: .:
// * ,;;;'````' `;;;, .,;; ;;;'';;' `;;;, .,;;
// * [[[ '[[,,[[' [[[__[[\. '[[,,[['
// * $$$ Y$$$P $$""""Y$$ Y$$$P
// * `88bo,__,o, oP"``"Yo, _88o,,od8P oP"``"Yo,
// * "YUMMMMMP",m" "Mm,""YUMMMP" ,m" "Mm,
// *
// * Cxbx->Win32->CxbxKrnl->EmuX86.cpp
// *
// * This file is part of the Cxbx project.
// *
// * Cxbx and Cxbe are free software; you can redistribute them
// * and/or modify them under the terms of the GNU General Public
// * License as published by the Free Software Foundation; either
// * version 2 of the license, or (at your option) any later version.
// *
// * This program is distributed in the hope that it will be useful,
// * but WITHOUT ANY WARRANTY; without even the implied warranty of
// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// * GNU General Public License for more details.
// *
// * You should have recieved a copy of the GNU General Public License
// * along with this program; see the file COPYING.
// * If not, write to the Free Software Foundation, Inc.,
// * 59 Temple Place - Suite 330, Bostom, MA 02111-1307, USA.
// *
// * (c) 2002-2003 Aaron Robinson <caustik@caustik.com>
// * (c) 2016 Luke Usher <luke.usher@outlook.com>
// * All rights reserved
// *
// ******************************************************************
#define _CXBXKRNL_INTERNAL
#define _XBOXKRNL_DEFEXTRN_
#include <Zydis.hpp>
#include "CxbxKrnl.h"
#include "Emu.h"
#include "EmuX86.h"
bool EmuX86_DecodeException(LPEXCEPTION_POINTERS e)
{
// Only decode instructions within Xbox memory space
if (e->ContextRecord->Eip > XBOX_MEMORY_SIZE) {
return false;
}
Zydis::MemoryInput input((uint8_t*)e->ContextRecord->Eip, XBOX_MEMORY_SIZE - e->ContextRecord->Eip);
Zydis::InstructionInfo info;
Zydis::InstructionDecoder decoder;
decoder.setDisassemblerMode(Zydis::DisassemblerMode::M32BIT);
decoder.setDataSource(&input);
decoder.setInstructionPointer(e->ContextRecord->Eip);
Zydis::IntelInstructionFormatter formatter;
// Decode a single instruction
decoder.decodeInstruction(info);
if (info.flags & Zydis::IF_ERROR_MASK)
{
EmuWarning("EmuX86: Error decoding opcode at 0x%08X\n", info.instrAddress);
}
else
{
EmuWarning("EmuX86: %s Ignored\n", formatter.formatInstruction(info));
e->ContextRecord->Eip += info.length;
return true;
}
return false;
}

39
src/CxbxKrnl/EmuX86.h Normal file
View File

@ -0,0 +1,39 @@
// ******************************************************************
// *
// * .,-::::: .,:: .::::::::. .,:: .:
// * ,;;;'````' `;;;, .,;; ;;;'';;' `;;;, .,;;
// * [[[ '[[,,[[' [[[__[[\. '[[,,[['
// * $$$ Y$$$P $$""""Y$$ Y$$$P
// * `88bo,__,o, oP"``"Yo, _88o,,od8P oP"``"Yo,
// * "YUMMMMMP",m" "Mm,""YUMMMP" ,m" "Mm,
// *
// * Cxbx->Win32->CxbxKrnl->EmuX86.cpp
// *
// * This file is part of the Cxbx project.
// *
// * Cxbx and Cxbe are free software; you can redistribute them
// * and/or modify them under the terms of the GNU General Public
// * License as published by the Free Software Foundation; either
// * version 2 of the license, or (at your option) any later version.
// *
// * This program is distributed in the hope that it will be useful,
// * but WITHOUT ANY WARRANTY; without even the implied warranty of
// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// * GNU General Public License for more details.
// *
// * You should have recieved a copy of the GNU General Public License
// * along with this program; see the file COPYING.
// * If not, write to the Free Software Foundation, Inc.,
// * 59 Temple Place - Suite 330, Bostom, MA 02111-1307, USA.
// *
// * (c) 2002-2003 Aaron Robinson <caustik@caustik.com>
// * (c) 2016 Luke Usher <luke.usher@outlook.com>
// * All rights reserved
// *
// ******************************************************************
#ifndef EMUX86_H
#define EMUX86_H
bool EmuX86_DecodeException(LPEXCEPTION_POINTERS e);
#endif