ronin-asm 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.document +4 -0
- data/.gemtest +0 -0
- data/.gitignore +11 -0
- data/.rspec +1 -0
- data/.yardopts +1 -0
- data/COPYING.txt +674 -0
- data/ChangeLog.md +10 -0
- data/Gemfile +19 -0
- data/README.md +142 -0
- data/Rakefile +44 -0
- data/data/ronin/asm/freebsd/amd64/syscalls.yml +415 -0
- data/data/ronin/asm/freebsd/x86/syscalls.yml +415 -0
- data/data/ronin/asm/linux/amd64/syscalls.yml +306 -0
- data/data/ronin/asm/linux/x86/syscalls.yml +339 -0
- data/data/ronin/gen/asm/source_file.s.erb +4 -0
- data/gemspec.yml +20 -0
- data/lib/ronin/asm.rb +25 -0
- data/lib/ronin/asm/archs.rb +23 -0
- data/lib/ronin/asm/archs/amd64.rb +99 -0
- data/lib/ronin/asm/archs/x86.rb +166 -0
- data/lib/ronin/asm/asm.rb +66 -0
- data/lib/ronin/asm/config.rb +39 -0
- data/lib/ronin/asm/immediate_operand.rb +76 -0
- data/lib/ronin/asm/instruction.rb +65 -0
- data/lib/ronin/asm/memory_operand.rb +109 -0
- data/lib/ronin/asm/os.rb +24 -0
- data/lib/ronin/asm/os/freebsd.rb +34 -0
- data/lib/ronin/asm/os/linux.rb +34 -0
- data/lib/ronin/asm/os/os.rb +40 -0
- data/lib/ronin/asm/program.rb +476 -0
- data/lib/ronin/asm/register.rb +110 -0
- data/lib/ronin/asm/shellcode.rb +70 -0
- data/lib/ronin/asm/syntax.rb +23 -0
- data/lib/ronin/asm/syntax/att.rb +136 -0
- data/lib/ronin/asm/syntax/common.rb +202 -0
- data/lib/ronin/asm/syntax/intel.rb +150 -0
- data/lib/ronin/asm/version.rb +27 -0
- data/ronin-asm.gemspec +61 -0
- data/spec/asm_spec.rb +8 -0
- data/spec/helpers/database.rb +7 -0
- data/spec/immediate_operand_spec.rb +77 -0
- data/spec/instruction_spec.rb +62 -0
- data/spec/memory_operand_spec.rb +80 -0
- data/spec/program_spec.rb +365 -0
- data/spec/register_spec.rb +110 -0
- data/spec/shellcode_spec.rb +34 -0
- data/spec/spec_helper.rb +10 -0
- data/spec/syntax/att_spec.rb +171 -0
- data/spec/syntax/common_spec.rb +42 -0
- data/spec/syntax/intel_spec.rb +156 -0
- metadata +163 -0
data/lib/ronin/asm/os.rb
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
#
|
2
|
+
# Ronin ASM - A Ruby DSL for crafting Assembly programs and Shellcode.
|
3
|
+
#
|
4
|
+
# Copyright (c) 2007-2012 Hal Brodigan (postmodern.mod3 at gmail.com)
|
5
|
+
#
|
6
|
+
# This file is part of Ronin ASM.
|
7
|
+
#
|
8
|
+
# Ronin is free software: you can redistribute it and/or modify
|
9
|
+
# it under the terms of the GNU General Public License as published by
|
10
|
+
# the Free Software Foundation, either version 3 of the License, or
|
11
|
+
# (at your option) any later version.
|
12
|
+
#
|
13
|
+
# Ronin is distributed in the hope that it will be useful,
|
14
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
15
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
16
|
+
# GNU General Public License for more details.
|
17
|
+
#
|
18
|
+
# You should have received a copy of the GNU General Public License
|
19
|
+
# along with Ronin. If not, see <http://www.gnu.org/licenses/>
|
20
|
+
#
|
21
|
+
|
22
|
+
require 'ronin/asm/os/os'
|
23
|
+
require 'ronin/asm/os/freebsd'
|
24
|
+
require 'ronin/asm/os/linux'
|
@@ -0,0 +1,34 @@
|
|
1
|
+
#
|
2
|
+
# Ronin ASM - A Ruby DSL for crafting Assembly programs and Shellcode.
|
3
|
+
#
|
4
|
+
# Copyright (c) 2007-2012 Hal Brodigan (postmodern.mod3 at gmail.com)
|
5
|
+
#
|
6
|
+
# This file is part of Ronin ASM.
|
7
|
+
#
|
8
|
+
# Ronin is free software: you can redistribute it and/or modify
|
9
|
+
# it under the terms of the GNU General Public License as published by
|
10
|
+
# the Free Software Foundation, either version 3 of the License, or
|
11
|
+
# (at your option) any later version.
|
12
|
+
#
|
13
|
+
# Ronin is distributed in the hope that it will be useful,
|
14
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
15
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
16
|
+
# GNU General Public License for more details.
|
17
|
+
#
|
18
|
+
# You should have received a copy of the GNU General Public License
|
19
|
+
# along with Ronin. If not, see <http://www.gnu.org/licenses/>
|
20
|
+
#
|
21
|
+
|
22
|
+
require 'ronin/asm/config'
|
23
|
+
|
24
|
+
module Ronin
|
25
|
+
module ASM
|
26
|
+
module OS
|
27
|
+
#
|
28
|
+
# Contains FreeBSD specific helper methods.
|
29
|
+
#
|
30
|
+
module FreeBSD
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
#
|
2
|
+
# Ronin ASM - A Ruby DSL for crafting Assembly programs and Shellcode.
|
3
|
+
#
|
4
|
+
# Copyright (c) 2007-2012 Hal Brodigan (postmodern.mod3 at gmail.com)
|
5
|
+
#
|
6
|
+
# This file is part of Ronin ASM.
|
7
|
+
#
|
8
|
+
# Ronin is free software: you can redistribute it and/or modify
|
9
|
+
# it under the terms of the GNU General Public License as published by
|
10
|
+
# the Free Software Foundation, either version 3 of the License, or
|
11
|
+
# (at your option) any later version.
|
12
|
+
#
|
13
|
+
# Ronin is distributed in the hope that it will be useful,
|
14
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
15
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
16
|
+
# GNU General Public License for more details.
|
17
|
+
#
|
18
|
+
# You should have received a copy of the GNU General Public License
|
19
|
+
# along with Ronin. If not, see <http://www.gnu.org/licenses/>
|
20
|
+
#
|
21
|
+
|
22
|
+
require 'ronin/asm/config'
|
23
|
+
|
24
|
+
module Ronin
|
25
|
+
module ASM
|
26
|
+
module OS
|
27
|
+
#
|
28
|
+
# Contains Linux specific helper methods.
|
29
|
+
#
|
30
|
+
module Linux
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
#
|
2
|
+
# Ronin ASM - A Ruby DSL for crafting Assembly programs and Shellcode.
|
3
|
+
#
|
4
|
+
# Copyright (c) 2007-2012 Hal Brodigan (postmodern.mod3 at gmail.com)
|
5
|
+
#
|
6
|
+
# This file is part of Ronin ASM.
|
7
|
+
#
|
8
|
+
# Ronin is free software: you can redistribute it and/or modify
|
9
|
+
# it under the terms of the GNU General Public License as published by
|
10
|
+
# the Free Software Foundation, either version 3 of the License, or
|
11
|
+
# (at your option) any later version.
|
12
|
+
#
|
13
|
+
# Ronin is distributed in the hope that it will be useful,
|
14
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
15
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
16
|
+
# GNU General Public License for more details.
|
17
|
+
#
|
18
|
+
# You should have received a copy of the GNU General Public License
|
19
|
+
# along with Ronin. If not, see <http://www.gnu.org/licenses/>
|
20
|
+
#
|
21
|
+
|
22
|
+
require 'ronin/asm/config'
|
23
|
+
|
24
|
+
module Ronin
|
25
|
+
module ASM
|
26
|
+
module OS
|
27
|
+
#
|
28
|
+
# Collection of all known syscalls, grouped by OS and Arch.
|
29
|
+
#
|
30
|
+
# @return [Hash{Symbol => Hash{Symbol => Hash{Symbol => Integer}}}]
|
31
|
+
# Syscall names and numbers, organized by OS then Arch.
|
32
|
+
#
|
33
|
+
SYSCALLS = Hash.new do |hash,os|
|
34
|
+
hash[os] = Hash.new do |subhash,arch|
|
35
|
+
subhash[arch] = Config.load_yaml_file(File.join(Config::DATA_DIR,os.to_s.downcase,arch.to_s,'syscalls.yml'))
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,476 @@
|
|
1
|
+
#
|
2
|
+
# Ronin ASM - A Ruby DSL for crafting Assembly programs and Shellcode.
|
3
|
+
#
|
4
|
+
# Copyright (c) 2007-2012 Hal Brodigan (postmodern.mod3 at gmail.com)
|
5
|
+
#
|
6
|
+
# This file is part of Ronin ASM.
|
7
|
+
#
|
8
|
+
# Ronin is free software: you can redistribute it and/or modify
|
9
|
+
# it under the terms of the GNU General Public License as published by
|
10
|
+
# the Free Software Foundation, either version 3 of the License, or
|
11
|
+
# (at your option) any later version.
|
12
|
+
#
|
13
|
+
# Ronin is distributed in the hope that it will be useful,
|
14
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
15
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
16
|
+
# GNU General Public License for more details.
|
17
|
+
#
|
18
|
+
# You should have received a copy of the GNU General Public License
|
19
|
+
# along with Ronin. If not, see <http://www.gnu.org/licenses/>
|
20
|
+
#
|
21
|
+
|
22
|
+
require 'ronin/asm/archs'
|
23
|
+
require 'ronin/asm/os'
|
24
|
+
require 'ronin/asm/register'
|
25
|
+
require 'ronin/asm/instruction'
|
26
|
+
require 'ronin/asm/immediate_operand'
|
27
|
+
require 'ronin/asm/syntax'
|
28
|
+
|
29
|
+
require 'tempfile'
|
30
|
+
require 'yasm/program'
|
31
|
+
|
32
|
+
module Ronin
|
33
|
+
module ASM
|
34
|
+
#
|
35
|
+
# Represents a full Assembly program.
|
36
|
+
#
|
37
|
+
class Program
|
38
|
+
|
39
|
+
# Supported Assembly Syntaxs
|
40
|
+
SYNTAX = {
|
41
|
+
:att => Syntax::ATT,
|
42
|
+
:intel => Syntax::Intel
|
43
|
+
}
|
44
|
+
|
45
|
+
# The Assembly Parsers
|
46
|
+
PARSERS = {
|
47
|
+
:att => :gas,
|
48
|
+
:intel => :nasm
|
49
|
+
}
|
50
|
+
|
51
|
+
# The targeted architecture
|
52
|
+
attr_reader :arch
|
53
|
+
|
54
|
+
# The targeted Operating System
|
55
|
+
attr_reader :os
|
56
|
+
|
57
|
+
# The default word size
|
58
|
+
attr_reader :word_size
|
59
|
+
|
60
|
+
# The registers available to the program
|
61
|
+
#
|
62
|
+
# @return [Hash{Symbol => Register}]
|
63
|
+
# The names and registers.
|
64
|
+
attr_reader :registers
|
65
|
+
|
66
|
+
# The syscalls available to the program
|
67
|
+
#
|
68
|
+
# @return [Hash{Symbol => Integer}]
|
69
|
+
# The syscall names and numbers.
|
70
|
+
attr_reader :syscalls
|
71
|
+
|
72
|
+
# The registers used by the program
|
73
|
+
attr_reader :allocated_registers
|
74
|
+
|
75
|
+
# The instructions of the program
|
76
|
+
attr_reader :instructions
|
77
|
+
|
78
|
+
#
|
79
|
+
# Initializes a new Assembly Program.
|
80
|
+
#
|
81
|
+
# @param [Hash] options
|
82
|
+
# Additional options.
|
83
|
+
#
|
84
|
+
# @option options [String, Symbol] :arch (:x86)
|
85
|
+
# The Architecture to target.
|
86
|
+
#
|
87
|
+
# @option options [String, Symbol] :os
|
88
|
+
# The Operating System to target.
|
89
|
+
#
|
90
|
+
# @option options [Hash{Symbol => Object}] :define
|
91
|
+
# Constants to define in the program.
|
92
|
+
#
|
93
|
+
# @yield []
|
94
|
+
# The given block will be evaluated within the program.
|
95
|
+
#
|
96
|
+
# @example
|
97
|
+
# Program.new(:arch => :amd64) do
|
98
|
+
# push rax
|
99
|
+
# push rbx
|
100
|
+
#
|
101
|
+
# mov rsp, rax
|
102
|
+
# mov rax[8], rbx
|
103
|
+
# end
|
104
|
+
#
|
105
|
+
def initialize(options={},&block)
|
106
|
+
@arch = options.fetch(:arch,:x86).to_sym
|
107
|
+
|
108
|
+
arch = Archs.const_get(@arch.to_s.upcase)
|
109
|
+
|
110
|
+
@word_size = arch::WORD_SIZE
|
111
|
+
@registers = arch::REGISTERS
|
112
|
+
|
113
|
+
extend Archs.const_get(@arch.to_s.upcase)
|
114
|
+
|
115
|
+
@syscalls = {}
|
116
|
+
|
117
|
+
if options.has_key?(:os)
|
118
|
+
@os = options[:os].to_s
|
119
|
+
@syscalls = OS::SYSCALLS[@os][@arch]
|
120
|
+
|
121
|
+
extend OS.const_get(@os)
|
122
|
+
end
|
123
|
+
|
124
|
+
if options[:define]
|
125
|
+
options[:define].each do |name,value|
|
126
|
+
instance_variable_set("@#{name}",value)
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
@allocated_registers = []
|
131
|
+
@instructions = []
|
132
|
+
|
133
|
+
instance_eval(&block) if block
|
134
|
+
end
|
135
|
+
|
136
|
+
#
|
137
|
+
# Determines if a register exists.
|
138
|
+
#
|
139
|
+
# @param [Symbol] name
|
140
|
+
# The name of the register.
|
141
|
+
#
|
142
|
+
# @return [Boolean]
|
143
|
+
# Specifies whether the register exists.
|
144
|
+
#
|
145
|
+
def register?(name)
|
146
|
+
@registers.has_key?(name.to_sym)
|
147
|
+
end
|
148
|
+
|
149
|
+
#
|
150
|
+
# Accesses a register.
|
151
|
+
#
|
152
|
+
# @param [String, Symbol] name
|
153
|
+
# The name of the register.
|
154
|
+
#
|
155
|
+
# @return [Register]
|
156
|
+
# The register.
|
157
|
+
#
|
158
|
+
# @raise [ArgumentError]
|
159
|
+
# The register could not be found.
|
160
|
+
#
|
161
|
+
def register(name)
|
162
|
+
name = name.to_sym
|
163
|
+
|
164
|
+
unless register?(name)
|
165
|
+
raise(ArgumentError,"unknown register: #{name}")
|
166
|
+
end
|
167
|
+
|
168
|
+
unless @allocated_registers.include?(name)
|
169
|
+
# mark the register as being used, when it was first accessed
|
170
|
+
@allocated_registers << name
|
171
|
+
end
|
172
|
+
|
173
|
+
return @registers[name]
|
174
|
+
end
|
175
|
+
|
176
|
+
#
|
177
|
+
# Adds a new instruction to the program.
|
178
|
+
#
|
179
|
+
# @param [String, Symbol] name
|
180
|
+
#
|
181
|
+
# @param [Array] operands
|
182
|
+
#
|
183
|
+
# @return [Instruction]
|
184
|
+
# The newly created instruction.
|
185
|
+
#
|
186
|
+
def instruction(name,*operands)
|
187
|
+
insn = Instruction.new(name.to_sym,operands)
|
188
|
+
|
189
|
+
@instructions << insn
|
190
|
+
return insn
|
191
|
+
end
|
192
|
+
|
193
|
+
#
|
194
|
+
# Creates an operand of size 1 (byte).
|
195
|
+
#
|
196
|
+
# @param [Integer] number
|
197
|
+
# The value of the operand.
|
198
|
+
#
|
199
|
+
# @return [ImmediateOperand]
|
200
|
+
# The new operand value.
|
201
|
+
#
|
202
|
+
def byte(number)
|
203
|
+
ImmediateOperand.new(number,1)
|
204
|
+
end
|
205
|
+
|
206
|
+
#
|
207
|
+
# Creates a operand of size 2 (bytes).
|
208
|
+
#
|
209
|
+
# @param [Integer] number
|
210
|
+
# The value of the operand.
|
211
|
+
#
|
212
|
+
# @return [ImmediateOperand]
|
213
|
+
# The new operand value.
|
214
|
+
#
|
215
|
+
def word(number)
|
216
|
+
ImmediateOperand.new(number,2)
|
217
|
+
end
|
218
|
+
|
219
|
+
#
|
220
|
+
# Creates a operand of size 4 (bytes).
|
221
|
+
#
|
222
|
+
# @param [Integer] number
|
223
|
+
# The value of the operand.
|
224
|
+
#
|
225
|
+
# @return [ImmediateOperand]
|
226
|
+
# The new operand value.
|
227
|
+
#
|
228
|
+
def dword(number)
|
229
|
+
ImmediateOperand.new(number,4)
|
230
|
+
end
|
231
|
+
|
232
|
+
#
|
233
|
+
# Creates a operand of size 8 (bytes).
|
234
|
+
#
|
235
|
+
# @param [Integer] number
|
236
|
+
# The value of the operand.
|
237
|
+
#
|
238
|
+
# @return [ImmediateOperand]
|
239
|
+
# The new operand.
|
240
|
+
#
|
241
|
+
def qword(number)
|
242
|
+
ImmediateOperand.new(number,8)
|
243
|
+
end
|
244
|
+
|
245
|
+
#
|
246
|
+
# Adds a label to the program.
|
247
|
+
#
|
248
|
+
# @param [Symbol, String] name
|
249
|
+
# The name of the label.
|
250
|
+
#
|
251
|
+
# @yield []
|
252
|
+
# The given block will be evaluated after the label has been
|
253
|
+
# added.
|
254
|
+
#
|
255
|
+
# @return [Symbol]
|
256
|
+
# The label name.
|
257
|
+
#
|
258
|
+
def label(name,&block)
|
259
|
+
name = name.to_sym
|
260
|
+
|
261
|
+
@instructions << name
|
262
|
+
instance_eval(&block)
|
263
|
+
return name
|
264
|
+
end
|
265
|
+
|
266
|
+
#
|
267
|
+
# Generic method for generating the instruction for causing an interrupt.
|
268
|
+
#
|
269
|
+
# @param [Integer] number
|
270
|
+
# The interrupt number to call.
|
271
|
+
#
|
272
|
+
# @abstract
|
273
|
+
#
|
274
|
+
def interrupt(number)
|
275
|
+
end
|
276
|
+
|
277
|
+
#
|
278
|
+
# Generic method for generating the instruction for invoking a syscall.
|
279
|
+
#
|
280
|
+
# @abstract
|
281
|
+
#
|
282
|
+
def syscall
|
283
|
+
end
|
284
|
+
|
285
|
+
#
|
286
|
+
# Generic method for pushing onto the stack.
|
287
|
+
#
|
288
|
+
# @param [Register, Integer] value
|
289
|
+
# The value to push.
|
290
|
+
#
|
291
|
+
# @abstract
|
292
|
+
#
|
293
|
+
def stack_push(value)
|
294
|
+
end
|
295
|
+
|
296
|
+
#
|
297
|
+
# Generic method for popping off the stack.
|
298
|
+
#
|
299
|
+
# @param [Symbol] name
|
300
|
+
# The name of the reigster.
|
301
|
+
#
|
302
|
+
# @abstract
|
303
|
+
#
|
304
|
+
def stack_pop(name)
|
305
|
+
end
|
306
|
+
|
307
|
+
#
|
308
|
+
# Generic method for clearing a register.
|
309
|
+
#
|
310
|
+
# @param [Symbol] name
|
311
|
+
# The name of the reigster.
|
312
|
+
#
|
313
|
+
# @abstract
|
314
|
+
#
|
315
|
+
def register_clear(name)
|
316
|
+
end
|
317
|
+
|
318
|
+
#
|
319
|
+
# Generic method for setting a register.
|
320
|
+
#
|
321
|
+
# @param [Register, Immediate, Integer] value
|
322
|
+
# The new value for the register.
|
323
|
+
#
|
324
|
+
# @param [Symbol] name
|
325
|
+
# The name of the reigster.
|
326
|
+
#
|
327
|
+
# @abstract
|
328
|
+
#
|
329
|
+
def register_set(value,name)
|
330
|
+
end
|
331
|
+
|
332
|
+
#
|
333
|
+
# Generic method for saving a register.
|
334
|
+
#
|
335
|
+
# @param [Symbol] name
|
336
|
+
# The name of the reigster.
|
337
|
+
#
|
338
|
+
# @abstract
|
339
|
+
#
|
340
|
+
def register_save(name)
|
341
|
+
end
|
342
|
+
|
343
|
+
#
|
344
|
+
# Generic method for loading a register.
|
345
|
+
#
|
346
|
+
# @param [Symbol] name
|
347
|
+
# The name of the reigster.
|
348
|
+
#
|
349
|
+
# @abstract
|
350
|
+
#
|
351
|
+
def register_load(name)
|
352
|
+
end
|
353
|
+
|
354
|
+
#
|
355
|
+
# Defines a critical region, where the specified Registers
|
356
|
+
# should be saved and then reloaded.
|
357
|
+
#
|
358
|
+
# @param [Array<Symbol>] regs
|
359
|
+
# The registers to save and reload.
|
360
|
+
#
|
361
|
+
# @yield []
|
362
|
+
# The given block will be evaluated after the registers
|
363
|
+
# have been saved.
|
364
|
+
#
|
365
|
+
def critical(*regs,&block)
|
366
|
+
regs.each { |name| register_save(name) }
|
367
|
+
|
368
|
+
instance_eval(&block)
|
369
|
+
|
370
|
+
regs.reverse_each { |name| register_load(name) }
|
371
|
+
end
|
372
|
+
|
373
|
+
#
|
374
|
+
# Evaluates code within the Program.
|
375
|
+
#
|
376
|
+
# @yield []
|
377
|
+
# The code to evaluate.
|
378
|
+
#
|
379
|
+
def eval(&block)
|
380
|
+
instance_eval(&block)
|
381
|
+
end
|
382
|
+
|
383
|
+
#
|
384
|
+
# Converts the program to Assembly Source Code.
|
385
|
+
#
|
386
|
+
# @param [Symbol] syntax
|
387
|
+
# The syntax to compile the program to.
|
388
|
+
#
|
389
|
+
def to_asm(syntax=:att)
|
390
|
+
SYNTAX[syntax].emit_program(self)
|
391
|
+
end
|
392
|
+
|
393
|
+
#
|
394
|
+
# Assembles the program.
|
395
|
+
#
|
396
|
+
# @param [String] output
|
397
|
+
# The path for the assembled program.
|
398
|
+
#
|
399
|
+
# @param [Hash] options
|
400
|
+
# Additional options.
|
401
|
+
#
|
402
|
+
# @option options [Symbol, String] :syntax (:att)
|
403
|
+
# The syntax to compile the program to.
|
404
|
+
#
|
405
|
+
# @option options [Symbol] :format (:bin)
|
406
|
+
# The format of the assembled executable. May be one of:
|
407
|
+
#
|
408
|
+
# * `:dbg` - Trace of all info passed to object format module.
|
409
|
+
# * `:bin` - Flat format binary.
|
410
|
+
# * `:dosexe` - DOS .EXE format binary.
|
411
|
+
# * `:elf` - ELF.
|
412
|
+
# * `:elf32` - ELF (32-bit).
|
413
|
+
# * `:elf64` - ELF (64-bit).
|
414
|
+
# * `:coff` - COFF (DJGPP).
|
415
|
+
# * `:macho` - Mac OS X ABI Mach-O File Format.
|
416
|
+
# * `:macho32` - Mac OS X ABI Mach-O File Format (32-bit).
|
417
|
+
# * `:macho64` - Mac OS X ABI Mach-O File Format (64-bit).
|
418
|
+
# * `:rdf` - Relocatable Dynamic Object File Format (RDOFF) v2.0.
|
419
|
+
# * `:win32` - Win32.
|
420
|
+
# * `:win64` / `:x64` - Win64.
|
421
|
+
# * `:xdf` - Extended Dynamic Object.
|
422
|
+
#
|
423
|
+
# @return [String]
|
424
|
+
# The path to the assembled program.
|
425
|
+
#
|
426
|
+
def assemble(output,options={})
|
427
|
+
syntax = options.fetch(:syntax,:att)
|
428
|
+
format = options.fetch(:format,:bin)
|
429
|
+
parser = PARSERS[syntax]
|
430
|
+
|
431
|
+
source = Tempfile.new(['ronin-asm', '.s'])
|
432
|
+
source.write(to_asm(syntax))
|
433
|
+
source.close
|
434
|
+
|
435
|
+
YASM::Program.assemble(
|
436
|
+
:file => source.path,
|
437
|
+
:parser => PARSERS[syntax],
|
438
|
+
:target => @arch,
|
439
|
+
:output_format => format,
|
440
|
+
:output => output
|
441
|
+
)
|
442
|
+
|
443
|
+
return output
|
444
|
+
end
|
445
|
+
|
446
|
+
protected
|
447
|
+
|
448
|
+
# undefine the syscall method, so method_missing handles it
|
449
|
+
undef syscall
|
450
|
+
|
451
|
+
#
|
452
|
+
# Allows adding unknown instructions to the program.
|
453
|
+
#
|
454
|
+
# @param [Symbol] name
|
455
|
+
# The name of the instruction.
|
456
|
+
#
|
457
|
+
# @param [Array] arguments
|
458
|
+
# Additional operands.
|
459
|
+
#
|
460
|
+
def method_missing(name,*arguments,&block)
|
461
|
+
if (block && arguments.empty?)
|
462
|
+
label(name,&block)
|
463
|
+
elsif block.nil?
|
464
|
+
if (arguments.empty? && register?(name))
|
465
|
+
register(name)
|
466
|
+
else
|
467
|
+
instruction(name,*arguments)
|
468
|
+
end
|
469
|
+
else
|
470
|
+
super(name,*arguments,&block)
|
471
|
+
end
|
472
|
+
end
|
473
|
+
|
474
|
+
end
|
475
|
+
end
|
476
|
+
end
|