indis-core 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.md ADDED
@@ -0,0 +1,5 @@
1
+ [![Build Status](https://secure.travis-ci.org/indis/indis-core.png?branch=master)](http://travis-ci.org/indis/indis-core)
2
+
3
+ # Indis::Core
4
+
5
+ This is the base of indis framework, core classes that deal with target image load and analysis.
data/Rakefile ADDED
@@ -0,0 +1,9 @@
1
+ #!/usr/bin/env rake
2
+
3
+ require "bundler/gem_tasks"
4
+ Bundler::GemHelper.install_tasks
5
+
6
+ require 'rspec/core/rake_task'
7
+ RSpec::Core::RakeTask.new('spec')
8
+
9
+ task :default => :spec
@@ -0,0 +1,20 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../lib/indis-core/version', __FILE__)
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.authors = ["Vladimir Pouzanov"]
6
+ gem.email = ["farcaller@gmail.com"]
7
+ gem.description = "Core components of indis, the intelligent disassembler framework"
8
+ gem.summary = "Core indis components"
9
+ gem.homepage = "http://www.indis.org/"
10
+ gem.license = "GPL-3"
11
+
12
+ gem.files = `git ls-files`.split($\)
13
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
14
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
15
+ gem.name = "indis-core"
16
+ gem.require_paths = ["lib"]
17
+ gem.version = Indis::VERSION
18
+
19
+ gem.add_development_dependency 'rspec'
20
+ end
data/lib/indis-core.rb ADDED
@@ -0,0 +1,22 @@
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/version'
20
+
21
+ module Indis
22
+ end
@@ -0,0 +1,61 @@
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
+ # BinaryFormat manages a set of known binary formats and provides support
22
+ # for guessing the correct format for target binary.
23
+ module BinaryFormat
24
+
25
+ # Returns a list of all known binary formats.
26
+ #
27
+ # @return [Array] all known binary formats.
28
+ def self.known_formats
29
+ fmt = []
30
+ self.constants.each do |c|
31
+ e = const_get(c)
32
+ fmt << e if e.is_a?(Class) && e.superclass == Format
33
+ end
34
+ fmt
35
+ end
36
+
37
+ # Base class for any binary format.
38
+ class Format
39
+ # Basic constructor takes care of storing the target and io stream.
40
+ def initialize(target, io)
41
+ @target = target
42
+ @io = io
43
+ end
44
+
45
+ # @abstract Returns the format magic bytes.
46
+ #
47
+ # @return [Fixnum] Magic bytes that are checked against the first bytes in binary.
48
+ def self.magic
49
+ raise RuntimeError
50
+ end
51
+
52
+ # @abstract Returns the human-readable format name.
53
+ #
54
+ # @return [String] Human-readable format name.
55
+ def self.name
56
+ raise RuntimeError
57
+ end
58
+ end
59
+
60
+ end
61
+ end
@@ -0,0 +1,64 @@
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
+ # DataEntity represens "data bytes" that are directly used e.g. in a load
24
+ # to register instruction. There are four sizes of data: 8, 16, 32 and 64
25
+ # bits long, namely +byte+, +word+, +dword+ and +qword+
26
+ class DataEntity < Entity
27
+ KIND = {
28
+ 1 => :byte,
29
+ 2 => :word,
30
+ 4 => :dword,
31
+ 8 => :qword,
32
+ }
33
+
34
+ NAMED_TYPE = {
35
+ byte: 'DCB',
36
+ word: 'DCW',
37
+ dword: 'DCD',
38
+ qword: 'DCQ'
39
+ }
40
+
41
+ attr_reader :value # @return [Fixnum] the value of entity
42
+
43
+ # @param [Fixnum] ofs virtual address
44
+ # @param [Fixnum] size entity size in bytes
45
+ # @param [Indus::VMMap] vmmap map of the target to load value from
46
+ # @raise [AttributeError] if the size is not one of the known values
47
+ def initialize(ofs, size, vmmap)
48
+ raise ArgumentError, "Unaligned size" unless KIND[size]
49
+ super ofs
50
+ @size = size
51
+ @value = vmmap.bytes_at(ofs, size).reverse_each.reduce(0) { |v, i| (v << 8) + i }
52
+ end
53
+
54
+ # @return [KIND] entity kind
55
+ def kind
56
+ KIND[@size]
57
+ end
58
+
59
+ def to_s
60
+ "#{NAMED_TYPE[kind]}\t#{sprintf("%0#{@size*2}X", @value)}"
61
+ end
62
+ end
63
+
64
+ end
@@ -0,0 +1,43 @@
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
+ # Entity represens an object mapped to some given bytes in the traget's
22
+ # virtual address space
23
+ class Entity
24
+ attr_reader :vmaddr # @return [Fixnum] virtaul address of the entity
25
+
26
+ # @abstract You must provide @size value in a subclass
27
+ # @return [Fixnum] entity size in bytes
28
+ attr_reader :size
29
+
30
+ attr_reader :tags # @return [Hash] cross-references and additional attributes of entity
31
+
32
+ def initialize(ofs)
33
+ @vmaddr = ofs
34
+ @tags = {}
35
+ end
36
+
37
+ def unmap
38
+ # TODO: Reverse unmap tags
39
+ @tags = nil
40
+ end
41
+ end
42
+
43
+ end
@@ -0,0 +1,44 @@
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
+ class Section
22
+ attr_reader :name, :segment
23
+ attr_reader :vmaddr, :vmsize, :bytes
24
+
25
+ def initialize(seg, name, vmaddr, vmsize, iooff)
26
+ @segment = seg
27
+ @name = name
28
+ @vmaddr = vmaddr
29
+ @vmsize = vmsize
30
+ @iooff = iooff
31
+ end
32
+
33
+ def to_vmrange
34
+ @vmaddr..(@vmaddr+@vmsize)
35
+ end
36
+
37
+ def bytes
38
+ s = @iooff - @segment.iooff
39
+ e = s + @vmsize
40
+ @segment.bytes[s...e]
41
+ end
42
+ end
43
+
44
+ end
@@ -0,0 +1,75 @@
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
+ # A segment describes one given segment contained in the target binary.
22
+ # Segment's virtual size might be different from physical (stored in file),
23
+ # in this case the data is padded with zeroes
24
+ #
25
+ # @note this class is heavily based on Mach-O
26
+ class Segment
27
+ # Contains a list of current segment sections
28
+ # @return [Array]
29
+ attr_reader :sections
30
+
31
+ attr_reader :target # @return [Indis::Target] owning target
32
+
33
+ attr_reader :name # @return [String] segment name
34
+
35
+ attr_reader :vmaddr # @return [Fixnum] starting virtual address
36
+
37
+ attr_reader :vmsize # @return [Fixnum] segment size
38
+
39
+ # The whole (zero-padded if required) bytes string for a segment
40
+ # @return [String]
41
+ attr_reader :bytes
42
+
43
+ attr_reader :iooff # @return [Fixnum] offset from the beginning of of file to segment data
44
+
45
+ # @param [Indis::Target] target the target containing a segment
46
+ # @param [String] name segment name
47
+ # @param [Fixnum] vmaddr starting virtual address
48
+ # @param [Fixnum] vmsize size (in bytes)
49
+ # @param [Fixnum] iooff offset from the beginning of of file to segment data
50
+ # @param [String] bytes known data bytes (loaded from binary)
51
+ def initialize(target, name, vmaddr, vmsize, iooff, bytes)
52
+ @target = target
53
+ @name = name
54
+ @sections = []
55
+
56
+ @vmaddr = vmaddr
57
+ @vmsize = vmsize
58
+ @iooff = iooff
59
+ @bytes = pad_bytes(bytes)
60
+ end
61
+
62
+ # Constructs a Range of virtual addresses used by segment
63
+ #
64
+ # @return [Range] the range of all addresses
65
+ def to_vmrange
66
+ @vmaddr..(@vmaddr+@vmsize)
67
+ end
68
+
69
+ private
70
+ def pad_bytes(bytes)
71
+ bytes + ("\x0" * (@vmsize - bytes.length))
72
+ end
73
+ end
74
+
75
+ end
@@ -0,0 +1,33 @@
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
+ class Symbol
22
+ attr_reader :name, :section, :format_sym, :image, :vmaddr
23
+
24
+ def initialize(name, section, image, vmaddr, format_sym)
25
+ @name = name
26
+ @section = section
27
+ @image = image
28
+ @format_sym = format_sym
29
+ @vmaddr = vmaddr
30
+ end
31
+ end
32
+
33
+ end
@@ -0,0 +1,68 @@
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/binary_format'
20
+ require 'indis-core/vmmap'
21
+
22
+ module Indis
23
+
24
+ # The main entry point for indis. Target describes a given binary, performs
25
+ # format matching, loading the binary into memory and primary processing.
26
+ class Target
27
+ attr_reader :io # @return [IO] IO object for target binary
28
+
29
+ attr_reader :format # @return [Indis::BinaryFormat::Format] binary format of the target
30
+
31
+ attr_reader :vmmap # @return [Indis::VMMap] virtual memory map
32
+
33
+ attr_accessor :segments # @return [Array] list of all processed {Indis::Segment segments}
34
+
35
+ attr_accessor :symbols # @return [Array] list of all processed {Indis::Symbol symbols}
36
+
37
+ # @param [String] filename target binary file name
38
+ # @raise [AttributeError] if the file does not exist
39
+ # @raise [RuntimeError] if there is no known format for magic or there are several matching formats
40
+ def initialize(filename)
41
+ raise AttributeError, "File does not exist" unless FileTest.file?(filename)
42
+ @filename = filename
43
+ @io = StringIO.new(File.open(filename).read().force_encoding('BINARY'))
44
+
45
+ magic = @io.read(4).unpack('V')[0]
46
+ @io.seek(-4, IO::SEEK_CUR)
47
+
48
+ fmts = BinaryFormat.known_formats.map { |f| f if f.magic == magic }.compact
49
+
50
+ raise RuntimeError, "Unknown format for magic #{magic.to_s(16)}" if fmts.length == 0
51
+ raise RuntimeError, "Several possible formats: #{fmts}" if fmts.length > 1
52
+
53
+ @format = fmts.first.new(self, @io)
54
+
55
+ @vmmap = VMMap.new(self)
56
+ end
57
+
58
+ # A target can consist of several other targets (e.g. fat mach-o). In such
59
+ # a case the target is +meta+. It does not have any segments, sections or vmmap,
60
+ # but it has one or several subtargets.
61
+ # @todo implement meta targets
62
+ # @return True if the target is a meta target
63
+ def meta?
64
+ @subtargets && @subtargets.length > 0
65
+ end
66
+ end
67
+
68
+ end