ronin-asm 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (51) hide show
  1. data/.document +4 -0
  2. data/.gemtest +0 -0
  3. data/.gitignore +11 -0
  4. data/.rspec +1 -0
  5. data/.yardopts +1 -0
  6. data/COPYING.txt +674 -0
  7. data/ChangeLog.md +10 -0
  8. data/Gemfile +19 -0
  9. data/README.md +142 -0
  10. data/Rakefile +44 -0
  11. data/data/ronin/asm/freebsd/amd64/syscalls.yml +415 -0
  12. data/data/ronin/asm/freebsd/x86/syscalls.yml +415 -0
  13. data/data/ronin/asm/linux/amd64/syscalls.yml +306 -0
  14. data/data/ronin/asm/linux/x86/syscalls.yml +339 -0
  15. data/data/ronin/gen/asm/source_file.s.erb +4 -0
  16. data/gemspec.yml +20 -0
  17. data/lib/ronin/asm.rb +25 -0
  18. data/lib/ronin/asm/archs.rb +23 -0
  19. data/lib/ronin/asm/archs/amd64.rb +99 -0
  20. data/lib/ronin/asm/archs/x86.rb +166 -0
  21. data/lib/ronin/asm/asm.rb +66 -0
  22. data/lib/ronin/asm/config.rb +39 -0
  23. data/lib/ronin/asm/immediate_operand.rb +76 -0
  24. data/lib/ronin/asm/instruction.rb +65 -0
  25. data/lib/ronin/asm/memory_operand.rb +109 -0
  26. data/lib/ronin/asm/os.rb +24 -0
  27. data/lib/ronin/asm/os/freebsd.rb +34 -0
  28. data/lib/ronin/asm/os/linux.rb +34 -0
  29. data/lib/ronin/asm/os/os.rb +40 -0
  30. data/lib/ronin/asm/program.rb +476 -0
  31. data/lib/ronin/asm/register.rb +110 -0
  32. data/lib/ronin/asm/shellcode.rb +70 -0
  33. data/lib/ronin/asm/syntax.rb +23 -0
  34. data/lib/ronin/asm/syntax/att.rb +136 -0
  35. data/lib/ronin/asm/syntax/common.rb +202 -0
  36. data/lib/ronin/asm/syntax/intel.rb +150 -0
  37. data/lib/ronin/asm/version.rb +27 -0
  38. data/ronin-asm.gemspec +61 -0
  39. data/spec/asm_spec.rb +8 -0
  40. data/spec/helpers/database.rb +7 -0
  41. data/spec/immediate_operand_spec.rb +77 -0
  42. data/spec/instruction_spec.rb +62 -0
  43. data/spec/memory_operand_spec.rb +80 -0
  44. data/spec/program_spec.rb +365 -0
  45. data/spec/register_spec.rb +110 -0
  46. data/spec/shellcode_spec.rb +34 -0
  47. data/spec/spec_helper.rb +10 -0
  48. data/spec/syntax/att_spec.rb +171 -0
  49. data/spec/syntax/common_spec.rb +42 -0
  50. data/spec/syntax/intel_spec.rb +156 -0
  51. metadata +163 -0
@@ -0,0 +1,150 @@
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/syntax/common'
23
+
24
+ module Ronin
25
+ module ASM
26
+ module Syntax
27
+ class Intel < Common
28
+
29
+ # Data sizes and their identifiers
30
+ WIDTHS = {
31
+ 1 => 'BYTE',
32
+ 2 => 'WORD',
33
+ 4 => 'DWORD',
34
+ 8 => 'QWORD'
35
+ }
36
+
37
+ #
38
+ # Emits a register.
39
+ #
40
+ # @param [Register] reg
41
+ # The register.
42
+ #
43
+ # @return [String]
44
+ # The register name.
45
+ #
46
+ def self.emit_register(reg)
47
+ reg.name.to_s
48
+ end
49
+
50
+ #
51
+ # Emits an immediate operand.
52
+ #
53
+ # @param [ImmediateOperand] op
54
+ # The operand.
55
+ #
56
+ # @return [String]
57
+ # The formatted immediate operand.
58
+ #
59
+ def self.emit_immediate_operand(op)
60
+ "#{WIDTHS[op.width]} #{emit_integer(op.value)}"
61
+ end
62
+
63
+ #
64
+ # Emits a memory operand.
65
+ #
66
+ # @param [MemoryOperand] op
67
+ # The operand.
68
+ #
69
+ # @return [String]
70
+ # The formatted memory operand.
71
+ #
72
+ def self.emit_memory_operand(op)
73
+ asm = emit_register(op.base)
74
+
75
+ if op.index
76
+ asm << '+' << emit_register(op.index)
77
+ asm << '*' << emit_integer(op.scale) if op.scale > 1
78
+ end
79
+
80
+ if op.offset != 0
81
+ sign = if op.offset >= 0 then '+'
82
+ else '-'
83
+ end
84
+
85
+ asm << sign << emit_integer(op.offset)
86
+ end
87
+
88
+ return "[#{asm}]"
89
+ end
90
+
91
+ #
92
+ # Emits multiple operands.
93
+ #
94
+ # @param [Array<ImmediateOperand, MemoryOperand, Register, Symbol>] ops
95
+ # The Array of operands.
96
+ #
97
+ # @return [String]
98
+ # The formatted operands.
99
+ #
100
+ def self.emit_operands(ops)
101
+ if ops.length > 1
102
+ [ops[-1], *ops[0..-2]].map { |op| emit_operand(op) }.join(",\t")
103
+ else
104
+ super(ops)
105
+ end
106
+ end
107
+
108
+ #
109
+ # Emits an instruction.
110
+ #
111
+ # @param [Instruction] ins
112
+ # The instruction.
113
+ #
114
+ # @return [String]
115
+ # The formatted instruction.
116
+ #
117
+ def self.emit_instruction(ins)
118
+ line = emit_keyword(ins.name)
119
+
120
+ unless ins.operands.empty?
121
+ line << "\t" << emit_operands(ins.operands)
122
+ end
123
+
124
+ return line
125
+ end
126
+
127
+ #
128
+ # Emits a program.
129
+ #
130
+ # @param [Program] program
131
+ # The program.
132
+ #
133
+ # @return [String]
134
+ # The formatted program.
135
+ #
136
+ def self.emit_program(program)
137
+ asm = super(program)
138
+
139
+ # prepend the `BITS 64` directive for YASM
140
+ if program.arch == :amd64
141
+ asm = ["BITS 64", '', asm].join($/)
142
+ end
143
+
144
+ return asm
145
+ end
146
+
147
+ end
148
+ end
149
+ end
150
+ end
@@ -0,0 +1,27 @@
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 Asm 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 Asm 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 Asm. If not, see <http://www.gnu.org/licenses/>.
20
+ #
21
+
22
+ module Ronin
23
+ module ASM
24
+ # ronin-asm version
25
+ VERSION = '0.1.0'
26
+ end
27
+ end
@@ -0,0 +1,61 @@
1
+ # encoding: utf-8
2
+
3
+ require 'yaml'
4
+
5
+ Gem::Specification.new do |gem|
6
+ gemspec = YAML.load_file('gemspec.yml')
7
+
8
+ gem.name = gemspec.fetch('name')
9
+ gem.version = gemspec.fetch('version') do
10
+ lib_dir = File.join(File.dirname(__FILE__),'lib')
11
+ $LOAD_PATH << lib_dir unless $LOAD_PATH.include?(lib_dir)
12
+
13
+ require 'ronin/asm/version'
14
+ Ronin::ASM::VERSION
15
+ end
16
+
17
+ gem.summary = gemspec['summary']
18
+ gem.description = gemspec['description']
19
+ gem.licenses = Array(gemspec['license'])
20
+ gem.authors = Array(gemspec['authors'])
21
+ gem.email = gemspec['email']
22
+ gem.homepage = gemspec['homepage']
23
+
24
+ glob = lambda { |patterns| gem.files & Dir[*patterns] }
25
+
26
+ gem.files = `git ls-files`.split($/)
27
+ gem.files = glob[gemspec['files']] if gemspec['files']
28
+ gem.files += Array(gemspec['generated_files'])
29
+
30
+ gem.executables = gemspec.fetch('executables') do
31
+ glob['bin/*'].map { |path| File.basename(path) }
32
+ end
33
+ gem.default_executable = gem.executables.first if Gem::VERSION < '1.7.'
34
+
35
+ gem.extensions = glob[gemspec['extensions'] || 'ext/**/extconf.rb']
36
+ gem.test_files = glob[gemspec['test_files'] || '{test/{**/}*_test.rb']
37
+ gem.extra_rdoc_files = glob[gemspec['extra_doc_files'] || '*.{txt,md}']
38
+
39
+ gem.require_paths = Array(gemspec.fetch('require_paths') {
40
+ %w[ext lib].select { |dir| File.directory?(dir) }
41
+ })
42
+
43
+ gem.requirements = gemspec['requirements']
44
+ gem.required_ruby_version = gemspec['required_ruby_version']
45
+ gem.required_rubygems_version = gemspec['required_rubygems_version']
46
+ gem.post_install_message = gemspec['post_install_message']
47
+
48
+ split = lambda { |string| string.split(/,\s*/) }
49
+
50
+ if gemspec['dependencies']
51
+ gemspec['dependencies'].each do |name,versions|
52
+ gem.add_dependency(name,split[versions])
53
+ end
54
+ end
55
+
56
+ if gemspec['development_dependencies']
57
+ gemspec['development_dependencies'].each do |name,versions|
58
+ gem.add_development_dependency(name,split[versions])
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,8 @@
1
+ require 'spec_helper'
2
+ require 'ronin/asm/version'
3
+
4
+ describe ASM do
5
+ it "should have a version" do
6
+ subject.const_defined?('VERSION').should == true
7
+ end
8
+ end
@@ -0,0 +1,7 @@
1
+ require 'ronin/database'
2
+
3
+ require 'spec_helper'
4
+
5
+ module Helpers
6
+ Database.setup(ENV['DATABASE'] || 'sqlite3::memory:')
7
+ end
@@ -0,0 +1,77 @@
1
+ require 'spec_helper'
2
+
3
+ require 'ronin/asm/immediate_operand'
4
+
5
+ describe ImmediateOperand do
6
+ let(:value) { 0xff }
7
+
8
+ describe "#initialize" do
9
+ context "with a width" do
10
+ let(:width) { 2 }
11
+
12
+ subject { described_class.new(value,width) }
13
+
14
+ it "should set the width" do
15
+ subject.width.should == width
16
+ end
17
+ end
18
+
19
+ describe "default width for" do
20
+ context "0x100000000 .. 0xffffffffffffffff" do
21
+ subject { described_class.new(0xffffffffffffffff).width }
22
+
23
+ it { should == 8 }
24
+ end
25
+
26
+ context "-0x800000000 .. -0x7fffffffffffffff" do
27
+ subject { described_class.new(-0x7fffffffffffffff).width }
28
+
29
+ it { should == 8 }
30
+ end
31
+
32
+ context "0x10000 .. 0xffffffff" do
33
+ subject { described_class.new(0xffffffff).width }
34
+
35
+ it { should == 4 }
36
+ end
37
+
38
+ context "-0x80000 .. -0x7fffffff" do
39
+ subject { described_class.new(-0x7fffffff).width }
40
+
41
+ it { should == 4 }
42
+ end
43
+
44
+ context "0x100 .. 0xffff" do
45
+ subject { described_class.new(0xffff).width }
46
+
47
+ it { should == 2 }
48
+ end
49
+
50
+ context "-0x80 .. -0x7fff" do
51
+ subject { described_class.new(-0x7fff).width }
52
+
53
+ it { should == 2 }
54
+ end
55
+
56
+ context "0x0 .. 0xff" do
57
+ subject { described_class.new(0xff).width }
58
+
59
+ it { should == 1 }
60
+ end
61
+
62
+ context "0x0 .. -0x7f" do
63
+ subject { described_class.new(-0x7f).width }
64
+
65
+ it { should == 1 }
66
+ end
67
+ end
68
+ end
69
+
70
+ describe "#to_i" do
71
+ subject { described_class.new(value) }
72
+
73
+ it "should return the value" do
74
+ subject.to_i.should == value
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,62 @@
1
+ require 'spec_helper'
2
+
3
+ require 'ronin/asm/instruction'
4
+ require 'ronin/asm/register'
5
+ require 'ronin/asm/immediate_operand'
6
+ require 'ronin/asm/memory_operand'
7
+
8
+ describe Instruction do
9
+ let(:register) { Register.new(:eax, 4) }
10
+ let(:immediate) { ImmediateOperand.new(0xff, 1) }
11
+
12
+ describe "#initialize" do
13
+ let(:name) { :mov }
14
+ let(:operands) { [immediate, register] }
15
+
16
+ subject { described_class.new(name,operands) }
17
+
18
+ it "should set the name" do
19
+ subject.name.should == :mov
20
+ end
21
+
22
+ it "should set the operands" do
23
+ subject.operands.should == operands
24
+ end
25
+
26
+ context "when given an Integer operand" do
27
+ let(:integer) { 0xff }
28
+
29
+ subject { described_class.new(name, [integer, register]) }
30
+
31
+ it "should wrap the operand to in a ImmediateOperand" do
32
+ subject.operands[0].should be_kind_of(ImmediateOperand)
33
+ subject.operands[0].value.should == integer
34
+ end
35
+ end
36
+
37
+ context "when given a nil operand" do
38
+ subject { described_class.new(name, [nil, register]) }
39
+
40
+ it "should wrap the operand to in a ImmediateOperand" do
41
+ subject.operands[0].should be_kind_of(ImmediateOperand)
42
+ subject.operands[0].value.should == 0
43
+ end
44
+ end
45
+ end
46
+
47
+ describe "#width" do
48
+ subject { described_class.new(:mov, [immediate, register]) }
49
+
50
+ it "should return the maximum width of the operands" do
51
+ subject.width.should == register.width
52
+ end
53
+
54
+ context "when one of the operands does not define #width" do
55
+ subject { described_class.new(:mov, [:label, register]) }
56
+
57
+ it "should ignore them" do
58
+ subject.width.should == register.width
59
+ end
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,80 @@
1
+ require 'spec_helper'
2
+
3
+ require 'ronin/asm/memory_operand'
4
+ require 'ronin/asm/register'
5
+
6
+ describe MemoryOperand do
7
+ let(:register) { Register.new(:eax, 4) }
8
+
9
+ describe "#initialize" do
10
+ its(:base) { should be_nil }
11
+ its(:offset) { should == 0 }
12
+ its(:index) { should be_nil }
13
+ its(:scale) { should == 1 }
14
+
15
+ it "should only accept nil and a Register for base" do
16
+ lambda {
17
+ described_class.new(Object.new)
18
+ }.should raise_error(TypeError)
19
+ end
20
+
21
+ it "should only accept Integers for offset" do
22
+ lambda {
23
+ described_class.new(register,2.0)
24
+ }.should raise_error(TypeError)
25
+ end
26
+
27
+ it "should only accept nil and a Register for index" do
28
+ lambda {
29
+ described_class.new(register,0,Object.new)
30
+ }.should raise_error(TypeError)
31
+ end
32
+
33
+ it "should only accept Integers for offset" do
34
+ lambda {
35
+ described_class.new(register,0,nil,2.0)
36
+ }.should 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 "should add to offset" do
47
+ subject.offset.should == 8
48
+ end
49
+
50
+ it "should not change base, index or scale" do
51
+ subject.base.should == operand.base
52
+ subject.index.should == operand.index
53
+ subject.scale.should == 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 "should subtract from offset" do
63
+ subject.offset.should == 2
64
+ end
65
+
66
+ it "should not change base, index or scale" do
67
+ subject.base.should == operand.base
68
+ subject.index.should == operand.index
69
+ subject.scale.should == operand.scale
70
+ end
71
+ end
72
+
73
+ describe "#width" do
74
+ subject { described_class.new(register,10) }
75
+
76
+ it "should return the width of base" do
77
+ subject.width.should == register.width
78
+ end
79
+ end
80
+ end