turborex 0.1.1
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.
- 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
|