iced-x86 is a blazing fast and correct x86 (16/32/64-bit) instruction decoder, disassembler and assembler written in Rust.
- 👍 Supports all Intel and AMD instructions
- 👍 Correct: All instructions are tested and iced has been tested against other disassemblers/assemblers (xed, gas, objdump, masm, dumpbin, nasm, ndisasm) and fuzzed
- 👍 100% Rust code
- 👍 The formatter supports masm, nasm, gas (AT&T), Intel (XED) and there are many options to customize the output
- 👍 Blazing fast: Decodes >250 MB/s and decode+format >130 MB/s (see here)
- 👍 Small decoded instructions, only 40 bytes and the decoder doesn't allocate any memory
- 👍 Create instructions with code assembler, eg.
asm.mov(eax, edx)
- 👍 The encoder can be used to re-encode decoded instructions at any address
- 👍 API to get instruction info, eg. read/written registers, memory and rflags bits; CPUID feature flag, control flow info, etc
- 👍 Supports
#![no_std]
andWebAssembly
- 👍 Supports
rustc
1.57.0
or later - 👍 Few dependencies (
lazy_static
) - 👍 License: MIT
Usage
Add this to your Cargo.toml
:
[]
= "1.21.0"
Or to customize which features to use:
[]
= "1.21.0"
= false
# See below for all features
= ["std", "decoder", "masm"]
Crate feature flags
You can enable/disable these in your Cargo.toml
file.
decoder
: (👍 Enabled by default) Enables the decoderencoder
: (👍 Enabled by default) Enables the encoderblock_encoder
: (👍 Enabled by default) Enables theBlockEncoder
. This feature enablesencoder
op_code_info
: (👍 Enabled by default) Enables getting instruction metadata (OpCodeInfo
). This feature enablesencoder
instr_info
: (👍 Enabled by default) Enables the instruction info codegas
: (👍 Enabled by default) Enables the GNU Assembler (AT&T) formatterintel
: (👍 Enabled by default) Enables the Intel (XED) formattermasm
: (👍 Enabled by default) Enables the masm formatternasm
: (👍 Enabled by default) Enables the nasm formatterfast_fmt
: (👍 Enabled by default) EnablesSpecializedFormatter<TraitOptions>
(andFastFormatter
) (masm syntax) which is ~3.3x faster than the other formatters (the time includes decoding + formatting). Use it if formatting speed is more important than being able to re-assemble formatted instructions or if targeting wasm (this formatter uses less code).code_asm
: EnablesCodeAssembler
to allow easy creation of instructions, eg.a.xor(ecx, dword_ptr(edx))
instead of using the more verboseInstruction::with*()
methods.serde
: Enables serialization support (Instruction
). Not guaranteed to work if different versions of iced was used to serialize and deserialize it.std
: (👍 Enabled by default) Enables thestd
crate.std
orno_std
must be defined, but not both.no_std
: Enables#![no_std]
.std
orno_std
must be defined, but not both. This feature uses thealloc
crate.mvex
: EnablesMVEX
instructions (Knights Corner). You must also pass inDecoderOptions::KNC
to theDecoder
constructor.exhaustive_enums
: Enables exhaustive enums, i.e., no enum has the#[non_exhaustive]
attribute
How-tos
- Disassemble (decode and format instructions)
- Assemble instructions
- Disassemble with a symbol resolver
- Disassemble with colorized text
- Move code in memory (eg. hook a function)
- Get instruction info, eg. read/written regs/mem, control flow info, etc
- Get the virtual address of a memory operand
- Disassemble old/deprecated CPU instructions
- Disassemble as fast as possible
- Create and encode instructions
Disassemble (decode and format instructions)
This example uses a Decoder
and one of the Formatter
s to decode and format the code,
eg. GasFormatter
, IntelFormatter
, MasmFormatter
, NasmFormatter
, SpecializedFormatter<TraitOptions>
(or FastFormatter
).
use ;
/*
This method produces the following output:
00007FFAC46ACDA4 48895C2410 mov [rsp+10h],rbx
00007FFAC46ACDA9 4889742418 mov [rsp+18h],rsi
00007FFAC46ACDAE 55 push rbp
00007FFAC46ACDAF 57 push rdi
00007FFAC46ACDB0 4156 push r14
00007FFAC46ACDB2 488DAC2400FFFFFF lea rbp,[rsp-100h]
00007FFAC46ACDBA 4881EC00020000 sub rsp,200h
00007FFAC46ACDC1 488B0518570A00 mov rax,[rel 7FFA`C475`24E0h]
00007FFAC46ACDC8 4833C4 xor rax,rsp
00007FFAC46ACDCB 488985F0000000 mov [rbp+0F0h],rax
00007FFAC46ACDD2 4C8B052F240A00 mov r8,[rel 7FFA`C474`F208h]
00007FFAC46ACDD9 488D05787C0400 lea rax,[rel 7FFA`C46F`4A58h]
00007FFAC46ACDE0 33FF xor edi,edi
*/
pub
const HEXBYTES_COLUMN_BYTE_LENGTH: usize = 10;
const EXAMPLE_CODE_BITNESS: u32 = 64;
const EXAMPLE_CODE_RIP: u64 = 0x0000_7FFA_C46A_CDA4;
static EXAMPLE_CODE: & = &;
Assemble instructions
This allows you to easily create instructions (eg. a.xor(eax, ecx)?
) without having to use the more verbose Instruction::with*()
functions.
This requires the code_asm
feature to use (not enabled by default). Add it to your Cargo.toml
:
[]
= "1.21.0"
= ["code_asm"]
use *;
pub
Disassemble with a symbol resolver
Creates a custom SymbolResolver
that is called by a Formatter
.
use ;
use HashMap;
pub
Disassemble with colorized text
Creates a custom FormatterOutput
that is called by a Formatter
.
This example will fail to compile unless you install the colored
crate, see below.
// This example uses crate colored = "2.0.0"
use ;
use ;
// Custom formatter output that stores the output in a vector.
pub
const EXAMPLE_CODE_BITNESS: u32 = 64;
const EXAMPLE_CODE_RIP: u64 = 0x0000_7FFA_C46A_CDA4;
static EXAMPLE_CODE: & = &;
Move code in memory (eg. hook a function)
Uses instruction info API and the encoder to patch a function to jump to the programmer's function.
use ;
// Decodes instructions from some address, then encodes them starting at some
// other address. This can be used to hook a function. You decode enough instructions
// until you have enough bytes to add a JMP instruction that jumps to your code.
// Your code will then conditionally jump to the original code that you re-encoded.
//
// This code uses the BlockEncoder which will help with some things, eg. converting
// short branches to longer branches if the target is too far away.
//
// 64-bit mode also supports RIP relative addressing, but the encoder can't rewrite
// those to use a longer displacement. If any of the moved instructions have RIP
// relative addressing and it tries to access data too far away, the encoder will fail.
// The easiest solution is to use OS alloc functions that allocate memory close to the
// original code (+/-2GB).
/*
This method produces the following output:
Original code:
00007FFAC46ACDA4 mov [rsp+10h],rbx
00007FFAC46ACDA9 mov [rsp+18h],rsi
00007FFAC46ACDAE push rbp
00007FFAC46ACDAF push rdi
00007FFAC46ACDB0 push r14
00007FFAC46ACDB2 lea rbp,[rsp-100h]
00007FFAC46ACDBA sub rsp,200h
00007FFAC46ACDC1 mov rax,[rel 7FFAC47524E0h]
00007FFAC46ACDC8 xor rax,rsp
00007FFAC46ACDCB mov [rbp+0F0h],rax
00007FFAC46ACDD2 mov r8,[rel 7FFAC474F208h]
00007FFAC46ACDD9 lea rax,[rel 7FFAC46F4A58h]
00007FFAC46ACDE0 xor edi,edi
Original + patched code:
00007FFAC46ACDA4 mov rax,123456789ABCDEF0h
00007FFAC46ACDAE jmp rax
00007FFAC46ACDB0 push r14
00007FFAC46ACDB2 lea rbp,[rsp-100h]
00007FFAC46ACDBA sub rsp,200h
00007FFAC46ACDC1 mov rax,[rel 7FFAC47524E0h]
00007FFAC46ACDC8 xor rax,rsp
00007FFAC46ACDCB mov [rbp+0F0h],rax
00007FFAC46ACDD2 mov r8,[rel 7FFAC474F208h]
00007FFAC46ACDD9 lea rax,[rel 7FFAC46F4A58h]
00007FFAC46ACDE0 xor edi,edi
Moved code:
00007FFAC48ACDA4 mov [rsp+10h],rbx
00007FFAC48ACDA9 mov [rsp+18h],rsi
00007FFAC48ACDAE push rbp
00007FFAC48ACDAF push rdi
00007FFAC48ACDB0 jmp 00007FFAC46ACDB0h
*/
pub
const EXAMPLE_CODE_BITNESS: u32 = 64;
const EXAMPLE_CODE_RIP: u64 = 0x0000_7FFA_C46A_CDA4;
static EXAMPLE_CODE: & = &;
Get instruction info, eg. read/written regs/mem, control flow info, etc
Shows how to get used registers/memory and other info. It uses Instruction
methods
and an InstructionInfoFactory
to get this info.
use ;
/*
This method produces the following output:
00007FFAC46ACDA4 mov [rsp+10h],rbx
OpCode: o64 89 /r
Instruction: MOV r/m64, r64
Encoding: Legacy
Mnemonic: Mov
Code: Mov_rm64_r64
CpuidFeature: X64
FlowControl: Next
Displacement offset = 4, size = 1
Memory size: 8
Op0Access: Write
Op1Access: Read
Op0: r64_or_mem
Op1: r64_reg
Used reg: RSP:Read
Used reg: RBX:Read
Used mem: [SS:RSP+0x10;UInt64;Write]
00007FFAC46ACDA9 mov [rsp+18h],rsi
OpCode: o64 89 /r
Instruction: MOV r/m64, r64
Encoding: Legacy
Mnemonic: Mov
Code: Mov_rm64_r64
CpuidFeature: X64
FlowControl: Next
Displacement offset = 4, size = 1
Memory size: 8
Op0Access: Write
Op1Access: Read
Op0: r64_or_mem
Op1: r64_reg
Used reg: RSP:Read
Used reg: RSI:Read
Used mem: [SS:RSP+0x18;UInt64;Write]
00007FFAC46ACDAE push rbp
OpCode: o64 50+ro
Instruction: PUSH r64
Encoding: Legacy
Mnemonic: Push
Code: Push_r64
CpuidFeature: X64
FlowControl: Next
SP Increment: -8
Op0Access: Read
Op0: r64_opcode
Used reg: RBP:Read
Used reg: RSP:ReadWrite
Used mem: [SS:RSP+0xFFFFFFFFFFFFFFF8;UInt64;Write]
00007FFAC46ACDAF push rdi
OpCode: o64 50+ro
Instruction: PUSH r64
Encoding: Legacy
Mnemonic: Push
Code: Push_r64
CpuidFeature: X64
FlowControl: Next
SP Increment: -8
Op0Access: Read
Op0: r64_opcode
Used reg: RDI:Read
Used reg: RSP:ReadWrite
Used mem: [SS:RSP+0xFFFFFFFFFFFFFFF8;UInt64;Write]
00007FFAC46ACDB0 push r14
OpCode: o64 50+ro
Instruction: PUSH r64
Encoding: Legacy
Mnemonic: Push
Code: Push_r64
CpuidFeature: X64
FlowControl: Next
SP Increment: -8
Op0Access: Read
Op0: r64_opcode
Used reg: R14:Read
Used reg: RSP:ReadWrite
Used mem: [SS:RSP+0xFFFFFFFFFFFFFFF8;UInt64;Write]
00007FFAC46ACDB2 lea rbp,[rsp-100h]
OpCode: o64 8D /r
Instruction: LEA r64, m
Encoding: Legacy
Mnemonic: Lea
Code: Lea_r64_m
CpuidFeature: X64
FlowControl: Next
Displacement offset = 4, size = 4
Op0Access: Write
Op1Access: NoMemAccess
Op0: r64_reg
Op1: mem
Used reg: RBP:Write
Used reg: RSP:Read
00007FFAC46ACDBA sub rsp,200h
OpCode: o64 81 /5 id
Instruction: SUB r/m64, imm32
Encoding: Legacy
Mnemonic: Sub
Code: Sub_rm64_imm32
CpuidFeature: X64
FlowControl: Next
Immediate offset = 3, size = 4
RFLAGS Written: OF, SF, ZF, AF, CF, PF
RFLAGS Modified: OF, SF, ZF, AF, CF, PF
Op0Access: ReadWrite
Op1Access: Read
Op0: r64_or_mem
Op1: imm32sex64
Used reg: RSP:ReadWrite
00007FFAC46ACDC1 mov rax,[7FFAC47524E0h]
OpCode: o64 8B /r
Instruction: MOV r64, r/m64
Encoding: Legacy
Mnemonic: Mov
Code: Mov_r64_rm64
CpuidFeature: X64
FlowControl: Next
Displacement offset = 3, size = 4
Memory size: 8
Op0Access: Write
Op1Access: Read
Op0: r64_reg
Op1: r64_or_mem
Used reg: RAX:Write
Used mem: [DS:0x7FFAC47524E0;UInt64;Read]
00007FFAC46ACDC8 xor rax,rsp
OpCode: o64 33 /r
Instruction: XOR r64, r/m64
Encoding: Legacy
Mnemonic: Xor
Code: Xor_r64_rm64
CpuidFeature: X64
FlowControl: Next
RFLAGS Written: SF, ZF, PF
RFLAGS Cleared: OF, CF
RFLAGS Undefined: AF
RFLAGS Modified: OF, SF, ZF, AF, CF, PF
Op0Access: ReadWrite
Op1Access: Read
Op0: r64_reg
Op1: r64_or_mem
Used reg: RAX:ReadWrite
Used reg: RSP:Read
00007FFAC46ACDCB mov [rbp+0F0h],rax
OpCode: o64 89 /r
Instruction: MOV r/m64, r64
Encoding: Legacy
Mnemonic: Mov
Code: Mov_rm64_r64
CpuidFeature: X64
FlowControl: Next
Displacement offset = 3, size = 4
Memory size: 8
Op0Access: Write
Op1Access: Read
Op0: r64_or_mem
Op1: r64_reg
Used reg: RBP:Read
Used reg: RAX:Read
Used mem: [SS:RBP+0xF0;UInt64;Write]
00007FFAC46ACDD2 mov r8,[7FFAC474F208h]
OpCode: o64 8B /r
Instruction: MOV r64, r/m64
Encoding: Legacy
Mnemonic: Mov
Code: Mov_r64_rm64
CpuidFeature: X64
FlowControl: Next
Displacement offset = 3, size = 4
Memory size: 8
Op0Access: Write
Op1Access: Read
Op0: r64_reg
Op1: r64_or_mem
Used reg: R8:Write
Used mem: [DS:0x7FFAC474F208;UInt64;Read]
00007FFAC46ACDD9 lea rax,[7FFAC46F4A58h]
OpCode: o64 8D /r
Instruction: LEA r64, m
Encoding: Legacy
Mnemonic: Lea
Code: Lea_r64_m
CpuidFeature: X64
FlowControl: Next
Displacement offset = 3, size = 4
Op0Access: Write
Op1Access: NoMemAccess
Op0: r64_reg
Op1: mem
Used reg: RAX:Write
00007FFAC46ACDE0 xor edi,edi
OpCode: o32 33 /r
Instruction: XOR r32, r/m32
Encoding: Legacy
Mnemonic: Xor
Code: Xor_r32_rm32
CpuidFeature: INTEL386
FlowControl: Next
RFLAGS Cleared: OF, SF, CF
RFLAGS Set: ZF, PF
RFLAGS Undefined: AF
RFLAGS Modified: OF, SF, ZF, AF, CF, PF
Op0Access: Write
Op1Access: None
Op0: r32_reg
Op1: r32_or_mem
Used reg: RDI:Write
*/
pub
const EXAMPLE_CODE_BITNESS: u32 = 64;
const EXAMPLE_CODE_RIP: u64 = 0x0000_7FFA_C46A_CDA4;
static EXAMPLE_CODE: & = &;
Get the virtual address of a memory operand
use ;
pub
Disassemble old/deprecated CPU instructions
use ;
/*
This method produces the following output:
731E0A03 bndmov bnd1, [eax]
731E0A07 mov tr3, esi
731E0A0A rdshr [eax]
731E0A0D dmint
731E0A0F svdc [eax], cs
731E0A12 cpu_read
731E0A14 pmvzb mm1, [eax]
731E0A17 frinear
731E0A19 altinst
*/
pub
Disassemble as fast as possible
For fastest possible disassembly you should set ENABLE_DB_DW_DD_DQ
to false
and you should also override the unsafe verify_output_has_enough_bytes_left()
and return false
.
use ;
pub
Also add this to your Cargo.toml
file:
[]
= 1
= true
= 3
Create and encode instructions
NOTE: It's much easier to just use CodeAssembler
, see the example above.
This example shows how to create instructions without using it.
This example uses a BlockEncoder
to encode created Instruction
s.
use ;
pub
/*
Output:
00001248FC840000 push %rbp
00001248FC840001 push %rdi
00001248FC840002 push %rsi
00001248FC840003 sub $0x50,%rsp
00001248FC84000A vzeroupper
00001248FC84000D lea 0x60(%rsp),%rbp
00001248FC840012 mov %rcx,%rsi
00001248FC840015 lea -0x38(%rbp),%rdi
00001248FC840019 mov $0xA,%ecx
00001248FC84001E xor %eax,%eax
00001248FC840020 rep stos %eax,(%rdi)
00001248FC840022 cmp $0x12345678,%rsi
00001248FC840029 jne 0x00001248FC84002C
00001248FC84002B nop
00001248FC84002C xor %r15d,%r15d
00001248FC84002F lea 0x1248FC840037,%r14
00001248FC840036 nop
00001248FC840037 .byte 0x12,0x34,0x56,0x78
*/
Minimum supported rustc
version
iced-x86 supports rustc
1.57.0
or later.
This is checked in CI builds where the minimum supported version and the latest stable version are used to build the source code and run tests.
Bumping the minimum supported version of rustc
is considered a minor breaking change. The minor version of iced-x86 will be incremented.