Add x86 arch

This commit is contained in:
windy 2021-08-10 23:56:33 +08:00
parent 4432fe9e53
commit 17d356f87f
6 changed files with 486 additions and 0 deletions

1
VTIL-Common/arch/.gitignore vendored Normal file
View file

@ -0,0 +1 @@
!/x86/

View file

@ -0,0 +1,80 @@
// Copyright (c) 2020 Can Boluk and contributors of the VTIL Project
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// 3. Neither the name of VTIL Project nor the names of its contributors
// may be used to endorse or promote products derived from this software
// without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// Furthermore, the following pieces of software have additional copyrights
// licenses, and/or restrictions:
//
// |--------------------------------------------------------------------------|
// | File name | Link for further information |
// |-------------------------|------------------------------------------------|
// | x86/* | https://github.com/aquynh/capstone/ |
// | | https://github.com/keystone-engine/keystone/ |
// |--------------------------------------------------------------------------|
//
#include "x86_assembler.hpp"
#include <stdexcept>
namespace vtil::x86
{
ks_struct* get_ks_handle()
{
// Keystone engine is not created until the first call.
//
static ks_engine* handle = [ ] ()
{
ks_engine* handle;
if ( ks_open( KS_ARCH_X86, KS_MODE_64, &handle ) != KS_ERR_OK )
throw std::runtime_error( "Failed to create the Keystone engine!" );
return handle;
}( );
return handle;
}
std::vector<uint8_t> assemble( const std::string& src, uint64_t va )
{
// Assemble the given instruction in text format.
// - (Not too sure why I have to do the .code64; hack, but won't question.)
//
size_t size;
size_t count;
unsigned char* encode = nullptr;
if ( ks_asm( get_ks_handle(), ( ".code64;" + src ).data(), va, &encode, &size, &count ) )
{
// Free (if relevant) and return on failure.
//
if ( encode ) ks_free( encode );
return {};
}
// Convert to a vector of bytes, free the encoding and return it.
//
std::vector<uint8_t> output = { encode, encode + size };
ks_free( encode );
return output;
}
};

View file

@ -0,0 +1,50 @@
// Copyright (c) 2020 Can Boluk and contributors of the VTIL Project
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// 3. Neither the name of VTIL Project nor the names of its contributors
// may be used to endorse or promote products derived from this software
// without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// Furthermore, the following pieces of software have additional copyrights
// licenses, and/or restrictions:
//
// |--------------------------------------------------------------------------|
// | File name | Link for further information |
// |-------------------------|------------------------------------------------|
// | x86/* | https://github.com/aquynh/capstone/ |
// | | https://github.com/keystone-engine/keystone/ |
// |--------------------------------------------------------------------------|
//
#pragma once
#include <string>
#include <vector>
#include <keystone/keystone.h>
// Simple wrapper around Keystone assembler.
//
namespace vtil::x86
{
ks_struct* get_ks_handle();
std::vector<uint8_t> assemble( const std::string& src, uint64_t va = 0 );
};

View file

@ -0,0 +1,128 @@
// Copyright (c) 2020 Can Boluk and contributors of the VTIL Project
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// 3. Neither the name of VTIL Project nor the names of its contributors
// may be used to endorse or promote products derived from this software
// without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// Furthermore, the following pieces of software have additional copyrights
// licenses, and/or restrictions:
//
// |--------------------------------------------------------------------------|
// | File name | Link for further information |
// |-------------------------|------------------------------------------------|
// | x86/* | https://github.com/aquynh/capstone/ |
// | | https://github.com/keystone-engine/keystone/ |
// |--------------------------------------------------------------------------|
//
#include "x86_disassembler.hpp"
#include <stdexcept>
namespace vtil::x86
{
csh get_cs_handle()
{
// Capstone engine is not created until the first call.
//
static csh handle = [ ] ()
{
csh handle;
if ( cs_open( CS_ARCH_X86, CS_MODE_32, &handle ) != CS_ERR_OK
|| cs_option( handle, CS_OPT_DETAIL, CS_OPT_ON ) != CS_ERR_OK )
throw std::runtime_error( "Failed to create the Capstone engine!" );
return handle;
}( );
return handle;
}
std::vector<instruction> disasm( const void* bytes, uint64_t address, size_t size, size_t count )
{
// Disasemble the instruction.
//
cs_insn* ins;
count = cs_disasm
(
get_cs_handle(),
( uint8_t* ) bytes,
size ? size : -1,
address,
size ? 0 : count,
&ins
);
// Convert each output into vtil::amd64 format and push it to a vector.
//
std::vector<instruction> vec;
for ( int i = 0; i < count; i++ )
{
instruction out;
cs_insn& in = ins[ i ];
// Copy cs_insn base.
//
out.id = in.id;
out.address = in.address;
out.mnemonic = in.mnemonic;
out.operand_string = in.op_str;
out.bytes = { in.bytes, in.bytes + in.size };
// Copy cs_insn::detail.
//
out.regs_read = { in.detail->regs_read, in.detail->regs_read + in.detail->regs_read_count };
out.regs_write = { in.detail->regs_write, in.detail->regs_write + in.detail->regs_write_count };
out.groups = { in.detail->groups, in.detail->groups + in.detail->groups_count };
// Copy cs_insn::detail::x86.
//
std::copy( std::begin( in.detail->x86.prefix ), std::end( in.detail->x86.prefix ), out.prefix );
for ( int i = 0; i < 4 && in.detail->x86.opcode[ i ] != 0x0; i++ )
out.opcode.push_back( in.detail->x86.opcode[ i ] );
out.rex = in.detail->x86.rex;
out.addr_size = in.detail->x86.addr_size;
out.modrm = in.detail->x86.modrm;
out.sib = in.detail->x86.sib;
out.disp = in.detail->x86.disp;
out.sib_index = in.detail->x86.sib_index;
out.sib_scale = in.detail->x86.sib_scale;
out.sib_base = in.detail->x86.sib_base;
out.xop_cc = in.detail->x86.xop_cc;
out.sse_cc = in.detail->x86.sse_cc;
out.avx_cc = in.detail->x86.avx_cc;
out.avx_sae = in.detail->x86.avx_sae;
out.avx_rm = in.detail->x86.avx_rm;
out.eflags = in.detail->x86.eflags;
out.operands = { in.detail->x86.operands, in.detail->x86.operands + in.detail->x86.op_count };
out.encoding = in.detail->x86.encoding;
// Push it to up the vector.
//
vec.push_back( std::move( out ) );
}
// Free the output from Capstone and return the vector.
//
cs_free( ins, count );
return vec;
}
};

View file

@ -0,0 +1,129 @@
// Copyright (c) 2020 Can Boluk and contributors of the VTIL Project
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// 3. Neither the name of VTIL Project nor the names of its contributors
// may be used to endorse or promote products derived from this software
// without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// Furthermore, the following pieces of software have additional copyrights
// licenses, and/or restrictions:
//
// |--------------------------------------------------------------------------|
// | File name | Link for further information |
// |-------------------------|------------------------------------------------|
// | x86/* | https://github.com/aquynh/capstone/ |
// | | https://github.com/keystone-engine/keystone/ |
// |--------------------------------------------------------------------------|
//
#pragma once
#include <vector>
#include <map>
#include <string>
#include <cstring>
#include <set>
#include <capstone/capstone.h>
#include <algorithm>
#include "../../io/formatting.hpp"
namespace vtil::x86
{
struct instruction
{
// Data copied from base of [cs_insn].
//
uint32_t id = 0;
uint64_t address = 0;
std::vector<uint8_t> bytes;
std::string mnemonic;
std::string operand_string;
// Data copied from [cs_insn::detail].
//
std::set<uint16_t> regs_read;
std::set<uint16_t> regs_write;
std::set<uint8_t> groups;
// Data copied from [cs_insn::detail::x86]
//
uint8_t prefix[ 4 ] = { 0 };
std::vector<uint8_t> opcode;
uint8_t rex = 0;
uint8_t addr_size = 0;
uint8_t modrm = 0;
uint8_t sib = 0;
int64_t disp = 0;
x86_reg sib_index = X86_REG_INVALID;
int8_t sib_scale = 0;
x86_reg sib_base = X86_REG_INVALID;
x86_xop_cc xop_cc = X86_XOP_CC_INVALID;
x86_sse_cc sse_cc = X86_SSE_CC_INVALID;
x86_avx_cc avx_cc = X86_AVX_CC_INVALID;
bool avx_sae = false;
x86_avx_rm avx_rm = X86_AVX_RM_INVALID;
union
{
uint64_t eflags;
uint64_t fpu_flags;
};
std::vector<cs_x86_op> operands;
cs_x86_encoding encoding;
// Returns human readable disassembly.
//
std::string to_string() const
{
return format::str( "%p: %s\t%s", (uintptr_t) address, mnemonic, operand_string );
}
// Helper to check if instruction is of type <x86_INS_*, {X86_OP_*...}>.
//
bool is( uint32_t idx, const std::vector<x86_op_type>& operand_types ) const
{
if ( id != idx ) return false;
if ( operands.size() != operand_types.size() ) return false;
for ( int i = 0; i < operands.size(); i++ )
if ( operands[ i ].type != operand_types[ i ] )
return false;
return true;
}
// Helper to check if instruction belongs to the given group.
//
bool in_group( uint8_t group_searched ) const
{
return std::find( groups.begin(), groups.end(), group_searched ) != groups.end();
}
};
// Simple wrapper around Capstone disasembler.
//
csh get_cs_handle();
std::vector<instruction> disasm( const void* bytes, uint64_t address, size_t size = 0, size_t count = 1 );
};

View file

@ -0,0 +1,98 @@
// Copyright (c) 2020 Can Boluk and contributors of the VTIL Project
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// 3. Neither the name of VTIL Project nor the names of its contributors
// may be used to endorse or promote products derived from this software
// without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
// Furthermore, the following pieces of software have additional copyright
// licenses, and/or restrictions:
//
// |--------------------------------------------------------------------------|
// | File name | Link for further information |
// |-------------------------|------------------------------------------------|
// | x86/* | https://github.com/aquynh/capstone/ |
// | | https://github.com/keystone-engine/keystone/ |
// |--------------------------------------------------------------------------|
//
#pragma once
#include <map>
#include <tuple>
#include <string>
#include "../../io/asserts.hpp"
#include "x86_disassembler.hpp"
#include "../register_mapping.hpp"
namespace vtil::x86
{
// List of all physical registers and the base registers they map to <0> at offset <1> of size <2>.
//
static constexpr register_map<x86_reg, X86_REG_ENDING> registers =
{
{
/* [Instance] [Base] [Offset] [Size] */
{ X86_REG_EAX, { X86_REG_EAX, 0, 4 } },
{ X86_REG_AX, { X86_REG_EAX, 0, 2 } },
{ X86_REG_AH, { X86_REG_EAX, 1, 1 } },
{ X86_REG_AL, { X86_REG_EAX, 0, 1 } },
{ X86_REG_EBX, { X86_REG_EBX, 0, 4 } },
{ X86_REG_BX, { X86_REG_EBX, 0, 2 } },
{ X86_REG_BH, { X86_REG_EBX, 1, 1 } },
{ X86_REG_BL, { X86_REG_EBX, 0, 1 } },
{ X86_REG_ECX, { X86_REG_ECX, 0, 4 } },
{ X86_REG_CX, { X86_REG_ECX, 0, 2 } },
{ X86_REG_CH, { X86_REG_ECX, 1, 1 } },
{ X86_REG_CL, { X86_REG_ECX, 0, 1 } },
{ X86_REG_EDX, { X86_REG_EDX, 0, 4 } },
{ X86_REG_DX, { X86_REG_EDX, 0, 2 } },
{ X86_REG_DH, { X86_REG_EDX, 1, 1 } },
{ X86_REG_DL, { X86_REG_EDX, 0, 1 } },
{ X86_REG_EDI, { X86_REG_EDI, 0, 4 } },
{ X86_REG_DI, { X86_REG_EDI, 0, 2 } },
{ X86_REG_DIL, { X86_REG_EDI, 0, 1 } },
{ X86_REG_ESI, { X86_REG_ESI, 0, 4 } },
{ X86_REG_SI, { X86_REG_ESI, 0, 2 } },
{ X86_REG_SIL, { X86_REG_ESI, 0, 1 } },
{ X86_REG_EBP, { X86_REG_EBP, 0, 4 } },
{ X86_REG_BP, { X86_REG_EBP, 0, 2 } },
{ X86_REG_BPL, { X86_REG_EBP, 0, 1 } },
{ X86_REG_ESP, { X86_REG_ESP, 0, 4 } },
{ X86_REG_SP, { X86_REG_ESP, 0, 2 } },
{ X86_REG_SPL, { X86_REG_ESP, 0, 1 } },
{ X86_REG_EFLAGS, { X86_REG_EFLAGS, 0, 4 } },
}
};
// Converts the enum into human-readable format.
//
static const char* name( uint32_t _reg ) { return cs_reg_name( get_cs_handle(), _reg ); }
};