From 17d356f87fa021e900a8975a112698a1db09bd7c Mon Sep 17 00:00:00 2001 From: windy <19060@qq.com> Date: Tue, 10 Aug 2021 23:56:33 +0800 Subject: [PATCH] Add x86 arch --- VTIL-Common/arch/.gitignore | 1 + VTIL-Common/arch/x86/x86_assembler.cpp | 80 +++++++++++ VTIL-Common/arch/x86/x86_assembler.hpp | 50 +++++++ VTIL-Common/arch/x86/x86_disassembler.cpp | 128 +++++++++++++++++ VTIL-Common/arch/x86/x86_disassembler.hpp | 129 ++++++++++++++++++ VTIL-Common/arch/x86/x86_register_details.hpp | 98 +++++++++++++ 6 files changed, 486 insertions(+) create mode 100644 VTIL-Common/arch/.gitignore create mode 100644 VTIL-Common/arch/x86/x86_assembler.cpp create mode 100644 VTIL-Common/arch/x86/x86_assembler.hpp create mode 100644 VTIL-Common/arch/x86/x86_disassembler.cpp create mode 100644 VTIL-Common/arch/x86/x86_disassembler.hpp create mode 100644 VTIL-Common/arch/x86/x86_register_details.hpp diff --git a/VTIL-Common/arch/.gitignore b/VTIL-Common/arch/.gitignore new file mode 100644 index 0000000..5b00b99 --- /dev/null +++ b/VTIL-Common/arch/.gitignore @@ -0,0 +1 @@ +!/x86/ \ No newline at end of file diff --git a/VTIL-Common/arch/x86/x86_assembler.cpp b/VTIL-Common/arch/x86/x86_assembler.cpp new file mode 100644 index 0000000..dc05c16 --- /dev/null +++ b/VTIL-Common/arch/x86/x86_assembler.cpp @@ -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 + +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 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 output = { encode, encode + size }; + ks_free( encode ); + return output; + } +}; \ No newline at end of file diff --git a/VTIL-Common/arch/x86/x86_assembler.hpp b/VTIL-Common/arch/x86/x86_assembler.hpp new file mode 100644 index 0000000..3394e9d --- /dev/null +++ b/VTIL-Common/arch/x86/x86_assembler.hpp @@ -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 +#include +#include + +// Simple wrapper around Keystone assembler. +// +namespace vtil::x86 +{ + ks_struct* get_ks_handle(); + std::vector assemble( const std::string& src, uint64_t va = 0 ); +}; diff --git a/VTIL-Common/arch/x86/x86_disassembler.cpp b/VTIL-Common/arch/x86/x86_disassembler.cpp new file mode 100644 index 0000000..3ce52e9 --- /dev/null +++ b/VTIL-Common/arch/x86/x86_disassembler.cpp @@ -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 + +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 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 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; + } +}; \ No newline at end of file diff --git a/VTIL-Common/arch/x86/x86_disassembler.hpp b/VTIL-Common/arch/x86/x86_disassembler.hpp new file mode 100644 index 0000000..473e6a8 --- /dev/null +++ b/VTIL-Common/arch/x86/x86_disassembler.hpp @@ -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 +#include +#include +#include +#include +#include +#include +#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 bytes; + std::string mnemonic; + std::string operand_string; + + // Data copied from [cs_insn::detail]. + // + std::set regs_read; + std::set regs_write; + std::set groups; + + // Data copied from [cs_insn::detail::x86] + // + uint8_t prefix[ 4 ] = { 0 }; + std::vector 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 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 . + // + bool is( uint32_t idx, const std::vector& 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 disasm( const void* bytes, uint64_t address, size_t size = 0, size_t count = 1 ); +}; \ No newline at end of file diff --git a/VTIL-Common/arch/x86/x86_register_details.hpp b/VTIL-Common/arch/x86/x86_register_details.hpp new file mode 100644 index 0000000..76a9ede --- /dev/null +++ b/VTIL-Common/arch/x86/x86_register_details.hpp @@ -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 +#include +#include +#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 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 ); } +};