indis-core 0.1.3 → 0.1.4
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +1 -0
- data/.rspec +1 -0
- data/.travis.yml +1 -0
- data/lib/indis-core/binary_architecture.rb +50 -0
- data/lib/indis-core/binaryops_fixnum.rb +54 -0
- data/lib/indis-core/cstring_entity.rb +52 -0
- data/lib/indis-core/data_entity.rb +4 -0
- data/lib/indis-core/section.rb +1 -1
- data/lib/indis-core/segment.rb +1 -1
- data/lib/indis-core/symbol.rb +3 -4
- data/lib/indis-core/target.rb +10 -1
- data/lib/indis-core/version.rb +1 -1
- data/lib/indis-core/vmmap.rb +10 -8
- data/spec/indis-core/cstring_entity_spec.rb +12 -0
- data/spec/indis-core/section_spec.rb +1 -1
- data/spec/indis-core/segment_spec.rb +1 -1
- data/spec/indis-core/target_spec.rb +25 -4
- metadata +7 -2
data/.gitignore
CHANGED
data/.rspec
CHANGED
data/.travis.yml
CHANGED
@@ -0,0 +1,50 @@
|
|
1
|
+
##############################################################################
|
2
|
+
# Indis framework #
|
3
|
+
# Copyright (C) 2012 Vladimir "Farcaller" Pouzanov <farcaller@gmail.com> #
|
4
|
+
# #
|
5
|
+
# This program is free software: you can redistribute it and/or modify #
|
6
|
+
# it under the terms of the GNU General Public License as published by #
|
7
|
+
# the Free Software Foundation, either version 3 of the License, or #
|
8
|
+
# (at your option) any later version. #
|
9
|
+
# #
|
10
|
+
# This program is distributed in the hope that it will be useful, #
|
11
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
|
12
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
|
13
|
+
# GNU General Public License for more details. #
|
14
|
+
# #
|
15
|
+
# You should have received a copy of the GNU General Public License #
|
16
|
+
# along with this program. If not, see <http://www.gnu.org/licenses/>. #
|
17
|
+
##############################################################################
|
18
|
+
|
19
|
+
module Indis
|
20
|
+
|
21
|
+
# BinaryArchitecture manages all known architectures and provides support
|
22
|
+
# for resolving the correct class for named architecture
|
23
|
+
module BinaryArchitecture
|
24
|
+
|
25
|
+
def self.known_archs
|
26
|
+
fmt = {}
|
27
|
+
self.constants.each do |c|
|
28
|
+
e = const_get(c)
|
29
|
+
fmt[e.name] = e if e.is_a?(Class) && e.superclass == Architecture
|
30
|
+
end
|
31
|
+
fmt
|
32
|
+
end
|
33
|
+
|
34
|
+
# Base class for any binary architecture
|
35
|
+
class Architecture
|
36
|
+
# Basic constructor takes care of storing the target
|
37
|
+
def initialize(target)
|
38
|
+
@target = target
|
39
|
+
end
|
40
|
+
|
41
|
+
# @abstract Returns the format magic bytes.
|
42
|
+
#
|
43
|
+
# @return [Symbol] symbolicated name of the architecture
|
44
|
+
def self.name
|
45
|
+
raise RuntimeError, "#name not implemented in architecture #{self.class}"
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
##############################################################################
|
2
|
+
# Indis framework #
|
3
|
+
# Copyright (C) 2012 Vladimir "Farcaller" Pouzanov <farcaller@gmail.com> #
|
4
|
+
# #
|
5
|
+
# This program is free software: you can redistribute it and/or modify #
|
6
|
+
# it under the terms of the GNU General Public License as published by #
|
7
|
+
# the Free Software Foundation, either version 3 of the License, or #
|
8
|
+
# (at your option) any later version. #
|
9
|
+
# #
|
10
|
+
# This program is distributed in the hope that it will be useful, #
|
11
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
|
12
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
|
13
|
+
# GNU General Public License for more details. #
|
14
|
+
# #
|
15
|
+
# You should have received a copy of the GNU General Public License #
|
16
|
+
# along with this program. If not, see <http://www.gnu.org/licenses/>. #
|
17
|
+
##############################################################################
|
18
|
+
|
19
|
+
# BinaryopsFixnum is a lightweight BinaryopsString, a few methods extending
|
20
|
+
# Fixnum with enough operations so that it's usable in bit calculations.
|
21
|
+
class Fixnum
|
22
|
+
def bitlen=(bitlen)
|
23
|
+
@bitlen = bitlen
|
24
|
+
end
|
25
|
+
|
26
|
+
def bitlen
|
27
|
+
@bitlen ||= self.to_s(2).length
|
28
|
+
end
|
29
|
+
|
30
|
+
def set_bitlen(i)
|
31
|
+
@bitlen = i
|
32
|
+
self
|
33
|
+
end
|
34
|
+
|
35
|
+
def msb
|
36
|
+
self >> (self.bitlen-1)
|
37
|
+
end
|
38
|
+
|
39
|
+
def to_signed
|
40
|
+
if msb == 1
|
41
|
+
- ((1 << @bitlen) - self)
|
42
|
+
else
|
43
|
+
self
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
alias :old_range :[]
|
48
|
+
|
49
|
+
def [](range)
|
50
|
+
return old_range(range) unless range.is_a?(Range)
|
51
|
+
raise ArgumentError, "Only inclusive ranges are supported" if range.exclude_end?
|
52
|
+
(self >> range.begin) & ((1 << (range.end-range.begin+1)) - 1)
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
##############################################################################
|
2
|
+
# Indis framework #
|
3
|
+
# Copyright (C) 2012 Vladimir "Farcaller" Pouzanov <farcaller@gmail.com> #
|
4
|
+
# #
|
5
|
+
# This program is free software: you can redistribute it and/or modify #
|
6
|
+
# it under the terms of the GNU General Public License as published by #
|
7
|
+
# the Free Software Foundation, either version 3 of the License, or #
|
8
|
+
# (at your option) any later version. #
|
9
|
+
# #
|
10
|
+
# This program is distributed in the hope that it will be useful, #
|
11
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
|
12
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
|
13
|
+
# GNU General Public License for more details. #
|
14
|
+
# #
|
15
|
+
# You should have received a copy of the GNU General Public License #
|
16
|
+
# along with this program. If not, see <http://www.gnu.org/licenses/>. #
|
17
|
+
##############################################################################
|
18
|
+
|
19
|
+
require 'indis-core/entity'
|
20
|
+
|
21
|
+
module Indis
|
22
|
+
|
23
|
+
class CStringEntity < Entity
|
24
|
+
attr_reader :value # @return [String] the value of entity
|
25
|
+
|
26
|
+
# @param [Fixnum] ofs virtual address
|
27
|
+
# @param [Indus::VMMap] vmmap map of the target to load value from
|
28
|
+
def initialize(ofs, vmmap)
|
29
|
+
super ofs
|
30
|
+
|
31
|
+
@value = ''
|
32
|
+
addr = ofs
|
33
|
+
begin
|
34
|
+
c = vmmap.byte_at(addr)
|
35
|
+
@value += c.chr
|
36
|
+
addr += 1
|
37
|
+
end while c != 0
|
38
|
+
|
39
|
+
@size = @value.length
|
40
|
+
end
|
41
|
+
|
42
|
+
def to_s
|
43
|
+
"DCB\t\"#{@value[0...-1]}\",0"
|
44
|
+
end
|
45
|
+
|
46
|
+
def to_a
|
47
|
+
['DCB', "\"#{@value[0...-1]}\",0"]
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
data/lib/indis-core/section.rb
CHANGED
data/lib/indis-core/segment.rb
CHANGED
data/lib/indis-core/symbol.rb
CHANGED
@@ -19,18 +19,17 @@
|
|
19
19
|
module Indis
|
20
20
|
|
21
21
|
class Symbol
|
22
|
-
attr_reader :name, :section, :
|
22
|
+
attr_reader :name, :section, :image, :vmaddr, :type
|
23
23
|
|
24
|
-
def initialize(name, section, image, vmaddr
|
24
|
+
def initialize(name, section, image, vmaddr)
|
25
25
|
@name = name
|
26
26
|
@section = section
|
27
27
|
@image = image
|
28
|
-
@format_sym = format_sym
|
29
28
|
@vmaddr = vmaddr
|
30
29
|
end
|
31
30
|
|
32
31
|
def to_s
|
33
|
-
"
|
32
|
+
"#<#{self.class} #{@name} at #{@vmaddr.to_s 16}>"
|
34
33
|
end
|
35
34
|
end
|
36
35
|
|
data/lib/indis-core/target.rb
CHANGED
@@ -18,6 +18,7 @@
|
|
18
18
|
|
19
19
|
require 'stringio'
|
20
20
|
require 'indis-core/binary_format'
|
21
|
+
require 'indis-core/binary_architecture'
|
21
22
|
require 'indis-core/vmmap'
|
22
23
|
|
23
24
|
module Indis
|
@@ -29,6 +30,8 @@ module Indis
|
|
29
30
|
|
30
31
|
attr_reader :format # @return [Indis::BinaryFormat::Format] binary format of the target
|
31
32
|
|
33
|
+
attr_reader :architecture # @return [Indis::BinaryArchitecture::Arcitecture] binary architecture of the target
|
34
|
+
|
32
35
|
attr_reader :vmmap # @return [Indis::VMMap] virtual memory map
|
33
36
|
|
34
37
|
attr_accessor :segments # @return [Array<Indis::Segment>] list of all processed {Indis::Segment segments}
|
@@ -61,6 +64,10 @@ module Indis
|
|
61
64
|
@format = @format_class.new(self, @io)
|
62
65
|
@format_class = nil
|
63
66
|
|
67
|
+
archClass = BinaryArchitecture.known_archs[@format.architecture]
|
68
|
+
raise RuntimeError, "Architecture not defined" unless archClass
|
69
|
+
@architecture = archClass.new(self)
|
70
|
+
|
64
71
|
@vmmap = VMMap.new(self)
|
65
72
|
|
66
73
|
@format_load_complete = true
|
@@ -107,7 +114,9 @@ module Indis
|
|
107
114
|
def resolve_symbol_at_address(vmaddr)
|
108
115
|
s = @symbols.find { |sym| sym.vmaddr == vmaddr }
|
109
116
|
return s if s
|
110
|
-
|
117
|
+
s = @format.resolve_symbol_at_address(vmaddr) if @format.respond_to?(:resolve_symbol_at_address)
|
118
|
+
@symbols << s if s
|
119
|
+
s
|
111
120
|
end
|
112
121
|
|
113
122
|
private
|
data/lib/indis-core/version.rb
CHANGED
data/lib/indis-core/vmmap.rb
CHANGED
@@ -115,25 +115,27 @@ module Indis
|
|
115
115
|
def [](range)
|
116
116
|
return entity_at(range) if range.is_a?(Fixnum)
|
117
117
|
|
118
|
-
raise ArgumentError unless range.is_a?(Range)
|
118
|
+
raise ArgumentError, "Unknown argument type #{range.class}" unless range.is_a?(Range)
|
119
119
|
seg = segment_at(range.begin)
|
120
|
-
raise ArgumentError unless seg
|
121
|
-
|
120
|
+
raise ArgumentError, "No segment mapped at #{range.begin}" unless seg
|
121
|
+
range_max = range.exclude_end? ? range.last-1 : range.last
|
122
|
+
raise ArgumentError, "Segment #{seg} at #{range.begin}, but segment #{segment_at(range_max)} at #{range.end}" unless seg == segment_at(range_max)
|
122
123
|
|
123
|
-
a =
|
124
|
+
a = Array.new(range_max - range.begin + 1)
|
124
125
|
ofs = range.begin
|
126
|
+
range_begin = range.begin
|
127
|
+
seg_vmaddr = seg.vmaddr
|
125
128
|
|
126
129
|
begin
|
127
130
|
b = @blocks[ofs]
|
128
131
|
if b
|
129
|
-
a
|
130
|
-
(b.size-1).times { a << nil }
|
132
|
+
a[ofs-range_begin] = b
|
131
133
|
ofs += b.size
|
132
134
|
else
|
133
|
-
a
|
135
|
+
a[ofs-range_begin] = seg.bytes[ofs-seg_vmaddr].ord
|
134
136
|
ofs += 1
|
135
137
|
end
|
136
|
-
end while ofs <=
|
138
|
+
end while ofs <= range_max
|
137
139
|
a
|
138
140
|
end
|
139
141
|
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
require 'indis-core/cstring_entity'
|
2
|
+
|
3
|
+
describe Indis::CStringEntity do
|
4
|
+
it "should load its value from vmmap" do
|
5
|
+
str = "hello\0world".unpack('C*')
|
6
|
+
map = double('VMMap')
|
7
|
+
map.should_receive(:byte_at) { |i| str[i] }.exactly(6).times
|
8
|
+
e = Indis::CStringEntity.new(0, map)
|
9
|
+
e.to_s.should == "DCB\t\"hello\",0"
|
10
|
+
e.value.should == "hello\x0"
|
11
|
+
end
|
12
|
+
end
|
@@ -3,7 +3,7 @@ require 'indis-core/section'
|
|
3
3
|
describe Indis::Section do
|
4
4
|
it "should provide a correct range for its vm region" do
|
5
5
|
sect = Indis::Section.new(double('Segment'), '__text', 0x4096, 120, 0, :undef, [])
|
6
|
-
sect.to_vmrange.should == (0x4096
|
6
|
+
sect.to_vmrange.should == (0x4096...0x410e)
|
7
7
|
end
|
8
8
|
|
9
9
|
it "should provide bytes value from segment based on io offset" do
|
@@ -3,7 +3,7 @@ require 'indis-core/segment'
|
|
3
3
|
describe Indis::Segment do
|
4
4
|
it "should provide a correct range for its vm region" do
|
5
5
|
seg = Indis::Segment.new(double('Target'), '__TEXT', 0x4096, 120, 0, '')
|
6
|
-
seg.to_vmrange.should == (0x4096
|
6
|
+
seg.to_vmrange.should == (0x4096...0x410e)
|
7
7
|
end
|
8
8
|
|
9
9
|
it "should provide bytes value based on io offset" do
|
@@ -1,12 +1,24 @@
|
|
1
1
|
require 'indis-core/target'
|
2
2
|
|
3
|
+
def macho_format_cls_double
|
4
|
+
double('MachO Class', magic: 0xfeedface, name: 'Mach-O',
|
5
|
+
new: double('MachO', architecture: :test)
|
6
|
+
)
|
7
|
+
end
|
8
|
+
|
9
|
+
module Indis; module BinaryArchitecture;
|
10
|
+
class TestArch < Architecture
|
11
|
+
def self.name; :test; end
|
12
|
+
end
|
13
|
+
end; end
|
14
|
+
|
3
15
|
describe Indis::Target do
|
4
16
|
it "should require an existing file to operate" do
|
5
17
|
expect { Indis::Target.new("qwerty") }.to raise_error
|
6
18
|
end
|
7
19
|
|
8
20
|
it "should load file for known format" do
|
9
|
-
fmt =
|
21
|
+
fmt = macho_format_cls_double
|
10
22
|
Indis::BinaryFormat.stub(:known_formats).and_return([fmt])
|
11
23
|
t = Indis::Target.new("spec/fixtures/single-object.o")
|
12
24
|
t.load
|
@@ -14,12 +26,21 @@ describe Indis::Target do
|
|
14
26
|
t.format.should_not be_nil
|
15
27
|
end
|
16
28
|
|
29
|
+
it "should have an architecture set up after loading" do
|
30
|
+
fmt = macho_format_cls_double
|
31
|
+
Indis::BinaryFormat.stub(:known_formats).and_return([fmt])
|
32
|
+
t = Indis::Target.new("spec/fixtures/single-object.o")
|
33
|
+
t.architecture.should be_nil
|
34
|
+
t.load
|
35
|
+
t.architecture.should_not be_nil
|
36
|
+
end
|
37
|
+
|
17
38
|
it "should raise if there is no known format to process binary" do
|
18
39
|
expect { Indis::Target.new("spec/fixtures/single-object.o") }.to raise_error(RuntimeError)
|
19
40
|
end
|
20
41
|
|
21
42
|
it "should trigger load event" do
|
22
|
-
fmt =
|
43
|
+
fmt = macho_format_cls_double
|
23
44
|
Indis::BinaryFormat.stub(:known_formats).and_return([fmt])
|
24
45
|
t = Indis::Target.new("spec/fixtures/single-object.o")
|
25
46
|
|
@@ -32,7 +53,7 @@ describe Indis::Target do
|
|
32
53
|
end
|
33
54
|
|
34
55
|
it "should queue up events that happen before load" do
|
35
|
-
fmt =
|
56
|
+
fmt = macho_format_cls_double
|
36
57
|
Indis::BinaryFormat.stub(:known_formats).and_return([fmt])
|
37
58
|
t = Indis::Target.new("spec/fixtures/single-object.o")
|
38
59
|
|
@@ -48,7 +69,7 @@ describe Indis::Target do
|
|
48
69
|
end
|
49
70
|
|
50
71
|
it "should pass arguments to event subscriptions" do
|
51
|
-
fmt =
|
72
|
+
fmt = macho_format_cls_double
|
52
73
|
Indis::BinaryFormat.stub(:known_formats).and_return([fmt])
|
53
74
|
t = Indis::Target.new("spec/fixtures/single-object.o")
|
54
75
|
t.load
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: indis-core
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.4
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-
|
12
|
+
date: 2012-05-11 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rspec
|
@@ -44,8 +44,11 @@ files:
|
|
44
44
|
- Rakefile
|
45
45
|
- indis-core.gemspec
|
46
46
|
- lib/indis-core.rb
|
47
|
+
- lib/indis-core/binary_architecture.rb
|
47
48
|
- lib/indis-core/binary_format.rb
|
49
|
+
- lib/indis-core/binaryops_fixnum.rb
|
48
50
|
- lib/indis-core/binaryops_string.rb
|
51
|
+
- lib/indis-core/cstring_entity.rb
|
49
52
|
- lib/indis-core/data_entity.rb
|
50
53
|
- lib/indis-core/entity.rb
|
51
54
|
- lib/indis-core/section.rb
|
@@ -57,6 +60,7 @@ files:
|
|
57
60
|
- spec/fixtures/single-object.o
|
58
61
|
- spec/indis-core/binary_format_spec.rb
|
59
62
|
- spec/indis-core/binaryops_string_spec.rb
|
63
|
+
- spec/indis-core/cstring_entity_spec.rb
|
60
64
|
- spec/indis-core/data_entity_spec.rb
|
61
65
|
- spec/indis-core/section_spec.rb
|
62
66
|
- spec/indis-core/segment_spec.rb
|
@@ -93,6 +97,7 @@ test_files:
|
|
93
97
|
- spec/fixtures/single-object.o
|
94
98
|
- spec/indis-core/binary_format_spec.rb
|
95
99
|
- spec/indis-core/binaryops_string_spec.rb
|
100
|
+
- spec/indis-core/cstring_entity_spec.rb
|
96
101
|
- spec/indis-core/data_entity_spec.rb
|
97
102
|
- spec/indis-core/section_spec.rb
|
98
103
|
- spec/indis-core/segment_spec.rb
|