turborex 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/LICENSE +674 -0
- data/README.md +38 -0
- data/README.rdoc +19 -0
- data/examples/alpc_client.rb +15 -0
- data/examples/alpc_server.rb +14 -0
- data/examples/com_client.rb +19 -0
- data/examples/com_finder.rb +39 -0
- data/examples/create_instance.rb +15 -0
- data/examples/cstruct.rb +19 -0
- data/examples/find_com_client_calls.rb +16 -0
- data/examples/find_rpc_security_callback.rb +12 -0
- data/examples/rpc_finder.rb +117 -0
- data/examples/scan_exports.rb +5 -0
- data/examples/scan_imports.rb +5 -0
- data/examples/tinysdk.rb +17 -0
- data/lib/turborex.rb +21 -0
- data/lib/turborex/cstruct.rb +565 -0
- data/lib/turborex/cstruct/struct_helper.rb +7 -0
- data/lib/turborex/exception.rb +65 -0
- data/lib/turborex/fuzzer.rb +204 -0
- data/lib/turborex/fuzzer/containers.rb +115 -0
- data/lib/turborex/fuzzer/coverage.rb +67 -0
- data/lib/turborex/fuzzer/mutators.rb +25 -0
- data/lib/turborex/fuzzer/seed.rb +30 -0
- data/lib/turborex/monkey.rb +11 -0
- data/lib/turborex/msrpc.rb +14 -0
- data/lib/turborex/msrpc/decompiler.rb +244 -0
- data/lib/turborex/msrpc/midl.rb +747 -0
- data/lib/turborex/msrpc/ndrtype.rb +167 -0
- data/lib/turborex/msrpc/rpcbase.rb +777 -0
- data/lib/turborex/msrpc/rpcfinder.rb +1426 -0
- data/lib/turborex/msrpc/utils.rb +70 -0
- data/lib/turborex/pefile.rb +8 -0
- data/lib/turborex/pefile/pe.rb +61 -0
- data/lib/turborex/pefile/scanner.rb +82 -0
- data/lib/turborex/utils.rb +321 -0
- data/lib/turborex/windows.rb +402 -0
- data/lib/turborex/windows/alpc.rb +844 -0
- data/lib/turborex/windows/com.rb +266 -0
- data/lib/turborex/windows/com/client.rb +84 -0
- data/lib/turborex/windows/com/com_finder.rb +330 -0
- data/lib/turborex/windows/com/com_registry.rb +100 -0
- data/lib/turborex/windows/com/interface.rb +522 -0
- data/lib/turborex/windows/com/utils.rb +210 -0
- data/lib/turborex/windows/constants.rb +82 -0
- data/lib/turborex/windows/process.rb +56 -0
- data/lib/turborex/windows/security.rb +12 -0
- data/lib/turborex/windows/security/ace.rb +76 -0
- data/lib/turborex/windows/security/acl.rb +25 -0
- data/lib/turborex/windows/security/security_descriptor.rb +118 -0
- data/lib/turborex/windows/tinysdk.rb +89 -0
- data/lib/turborex/windows/utils.rb +138 -0
- data/resources/headers/alpc/ntdef.h +72 -0
- data/resources/headers/alpc/ntlpcapi.h +1014 -0
- data/resources/headers/rpc/common.h +162 -0
- data/resources/headers/rpc/guiddef.h +191 -0
- data/resources/headers/rpc/internal_ndrtypes.h +262 -0
- data/resources/headers/rpc/rpc.h +10 -0
- data/resources/headers/rpc/rpcdce.h +266 -0
- data/resources/headers/rpc/rpcdcep.h +187 -0
- data/resources/headers/rpc/rpcndr.h +39 -0
- data/resources/headers/rpc/v4_x64/rpcinternals.h +154 -0
- data/resources/headers/rpc/wintype.h +517 -0
- data/resources/headers/tinysdk/tinysdk.h +5 -0
- data/resources/headers/tinysdk/tinysdk/comdef.h +645 -0
- data/resources/headers/tinysdk/tinysdk/dbghelp.h +118 -0
- data/resources/headers/tinysdk/tinysdk/guiddef.h +194 -0
- data/resources/headers/tinysdk/tinysdk/memoryapi.h +12 -0
- data/resources/headers/tinysdk/tinysdk/poppack.h +12 -0
- data/resources/headers/tinysdk/tinysdk/pshpack4.h +13 -0
- data/resources/headers/tinysdk/tinysdk/winnt.h +1059 -0
- data/resources/headers/tinysdk/tinysdk/wintype.h +326 -0
- metadata +290 -0
@@ -0,0 +1,25 @@
|
|
1
|
+
module TurboRex
|
2
|
+
module Fuzzer
|
3
|
+
module Mutators
|
4
|
+
class CharlieMillerMutator
|
5
|
+
attr_accessor :factor
|
6
|
+
|
7
|
+
def initialize(factor=100)
|
8
|
+
@factor = factor
|
9
|
+
end
|
10
|
+
|
11
|
+
def mutate(buf)
|
12
|
+
numwrites = rand(buf.bytesize.to_f / @factor)+1
|
13
|
+
numwrites.to_i.times do |i|
|
14
|
+
rbytes = rand(256)
|
15
|
+
rn = rand(buf.bytesize)
|
16
|
+
buf[rn] = rbytes.chr
|
17
|
+
end
|
18
|
+
|
19
|
+
buf
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module TurboRex
|
2
|
+
module Fuzzer
|
3
|
+
class Seed
|
4
|
+
attr_reader :seed
|
5
|
+
|
6
|
+
def initialize(seed)
|
7
|
+
@seed = seed
|
8
|
+
end
|
9
|
+
|
10
|
+
def container=(c)
|
11
|
+
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.from_file(path, separator="\n")
|
15
|
+
File.read(path).split(separator).map {|s| new(s)}
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
class SeedGroup
|
20
|
+
attr_reader :seeds
|
21
|
+
attr_accessor :energy
|
22
|
+
|
23
|
+
def initialize(seeds, energy)
|
24
|
+
@seeds = seeds
|
25
|
+
@energy = energy
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'rex/peparsey'
|
2
|
+
require 'turborex/cstruct'
|
3
|
+
require 'turborex/msrpc/rpcbase'
|
4
|
+
require 'turborex/msrpc/utils'
|
5
|
+
require 'turborex/msrpc/ndrtype.rb'
|
6
|
+
require 'turborex/msrpc/midl.rb'
|
7
|
+
require 'turborex/msrpc/decompiler.rb'
|
8
|
+
require 'turborex/msrpc/rpcfinder'
|
9
|
+
|
10
|
+
module TurboRex
|
11
|
+
module MSRPC
|
12
|
+
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,244 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module TurboRex
|
4
|
+
module MSRPC
|
5
|
+
class IStream
|
6
|
+
attr_reader :base
|
7
|
+
|
8
|
+
def initialize(isource, base)
|
9
|
+
@isource = isource
|
10
|
+
@base = @init_base = base
|
11
|
+
end
|
12
|
+
|
13
|
+
def read(len, offset=0)
|
14
|
+
@isource.read(@base+offset, len)
|
15
|
+
end
|
16
|
+
|
17
|
+
def set_base(base)
|
18
|
+
@base = base
|
19
|
+
end
|
20
|
+
|
21
|
+
def base_drift(drift)
|
22
|
+
@base += drift
|
23
|
+
end
|
24
|
+
|
25
|
+
def reset
|
26
|
+
@base = @init_base
|
27
|
+
true
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
class Decompiler
|
32
|
+
include TurboRex::MSRPC::RPCBase
|
33
|
+
include TurboRex::MSRPC::MIDL
|
34
|
+
|
35
|
+
attr_reader :parser
|
36
|
+
|
37
|
+
def initialize(opts = {})
|
38
|
+
arch = opts[:arch] || 'x86'
|
39
|
+
header_file = TurboRex.root + '/resources/headers/rpc/internal_ndrtypes.h'
|
40
|
+
case arch
|
41
|
+
when 'x86'
|
42
|
+
cpu = Metasm::Ia32
|
43
|
+
when 'x64'
|
44
|
+
cpu = Metasm::X86_64
|
45
|
+
else
|
46
|
+
raise 'Unknown architecture'
|
47
|
+
end
|
48
|
+
|
49
|
+
@parser = TurboRex::CStruct::NativeParser.new(nil, file: header_file, cpu: cpu, predefined: true)
|
50
|
+
end
|
51
|
+
|
52
|
+
def decompile(iface)
|
53
|
+
return false if iface.client?
|
54
|
+
switches = iface.midl_switches
|
55
|
+
return false if switches.has_one_of_switches?(%w[Os])
|
56
|
+
|
57
|
+
mode = :oif
|
58
|
+
if switches.has_switch?('Oi')
|
59
|
+
mode = :oi
|
60
|
+
elsif switches.has_switch?('all') && switches.arch_64?
|
61
|
+
return false # TODO: Implement
|
62
|
+
end
|
63
|
+
|
64
|
+
public_send "decompile_#{mode}", iface
|
65
|
+
end
|
66
|
+
|
67
|
+
def decompile_oif(iface)
|
68
|
+
OifDecompiler.new(iface, @parser).decompile
|
69
|
+
end
|
70
|
+
|
71
|
+
def parse_proc_fs_header(raw_header, mode = :Oif)
|
72
|
+
offset = 0
|
73
|
+
header_s = Struct.new(:oi_header, :oif_header, :win2k_ext).new
|
74
|
+
oi_header_s = Struct.new(:common, :explicit_handle_desc).new
|
75
|
+
|
76
|
+
oi_header_p1 = @parser.decode_c_struct('Oi_Header_HType_Flags_t', raw_header)
|
77
|
+
oi_header = if (oi_header_p1.OiFlags & Oi_HAS_RPCFLAGS) == Oi_HAS_RPCFLAGS
|
78
|
+
@parser.decode_c_struct('Oi_Header_t', raw_header)
|
79
|
+
else
|
80
|
+
@parser.decode_c_struct('Oi_Header_Without_RPCFlags_t', raw_header)
|
81
|
+
end
|
82
|
+
|
83
|
+
oi_header_s.common = oi_header
|
84
|
+
offset += oi_header.sizeof
|
85
|
+
if oi_header_p1.HandleType == FC_EXPLICIT_HANDLE
|
86
|
+
explicit_hdesc = @parser.decode_c_struct('Handle_Desc_Common_t', raw_header, offset)
|
87
|
+
case explicit_hdesc.HandleType
|
88
|
+
when FC_BIND_PRIMITIVE
|
89
|
+
explicit_handle_desc = @parser.decode_c_struct('ExplicitHandlePrimitive_t', raw_header, offset)
|
90
|
+
when FC_BIND_GENERIC
|
91
|
+
explicit_handle_desc = @parser.decode_c_struct('ExplicitHandleGeneric_t', raw_header, offset)
|
92
|
+
when FC_BIND_CONTEXT
|
93
|
+
explicit_handle_desc = @parser.decode_c_struct('ExplicitHandleContext_t', raw_header, offset)
|
94
|
+
end
|
95
|
+
|
96
|
+
offset += explicit_handle_desc.sizeof
|
97
|
+
oi_header_s.explicit_handle_desc = explicit_handle_desc
|
98
|
+
end
|
99
|
+
|
100
|
+
header_s.oi_header = oi_header_s
|
101
|
+
|
102
|
+
case mode
|
103
|
+
when :Oi
|
104
|
+
return oi_header_s, offset
|
105
|
+
when :Oif
|
106
|
+
oif_header = @parser.decode_c_struct('Oif_Header_t', raw_header, offset)
|
107
|
+
offset += oif_header.sizeof
|
108
|
+
header_s.oif_header = oif_header
|
109
|
+
|
110
|
+
if (oif_header.InterpreterOptFlags.HasExtensions) == 1 # Has win2k extension part
|
111
|
+
size = @parser.decode_c_struct('WIN2K_EXT', raw_header, offset).ExtensionVersion
|
112
|
+
case size
|
113
|
+
when WIN2K_EXT_SIZE
|
114
|
+
win2k_ext = @parser.decode_c_struct('WIN2K_EXT', raw_header, offset)
|
115
|
+
when WIN2K_EXT64_SIZE
|
116
|
+
win2k_ext = @parser.decode_c_struct('WIN2K_EXT64', raw_header, offset)
|
117
|
+
end
|
118
|
+
offset += win2k_ext.sizeof
|
119
|
+
header_s.win2k_ext = win2k_ext
|
120
|
+
end
|
121
|
+
when :Os
|
122
|
+
raise NotImplementedError
|
123
|
+
end
|
124
|
+
|
125
|
+
[header_s, offset]
|
126
|
+
end
|
127
|
+
|
128
|
+
def parse_proc_fs_header_dasm(dasm, addr, mode = :Oif)
|
129
|
+
offset = 0
|
130
|
+
header_s = Struct.new(:oi_header, :oif_header, :win2k_ext).new
|
131
|
+
oi_header_s = Struct.new(:common, :explicit_handle_desc).new
|
132
|
+
|
133
|
+
oi_header_p1 = dasm.decode_c_struct('Oi_Header_HType_Flags_t', addr + offset)
|
134
|
+
oi_header = if (oi_header_p1.OiFlags & Oi_HAS_RPCFLAGS) == Oi_HAS_RPCFLAGS
|
135
|
+
dasm.decode_c_struct('Oi_Header_t', addr + offset)
|
136
|
+
else
|
137
|
+
dasm.decode_c_struct('Oi_Header_Without_RPCFlags_t', addr + offset)
|
138
|
+
end
|
139
|
+
|
140
|
+
oi_header_s.common = oi_header
|
141
|
+
offset += oi_header.sizeof
|
142
|
+
if oi_header_p1.HandleType == FC_EXPLICIT_HANDLE
|
143
|
+
explicit_hdesc = dasm.decode_c_struct('Handle_Desc_Common_t', addr + offset)
|
144
|
+
case explicit_hdesc.HandleType
|
145
|
+
when FC_BIND_PRIMITIVE
|
146
|
+
explicit_handle_desc = dasm.decode_c_struct('ExplicitHandlePrimitive_t', addr + offset)
|
147
|
+
when FC_BIND_GENERIC
|
148
|
+
explicit_handle_desc = dasm.decode_c_struct('ExplicitHandleGeneric_t', addr + offset)
|
149
|
+
when FC_BIND_CONTEXT
|
150
|
+
explicit_handle_desc = dasm.decode_c_struct('ExplicitHandleContext_t', addr + offset)
|
151
|
+
end
|
152
|
+
|
153
|
+
offset += explicit_handle_desc.sizeof
|
154
|
+
oi_header_s.explicit_handle_desc = explicit_handle_desc
|
155
|
+
end
|
156
|
+
|
157
|
+
header_s.oi_header = oi_header_s
|
158
|
+
|
159
|
+
case mode
|
160
|
+
when :Oi
|
161
|
+
raise NotImplementedError
|
162
|
+
when :Oif
|
163
|
+
oif_header = dasm.decode_c_struct('Oif_Header_t', addr + offset)
|
164
|
+
offset += oif_header.sizeof
|
165
|
+
header_s.oif_header = oif_header
|
166
|
+
|
167
|
+
if oif_header.InterpreterOptFlags.HasExtensions == 1 # Has win2k extension part
|
168
|
+
size = dasm.decode_c_struct('WIN2K_EXT', addr + offset).ExtensionVersion
|
169
|
+
case size
|
170
|
+
when WIN2K_EXT_SIZE
|
171
|
+
win2k_ext = dasm.decode_c_struct('WIN2K_EXT', addr + offset)
|
172
|
+
when WIN2K_EXT64_SIZE
|
173
|
+
win2k_ext = dasm.decode_c_struct('WIN2K_EXT64', addr + offset)
|
174
|
+
end
|
175
|
+
offset += win2k_ext.sizeof
|
176
|
+
header_s.win2k_ext = win2k_ext
|
177
|
+
end
|
178
|
+
when :Os
|
179
|
+
raise NotImplementedError
|
180
|
+
end
|
181
|
+
|
182
|
+
[header_s, offset]
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
class OifDecompiler < Decompiler
|
187
|
+
FORMAT_STRING_STYLE = {
|
188
|
+
proc_fs: OifProcFormatString,
|
189
|
+
param_desc: OifParamDesc
|
190
|
+
}
|
191
|
+
|
192
|
+
def initialize(interface, cparser)
|
193
|
+
@interface = interface
|
194
|
+
@interface.decompiler = self
|
195
|
+
@cparser = cparser
|
196
|
+
|
197
|
+
@procfs_stream = nil
|
198
|
+
@typefs_stream = nil
|
199
|
+
@offset_table = interface.offset_table
|
200
|
+
|
201
|
+
make_istream
|
202
|
+
end
|
203
|
+
|
204
|
+
def decompile(interface=nil)
|
205
|
+
interface ||= @interface
|
206
|
+
midl_interface = Interface.new(interface)
|
207
|
+
|
208
|
+
@offset_table.each do |offset|
|
209
|
+
_procfs = @procfs_stream.dup
|
210
|
+
_procfs.base_drift(offset)
|
211
|
+
proc_fs = FORMAT_STRING_STYLE[:proc_fs].new(_procfs, @typefs_stream, @cparser)
|
212
|
+
procedure = proc_fs.decompile
|
213
|
+
midl_interface.push_procedure(procedure)
|
214
|
+
midl_interface.push_typedef(procedure.typedefs)
|
215
|
+
end
|
216
|
+
|
217
|
+
midl_interface
|
218
|
+
end
|
219
|
+
|
220
|
+
def parse_proc_fs_header(raw_header, mode = :Oif)
|
221
|
+
mode = :Oif
|
222
|
+
super(raw_header, mode)
|
223
|
+
end
|
224
|
+
|
225
|
+
def parse_proc_fs_header_dasm(dasm, addr, mode = :Oif)
|
226
|
+
mode = :Oif
|
227
|
+
super(dasm, addr ,mode)
|
228
|
+
end
|
229
|
+
|
230
|
+
private
|
231
|
+
|
232
|
+
def make_istream
|
233
|
+
unless (@interface.pproc_fs && @interface.ptype_fs && @interface.offset_table)
|
234
|
+
raise "The format string is not initialized."
|
235
|
+
end
|
236
|
+
|
237
|
+
isource = @interface.finder.pe._isource
|
238
|
+
@procfs_stream = IStream.new(isource, @interface.pproc_fs)
|
239
|
+
@typefs_stream = IStream.new(isource, @interface.ptype_fs)
|
240
|
+
true
|
241
|
+
end
|
242
|
+
end
|
243
|
+
end
|
244
|
+
end
|
@@ -0,0 +1,747 @@
|
|
1
|
+
module TurboRex
|
2
|
+
module MSRPC
|
3
|
+
module MIDL
|
4
|
+
include NDRType
|
5
|
+
|
6
|
+
class Interface
|
7
|
+
attr_reader :uuid
|
8
|
+
attr_reader :typedefs
|
9
|
+
attr_reader :if_attrs
|
10
|
+
attr_reader :procedures
|
11
|
+
|
12
|
+
def initialize(interface)
|
13
|
+
@uuid = interface.uuid
|
14
|
+
@typedefs = []
|
15
|
+
@if_attrs = [
|
16
|
+
Attribute::EndpointAttr.new(interface.endpoints)
|
17
|
+
]
|
18
|
+
@procedures = []
|
19
|
+
end
|
20
|
+
|
21
|
+
def push_procedure(proc)
|
22
|
+
@procedures << proc
|
23
|
+
end
|
24
|
+
|
25
|
+
def push_typedef(typedef)
|
26
|
+
@typedefs << typedef
|
27
|
+
end
|
28
|
+
|
29
|
+
def human
|
30
|
+
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
class Procedure
|
35
|
+
attr_reader :proc_num
|
36
|
+
attr_accessor :name
|
37
|
+
attr_reader :params
|
38
|
+
attr_reader :return_type
|
39
|
+
attr_reader :arity
|
40
|
+
|
41
|
+
def initialize(proc_num)
|
42
|
+
@proc_num = proc_num
|
43
|
+
@name = "Proc#{proc_num}"
|
44
|
+
@params = []
|
45
|
+
@return_type = nil
|
46
|
+
@arity = 0
|
47
|
+
end
|
48
|
+
|
49
|
+
def push_param(param)
|
50
|
+
@params << param
|
51
|
+
@arity += 1
|
52
|
+
end
|
53
|
+
|
54
|
+
def set_return_type(type)
|
55
|
+
@return_type = type
|
56
|
+
end
|
57
|
+
|
58
|
+
def typedefs
|
59
|
+
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
class Parameter
|
64
|
+
attr_reader :data_type
|
65
|
+
attr_accessor :name
|
66
|
+
attr_reader :attributes
|
67
|
+
|
68
|
+
def initialize(name, data_type=nil)
|
69
|
+
@data_type = data_type
|
70
|
+
@name = name
|
71
|
+
@attributes = []
|
72
|
+
@type_return = false
|
73
|
+
end
|
74
|
+
|
75
|
+
def push_attribute(attribute)
|
76
|
+
@attributes << attribute
|
77
|
+
end
|
78
|
+
|
79
|
+
def set_data_type(type)
|
80
|
+
@data_type = type
|
81
|
+
end
|
82
|
+
|
83
|
+
def type_return
|
84
|
+
@type_return = true
|
85
|
+
end
|
86
|
+
|
87
|
+
def is_return_type?
|
88
|
+
@type_return
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
class Attribute
|
93
|
+
def human
|
94
|
+
|
95
|
+
end
|
96
|
+
|
97
|
+
class VersionAttr < Attribute
|
98
|
+
SYMBOL_NAME = 'version'
|
99
|
+
|
100
|
+
def initialize(major, minor)
|
101
|
+
@major = major
|
102
|
+
@minor = minor
|
103
|
+
end
|
104
|
+
|
105
|
+
def human
|
106
|
+
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
class EndpointAttr < Attribute
|
111
|
+
SYMBOL_NAME = 'endpoint'
|
112
|
+
|
113
|
+
def initialize(endpoints)
|
114
|
+
@endpoints = endpoints
|
115
|
+
end
|
116
|
+
|
117
|
+
def human
|
118
|
+
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
class UUIDAttr < Attribute
|
123
|
+
SYMBOL_NAME = 'uuid'
|
124
|
+
|
125
|
+
def initialize(uuid)
|
126
|
+
@uuid = uuid
|
127
|
+
end
|
128
|
+
|
129
|
+
def human
|
130
|
+
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
class DataType
|
136
|
+
attr_reader :symbol_name
|
137
|
+
attr_reader :bytesize
|
138
|
+
|
139
|
+
class BaseType < DataType
|
140
|
+
attr_reader :signed
|
141
|
+
|
142
|
+
SYMBOL_NAME_TABLE = [
|
143
|
+
:boolean,
|
144
|
+
:byte,
|
145
|
+
:char,
|
146
|
+
:double,
|
147
|
+
:float,
|
148
|
+
:handle_t,
|
149
|
+
:hyper,
|
150
|
+
:__int8,
|
151
|
+
:__int16,
|
152
|
+
:int,
|
153
|
+
:__int32,
|
154
|
+
:__int3264,
|
155
|
+
:__int64,
|
156
|
+
:long,
|
157
|
+
:short,
|
158
|
+
:small,
|
159
|
+
:wchar_t,
|
160
|
+
:error_status_t
|
161
|
+
]
|
162
|
+
|
163
|
+
BYTESIZE_MAPPING = {
|
164
|
+
boolean: 1,
|
165
|
+
byte: 1,
|
166
|
+
char: 1,
|
167
|
+
double: 8,
|
168
|
+
float: 4,
|
169
|
+
handle_t: :variable,
|
170
|
+
hyper: 8,
|
171
|
+
int: 4,
|
172
|
+
__int3264: :variable,
|
173
|
+
long: 4,
|
174
|
+
short: 2,
|
175
|
+
small: 1,
|
176
|
+
wchar_t: 2,
|
177
|
+
error_status_t: 4
|
178
|
+
}
|
179
|
+
|
180
|
+
def initialize(symbol_name, signed)
|
181
|
+
raise TurboRex::Exception::MSRPC::UnknownSymbolName unless index = SYMBOL_NAME_TABLE.index(symbol_name.to_sym)
|
182
|
+
@symbol_name ||= SYMBOL_NAME_TABLE[index]
|
183
|
+
@signed = signed
|
184
|
+
@bytesize = BYTESIZE_MAPPING[@symbol_name]
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
188
|
+
class Pointer < DataType
|
189
|
+
attr_reader :pointee
|
190
|
+
attr_reader :type
|
191
|
+
attr_accessor :level
|
192
|
+
|
193
|
+
def initialize(pointee, type, level=1)
|
194
|
+
@pointee = pointee
|
195
|
+
@type = type # ref, full, unique
|
196
|
+
@level = level
|
197
|
+
|
198
|
+
get_level
|
199
|
+
end
|
200
|
+
|
201
|
+
protected
|
202
|
+
|
203
|
+
def get_level
|
204
|
+
@pointee.is_a?(Pointer) ? @level += @pointee.get_level : @level
|
205
|
+
end
|
206
|
+
end
|
207
|
+
|
208
|
+
class Enum < DataType
|
209
|
+
attr_reader :attributes
|
210
|
+
attr_reader :member
|
211
|
+
|
212
|
+
def initialize(symbol_name, *member)
|
213
|
+
@symbol_name = symbol_name
|
214
|
+
@member = member
|
215
|
+
@attributes = []
|
216
|
+
end
|
217
|
+
end
|
218
|
+
|
219
|
+
class TypeDefinition < DataType
|
220
|
+
def initialize(symbol_name, type_specifier, declarator_list, attributes=[])
|
221
|
+
@symbol_name = symbol_name
|
222
|
+
@type_specifier = type_specifier
|
223
|
+
@declarator_list = declarator_list
|
224
|
+
@attributes = attributes
|
225
|
+
end
|
226
|
+
end
|
227
|
+
|
228
|
+
class Array < DataType
|
229
|
+
attr_reader :member
|
230
|
+
attr_reader :length
|
231
|
+
|
232
|
+
def initialize(*member)
|
233
|
+
@member = member
|
234
|
+
@length = member.length
|
235
|
+
end
|
236
|
+
|
237
|
+
def method_missing(m, *args, &block)
|
238
|
+
@member.send(m, *args, &block)
|
239
|
+
end
|
240
|
+
end
|
241
|
+
end
|
242
|
+
|
243
|
+
class ProcFormatString
|
244
|
+
include NDRType
|
245
|
+
|
246
|
+
attr_reader :header
|
247
|
+
attr_reader :param_desc
|
248
|
+
attr_accessor :cparser
|
249
|
+
|
250
|
+
def initialize(procfs_stream, typefs_stream, cparser)
|
251
|
+
@procfs_stream = procfs_stream
|
252
|
+
@typefs_stream = typefs_stream
|
253
|
+
@cparser = cparser
|
254
|
+
end
|
255
|
+
|
256
|
+
def decompile
|
257
|
+
|
258
|
+
end
|
259
|
+
|
260
|
+
def fs_length
|
261
|
+
|
262
|
+
end
|
263
|
+
|
264
|
+
private
|
265
|
+
|
266
|
+
def parse_proc_fs_header_stream(stream)
|
267
|
+
|
268
|
+
end
|
269
|
+
end
|
270
|
+
|
271
|
+
class ParamDesc
|
272
|
+
attr_reader :stream
|
273
|
+
attr_reader :typefs
|
274
|
+
attr_reader :stack_offset
|
275
|
+
|
276
|
+
|
277
|
+
def initialize(stream, typefs_stream, cparser, stack_index=nil)
|
278
|
+
@stream = stream
|
279
|
+
@typefs_stream = typefs_stream # IStream object
|
280
|
+
@cparser = cparser
|
281
|
+
@stack_index = stack_index
|
282
|
+
end
|
283
|
+
|
284
|
+
def decompile
|
285
|
+
|
286
|
+
end
|
287
|
+
|
288
|
+
def fs_length
|
289
|
+
|
290
|
+
end
|
291
|
+
end
|
292
|
+
|
293
|
+
class OifParamDesc < ParamDesc
|
294
|
+
FS_LENGTH = 6
|
295
|
+
|
296
|
+
attr_reader :param_attrs
|
297
|
+
attr_reader :typefs
|
298
|
+
|
299
|
+
# return Parameter object
|
300
|
+
def decompile
|
301
|
+
raw = @stream.read(FS_LENGTH)
|
302
|
+
header = @cparser.decode_c_struct('Oif_ParamDesc_Header_t', raw)
|
303
|
+
|
304
|
+
@param_attrs = header.ParamAttributes
|
305
|
+
@stack_offset = header.StackOffset
|
306
|
+
|
307
|
+
case @cparser.cpu.size
|
308
|
+
when 32
|
309
|
+
ptr_len = 4
|
310
|
+
when 64
|
311
|
+
ptr_len = 8
|
312
|
+
end
|
313
|
+
|
314
|
+
virtual_stack_index = @stack_offset / ptr_len
|
315
|
+
param_name = "arg_#{virtual_stack_index}"
|
316
|
+
|
317
|
+
parameter = Parameter.new(param_name)
|
318
|
+
|
319
|
+
if @param_attrs.IsBasetype == 1
|
320
|
+
struct = @cparser.decode_c_struct('Oif_Param_Desc_BaseType_t', raw)
|
321
|
+
_stream = @stream.dup
|
322
|
+
_stream.base_drift(4)
|
323
|
+
data_type = TypeFormatString::SimpleType.new(_stream, @cparser).decompile
|
324
|
+
else
|
325
|
+
struct = @cparser.decode_c_struct('Oif_Param_Desc_Other_t', raw)
|
326
|
+
typefs_offset = struct.TypeOffset
|
327
|
+
_typefs_stream = @typefs_stream.dup
|
328
|
+
_typefs_stream.base_drift(typefs_offset)
|
329
|
+
@typefs = TypeFormatString.new(_typefs_stream, @cparser)
|
330
|
+
|
331
|
+
begin
|
332
|
+
data_type = @typefs.decompile
|
333
|
+
rescue TurboRex::Exception::MSRPC::InvalidTypeFormatString
|
334
|
+
raise TurboRex::Exception::MSRPC::InvalidParamDescriptor
|
335
|
+
end
|
336
|
+
end
|
337
|
+
|
338
|
+
if @param_attrs.IsSimpleRef == 1 # First-level refenrence pointer
|
339
|
+
data_type = DataType::Pointer.new(data_type, :ref)
|
340
|
+
end
|
341
|
+
|
342
|
+
parameter.set_data_type(data_type)
|
343
|
+
|
344
|
+
if @param_attrs.IsReturn == 1
|
345
|
+
parameter.type_return
|
346
|
+
parameter.name = nil
|
347
|
+
else
|
348
|
+
if @param_attrs.IsIn == 1
|
349
|
+
parameter.attributes << :in
|
350
|
+
end
|
351
|
+
|
352
|
+
if @param_attrs.IsOut == 1
|
353
|
+
parameter.attributes << :out
|
354
|
+
end
|
355
|
+
end
|
356
|
+
|
357
|
+
|
358
|
+
parameter
|
359
|
+
end
|
360
|
+
|
361
|
+
def fs_length
|
362
|
+
FS_LENGTH
|
363
|
+
end
|
364
|
+
end
|
365
|
+
|
366
|
+
class OifProcFormatString < ProcFormatString
|
367
|
+
# return Procedure object
|
368
|
+
def decompile
|
369
|
+
header, hlength = parse_proc_fs_header_stream(@procfs_stream)
|
370
|
+
@header = header
|
371
|
+
@param_desc = []
|
372
|
+
procedure = Procedure.new(header.oi_header.common.ProcNum)
|
373
|
+
|
374
|
+
offset = hlength
|
375
|
+
loop do |i|
|
376
|
+
stream = @procfs_stream.dup
|
377
|
+
stream.base_drift(offset)
|
378
|
+
|
379
|
+
param_desc = OifParamDesc.new(stream, @typefs_stream, @cparser)
|
380
|
+
|
381
|
+
begin
|
382
|
+
param = param_desc.decompile # return Parameter object
|
383
|
+
rescue TurboRex::Exception::MSRPC::InvalidParamDescriptor
|
384
|
+
break
|
385
|
+
end
|
386
|
+
|
387
|
+
@param_desc << param_desc
|
388
|
+
|
389
|
+
if param.is_return_type?
|
390
|
+
procedure.set_return_type(param)
|
391
|
+
else
|
392
|
+
procedure.push_param(param)
|
393
|
+
end
|
394
|
+
|
395
|
+
offset += param_desc.fs_length
|
396
|
+
end
|
397
|
+
|
398
|
+
procedure
|
399
|
+
end
|
400
|
+
|
401
|
+
def parse_proc_fs_header_stream(stream)
|
402
|
+
raw_header = stream.read(28)
|
403
|
+
offset = 0
|
404
|
+
header_s = Struct.new(:oi_header, :oif_header, :win2k_ext).new
|
405
|
+
oi_header_s = Struct.new(:common, :explicit_handle_desc).new
|
406
|
+
|
407
|
+
oi_header_p1 = @cparser.decode_c_struct('Oi_Header_HType_Flags_t', raw_header)
|
408
|
+
oi_header = if (oi_header_p1.OiFlags & Oi_HAS_RPCFLAGS) == Oi_HAS_RPCFLAGS
|
409
|
+
@cparser.decode_c_struct('Oi_Header_t', raw_header)
|
410
|
+
else
|
411
|
+
@cparser.decode_c_struct('Oi_Header_Without_RPCFlags_t', raw_header)
|
412
|
+
end
|
413
|
+
|
414
|
+
oi_header_s.common = oi_header
|
415
|
+
offset += oi_header.sizeof
|
416
|
+
if oi_header_p1.HandleType == FC_EXPLICIT_HANDLE
|
417
|
+
explicit_hdesc = @cparser.decode_c_struct('Handle_Desc_Common_t', raw_header, offset)
|
418
|
+
case explicit_hdesc.HandleType
|
419
|
+
when FC_BIND_PRIMITIVE
|
420
|
+
explicit_handle_desc = @cparser.decode_c_struct('ExplicitHandlePrimitive_t', raw_header, offset)
|
421
|
+
when FC_BIND_GENERIC
|
422
|
+
explicit_handle_desc = @cparser.decode_c_struct('ExplicitHandleGeneric_t', raw_header, offset)
|
423
|
+
when FC_BIND_CONTEXT
|
424
|
+
explicit_handle_desc = @cparser.decode_c_struct('ExplicitHandleContext_t', raw_header, offset)
|
425
|
+
end
|
426
|
+
|
427
|
+
offset += explicit_handle_desc.sizeof
|
428
|
+
oi_header_s.explicit_handle_desc = explicit_handle_desc
|
429
|
+
end
|
430
|
+
|
431
|
+
header_s.oi_header = oi_header_s
|
432
|
+
oif_header = @cparser.decode_c_struct('Oif_Header_t', raw_header, offset)
|
433
|
+
offset += oif_header.sizeof
|
434
|
+
header_s.oif_header = oif_header
|
435
|
+
|
436
|
+
if (oif_header.InterpreterOptFlags.HasExtensions) == 1
|
437
|
+
size = @cparser.decode_c_struct('WIN2K_EXT', raw_header, offset).ExtensionVersion
|
438
|
+
case size
|
439
|
+
when WIN2K_EXT_SIZE
|
440
|
+
win2k_ext = @cparser.decode_c_struct('WIN2K_EXT', raw_header, offset)
|
441
|
+
when WIN2K_EXT64_SIZE
|
442
|
+
win2k_ext = @cparser.decode_c_struct('WIN2K_EXT64', raw_header, offset)
|
443
|
+
end
|
444
|
+
offset += win2k_ext.sizeof
|
445
|
+
header_s.win2k_ext = win2k_ext
|
446
|
+
end
|
447
|
+
|
448
|
+
|
449
|
+
[header_s, offset]
|
450
|
+
end
|
451
|
+
end
|
452
|
+
|
453
|
+
class TypeFormatString
|
454
|
+
include NDRType
|
455
|
+
|
456
|
+
def initialize(typefs_stream, cparser)
|
457
|
+
@typefs_stream = typefs_stream
|
458
|
+
@cparser = cparser
|
459
|
+
end
|
460
|
+
|
461
|
+
# return an object of the subclass of DataType
|
462
|
+
def decompile
|
463
|
+
fc = @typefs_stream.read(1).unpack('C').first
|
464
|
+
select_handler(fc).new(@typefs_stream, @cparser).decompile
|
465
|
+
end
|
466
|
+
|
467
|
+
def fs_length
|
468
|
+
|
469
|
+
end
|
470
|
+
|
471
|
+
def select_handler(type_fc)
|
472
|
+
HANDLER_TABLE.each do |h|
|
473
|
+
if h[:type].include?(type_fc)
|
474
|
+
return h[:handler]
|
475
|
+
end
|
476
|
+
end
|
477
|
+
|
478
|
+
raise TurboRex::Exception::MSRPC::InvalidTypeFormatString
|
479
|
+
end
|
480
|
+
|
481
|
+
class SimpleType < TypeFormatString
|
482
|
+
MAPPING = [
|
483
|
+
{value: FC_BYTE, mapping: :byte},
|
484
|
+
{value: FC_CHAR, mapping: :char},
|
485
|
+
{value: FC_SMALL, mapping: :small},
|
486
|
+
{value: FC_USMALL, mapping: {type: :small, signed: false}},
|
487
|
+
{value: FC_WCHAR, mapping: :wchar_t},
|
488
|
+
{value: FC_SHORT, mapping: :short},
|
489
|
+
{value: FC_USHORT, mapping: {type: :short, signed: false}},
|
490
|
+
{value: FC_LONG, mapping: :long},
|
491
|
+
{value: FC_ULONG, mapping: {type: :long, signed: false}},
|
492
|
+
{value: FC_FLOAT, mapping: :float},
|
493
|
+
{value: FC_HYPER, mapping: :hyper},
|
494
|
+
{value: FC_DOUBLE, mapping: :double},
|
495
|
+
{value: FC_ERROR_STATUS_T, mapping: :error_status_t},
|
496
|
+
{value: FC_INT3264, mapping: :__int3264},
|
497
|
+
{value: FC_UINT3264, mapping: {type: :__int3264, signed: false}}
|
498
|
+
]
|
499
|
+
|
500
|
+
def decompile
|
501
|
+
type_fc = @typefs_stream.read(1).unpack('C').first
|
502
|
+
case type_fc
|
503
|
+
when FC_ENUM16
|
504
|
+
symbol_name = "DUMMY_ENUM16_#{SecureRandom.hex(2).upcase}".to_sym
|
505
|
+
enum = DataType::Enum.new(symbol_name, :dummy_member)
|
506
|
+
|
507
|
+
return DataType::TypeDefinition.new(symbol_name, enum, [symbol_name])
|
508
|
+
when FC_ENUM32
|
509
|
+
symbol_name = "DUMMY_ENUM32_#{SecureRandom.hex(2).upcase}".to_sym
|
510
|
+
enum = DataType::Enum.new(symbol_name, :dummy_member)
|
511
|
+
enum.attributes << :v1_enum
|
512
|
+
return DataType::TypeDefinition.new(symbol_name, enum, [symbol_name], enum.attributes)
|
513
|
+
else
|
514
|
+
MAPPING.each do |m|
|
515
|
+
if m[:value] == type_fc
|
516
|
+
signed = true
|
517
|
+
if m[:mapping].is_a?(Hash)
|
518
|
+
symbol_name = m[:mapping][:type]
|
519
|
+
signed = m[:mapping][:signed]
|
520
|
+
else
|
521
|
+
symbol_name = m[:mapping]
|
522
|
+
end
|
523
|
+
return DataType::BaseType.new(symbol_name, signed)
|
524
|
+
end
|
525
|
+
end
|
526
|
+
end
|
527
|
+
|
528
|
+
raise TurboRex::Exception::MSRPC::InvalidTypeFormatString
|
529
|
+
end
|
530
|
+
end
|
531
|
+
|
532
|
+
class CommonPtr < TypeFormatString
|
533
|
+
FC_ALLOCATE_ALL_NODES = 0x01
|
534
|
+
FC_DONT_FREE = 0x02
|
535
|
+
FC_ALLOCED_ON_STACK = 0x04
|
536
|
+
FC_SIMPLE_POINTER = 0x08
|
537
|
+
FC_POINTER_DEREF = 0x10
|
538
|
+
|
539
|
+
def decompile
|
540
|
+
raw = @typefs_stream.read(4)
|
541
|
+
header = @cparser.decode_c_struct('CommonPtr_Header_t', raw)
|
542
|
+
|
543
|
+
case header.PointerType
|
544
|
+
when FC_RP
|
545
|
+
pointer_type = :ref
|
546
|
+
when FC_UP
|
547
|
+
pointer_type = :unique
|
548
|
+
when FC_FP
|
549
|
+
pointer_type = :full
|
550
|
+
when FC_OP
|
551
|
+
pointer_type = :unknown # Not Implement
|
552
|
+
end
|
553
|
+
|
554
|
+
if (header.PointerAttributes & FC_SIMPLE_POINTER) == FC_SIMPLE_POINTER
|
555
|
+
struct = @cparser.decode_c_struct('CommonPtr_Simple_t', raw)
|
556
|
+
simple_type = struct.SimpleType
|
557
|
+
_stream = @typefs_stream.dup
|
558
|
+
_stream.base_drift(2)
|
559
|
+
pointee = SimpleType.new(_stream, @cparser).decompile
|
560
|
+
return DataType::Pointer.new(pointee, pointer_type)
|
561
|
+
else
|
562
|
+
cstruct = @cparser.find_c_struct('CommonPtr_Complex_t')
|
563
|
+
struct = @cparser.decode_c_struct('CommonPtr_Complex_t', raw)
|
564
|
+
desc_offset = struct.Offset
|
565
|
+
_stream = @typefs_stream.dup
|
566
|
+
_stream.base_drift(cstruct.offsetof(@cparser, 'Offset')+desc_offset)
|
567
|
+
return TypeFormatString.new(_stream, @cparser).decompile
|
568
|
+
end
|
569
|
+
end
|
570
|
+
end
|
571
|
+
|
572
|
+
class FixedSizedArray < TypeFormatString
|
573
|
+
def decompile
|
574
|
+
offset = 0
|
575
|
+
type = @typefs_stream.read(1).unpack('C').first
|
576
|
+
case type
|
577
|
+
when FC_SMFARRAY
|
578
|
+
size = @cparser.sizeof(@cparser.find_c_struct('SM_FArray_Header_t'))
|
579
|
+
header = @cparser.decode_c_struct('SM_FArray_Header_t', @typefs_stream.read(size))
|
580
|
+
when FC_LGFARRAY
|
581
|
+
size = @cparser.sizeof(@cparser.find_c_struct('LG_FArray_Header_t'))
|
582
|
+
header = @cparser.decode_c_struct('LG_FArray_Header_t', @typefs_stream.read(size))
|
583
|
+
end
|
584
|
+
|
585
|
+
total_size = header.TotalSize
|
586
|
+
offset += size
|
587
|
+
_stream = @typefs_stream.dup
|
588
|
+
_stream.base_drift(offset)
|
589
|
+
if @typefs_stream.read(1, offset).unpack('C').first == FC_PP # Pointer layout
|
590
|
+
ptr_layout = PointerLayout.new(_stream, @cparser) # TODO: How to handle when the count of pointer instance greater than one?
|
591
|
+
layout = ptr_layout.decompile.first
|
592
|
+
offset += ptr_layout.fs_length
|
593
|
+
_stream.base_drift(ptr_layout.fs_length)
|
594
|
+
element = TypeFormatString.new(_stream, @cparser).decompile
|
595
|
+
ary = ::Array.new(layout[:repeat], element)
|
596
|
+
case layout[:type]
|
597
|
+
when :fixed
|
598
|
+
return DataType::Array.new(*ary)
|
599
|
+
end
|
600
|
+
end
|
601
|
+
|
602
|
+
element = TypeFormatString.new(_stream, @cparser).decompile
|
603
|
+
if (element_size = element.bytesize) == :variable
|
604
|
+
case @cparser.cpu.size
|
605
|
+
when 32
|
606
|
+
element_size = 4
|
607
|
+
when 64
|
608
|
+
element_size = 8
|
609
|
+
end
|
610
|
+
end
|
611
|
+
|
612
|
+
ary_len = total_size / element_size
|
613
|
+
ary = ::Array.new(ary_len, element)
|
614
|
+
DataType::Array.new(*ary)
|
615
|
+
end
|
616
|
+
end
|
617
|
+
|
618
|
+
class ConformatArray < TypeFormatString
|
619
|
+
def decompile
|
620
|
+
size = @cparser.sizeof(@cparser.find_c_struct('Conformant_Array_Header_t'))
|
621
|
+
header = @cparser.decode_c_struct('Conformant_Array_Header_t', @typefs_stream.read(size))
|
622
|
+
|
623
|
+
end
|
624
|
+
end
|
625
|
+
|
626
|
+
class PointerLayout < TypeFormatString
|
627
|
+
def decompile
|
628
|
+
offset = 2
|
629
|
+
layouts = []
|
630
|
+
loop do
|
631
|
+
begin
|
632
|
+
layout, len = decompile_instance_layout(offset)
|
633
|
+
offset += len
|
634
|
+
layouts << layout
|
635
|
+
rescue TurboRex::Exception::MSRPC::InvalidTypeFormatString
|
636
|
+
break
|
637
|
+
end
|
638
|
+
end
|
639
|
+
|
640
|
+
@fs_length = offset + 1
|
641
|
+
|
642
|
+
layouts
|
643
|
+
end
|
644
|
+
|
645
|
+
def fs_length
|
646
|
+
@fs_length
|
647
|
+
end
|
648
|
+
|
649
|
+
private
|
650
|
+
|
651
|
+
def decompile_instance_layout(offset)
|
652
|
+
length = 0
|
653
|
+
ptr_instance_cstruct = @cparser.find_c_struct('Pointer_Instance_t')
|
654
|
+
ptr_instance_size = @cparser.sizeof(ptr_instance_cstruct)
|
655
|
+
|
656
|
+
case @typefs_stream.read(1, offset).unpack('C').first
|
657
|
+
when FC_NO_REPEAT
|
658
|
+
cstruct = @cparser.find_c_struct('No_Repeat_Layout_t')
|
659
|
+
size = @cparser.sizeof(cstruct)
|
660
|
+
layout = @cparser.decode_c_struct('No_Repeat_Layout_t', @typefs_stream.read(size))
|
661
|
+
ptr_desc = layout.PtrDesc
|
662
|
+
_stream = @typefs_stream.dup
|
663
|
+
_stream.base_drift(offset+cstruct.offsetof(@cparser, 'Simple'))
|
664
|
+
length = layout.sizeof
|
665
|
+
pointer = CommonPtr.new(_stream, @cparser).decompile
|
666
|
+
|
667
|
+
return {repeat: 0, type: :no_repeat, pointer: pointer}, length
|
668
|
+
when FC_FIXED_REPEAT
|
669
|
+
cstruct = @cparser.find_c_struct('Fixed_Repeat_Layout_Header_t')
|
670
|
+
size = @cparser.sizeof(cstruct)
|
671
|
+
layout_header = @cparser.decode_c_struct('Fixed_Repeat_Layout_Header_t', @typefs_stream.read(size, offset))
|
672
|
+
|
673
|
+
ary_size = layout_header.NumberOfPointers
|
674
|
+
#ptr_instance_ary = @cparser.decode_c_ary('Pointer_Instance_t', ary_size, @typefs_stream.read(ary_size*ptr_instance_size, offset+size))
|
675
|
+
|
676
|
+
ptr_ary = []
|
677
|
+
ary_size.times do |i|
|
678
|
+
_stream = @typefs_stream.dup
|
679
|
+
_stream.base_drift(offset+layout_header.sizeof+i*ptr_instance_size+ptr_instance_cstruct.offsetof(@cparser, 'Simple'))
|
680
|
+
ptr_ary << CommonPtr.new(_stream, @cparser).decompile
|
681
|
+
end
|
682
|
+
|
683
|
+
length = layout_header.sizeof + ary_size*ptr_instance_size
|
684
|
+
return {repeat: layout_header.Iterations, type: :fixed, pointer: ptr_ary}, length
|
685
|
+
when FC_VARIABLE_REPEAT
|
686
|
+
cstruct = @cparser.find_c_struct('Variable_Repeat_Layout_Header_t')
|
687
|
+
size = @cparser.sizeof(cstruct)
|
688
|
+
layout_header = @cparser.decode_c_struct('Variable_Repeat_Layout_Header_t', @typefs_stream.read(size, offset))
|
689
|
+
|
690
|
+
case layout_header.OffsetType
|
691
|
+
when FC_FIXED_OFFSET
|
692
|
+
offset_type = :fixed
|
693
|
+
when FC_VARIABLE_OFFSET
|
694
|
+
offset_type = :variable
|
695
|
+
end
|
696
|
+
|
697
|
+
ary_size = layout_header.NumberOfPointers
|
698
|
+
ptr_ary = []
|
699
|
+
ary_size.times do |i|
|
700
|
+
_stream = @typefs_stream.dup
|
701
|
+
_stream.base_drift(offset+layout_header.sizeof+i*ptr_instance_size+ptr_instance_cstruct.offsetof(@cparser, 'Simple'))
|
702
|
+
ptr_ary << CommonPtr.new(_stream, @cparser).decompile
|
703
|
+
end
|
704
|
+
|
705
|
+
length = layout_header.sizeof + ary_size*ptr_instance_size
|
706
|
+
return {repeat: layout_header.Iterations, type: :variable, offset: offset_type, pointer: ptr_ary}, length
|
707
|
+
else
|
708
|
+
raise TurboRex::Exception::MSRPC::InvalidTypeFormatString
|
709
|
+
end
|
710
|
+
end
|
711
|
+
end
|
712
|
+
|
713
|
+
HANDLER_TABLE = [
|
714
|
+
{
|
715
|
+
type: [FC_BYTE,
|
716
|
+
FC_CHAR,
|
717
|
+
FC_SMALL,
|
718
|
+
FC_USMALL,
|
719
|
+
FC_WCHAR,
|
720
|
+
FC_SHORT,
|
721
|
+
FC_USHORT,
|
722
|
+
FC_LONG,
|
723
|
+
FC_ULONG,
|
724
|
+
FC_FLOAT,
|
725
|
+
FC_HYPER,
|
726
|
+
FC_DOUBLE,
|
727
|
+
FC_ENUM16,
|
728
|
+
FC_ENUM32,
|
729
|
+
FC_ERROR_STATUS_T,
|
730
|
+
FC_INT3264,
|
731
|
+
FC_UINT3264],
|
732
|
+
handler: SimpleType
|
733
|
+
},
|
734
|
+
{
|
735
|
+
type: [FC_RP, FC_UP, FC_FP, FC_OP], handler: CommonPtr,
|
736
|
+
},
|
737
|
+
{
|
738
|
+
type: [FC_SMFARRAY, FC_LGFARRAY], handler: FixedSizedArray
|
739
|
+
},
|
740
|
+
{
|
741
|
+
type: [FC_PP], handler: PointerLayout
|
742
|
+
}
|
743
|
+
]
|
744
|
+
end
|
745
|
+
end
|
746
|
+
end
|
747
|
+
end
|