ronin-code-asm 1.0.0.beta1 → 1.0.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.
- checksums.yaml +4 -4
- data/.github/workflows/ruby.yml +1 -0
- data/.yardopts +1 -1
- data/README.md +2 -1
- data/gemspec.yml +2 -2
- data/lib/ronin/code/asm/archs/amd64.rb +2 -2
- data/lib/ronin/code/asm/archs/x86.rb +2 -2
- data/lib/ronin/code/asm/archs.rb +1 -1
- data/lib/ronin/code/asm/config.rb +1 -1
- data/lib/ronin/code/asm/immediate_operand.rb +1 -1
- data/lib/ronin/code/asm/instruction.rb +1 -1
- data/lib/ronin/code/asm/memory_operand.rb +1 -1
- data/lib/ronin/code/asm/os/freebsd.rb +1 -1
- data/lib/ronin/code/asm/os/linux.rb +1 -1
- data/lib/ronin/code/asm/os/os.rb +1 -1
- data/lib/ronin/code/asm/os.rb +1 -1
- data/lib/ronin/code/asm/program.rb +6 -6
- data/lib/ronin/code/asm/register.rb +2 -2
- data/lib/ronin/code/asm/shellcode.rb +1 -1
- data/lib/ronin/code/asm/syntax/att.rb +1 -1
- data/lib/ronin/code/asm/syntax/common.rb +1 -1
- data/lib/ronin/code/asm/syntax/intel.rb +1 -1
- data/lib/ronin/code/asm/syntax.rb +1 -1
- data/lib/ronin/code/asm/version.rb +2 -2
- data/lib/ronin/code/asm.rb +1 -1
- data/ronin-code-asm.gemspec +2 -1
- metadata +5 -30
- data/spec/asm_spec.rb +0 -14
- data/spec/config_spec.rb +0 -10
- data/spec/immediate_operand_spec.rb +0 -79
- data/spec/instruction_spec.rb +0 -62
- data/spec/memory_operand_spec.rb +0 -80
- data/spec/os_spec.rb +0 -68
- data/spec/program_spec.rb +0 -439
- data/spec/register_spec.rb +0 -112
- data/spec/shellcode_spec.rb +0 -58
- data/spec/spec_helper.rb +0 -7
- data/spec/syntax/att_spec.rb +0 -181
- data/spec/syntax/common_spec.rb +0 -42
- data/spec/syntax/intel_spec.rb +0 -174
data/spec/memory_operand_spec.rb
DELETED
@@ -1,80 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
require 'ronin/code/asm/memory_operand'
|
4
|
-
require 'ronin/code/asm/register'
|
5
|
-
|
6
|
-
describe Ronin::Code::ASM::MemoryOperand do
|
7
|
-
let(:register) { Ronin::Code::ASM::Register.new(:eax, 4) }
|
8
|
-
|
9
|
-
describe "#initialize" do
|
10
|
-
it { expect(subject.base).to be_nil }
|
11
|
-
it { expect(subject.offset).to eq(0) }
|
12
|
-
it { expect(subject.index).to be_nil }
|
13
|
-
it { expect(subject.scale).to eq(1) }
|
14
|
-
|
15
|
-
it "must only accept nil and a Register for base" do
|
16
|
-
expect {
|
17
|
-
described_class.new(Object.new)
|
18
|
-
}.to raise_error(TypeError)
|
19
|
-
end
|
20
|
-
|
21
|
-
it "must only accept Integers for offset" do
|
22
|
-
expect {
|
23
|
-
described_class.new(register,2.0)
|
24
|
-
}.to raise_error(TypeError)
|
25
|
-
end
|
26
|
-
|
27
|
-
it "must only accept nil and a Register for index" do
|
28
|
-
expect {
|
29
|
-
described_class.new(register,0,Object.new)
|
30
|
-
}.to raise_error(TypeError)
|
31
|
-
end
|
32
|
-
|
33
|
-
it "must only accept Integers for offset" do
|
34
|
-
expect {
|
35
|
-
described_class.new(register,0,nil,2.0)
|
36
|
-
}.to raise_error(TypeError)
|
37
|
-
end
|
38
|
-
|
39
|
-
end
|
40
|
-
|
41
|
-
describe "#+" do
|
42
|
-
let(:operand) { described_class.new(register,4,register,2) }
|
43
|
-
|
44
|
-
subject { operand + 4 }
|
45
|
-
|
46
|
-
it "must add to offset" do
|
47
|
-
expect(subject.offset).to eq(8)
|
48
|
-
end
|
49
|
-
|
50
|
-
it "must not change base, index or scale" do
|
51
|
-
expect(subject.base).to eq(operand.base)
|
52
|
-
expect(subject.index).to eq(operand.index)
|
53
|
-
expect(subject.scale).to eq(operand.scale)
|
54
|
-
end
|
55
|
-
end
|
56
|
-
|
57
|
-
describe "#-" do
|
58
|
-
let(:operand) { described_class.new(register,4,register,2) }
|
59
|
-
|
60
|
-
subject { operand - 2 }
|
61
|
-
|
62
|
-
it "must subtract from offset" do
|
63
|
-
expect(subject.offset).to eq(2)
|
64
|
-
end
|
65
|
-
|
66
|
-
it "must not change base, index or scale" do
|
67
|
-
expect(subject.base).to eq(operand.base)
|
68
|
-
expect(subject.index).to eq(operand.index)
|
69
|
-
expect(subject.scale).to eq(operand.scale)
|
70
|
-
end
|
71
|
-
end
|
72
|
-
|
73
|
-
describe "#width" do
|
74
|
-
subject { described_class.new(register,10) }
|
75
|
-
|
76
|
-
it "must return the width of base" do
|
77
|
-
expect(subject.width).to eq(register.width)
|
78
|
-
end
|
79
|
-
end
|
80
|
-
end
|
data/spec/os_spec.rb
DELETED
@@ -1,68 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
require 'ronin/code/asm/os'
|
3
|
-
|
4
|
-
describe Ronin::Code::ASM::OS do
|
5
|
-
describe "SYSCALLS" do
|
6
|
-
subject { described_class::SYSCALLS }
|
7
|
-
|
8
|
-
let(:data_dir) { Ronin::Code::ASM::Config::DATA_DIR }
|
9
|
-
|
10
|
-
it { expect(subject).to be_kind_of(Hash) }
|
11
|
-
|
12
|
-
it "must load syscalls for :freebsd and :amd64" do
|
13
|
-
expect(subject[:freebsd][:amd64]).to eq(
|
14
|
-
YAML.load_file(
|
15
|
-
File.join(data_dir,'os','freebsd','amd64','syscalls.yml')
|
16
|
-
)
|
17
|
-
)
|
18
|
-
end
|
19
|
-
|
20
|
-
it "must load syscalls for :freebsd and :x86" do
|
21
|
-
expect(subject[:freebsd][:amd64]).to eq(
|
22
|
-
YAML.load_file(
|
23
|
-
File.join(data_dir,'os','freebsd','x86','syscalls.yml')
|
24
|
-
)
|
25
|
-
)
|
26
|
-
end
|
27
|
-
|
28
|
-
it "must load syscalls for :linux and :amd64" do
|
29
|
-
expect(subject[:linux][:amd64]).to eq(
|
30
|
-
YAML.load_file(
|
31
|
-
File.join(data_dir,'os','linux','amd64','syscalls.yml')
|
32
|
-
)
|
33
|
-
)
|
34
|
-
end
|
35
|
-
|
36
|
-
it "must load syscalls for :linux and :x86" do
|
37
|
-
expect(subject[:linux][:x86]).to eq(
|
38
|
-
YAML.load_file(
|
39
|
-
File.join(data_dir,'os','linux','x86','syscalls.yml')
|
40
|
-
)
|
41
|
-
)
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
45
|
-
describe ".[]" do
|
46
|
-
context "when given :linux" do
|
47
|
-
it "must return #{described_class}::Linux" do
|
48
|
-
expect(subject[:linux]).to be(described_class::Linux)
|
49
|
-
end
|
50
|
-
end
|
51
|
-
|
52
|
-
context "when given :freebsd" do
|
53
|
-
it "must return #{described_class}::FreeBSD" do
|
54
|
-
expect(subject[:freebsd]).to be(described_class::FreeBSD)
|
55
|
-
end
|
56
|
-
end
|
57
|
-
|
58
|
-
context "when given an unknown Symbol" do
|
59
|
-
let(:name) { :foo }
|
60
|
-
|
61
|
-
it do
|
62
|
-
expect {
|
63
|
-
subject[name]
|
64
|
-
}.to raise_error(ArgumentError,"unknown OS name: #{name.inspect}")
|
65
|
-
end
|
66
|
-
end
|
67
|
-
end
|
68
|
-
end
|
data/spec/program_spec.rb
DELETED
@@ -1,439 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
require 'ronin/code/asm/program'
|
3
|
-
|
4
|
-
describe Ronin::Code::ASM::Program do
|
5
|
-
describe "#arch" do
|
6
|
-
it "must default to :x86" do
|
7
|
-
expect(subject.arch).to eq(:x86)
|
8
|
-
end
|
9
|
-
end
|
10
|
-
|
11
|
-
context "when :arch is :x86" do
|
12
|
-
subject { described_class.new(arch: :x86) }
|
13
|
-
|
14
|
-
it { expect(subject.word_size).to eq(4) }
|
15
|
-
|
16
|
-
describe "#stask_base" do
|
17
|
-
it "must be ebp" do
|
18
|
-
expect(subject.stack_base.name).to eq(:ebp)
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
|
-
describe "#stask_pointer" do
|
23
|
-
it "must be esp" do
|
24
|
-
expect(subject.stack_pointer.name).to eq(:esp)
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
28
|
-
describe "#stack_push" do
|
29
|
-
let(:value) { 0xff }
|
30
|
-
|
31
|
-
before { subject.stack_push(value) }
|
32
|
-
|
33
|
-
it "must add a 'push' instruction with a value" do
|
34
|
-
expect(subject.instructions[-1].name).to eq(:push)
|
35
|
-
expect(subject.instructions[-1].operands[0].value).to eq(value)
|
36
|
-
end
|
37
|
-
end
|
38
|
-
|
39
|
-
describe "#stack_pop" do
|
40
|
-
let(:register) { subject.register(:eax) }
|
41
|
-
|
42
|
-
before { subject.stack_pop(register) }
|
43
|
-
|
44
|
-
it "must add a 'pop' instruction with a register" do
|
45
|
-
expect(subject.instructions[-1].name).to eq(:pop)
|
46
|
-
expect(subject.instructions[-1].operands[0]).to eq(register)
|
47
|
-
end
|
48
|
-
end
|
49
|
-
|
50
|
-
describe "#register_clear" do
|
51
|
-
let(:name) { :eax }
|
52
|
-
|
53
|
-
before { subject.register_clear(name) }
|
54
|
-
|
55
|
-
it "must add a 'xor' instruction with a registers" do
|
56
|
-
expect(subject.instructions[-1].name).to eq(:xor)
|
57
|
-
expect(subject.instructions[-1].operands[0].name).to eq(name)
|
58
|
-
expect(subject.instructions[-1].operands[1].name).to eq(name)
|
59
|
-
end
|
60
|
-
end
|
61
|
-
|
62
|
-
describe "#register_set" do
|
63
|
-
let(:name) { :eax }
|
64
|
-
let(:value) { 0xff }
|
65
|
-
|
66
|
-
before { subject.register_set(name,value) }
|
67
|
-
|
68
|
-
it "must add a 'xor' instruction with a registers" do
|
69
|
-
expect(subject.instructions[-1].name).to eq(:mov)
|
70
|
-
expect(subject.instructions[-1].operands[0].value).to eq(value)
|
71
|
-
expect(subject.instructions[-1].operands[1].name).to eq(name)
|
72
|
-
end
|
73
|
-
end
|
74
|
-
|
75
|
-
describe "#register_save" do
|
76
|
-
let(:name) { :eax }
|
77
|
-
|
78
|
-
before { subject.register_save(name) }
|
79
|
-
|
80
|
-
it "must add a 'xor' instruction with a registers" do
|
81
|
-
expect(subject.instructions[-1].name).to eq(:push)
|
82
|
-
expect(subject.instructions[-1].operands[0].name).to eq(name)
|
83
|
-
end
|
84
|
-
end
|
85
|
-
|
86
|
-
describe "#register_save" do
|
87
|
-
let(:name) { :eax }
|
88
|
-
|
89
|
-
before { subject.register_load(name) }
|
90
|
-
|
91
|
-
it "must add a 'xor' instruction with a registers" do
|
92
|
-
expect(subject.instructions[-1].name).to eq(:pop)
|
93
|
-
expect(subject.instructions[-1].operands[0].name).to eq(name)
|
94
|
-
end
|
95
|
-
end
|
96
|
-
|
97
|
-
describe "#interrupt" do
|
98
|
-
let(:number) { 0x0a }
|
99
|
-
|
100
|
-
before { subject.interrupt(number) }
|
101
|
-
|
102
|
-
it "must add an 'int' instruction with the interrupt number" do
|
103
|
-
expect(subject.instructions[-1].name).to eq(:int)
|
104
|
-
expect(subject.instructions[-1].operands[0].value).to eq(number)
|
105
|
-
end
|
106
|
-
end
|
107
|
-
|
108
|
-
describe "#syscall" do
|
109
|
-
before { subject.syscall }
|
110
|
-
|
111
|
-
it "must add an 'int 0x80' instruction" do
|
112
|
-
expect(subject.instructions[-1].name).to eq(:int)
|
113
|
-
expect(subject.instructions[-1].operands[0].value).to eq(0x80)
|
114
|
-
end
|
115
|
-
end
|
116
|
-
|
117
|
-
context "when :os is :linux" do
|
118
|
-
subject { described_class.new(arch: :x86, os: :linux) }
|
119
|
-
|
120
|
-
it { expect(subject.syscalls).to_not be_empty }
|
121
|
-
end
|
122
|
-
|
123
|
-
context "when :os is :freebsd" do
|
124
|
-
subject { described_class.new(arch: :x86, os: :freebsd) }
|
125
|
-
|
126
|
-
it { expect(subject.syscalls).to_not be_empty }
|
127
|
-
end
|
128
|
-
end
|
129
|
-
|
130
|
-
context "when :arch is :amd64" do
|
131
|
-
subject { described_class.new(arch: :amd64) }
|
132
|
-
|
133
|
-
it { expect(subject.word_size).to eq(8) }
|
134
|
-
|
135
|
-
describe "#syscall" do
|
136
|
-
before { subject.syscall }
|
137
|
-
|
138
|
-
it "must add a 'syscall' instruction" do
|
139
|
-
expect(subject.instructions[-1].name).to eq(:syscall)
|
140
|
-
end
|
141
|
-
end
|
142
|
-
|
143
|
-
context "when :os is :linux" do
|
144
|
-
subject { described_class.new(arch: :amd64, os: :linux) }
|
145
|
-
|
146
|
-
it { expect(subject.syscalls).to_not be_empty }
|
147
|
-
end
|
148
|
-
|
149
|
-
context "when :os is :freebsd" do
|
150
|
-
subject { described_class.new(arch: :amd64, os: :freebsd) }
|
151
|
-
|
152
|
-
it { expect(subject.syscalls).to_not be_empty }
|
153
|
-
end
|
154
|
-
end
|
155
|
-
|
156
|
-
describe "#register?" do
|
157
|
-
it "must return true for existing registers" do
|
158
|
-
expect(subject.register?(:eax)).to be(true)
|
159
|
-
end
|
160
|
-
|
161
|
-
it "must return false for unknown registers" do
|
162
|
-
expect(subject.register?(:foo)).to be(false)
|
163
|
-
end
|
164
|
-
end
|
165
|
-
|
166
|
-
describe "#register" do
|
167
|
-
it "must return a Register" do
|
168
|
-
expect(subject.register(:eax)).to be_kind_of(Ronin::Code::ASM::Register)
|
169
|
-
end
|
170
|
-
|
171
|
-
it "must allocate the register" do
|
172
|
-
subject.register(:ebx)
|
173
|
-
|
174
|
-
expect(subject.allocated_registers).to include(:ebx)
|
175
|
-
end
|
176
|
-
|
177
|
-
context "when given an unknown register name" do
|
178
|
-
it "must raise an ArgumentError" do
|
179
|
-
expect {
|
180
|
-
subject.register(:foo)
|
181
|
-
}.to raise_error(ArgumentError)
|
182
|
-
end
|
183
|
-
end
|
184
|
-
end
|
185
|
-
|
186
|
-
describe "#instruction" do
|
187
|
-
it "must return an Instruction" do
|
188
|
-
expect(subject.instruction(:hlt)).to be_kind_of(Ronin::Code::ASM::Instruction)
|
189
|
-
end
|
190
|
-
|
191
|
-
it "must append the new Instruction" do
|
192
|
-
subject.instruction(:push, 1)
|
193
|
-
|
194
|
-
expect(subject.instructions.last.name).to eq(:push)
|
195
|
-
end
|
196
|
-
end
|
197
|
-
|
198
|
-
describe "#byte" do
|
199
|
-
it "must return a ImmedateOperand" do
|
200
|
-
expect(subject.byte(1)).to be_kind_of(Ronin::Code::ASM::ImmediateOperand)
|
201
|
-
end
|
202
|
-
|
203
|
-
it "must have width of 1" do
|
204
|
-
expect(subject.byte(1).width).to eq(1)
|
205
|
-
end
|
206
|
-
|
207
|
-
context "when given a MemoryOperand" do
|
208
|
-
let(:register) { Ronin::Code::ASM::Register.new(:eax, 4) }
|
209
|
-
let(:memory_operand) { Ronin::Code::ASM::MemoryOperand.new(register) }
|
210
|
-
|
211
|
-
it "must return a MemoryOperand" do
|
212
|
-
expect(subject.byte(memory_operand)).to be_kind_of(
|
213
|
-
Ronin::Code::ASM::MemoryOperand
|
214
|
-
)
|
215
|
-
end
|
216
|
-
|
217
|
-
it "must have a width of 1" do
|
218
|
-
expect(subject.byte(memory_operand).width).to eq(1)
|
219
|
-
end
|
220
|
-
end
|
221
|
-
end
|
222
|
-
|
223
|
-
describe "#word" do
|
224
|
-
it "must return a Ronin::Code::ASM::ImmediateOperand" do
|
225
|
-
expect(subject.word(1)).to be_kind_of(Ronin::Code::ASM::ImmediateOperand)
|
226
|
-
end
|
227
|
-
|
228
|
-
it "must have width of 2" do
|
229
|
-
expect(subject.word(1).width).to eq(2)
|
230
|
-
end
|
231
|
-
|
232
|
-
context "when given a MemoryOperand" do
|
233
|
-
let(:register) { Ronin::Code::ASM::Register.new(:eax, 4) }
|
234
|
-
let(:memory_operand) { Ronin::Code::ASM::MemoryOperand.new(register) }
|
235
|
-
|
236
|
-
it "must return a MemoryOperand" do
|
237
|
-
expect(subject.word(memory_operand)).to be_kind_of(
|
238
|
-
Ronin::Code::ASM::MemoryOperand
|
239
|
-
)
|
240
|
-
end
|
241
|
-
|
242
|
-
it "must have a width of 2" do
|
243
|
-
expect(subject.word(memory_operand).width).to eq(2)
|
244
|
-
end
|
245
|
-
end
|
246
|
-
end
|
247
|
-
|
248
|
-
describe "#dword" do
|
249
|
-
it "must return a Ronin::Code::ASM::ImmediateOperand" do
|
250
|
-
expect(subject.dword(1)).to be_kind_of(Ronin::Code::ASM::ImmediateOperand)
|
251
|
-
end
|
252
|
-
|
253
|
-
it "must have width of 4" do
|
254
|
-
expect(subject.dword(1).width).to eq(4)
|
255
|
-
end
|
256
|
-
|
257
|
-
context "when given a MemoryOperand" do
|
258
|
-
let(:register) { Ronin::Code::ASM::Register.new(:eax, 4) }
|
259
|
-
let(:memory_operand) { Ronin::Code::ASM::MemoryOperand.new(register) }
|
260
|
-
|
261
|
-
it "must return a MemoryOperand" do
|
262
|
-
expect(subject.dword(memory_operand)).to be_kind_of(
|
263
|
-
Ronin::Code::ASM::MemoryOperand
|
264
|
-
)
|
265
|
-
end
|
266
|
-
|
267
|
-
it "must have a width of 4" do
|
268
|
-
expect(subject.dword(memory_operand).width).to eq(4)
|
269
|
-
end
|
270
|
-
end
|
271
|
-
end
|
272
|
-
|
273
|
-
describe "#qword" do
|
274
|
-
it "must return a Ronin::Code::ASM::ImmediateOperand" do
|
275
|
-
expect(subject.qword(1)).to be_kind_of(Ronin::Code::ASM::ImmediateOperand)
|
276
|
-
end
|
277
|
-
|
278
|
-
it "must have width of 8" do
|
279
|
-
expect(subject.qword(1).width).to eq(8)
|
280
|
-
end
|
281
|
-
|
282
|
-
context "when given a MemoryOperand" do
|
283
|
-
let(:register) { Ronin::Code::ASM::Register.new(:eax, 4) }
|
284
|
-
let(:memory_operand) { Ronin::Code::ASM::MemoryOperand.new(register) }
|
285
|
-
|
286
|
-
it "must return a MemoryOperand" do
|
287
|
-
expect(subject.qword(memory_operand)).to be_kind_of(
|
288
|
-
Ronin::Code::ASM::MemoryOperand
|
289
|
-
)
|
290
|
-
end
|
291
|
-
|
292
|
-
it "must have a width of 8" do
|
293
|
-
expect(subject.qword(memory_operand).width).to eq(8)
|
294
|
-
end
|
295
|
-
end
|
296
|
-
end
|
297
|
-
|
298
|
-
describe "#label" do
|
299
|
-
let(:name) { :_start }
|
300
|
-
|
301
|
-
it "must return the label name" do
|
302
|
-
label = subject.label(name) { }
|
303
|
-
|
304
|
-
expect(label).to eq(name)
|
305
|
-
end
|
306
|
-
|
307
|
-
it "must add the label to the instructions" do
|
308
|
-
subject.label(name) { }
|
309
|
-
|
310
|
-
expect(subject.instructions.last).to eq(name)
|
311
|
-
end
|
312
|
-
|
313
|
-
it "must accept a block" do
|
314
|
-
subject.label(name) { push 2 }
|
315
|
-
|
316
|
-
expect(subject.instructions[-1].name).to eq(:push)
|
317
|
-
expect(subject.instructions[-2]).to eq(name)
|
318
|
-
end
|
319
|
-
end
|
320
|
-
|
321
|
-
describe "#method_missing" do
|
322
|
-
context "when called without a block" do
|
323
|
-
it "must add a new instruction" do
|
324
|
-
subject.pop
|
325
|
-
|
326
|
-
expect(subject.instructions[-1].name).to eq(:pop)
|
327
|
-
end
|
328
|
-
end
|
329
|
-
|
330
|
-
context "when called with one argument and a block" do
|
331
|
-
it "must add a new label" do
|
332
|
-
subject._loop { mov eax, ebx }
|
333
|
-
|
334
|
-
expect(subject.instructions[-2]).to eq(:_loop)
|
335
|
-
expect(subject.instructions[-1].name).to eq(:mov)
|
336
|
-
end
|
337
|
-
end
|
338
|
-
end
|
339
|
-
|
340
|
-
describe "#to_asm" do
|
341
|
-
subject do
|
342
|
-
described_class.new do
|
343
|
-
push eax
|
344
|
-
push ebx
|
345
|
-
push ecx
|
346
|
-
|
347
|
-
mov ebx, eax
|
348
|
-
mov ebx, eax+0
|
349
|
-
mov ebx, eax+4
|
350
|
-
mov ebx, eax+esi
|
351
|
-
mov ebx, eax+(esi*4)
|
352
|
-
mov ebx, eax+(esi*4)+10
|
353
|
-
end
|
354
|
-
end
|
355
|
-
|
356
|
-
it "must convert the program to Intel syntax" do
|
357
|
-
expect(subject.to_asm).to eq([
|
358
|
-
"BITS 32",
|
359
|
-
"section .text",
|
360
|
-
"_start:",
|
361
|
-
"\tpush\teax",
|
362
|
-
"\tpush\tebx",
|
363
|
-
"\tpush\tecx",
|
364
|
-
"\tmov\tebx,\teax",
|
365
|
-
"\tmov\tebx,\t[eax]",
|
366
|
-
"\tmov\tebx,\t[eax+0x4]",
|
367
|
-
"\tmov\tebx,\t[eax+esi]",
|
368
|
-
"\tmov\tebx,\t[eax+esi*0x4]",
|
369
|
-
"\tmov\tebx,\t[eax+esi*0x4+0xa]",
|
370
|
-
""
|
371
|
-
].join($/))
|
372
|
-
end
|
373
|
-
|
374
|
-
context "when given :att" do
|
375
|
-
it "must convert the program to ATT syntax" do
|
376
|
-
expect(subject.to_asm(:att)).to eq([
|
377
|
-
".code32",
|
378
|
-
".text",
|
379
|
-
"_start:",
|
380
|
-
"\tpushl\t%eax",
|
381
|
-
"\tpushl\t%ebx",
|
382
|
-
"\tpushl\t%ecx",
|
383
|
-
"\tmovl\t%eax,\t%ebx",
|
384
|
-
"\tmovl\t(%eax),\t%ebx",
|
385
|
-
"\tmovl\t0x4(%eax),\t%ebx",
|
386
|
-
"\tmovl\t(%eax,%esi),\t%ebx",
|
387
|
-
"\tmovl\t(%eax,%esi,4),\t%ebx",
|
388
|
-
"\tmovl\t0xa(%eax,%esi,4),\t%ebx",
|
389
|
-
""
|
390
|
-
].join($/))
|
391
|
-
end
|
392
|
-
end
|
393
|
-
end
|
394
|
-
|
395
|
-
describe "#assemble", integration: true do
|
396
|
-
subject do
|
397
|
-
described_class.new do
|
398
|
-
push eax
|
399
|
-
push ebx
|
400
|
-
push ecx
|
401
|
-
|
402
|
-
mov ebx, eax
|
403
|
-
mov ebx, eax+0
|
404
|
-
mov ebx, eax+4
|
405
|
-
mov ebx, eax+esi
|
406
|
-
mov ebx, eax+(esi*4)
|
407
|
-
mov ebx, eax+(esi*4)+10
|
408
|
-
end
|
409
|
-
end
|
410
|
-
|
411
|
-
let(:output) { Tempfile.new(['ronin-asm', '.o']).path }
|
412
|
-
|
413
|
-
before { subject.assemble(output) }
|
414
|
-
|
415
|
-
it "must write to the output file" do
|
416
|
-
expect(File.size(output)).to be > 0
|
417
|
-
end
|
418
|
-
|
419
|
-
context "when syntax: :intel is given" do
|
420
|
-
let(:output) { Tempfile.new(['ronin-asm', '.o']).path }
|
421
|
-
|
422
|
-
before { subject.assemble(output, syntax: :intel) }
|
423
|
-
|
424
|
-
it "must write to the output file" do
|
425
|
-
expect(File.size(output)).to be > 0
|
426
|
-
end
|
427
|
-
end
|
428
|
-
|
429
|
-
context "when syntax is unknown" do
|
430
|
-
let(:syntax) { :foo }
|
431
|
-
|
432
|
-
it do
|
433
|
-
expect {
|
434
|
-
subject.assemble(output, syntax: syntax)
|
435
|
-
}.to raise_error(ArgumentError,"unknown ASM syntax: #{syntax.inspect}")
|
436
|
-
end
|
437
|
-
end
|
438
|
-
end
|
439
|
-
end
|
data/spec/register_spec.rb
DELETED
@@ -1,112 +0,0 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
require 'ronin/code/asm/register'
|
4
|
-
|
5
|
-
describe Ronin::Code::ASM::Register do
|
6
|
-
let(:register) { described_class.new(:eax, 4) }
|
7
|
-
|
8
|
-
subject { register }
|
9
|
-
|
10
|
-
describe "#+" do
|
11
|
-
context "when given an Ronin::Code::ASM::MemoryOperand" do
|
12
|
-
let(:operand) do
|
13
|
-
Ronin::Code::ASM::MemoryOperand.new(nil,10,register,2)
|
14
|
-
end
|
15
|
-
|
16
|
-
subject { register + operand }
|
17
|
-
|
18
|
-
it { expect(subject).to be_kind_of(Ronin::Code::ASM::MemoryOperand) }
|
19
|
-
|
20
|
-
it "must set the base" do
|
21
|
-
expect(subject.base).to eq(register)
|
22
|
-
end
|
23
|
-
|
24
|
-
it "must preserve the offset, index and scale" do
|
25
|
-
expect(subject.offset).to eq(operand.offset)
|
26
|
-
expect(subject.index).to eq(operand.index)
|
27
|
-
expect(subject.scale).to eq(operand.scale)
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
31
|
-
context "when given a Register" do
|
32
|
-
subject { register + register }
|
33
|
-
|
34
|
-
it { expect(subject).to be_kind_of(Ronin::Code::ASM::MemoryOperand) }
|
35
|
-
|
36
|
-
it "must set the base" do
|
37
|
-
expect(subject.base).to eq(register)
|
38
|
-
end
|
39
|
-
|
40
|
-
it { expect(subject.offset).to eq(0) }
|
41
|
-
|
42
|
-
it "must set the index" do
|
43
|
-
expect(subject.index).to eq(register)
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
|
-
context "when given an Integer" do
|
48
|
-
let(:offset) { 10 }
|
49
|
-
|
50
|
-
subject { register + offset }
|
51
|
-
|
52
|
-
it { expect(subject).to be_kind_of(Ronin::Code::ASM::MemoryOperand) }
|
53
|
-
|
54
|
-
it "must set the base" do
|
55
|
-
expect(subject.base).to eq(register)
|
56
|
-
end
|
57
|
-
|
58
|
-
it "must set the offset" do
|
59
|
-
expect(subject.offset).to eq(offset)
|
60
|
-
end
|
61
|
-
end
|
62
|
-
|
63
|
-
context "otherwise" do
|
64
|
-
it "must raise a TypeError" do
|
65
|
-
expect {
|
66
|
-
register + Object.new
|
67
|
-
}.to raise_error(TypeError)
|
68
|
-
end
|
69
|
-
end
|
70
|
-
end
|
71
|
-
|
72
|
-
describe "#-" do
|
73
|
-
let(:offset) { 10 }
|
74
|
-
|
75
|
-
subject { register - offset }
|
76
|
-
|
77
|
-
it { expect(subject).to be_kind_of(Ronin::Code::ASM::MemoryOperand) }
|
78
|
-
|
79
|
-
it "must set the base" do
|
80
|
-
expect(subject.base).to eq(register)
|
81
|
-
end
|
82
|
-
|
83
|
-
it "must set a negative offset" do
|
84
|
-
expect(subject.offset).to eq(-offset)
|
85
|
-
end
|
86
|
-
end
|
87
|
-
|
88
|
-
describe "#*" do
|
89
|
-
let(:scale) { 2 }
|
90
|
-
|
91
|
-
subject { register * scale }
|
92
|
-
|
93
|
-
it { expect(subject).to be_kind_of(Ronin::Code::ASM::MemoryOperand) }
|
94
|
-
|
95
|
-
it { expect(subject.base).to be_nil }
|
96
|
-
it { expect(subject.offset).to eq(0) }
|
97
|
-
|
98
|
-
it "must set the index" do
|
99
|
-
expect(subject.index).to eq(register)
|
100
|
-
end
|
101
|
-
|
102
|
-
it "must set the scale" do
|
103
|
-
expect(subject.scale).to eq(scale)
|
104
|
-
end
|
105
|
-
end
|
106
|
-
|
107
|
-
describe "#to_s" do
|
108
|
-
it "must return the register name" do
|
109
|
-
expect(subject.to_s).to eq(subject.name.to_s)
|
110
|
-
end
|
111
|
-
end
|
112
|
-
end
|