ffi-udis86 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +8 -0
- data/.specopts +1 -0
- data/.yardopts +1 -0
- data/ChangeLog.md +10 -0
- data/LICENSE.txt +22 -0
- data/README.md +60 -0
- data/Rakefile +42 -0
- data/ffi-udis86.gemspec +88 -0
- data/lib/udis86.rb +4 -0
- data/lib/udis86/ffi.rb +30 -0
- data/lib/udis86/operand.rb +174 -0
- data/lib/udis86/operand_pointer.rb +36 -0
- data/lib/udis86/operand_value.rb +136 -0
- data/lib/udis86/types.rb +942 -0
- data/lib/udis86/ud.rb +563 -0
- data/lib/udis86/version.rb +6 -0
- data/spec/helpers/files.rb +11 -0
- data/spec/helpers/files/operands_index_scale +1 -0
- data/spec/helpers/files/operands_index_scale.s +2 -0
- data/spec/helpers/files/operands_memory +1 -0
- data/spec/helpers/files/operands_memory.s +2 -0
- data/spec/helpers/files/operands_offset +1 -0
- data/spec/helpers/files/operands_offset.s +2 -0
- data/spec/helpers/files/operands_simple +0 -0
- data/spec/helpers/files/operands_simple.s +2 -0
- data/spec/helpers/files/simple +1 -0
- data/spec/helpers/files/simple.s +4 -0
- data/spec/helpers/operands.rb +14 -0
- data/spec/operand_spec.rb +72 -0
- data/spec/spec_helper.rb +8 -0
- data/spec/ud_spec.rb +195 -0
- data/spec/udis86_spec.rb +25 -0
- metadata +122 -0
data/.gitignore
ADDED
data/.specopts
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--colour --format specdoc
|
data/.yardopts
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--markup markdown --title 'FFI UDis86 Documentation' --protected --files ChangeLog.md,LICENSE.txt
|
data/ChangeLog.md
ADDED
@@ -0,0 +1,10 @@
|
|
1
|
+
### 0.1.0 / 2010-02-19
|
2
|
+
|
3
|
+
* Initial release:
|
4
|
+
* Supports x86 and x86-64 instructions.
|
5
|
+
* Supports 16 and 32 disassembly modes.
|
6
|
+
* Supports Intel and ATT syntax output.
|
7
|
+
* Supports disassembling files and arbitrary input.
|
8
|
+
* Supports using input buffers.
|
9
|
+
* Supports using input callbacks.
|
10
|
+
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
|
2
|
+
Copyright (c) 2009-2010 Hal Brodigan
|
3
|
+
|
4
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
5
|
+
a copy of this software and associated documentation files (the
|
6
|
+
'Software'), to deal in the Software without restriction, including
|
7
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
8
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
9
|
+
permit persons to whom the Software is furnished to do so, subject to
|
10
|
+
the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be
|
13
|
+
included in all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
16
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
17
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
18
|
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
19
|
+
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
20
|
+
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
21
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
22
|
+
|
data/README.md
ADDED
@@ -0,0 +1,60 @@
|
|
1
|
+
# ffi-udis86
|
2
|
+
|
3
|
+
* [github.com/sophsec/ffi-udis86](http://github.com/sophsec/ffi-udis86/)
|
4
|
+
* [github.com/sophsec/ffi-udis86/issue](http://github.com/sophsec/ffi-udis86/)
|
5
|
+
* Postmodern (postmodern.mod3 at gmail.com)
|
6
|
+
|
7
|
+
## Description
|
8
|
+
|
9
|
+
Ruby FFI bindings for udis86, a x86 and x86-64 disassembler.
|
10
|
+
|
11
|
+
## Features
|
12
|
+
|
13
|
+
* Supports x86 and x86-64 instructions.
|
14
|
+
* Supports 16 and 32 disassembly modes.
|
15
|
+
* Supports Intel and ATT syntax output.
|
16
|
+
* Supports disassembling files and arbitrary input.
|
17
|
+
* Supports using input buffers.
|
18
|
+
* Supports using input callbacks.
|
19
|
+
|
20
|
+
## Examples
|
21
|
+
|
22
|
+
Create a new disassembler:
|
23
|
+
|
24
|
+
include FFI::UDis86
|
25
|
+
|
26
|
+
ud = UD.create(:syntax => :att, :mode => 64)
|
27
|
+
|
28
|
+
Set the input buffer:
|
29
|
+
|
30
|
+
ud.input_buffer = "\x90\x90\xc3"
|
31
|
+
|
32
|
+
Add an input callback:
|
33
|
+
|
34
|
+
ud.input_callback { |ud| ops.shift || -1 }
|
35
|
+
|
36
|
+
Read a file:
|
37
|
+
|
38
|
+
UD.open(path) do |ud|
|
39
|
+
...
|
40
|
+
end
|
41
|
+
|
42
|
+
Disassemble and print instructions:
|
43
|
+
|
44
|
+
ud.disas do |insn|
|
45
|
+
puts insn
|
46
|
+
end
|
47
|
+
|
48
|
+
## Requirements
|
49
|
+
|
50
|
+
* [udis86](http://udis86.sourceforge.net/) >= 1.7
|
51
|
+
* [ffi](http://github.com/ffi/ffi) >= 0.6.2
|
52
|
+
|
53
|
+
## Install
|
54
|
+
|
55
|
+
$ sudo gem install ffi-udis86
|
56
|
+
|
57
|
+
## License
|
58
|
+
|
59
|
+
See {file:LICENSE.txt} for license information.
|
60
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
require './lib/udis86/version.rb'
|
4
|
+
|
5
|
+
begin
|
6
|
+
require 'jeweler'
|
7
|
+
Jeweler::Tasks.new do |gem|
|
8
|
+
gem.name = 'ffi-udis86'
|
9
|
+
gem.version = FFI::UDis86::VERSION
|
10
|
+
gem.summary = %Q{Ruby FFI bindings for udis86, a x86 and x86-64 disassembler.}
|
11
|
+
gem.description = %Q{Ruby FFI bindings for udis86, a x86 and x86-64 disassembler.}
|
12
|
+
gem.email = 'postmodern.mod3@gmail.com'
|
13
|
+
gem.homepage = 'http://github.com/sophsec/ffi-udis86'
|
14
|
+
gem.authors = ['Postmodern']
|
15
|
+
gem.add_dependency 'ffi', '>= 0.6.2'
|
16
|
+
gem.add_development_dependency 'rspec', '>= 1.3.0'
|
17
|
+
gem.add_development_dependency 'yard', '>= 0.5.3'
|
18
|
+
gem.has_rdoc = 'yard'
|
19
|
+
end
|
20
|
+
rescue LoadError
|
21
|
+
puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
|
22
|
+
end
|
23
|
+
|
24
|
+
require 'spec/rake/spectask'
|
25
|
+
Spec::Rake::SpecTask.new(:spec) do |spec|
|
26
|
+
spec.libs += ['lib', 'spec']
|
27
|
+
spec.spec_files = FileList['spec/**/*_spec.rb']
|
28
|
+
spec.spec_opts = ['--options', '.specopts']
|
29
|
+
end
|
30
|
+
|
31
|
+
task :spec => :check_dependencies
|
32
|
+
task :default => :spec
|
33
|
+
|
34
|
+
begin
|
35
|
+
require 'yard'
|
36
|
+
|
37
|
+
YARD::Rake::YardocTask.new
|
38
|
+
rescue LoadError
|
39
|
+
task :yard do
|
40
|
+
abort "YARD is not available. In order to run yard, you must: gem install yard"
|
41
|
+
end
|
42
|
+
end
|
data/ffi-udis86.gemspec
ADDED
@@ -0,0 +1,88 @@
|
|
1
|
+
# Generated by jeweler
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
|
4
|
+
# -*- encoding: utf-8 -*-
|
5
|
+
|
6
|
+
Gem::Specification.new do |s|
|
7
|
+
s.name = %q{ffi-udis86}
|
8
|
+
s.version = "0.1.0"
|
9
|
+
|
10
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
+
s.authors = ["Postmodern"]
|
12
|
+
s.date = %q{2010-02-19}
|
13
|
+
s.description = %q{Ruby FFI bindings for udis86, a x86 and x86-64 disassembler.}
|
14
|
+
s.email = %q{postmodern.mod3@gmail.com}
|
15
|
+
s.extra_rdoc_files = [
|
16
|
+
"ChangeLog.md",
|
17
|
+
"LICENSE.txt",
|
18
|
+
"README.md"
|
19
|
+
]
|
20
|
+
s.files = [
|
21
|
+
".gitignore",
|
22
|
+
".specopts",
|
23
|
+
".yardopts",
|
24
|
+
"ChangeLog.md",
|
25
|
+
"LICENSE.txt",
|
26
|
+
"README.md",
|
27
|
+
"Rakefile",
|
28
|
+
"ffi-udis86.gemspec",
|
29
|
+
"lib/udis86.rb",
|
30
|
+
"lib/udis86/ffi.rb",
|
31
|
+
"lib/udis86/operand.rb",
|
32
|
+
"lib/udis86/operand_pointer.rb",
|
33
|
+
"lib/udis86/operand_value.rb",
|
34
|
+
"lib/udis86/types.rb",
|
35
|
+
"lib/udis86/ud.rb",
|
36
|
+
"lib/udis86/version.rb",
|
37
|
+
"spec/helpers/files.rb",
|
38
|
+
"spec/helpers/files/operands_index_scale",
|
39
|
+
"spec/helpers/files/operands_index_scale.s",
|
40
|
+
"spec/helpers/files/operands_memory",
|
41
|
+
"spec/helpers/files/operands_memory.s",
|
42
|
+
"spec/helpers/files/operands_offset",
|
43
|
+
"spec/helpers/files/operands_offset.s",
|
44
|
+
"spec/helpers/files/operands_simple",
|
45
|
+
"spec/helpers/files/operands_simple.s",
|
46
|
+
"spec/helpers/files/simple",
|
47
|
+
"spec/helpers/files/simple.s",
|
48
|
+
"spec/helpers/operands.rb",
|
49
|
+
"spec/operand_spec.rb",
|
50
|
+
"spec/spec_helper.rb",
|
51
|
+
"spec/ud_spec.rb",
|
52
|
+
"spec/udis86_spec.rb"
|
53
|
+
]
|
54
|
+
s.has_rdoc = %q{yard}
|
55
|
+
s.homepage = %q{http://github.com/sophsec/ffi-udis86}
|
56
|
+
s.rdoc_options = ["--charset=UTF-8"]
|
57
|
+
s.require_paths = ["lib"]
|
58
|
+
s.rubygems_version = %q{1.3.5}
|
59
|
+
s.summary = %q{Ruby FFI bindings for udis86, a x86 and x86-64 disassembler.}
|
60
|
+
s.test_files = [
|
61
|
+
"spec/spec_helper.rb",
|
62
|
+
"spec/udis86_spec.rb",
|
63
|
+
"spec/ud_spec.rb",
|
64
|
+
"spec/helpers/files.rb",
|
65
|
+
"spec/helpers/operands.rb",
|
66
|
+
"spec/operand_spec.rb"
|
67
|
+
]
|
68
|
+
|
69
|
+
if s.respond_to? :specification_version then
|
70
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
71
|
+
s.specification_version = 3
|
72
|
+
|
73
|
+
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
74
|
+
s.add_runtime_dependency(%q<ffi>, [">= 0.6.2"])
|
75
|
+
s.add_development_dependency(%q<rspec>, [">= 1.3.0"])
|
76
|
+
s.add_development_dependency(%q<yard>, [">= 0.5.3"])
|
77
|
+
else
|
78
|
+
s.add_dependency(%q<ffi>, [">= 0.6.2"])
|
79
|
+
s.add_dependency(%q<rspec>, [">= 1.3.0"])
|
80
|
+
s.add_dependency(%q<yard>, [">= 0.5.3"])
|
81
|
+
end
|
82
|
+
else
|
83
|
+
s.add_dependency(%q<ffi>, [">= 0.6.2"])
|
84
|
+
s.add_dependency(%q<rspec>, [">= 1.3.0"])
|
85
|
+
s.add_dependency(%q<yard>, [">= 0.5.3"])
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
data/lib/udis86.rb
ADDED
data/lib/udis86/ffi.rb
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'udis86/types'
|
2
|
+
require 'udis86/ud'
|
3
|
+
|
4
|
+
require 'ffi'
|
5
|
+
|
6
|
+
module FFI
|
7
|
+
module UDis86
|
8
|
+
extend FFI::Library
|
9
|
+
|
10
|
+
ffi_lib 'libudis86'
|
11
|
+
|
12
|
+
attach_function :ud_init, [:pointer], :void
|
13
|
+
attach_function :ud_set_input_hook, [:pointer, :ud_input_callback], :void
|
14
|
+
attach_function :ud_set_input_buffer, [:pointer, :pointer, :size_t], :void
|
15
|
+
attach_function :ud_set_mode, [:pointer, :uint8], :void
|
16
|
+
attach_function :ud_set_pc, [:pointer, :uint64], :void
|
17
|
+
attach_function :ud_translate_att, [:pointer], :void
|
18
|
+
attach_function :ud_translate_intel, [:pointer], :void
|
19
|
+
attach_function :ud_set_syntax, [:pointer, :ud_translator_callback], :void
|
20
|
+
attach_function :ud_set_vendor, [:pointer, :uint8], :void
|
21
|
+
attach_function :ud_disassemble, [:pointer], :uint
|
22
|
+
attach_function :ud_insn_len, [:pointer], :uint
|
23
|
+
attach_function :ud_insn_off, [:pointer], :uint64
|
24
|
+
attach_function :ud_insn_hex, [:pointer], :string
|
25
|
+
attach_function :ud_insn_ptr, [:pointer], :pointer
|
26
|
+
attach_function :ud_insn_asm, [:pointer], :string
|
27
|
+
attach_function :ud_input_skip, [:pointer, :size_t], :void
|
28
|
+
attach_function :ud_lookup_mnemonic, [:ud_mnemonic_code], :string
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,174 @@
|
|
1
|
+
require 'udis86/operand_value'
|
2
|
+
require 'udis86/types'
|
3
|
+
|
4
|
+
require 'ffi'
|
5
|
+
|
6
|
+
module FFI
|
7
|
+
module UDis86
|
8
|
+
class Operand < FFI::Struct
|
9
|
+
|
10
|
+
layout :type, :ud_type,
|
11
|
+
:size, :uint8,
|
12
|
+
:value, OperandValue,
|
13
|
+
:base, :ud_type,
|
14
|
+
:index, :ud_type,
|
15
|
+
:offset, :uint8,
|
16
|
+
:scale, :uint8
|
17
|
+
|
18
|
+
#
|
19
|
+
# The type of the operand.
|
20
|
+
#
|
21
|
+
# @return [Integer]
|
22
|
+
# The type of the operand.
|
23
|
+
#
|
24
|
+
def type
|
25
|
+
self[:type]
|
26
|
+
end
|
27
|
+
|
28
|
+
#
|
29
|
+
# Determines if the operand is a memory access.
|
30
|
+
#
|
31
|
+
# @return [Boolean]
|
32
|
+
# Specifies whether the operand is a memory access.
|
33
|
+
#
|
34
|
+
def is_mem?
|
35
|
+
self[:type] == :ud_op_mem
|
36
|
+
end
|
37
|
+
|
38
|
+
#
|
39
|
+
# Determines if the operand is Segment:Offset pointer.
|
40
|
+
#
|
41
|
+
# @return [Boolean]
|
42
|
+
# Specifies whether the operand is Segment:Offset pointer.
|
43
|
+
#
|
44
|
+
def is_seg_ptr?
|
45
|
+
self[:type] == :ud_op_ptr
|
46
|
+
end
|
47
|
+
|
48
|
+
#
|
49
|
+
# Determines if the operand is immediate data.
|
50
|
+
#
|
51
|
+
# @return [Boolean]
|
52
|
+
# Specifies whether the operand is immediate data.
|
53
|
+
#
|
54
|
+
def is_imm?
|
55
|
+
self[:type] == :ud_op_imm
|
56
|
+
end
|
57
|
+
|
58
|
+
#
|
59
|
+
# Determines if the operand is a relative offset used in a jump.
|
60
|
+
#
|
61
|
+
# @return [Boolean]
|
62
|
+
# Specifies whether the operand is a relative offset.
|
63
|
+
#
|
64
|
+
def is_jmp_imm?
|
65
|
+
self[:type] == :ud_op_jimm
|
66
|
+
end
|
67
|
+
|
68
|
+
#
|
69
|
+
# Determines if the operand is a data constant.
|
70
|
+
#
|
71
|
+
# @return [Boolean]
|
72
|
+
# Specifies whether the operand is a data constant.
|
73
|
+
#
|
74
|
+
def is_const?
|
75
|
+
self[:type] == :ud_op_const
|
76
|
+
end
|
77
|
+
|
78
|
+
#
|
79
|
+
# Determines if the operand is a register.
|
80
|
+
#
|
81
|
+
# @return [Boolean]
|
82
|
+
# Specifies whether the operand is a register.
|
83
|
+
#
|
84
|
+
def is_reg?
|
85
|
+
self[:type] == :ud_op_reg
|
86
|
+
end
|
87
|
+
|
88
|
+
#
|
89
|
+
# The size of the operand.
|
90
|
+
#
|
91
|
+
# @return [Integer]
|
92
|
+
# The size of the operand in bytes.
|
93
|
+
#
|
94
|
+
def size
|
95
|
+
self[:size]
|
96
|
+
end
|
97
|
+
|
98
|
+
#
|
99
|
+
# The value of the operand.
|
100
|
+
#
|
101
|
+
# @return [OperandValue, OperandPointer]
|
102
|
+
# The value of the operand. If the operand represents a pointer,
|
103
|
+
# an OperandPointer object will be returned.
|
104
|
+
#
|
105
|
+
def value
|
106
|
+
case type
|
107
|
+
when :ud_op_ptr
|
108
|
+
return self[:value].ptr
|
109
|
+
when :ud_op_reg
|
110
|
+
return nil
|
111
|
+
else
|
112
|
+
return self[:value]
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
#
|
117
|
+
# The base address used by the operand.
|
118
|
+
#
|
119
|
+
# @return [Integer]
|
120
|
+
# The base address of the operand.
|
121
|
+
#
|
122
|
+
def base
|
123
|
+
REGS[self[:base]]
|
124
|
+
end
|
125
|
+
|
126
|
+
alias reg base
|
127
|
+
|
128
|
+
#
|
129
|
+
# The index value used by the operand.
|
130
|
+
#
|
131
|
+
# @return [Integer]
|
132
|
+
# The index value of the operand.
|
133
|
+
#
|
134
|
+
def index
|
135
|
+
REGS[self[:index]]
|
136
|
+
end
|
137
|
+
|
138
|
+
#
|
139
|
+
# The offset value used by the operand.
|
140
|
+
#
|
141
|
+
# @return [OperandValue, 0]
|
142
|
+
# The offset value of the operand.
|
143
|
+
#
|
144
|
+
def offset
|
145
|
+
if self[:offset] > 0
|
146
|
+
return self[:value]
|
147
|
+
else
|
148
|
+
return 0
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
#
|
153
|
+
# The word-length of the offset used with the operand.
|
154
|
+
#
|
155
|
+
# @return [Integer]
|
156
|
+
# Word-length of the offset being used.
|
157
|
+
#
|
158
|
+
def offset_size
|
159
|
+
self[:offset]
|
160
|
+
end
|
161
|
+
|
162
|
+
#
|
163
|
+
# The scale value used by the operand.
|
164
|
+
#
|
165
|
+
# @return [Integer]
|
166
|
+
# The scale value of the operand.
|
167
|
+
#
|
168
|
+
def scale
|
169
|
+
self[:scale]
|
170
|
+
end
|
171
|
+
|
172
|
+
end
|
173
|
+
end
|
174
|
+
end
|