Hmm, this is preperation for something... I wonder what it might be ;)
This commit is contained in:
parent
27e86ff74a
commit
0f7ddacfd4
|
@ -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>
|
||||
|
|
|
@ -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/
|
|
@ -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
|
|
@ -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
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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;
|
||||
}
|
|
@ -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.
|
||||
|
|
@ -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;
|
||||
}
|
|
@ -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>
|
|
@ -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
|
@ -0,0 +1,90 @@
|
|||
Zyan Disassembler Engine (Zydis) [](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.
|
@ -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_ */
|
|
@ -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
|
@ -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_ */
|
|
@ -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()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/* ============================================================================================== */
|
||||
|
||||
}
|
|
@ -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
|
@ -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();
|
||||
}
|
||||
|
||||
/* ============================================================================================== */
|
||||
|
||||
}
|
|
@ -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_ */
|
|
@ -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_ */
|
|
@ -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;
|
||||
}
|
||||
|
||||
}
|
|
@ -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_ */
|
|
@ -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"
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -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
|
Loading…
Reference in New Issue