ronin-code-asm 1.0.0.beta1 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (40) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ruby.yml +1 -0
  3. data/.yardopts +1 -1
  4. data/README.md +2 -1
  5. data/gemspec.yml +2 -2
  6. data/lib/ronin/code/asm/archs/amd64.rb +2 -2
  7. data/lib/ronin/code/asm/archs/x86.rb +2 -2
  8. data/lib/ronin/code/asm/archs.rb +1 -1
  9. data/lib/ronin/code/asm/config.rb +1 -1
  10. data/lib/ronin/code/asm/immediate_operand.rb +1 -1
  11. data/lib/ronin/code/asm/instruction.rb +1 -1
  12. data/lib/ronin/code/asm/memory_operand.rb +1 -1
  13. data/lib/ronin/code/asm/os/freebsd.rb +1 -1
  14. data/lib/ronin/code/asm/os/linux.rb +1 -1
  15. data/lib/ronin/code/asm/os/os.rb +1 -1
  16. data/lib/ronin/code/asm/os.rb +1 -1
  17. data/lib/ronin/code/asm/program.rb +6 -6
  18. data/lib/ronin/code/asm/register.rb +2 -2
  19. data/lib/ronin/code/asm/shellcode.rb +1 -1
  20. data/lib/ronin/code/asm/syntax/att.rb +1 -1
  21. data/lib/ronin/code/asm/syntax/common.rb +1 -1
  22. data/lib/ronin/code/asm/syntax/intel.rb +1 -1
  23. data/lib/ronin/code/asm/syntax.rb +1 -1
  24. data/lib/ronin/code/asm/version.rb +2 -2
  25. data/lib/ronin/code/asm.rb +1 -1
  26. data/ronin-code-asm.gemspec +2 -1
  27. metadata +5 -30
  28. data/spec/asm_spec.rb +0 -14
  29. data/spec/config_spec.rb +0 -10
  30. data/spec/immediate_operand_spec.rb +0 -79
  31. data/spec/instruction_spec.rb +0 -62
  32. data/spec/memory_operand_spec.rb +0 -80
  33. data/spec/os_spec.rb +0 -68
  34. data/spec/program_spec.rb +0 -439
  35. data/spec/register_spec.rb +0 -112
  36. data/spec/shellcode_spec.rb +0 -58
  37. data/spec/spec_helper.rb +0 -7
  38. data/spec/syntax/att_spec.rb +0 -181
  39. data/spec/syntax/common_spec.rb +0 -42
  40. data/spec/syntax/intel_spec.rb +0 -174
@@ -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
@@ -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