indis-macho 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +17 -0
- data/.rspec +2 -0
- data/.travis.yml +5 -0
- data/Gemfile +5 -0
- data/Gemfile.ci +6 -0
- data/LICENSE +674 -0
- data/README.md +6 -0
- data/Rakefile +9 -0
- data/indis-macho.gemspec +21 -0
- data/lib/indis-macho.rb +224 -0
- data/lib/indis-macho/command.rb +271 -0
- data/lib/indis-macho/symbol.rb +143 -0
- data/lib/indis-macho/version.rb +23 -0
- data/spec/fixtures/app-arm-release.o +0 -0
- data/spec/fixtures/single-object.o +0 -0
- data/spec/indis-macho/binary_format_spec.rb +7 -0
- data/spec/indis-macho/macho_spec.rb +100 -0
- data/spec/spec_helper.rb +8 -0
- metadata +103 -0
@@ -0,0 +1,143 @@
|
|
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
|
+
module MachO
|
21
|
+
|
22
|
+
class Symbol
|
23
|
+
STAB_MASK = 0xe0
|
24
|
+
PEXT_MASK = 0x10
|
25
|
+
TYPE_MASK = 0x0e
|
26
|
+
EXT_MASK = 0x01
|
27
|
+
TYPE = {
|
28
|
+
0x0 => :UNDEF,
|
29
|
+
0x2 => :ABS,
|
30
|
+
0xe => :SECT,
|
31
|
+
0xc => :PBUD,
|
32
|
+
0xa => :INDR,
|
33
|
+
}
|
34
|
+
STAB = {
|
35
|
+
0x20 => :N_GSYM,
|
36
|
+
0x22 => :N_FNAME,
|
37
|
+
0x24 => :N_FUN,
|
38
|
+
0x26 => :N_STSYM,
|
39
|
+
0x28 => :N_LCSYM,
|
40
|
+
0x2e => :N_BNSYM,
|
41
|
+
0x3c => :N_OPT,
|
42
|
+
0x40 => :N_RSYM,
|
43
|
+
0x44 => :N_SLINE,
|
44
|
+
0x4e => :N_ENSYM,
|
45
|
+
0x60 => :N_SSYM,
|
46
|
+
0x64 => :N_SO,
|
47
|
+
0x66 => :N_OSO,
|
48
|
+
0x80 => :N_LSYM,
|
49
|
+
0x82 => :N_BINCL,
|
50
|
+
0x84 => :N_SOL,
|
51
|
+
0x86 => :N_PARAMS,
|
52
|
+
0x88 => :N_VERSION,
|
53
|
+
0x8A => :N_OLEVEL,
|
54
|
+
0xa0 => :N_PSYM,
|
55
|
+
0xa2 => :N_EINCL,
|
56
|
+
0xa4 => :N_ENTRY,
|
57
|
+
0xc0 => :N_LBRAC,
|
58
|
+
0xc2 => :N_EXCL,
|
59
|
+
0xe0 => :N_RBRAC,
|
60
|
+
0xe2 => :N_BCOMM,
|
61
|
+
0xe4 => :N_ECOMM,
|
62
|
+
0xe8 => :N_ECOML,
|
63
|
+
0xfe => :N_LENG,
|
64
|
+
}
|
65
|
+
REFERENCE_TYPE_MASK = 0xf
|
66
|
+
DESC_REFERENCE = {
|
67
|
+
0x0 => :REFERENCE_FLAG_UNDEFINED_NON_LAZY,
|
68
|
+
0x1 => :REFERENCE_FLAG_UNDEFINED_LAZY,
|
69
|
+
0x2 => :REFERENCE_FLAG_DEFINED,
|
70
|
+
0x3 => :REFERENCE_FLAG_PRIVATE_DEFINED,
|
71
|
+
0x4 => :REFERENCE_FLAG_PRIVATE_UNDEFINED_NON_LAZY,
|
72
|
+
0x5 => :REFERENCE_FLAG_PRIVATE_UNDEFINED_LAZY,
|
73
|
+
}
|
74
|
+
DESC_ADDITIONAL = {
|
75
|
+
0x08 => :N_ARM_THUMB_DEF,
|
76
|
+
0x10 => :REFERENCED_DYNAMICALLY,
|
77
|
+
0x20 => :N_DESC_DISCARDED_OR_N_NO_DEAD_STRIP, # TODO: resolve mach file type
|
78
|
+
0x40 => :N_WEAK_REF,
|
79
|
+
0x80 => :N_WEAK_DEF,
|
80
|
+
}
|
81
|
+
LIBRARY_ORDINAL = {
|
82
|
+
0x0 => :SELF_LIBRARY_ORDINAL,
|
83
|
+
0xfe => :DYNAMIC_LOOKUP_ORDINAL,
|
84
|
+
0xff => :EXECUTABLE_ORDINAL,
|
85
|
+
}
|
86
|
+
|
87
|
+
attr_reader :name, :sect, :value
|
88
|
+
|
89
|
+
def initialize(payload, strtab)
|
90
|
+
name_idx, @type_val, @sect, @desc_val, @value = payload.read(12).unpack('VCCSV')
|
91
|
+
if name_idx == 0
|
92
|
+
@name = ''
|
93
|
+
else
|
94
|
+
@name = strtab[name_idx..-1].split("\0", 2)[0]
|
95
|
+
end
|
96
|
+
|
97
|
+
#puts "#{printf('%08x', value)} #{@name} sect #{@sect} #{self.type ? self.type : 'UNK 0b'+@type_val.to_s(2)} #{self.stab? ? 'stab ' : ''} #{self.private_extern? ? 'pvt ' : ''} #{self.extern? ? 'extern' : ''}"
|
98
|
+
end
|
99
|
+
|
100
|
+
def type
|
101
|
+
if stab?
|
102
|
+
STAB[@type_val]
|
103
|
+
else
|
104
|
+
TYPE[@type_val & TYPE_MASK]
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
def stab?
|
109
|
+
@type_val & STAB_MASK != 0
|
110
|
+
end
|
111
|
+
|
112
|
+
def stab
|
113
|
+
if stab?
|
114
|
+
STAB[@type_val]
|
115
|
+
else
|
116
|
+
nil
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
def private_extern?
|
121
|
+
@type_val & PEXT_MASK == PEXT_MASK
|
122
|
+
end
|
123
|
+
|
124
|
+
def extern?
|
125
|
+
@type_val & EXT_MASK == EXT_MASK
|
126
|
+
end
|
127
|
+
|
128
|
+
def desc
|
129
|
+
d = [DESC_REFERENCE[@desc_val & REFERENCE_TYPE_MASK]]
|
130
|
+
DESC_ADDITIONAL.each_pair do |k, v|
|
131
|
+
d << v if @desc_val & k == k
|
132
|
+
end
|
133
|
+
d
|
134
|
+
end
|
135
|
+
|
136
|
+
def twolevel_library_ordinal
|
137
|
+
lo = (@desc_val >> 8) & 0xff
|
138
|
+
LIBRARY_ORDINAL[lo] || lo
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
end
|
143
|
+
end
|
@@ -0,0 +1,23 @@
|
|
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
|
+
module MachO
|
21
|
+
VERSION = '0.2.0'
|
22
|
+
end
|
23
|
+
end
|
Binary file
|
Binary file
|
@@ -0,0 +1,100 @@
|
|
1
|
+
require 'indis-macho'
|
2
|
+
|
3
|
+
def macho_target_double(*args)
|
4
|
+
o = args.length == 1 ? args[0] : {}
|
5
|
+
|
6
|
+
target = double("Target")
|
7
|
+
target.stub(:segments=)
|
8
|
+
if o[:segments]
|
9
|
+
target.should_receive(:segments){ o[:segments] }.any_number_of_times
|
10
|
+
else
|
11
|
+
target.should_receive(:segments).any_number_of_times.and_return([])
|
12
|
+
end
|
13
|
+
target.stub(:symbols=)
|
14
|
+
if o[:symbols]
|
15
|
+
target.should_receive(:symbols){ o[:symbols] }.any_number_of_times
|
16
|
+
else
|
17
|
+
target.should_receive(:symbols).any_number_of_times.and_return({})
|
18
|
+
end
|
19
|
+
target.stub(:vamap=)
|
20
|
+
target.stub(:io).and_return(o[:io])
|
21
|
+
target
|
22
|
+
end
|
23
|
+
|
24
|
+
describe Indis::BinaryFormat::MachO do
|
25
|
+
it "should parse mach-o header" do
|
26
|
+
io = StringIO.new(File.open('spec/fixtures/single-object.o', 'rb').read().force_encoding('BINARY'))
|
27
|
+
target = macho_target_double(io: io)
|
28
|
+
|
29
|
+
m = Indis::BinaryFormat::MachO.new(target, io)
|
30
|
+
|
31
|
+
m.cputype.should == :CPU_TYPE_ARM
|
32
|
+
m.cpusubtype.should == :CPU_SUBTYPE_ARM_V4T
|
33
|
+
m.filetype.should == :MH_OBJECT
|
34
|
+
m.flags.should == [:MH_SUBSECTIONS_VIA_SYMBOLS]
|
35
|
+
|
36
|
+
io = StringIO.new(File.open('spec/fixtures/app-arm-release.o', 'rb').read().force_encoding('BINARY'))
|
37
|
+
target = macho_target_double(io: io)
|
38
|
+
|
39
|
+
m = Indis::BinaryFormat::MachO.new(target, io)
|
40
|
+
|
41
|
+
m.cputype.should == :CPU_TYPE_ARM
|
42
|
+
m.cpusubtype.should == :CPU_SUBTYPE_ARM_V7
|
43
|
+
m.filetype.should == :MH_EXECUTE
|
44
|
+
m.flags.should == [:MH_NOUNDEFS, :MH_DYLDLINK, :MH_TWOLEVEL, :MH_PIE]
|
45
|
+
end
|
46
|
+
|
47
|
+
it "should parse mach-o commands" do
|
48
|
+
io = StringIO.new(File.open('spec/fixtures/single-object.o', 'rb').read().force_encoding('BINARY'))
|
49
|
+
target = macho_target_double(io: io)
|
50
|
+
|
51
|
+
m = Indis::BinaryFormat::MachO.new(target, io)
|
52
|
+
|
53
|
+
m.commands.length.should == 3
|
54
|
+
c = m.commands.first
|
55
|
+
c.cmd.should == :LC_SEGMENT
|
56
|
+
c.class.should == Indis::MachO::SegmentCommand
|
57
|
+
c.length.should == 464
|
58
|
+
|
59
|
+
c.segname.should == ''
|
60
|
+
c.vmaddr.should == 0x0
|
61
|
+
c.vmsize.should == 0x79
|
62
|
+
c.fileoff.should == 596
|
63
|
+
c.filesize.should == 121
|
64
|
+
c.maxprot.should == 0x7
|
65
|
+
c.initprot.should == 0x7
|
66
|
+
c.nsects.should == 6
|
67
|
+
c.flags.should == 0x0
|
68
|
+
|
69
|
+
c.sections.length.should == 6
|
70
|
+
s = c.sections.first
|
71
|
+
s.sectname.should == '__text'
|
72
|
+
s.segname.should == '__TEXT'
|
73
|
+
end
|
74
|
+
|
75
|
+
it "should parse stub segment from .o file" do
|
76
|
+
seg = []
|
77
|
+
|
78
|
+
io = StringIO.new(File.open('spec/fixtures/single-object.o', 'rb').read().force_encoding('BINARY'))
|
79
|
+
target = macho_target_double(io: io, segments: seg)
|
80
|
+
|
81
|
+
m = Indis::BinaryFormat::MachO.new(target, io)
|
82
|
+
|
83
|
+
seg.length.should == 1
|
84
|
+
seg[0].name.should == '__TEXT'
|
85
|
+
seg[0].sections.length.should == 6
|
86
|
+
seg[0].sections[0].name.should == '__text'
|
87
|
+
end
|
88
|
+
|
89
|
+
it "should parse symbols" do
|
90
|
+
sym = {}
|
91
|
+
io = StringIO.new(File.open('spec/fixtures/single-object.o', 'rb').read().force_encoding('BINARY'))
|
92
|
+
target = macho_target_double(io: io, symbols: sym)
|
93
|
+
|
94
|
+
m = Indis::BinaryFormat::MachO.new(target, io)
|
95
|
+
|
96
|
+
sym.keys.should include("_add")
|
97
|
+
sym.keys.should include("_sub")
|
98
|
+
sym.keys.should include("_printf")
|
99
|
+
end
|
100
|
+
end
|
data/spec/spec_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,103 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: indis-macho
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.2.0
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Vladimir Pouzanov
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-04-15 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: rspec
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :development
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0'
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: indis-core
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ! '>='
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '0'
|
38
|
+
type: :runtime
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
46
|
+
description: Mach-o format processor for indis provides support for loading mach-o
|
47
|
+
binaries for analysis
|
48
|
+
email:
|
49
|
+
- farcaller@gmail.com
|
50
|
+
executables: []
|
51
|
+
extensions: []
|
52
|
+
extra_rdoc_files: []
|
53
|
+
files:
|
54
|
+
- .gitignore
|
55
|
+
- .rspec
|
56
|
+
- .travis.yml
|
57
|
+
- Gemfile
|
58
|
+
- Gemfile.ci
|
59
|
+
- LICENSE
|
60
|
+
- README.md
|
61
|
+
- Rakefile
|
62
|
+
- indis-macho.gemspec
|
63
|
+
- lib/indis-macho.rb
|
64
|
+
- lib/indis-macho/command.rb
|
65
|
+
- lib/indis-macho/symbol.rb
|
66
|
+
- lib/indis-macho/version.rb
|
67
|
+
- spec/fixtures/app-arm-release.o
|
68
|
+
- spec/fixtures/single-object.o
|
69
|
+
- spec/indis-macho/binary_format_spec.rb
|
70
|
+
- spec/indis-macho/macho_spec.rb
|
71
|
+
- spec/spec_helper.rb
|
72
|
+
homepage: http://www.indis.org/
|
73
|
+
licenses:
|
74
|
+
- GPL-3
|
75
|
+
post_install_message:
|
76
|
+
rdoc_options: []
|
77
|
+
require_paths:
|
78
|
+
- lib
|
79
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
80
|
+
none: false
|
81
|
+
requirements:
|
82
|
+
- - ! '>='
|
83
|
+
- !ruby/object:Gem::Version
|
84
|
+
version: '0'
|
85
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
86
|
+
none: false
|
87
|
+
requirements:
|
88
|
+
- - ! '>='
|
89
|
+
- !ruby/object:Gem::Version
|
90
|
+
version: '0'
|
91
|
+
requirements: []
|
92
|
+
rubyforge_project:
|
93
|
+
rubygems_version: 1.8.21
|
94
|
+
signing_key:
|
95
|
+
specification_version: 3
|
96
|
+
summary: Mach-o format processor for indis
|
97
|
+
test_files:
|
98
|
+
- spec/fixtures/app-arm-release.o
|
99
|
+
- spec/fixtures/single-object.o
|
100
|
+
- spec/indis-macho/binary_format_spec.rb
|
101
|
+
- spec/indis-macho/macho_spec.rb
|
102
|
+
- spec/spec_helper.rb
|
103
|
+
has_rdoc:
|