Module: PWN::FFI::Capstone

Extended by:
Library
Defined in:
lib/pwn/ffi/capstone.rb

Overview

Thin libcapstone disassembler.

Defined Under Namespace

Classes: InsnV4, InsnV5

Constant Summary collapse

CS_ARCH_ARM =
0
CS_ARCH_ARM64 =
1
CS_ARCH_X86 =
3
CS_MODE_LITTLE_ENDIAN =
0
CS_MODE_32 =
4
CS_MODE_64 =
8

Class Attribute Summary collapse

Class Method Summary collapse

Class Attribute Details

.load_error ⇒ Object (readonly)

Returns the value of attribute load_error.



51
52
53
# File 'lib/pwn/ffi/capstone.rb', line 51

def load_error
  @load_error
end

Class Method Details

.authors ⇒ Object



114
115
116
# File 'lib/pwn/ffi/capstone.rb', line 114

public_class_method def self.authors
  "AUTHOR(S):\n  0day Inc. <[email protected]>\n"
end

.available?(opts = {}) ⇒ Boolean

Returns:

  • (Boolean)


62
63
64
65
# File 'lib/pwn/ffi/capstone.rb', line 62

public_class_method def self.available?(opts = {})
  opts[:mod]
  load_error.nil?
end

.disassemble(opts = {}) ⇒ Object



67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
# File 'lib/pwn/ffi/capstone.rb', line 67

public_class_method def self.disassemble(opts = {})
  raise 'ERROR: libcapstone not available' unless available?(mod: self)

  raw = opts[:bytes] || opts[:opcodes]
  raise 'ERROR: bytes is required' if raw.to_s.empty?

  bytes = raw.to_s.b
  arch, mode = arch_mode(arch: opts[:arch], endian: opts[:endian])
  handle = PubFFI::MemoryPointer.new(:size_t)
  raise 'ERROR: cs_open failed' unless cs_open(arch, mode, handle).zero?

  buf = PubFFI::MemoryPointer.from_string(bytes)
  insn_ptr = PubFFI::MemoryPointer.new(:pointer)
  count = cs_disasm(handle.read_ulong, buf, bytes.bytesize, (opts[:address] || 0).to_i, 0, insn_ptr)
  insns = []
  base = insn_ptr.read_pointer
  klass = insn_class
  count.times do |i|
    insn = klass.new(base + (i * klass.size))
    insns << { address: insn[:address], mnemonic: insn[:mnemonic].to_s, op_str: insn[:op_str].to_s, size: insn[:size] }
  end
  cs_free(base, count) unless base.null?
  cs_close(handle)
  { engine: 'capstone', insns: insns, count: count }
end

.help ⇒ Object



118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
# File 'lib/pwn/ffi/capstone.rb', line 118

public_class_method def self.help
  puts "USAGE:
    # True when libcapstone is loadable.
    #{self}.available?(
      mod: 'optional - ignored; present so (opts = {}) reads opts['
    )

    # Disassemble bytes with Capstone.
    #{self}.disassemble(
      bytes: 'required - raw machine-code bytes',
      opcodes: 'optional - alias for bytes',
      arch: 'optional - x86_64|x86|arm|aarch64',
      endian: 'optional - :little or :big byte order',
      address: 'optional - start address'
    )

    # Print the AUTHOR(S) string for this module.
    #{self}.authors
  "
  constants.sort
end