indis-core 0.1.3 → 0.1.4
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/.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
|