Skip to content

zyantific/zydis-go

Repository files navigation

zydis logo Go

License: MIT GitHub Actions Gitter Discord

Fast and lightweight x86/x86-64 disassembler and code generation library.

Features

  • Optimized for high performance, runs almost as fast as native Zydis
  • No dependencies on Cgo
  • Thread-safe by design
  • Very small file-size overhead compared to other common disassembler libraries
  • Supports all x86 and x86-64 (AMD64) instructions

Examples

Disassembler

The following example program uses Zydis to disassemble a given memory buffer and prints the output to the console.

data := []byte{
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,
}
// The runtime address (instruction pointer) was chosen arbitrarily here in order to better
// visualize relative addressing. In your actual program, set this to e.g. the memory address
// that the code being disassembled was read from.
runtimeAddress := uintptr(0x007FFFFFFF400000)
// Loop over the instructions in our buffer.
offset := 0
insn := zydis.DisassembledInstruction{}
for offset < len(data) {
status := zydis.DisassembleIntel(
zydis.MACHINE_MODE_LONG_64,
uint64(runtimeAddress),
unsafe.Pointer(&data[offset]),
uint64(len(data)-offset),
&insn,
)
if !zydis.Ok(status) {
break
}
textEnd := bytes.IndexByte(insn.Text[:], 0)
fmt.Printf("%016X %s\n", runtimeAddress, string(insn.Text[:textEnd]))
offset += int(insn.Info.Length)
runtimeAddress += uintptr(insn.Info.Length)
}

The above example program generates the following output:

007FFFFFFF400000  push rcx
007FFFFFFF400001  lea eax, [rbp-0x01]
007FFFFFFF400004  push rax
007FFFFFFF400005  push [rbp+0x0C]
007FFFFFFF400008  push [rbp+0x08]
007FFFFFFF40000B  call [0x008000007588A5B1]
007FFFFFFF400011  test eax, eax
007FFFFFFF400013  js 0x007FFFFFFF42DB15

Encoder

req := zydis.EncoderRequest{
Mnemonic: zydis.MNEMONIC_MOV,
MachineMode: zydis.MACHINE_MODE_LONG_64,
OperandCount: 2,
Operands: [5]zydis.EncoderOperand{
{Type: zydis.OPERAND_TYPE_REGISTER},
{Type: zydis.OPERAND_TYPE_IMMEDIATE},
},
}
req.Operands[0].Reg.Value = zydis.REGISTER_RAX
req.Operands[1].Imm.SetU(0x1337)
encodedInsn := [16]byte{}
encodedLength := uint64(len(encodedInsn))
if !zydis.Ok(req.EncodeInstruction(unsafe.Pointer(&encodedInsn[0]), &encodedLength)) {
fmt.Println("Failed to encode instruction")
return
}
for i := uint64(0); i < encodedLength; i++ {
fmt.Printf("%02X ", encodedInsn[i])
}

The above example program generates the following output:

48 C7 C0 37 13 00 00

More Examples

More examples can be found in the examples directory of this repository.

Build

Simply get the package using go get:

go get -u github.com/zyantific/zydis-go

If you are not on Windows AMD64 or Linux AMD64, you need to build the Zydis library for your platform and place the shared library nearby your executable. You can find the instructions for building the Zydis library here.

License

zydis-go is licensed under the MIT license, Zydis's license also applies under the same terms. See LICENSE.md for more information.

About

Pure Go bindings for Zydis.

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages