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,70 @@
|
|
1
|
+
module TurboRex
|
2
|
+
module MSRPC
|
3
|
+
module Utils
|
4
|
+
extend TurboRex::MSRPC::RPCBase
|
5
|
+
|
6
|
+
def get_interface_type
|
7
|
+
raise NotImplementedError
|
8
|
+
end
|
9
|
+
|
10
|
+
def gen_script_rpc_client_np(opts = {})
|
11
|
+
uuid = opts[:uuid]
|
12
|
+
version = opts[:version] || '1.0'
|
13
|
+
function = opts[:function]
|
14
|
+
data = opts[:data]
|
15
|
+
pipe = opts[:pipe]
|
16
|
+
output = opts[:output] || 'my_rpc_client.rb'
|
17
|
+
|
18
|
+
template = <<-EOS
|
19
|
+
#usage: ruby your_script.rb RHOST USERNAME PASSWORD
|
20
|
+
require 'rex'
|
21
|
+
require 'rex/encoder/ndr'
|
22
|
+
|
23
|
+
Rex::Proto::SMB::SimpleClient.class_eval do
|
24
|
+
attr_accessor :read_timeout
|
25
|
+
end
|
26
|
+
|
27
|
+
uuid = #{uuid}
|
28
|
+
version = #{version}
|
29
|
+
protocol = 'ncacn_np'
|
30
|
+
rhost = ARGV[0]
|
31
|
+
opts = ['#{pipe}']
|
32
|
+
handle = Rex::Proto::DCERPC::Handle.new([uuid, version], protocol, rhost, opts)
|
33
|
+
function = #{function}
|
34
|
+
data = #{data}
|
35
|
+
|
36
|
+
sock = Rex::Socket::Tcp.create('PeerHost' => rhost, 'PeerPort' => 445)
|
37
|
+
dcerpc = Rex::Proto::DCERPC::Client.new(handle, sock, {'smb_user' => ARGV[1], 'smb_pass' => ARGV[2]})
|
38
|
+
res = dcerpc.call(function, data, true)
|
39
|
+
|
40
|
+
puts res
|
41
|
+
EOS
|
42
|
+
|
43
|
+
file = File.new(output, 'rw')
|
44
|
+
file.puts template
|
45
|
+
file.close
|
46
|
+
|
47
|
+
true
|
48
|
+
end
|
49
|
+
|
50
|
+
def self.raw_to_guid_str(raw, upcase = true)
|
51
|
+
unpacked = raw.unpack("VvvCCa6")
|
52
|
+
mac = unpacked[5].unpack("C*")
|
53
|
+
unpacked[-1] = '%02x%02x%02x%02x%02x%02x' % mac
|
54
|
+
formatted = ("%08x-%04x-%04x-%02x%02x-%s" % unpacked)
|
55
|
+
upcase ? formatted.upcase : formatted
|
56
|
+
end
|
57
|
+
|
58
|
+
def self.read_cstring(isource, base=0)
|
59
|
+
len=0
|
60
|
+
cstr = ""
|
61
|
+
until (data=isource.read(base+len, 1)) == "\x00"
|
62
|
+
cstr << data
|
63
|
+
len+=1
|
64
|
+
end
|
65
|
+
|
66
|
+
return cstr, len
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
require 'rex/peparsey'
|
2
|
+
require 'pathname'
|
3
|
+
require 'rgl/adjacency'
|
4
|
+
|
5
|
+
module TurboRex
|
6
|
+
module PEFile
|
7
|
+
class PE < Rex::PeParsey::Pe
|
8
|
+
attr_accessor :image_path
|
9
|
+
attr_reader :data_sections
|
10
|
+
attr_reader :executable_sections
|
11
|
+
|
12
|
+
def initialize(isource)
|
13
|
+
super(isource)
|
14
|
+
|
15
|
+
get_data_sections
|
16
|
+
get_executable_sections
|
17
|
+
end
|
18
|
+
|
19
|
+
def data_section_names
|
20
|
+
unless @data_sections.empty?
|
21
|
+
names = []
|
22
|
+
@data_sections.each do |section|
|
23
|
+
names << section.name
|
24
|
+
end
|
25
|
+
|
26
|
+
return names
|
27
|
+
end
|
28
|
+
|
29
|
+
nil
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
def get_data_sections
|
35
|
+
@data_sections = []
|
36
|
+
self.all_sections.each do |section|
|
37
|
+
next if section.flags.nil?
|
38
|
+
if section.flags & 0x20000000 != 0 #IMAGE_SCN_MEM_EXECUTE
|
39
|
+
next
|
40
|
+
end
|
41
|
+
|
42
|
+
unless section.flags & 0x40000000 != 0 #IMAGE_SCN_MEM_READ
|
43
|
+
next
|
44
|
+
end
|
45
|
+
|
46
|
+
@data_sections << section
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def get_executable_sections
|
51
|
+
@executable_sections = []
|
52
|
+
self.all_sections.each do |section|
|
53
|
+
next if section.flags.nil?
|
54
|
+
if section.flags & 0x20000000 != 0 #IMAGE_SCN_MEM_EXECUTE
|
55
|
+
@executable_sections << section
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
module TurboRex
|
2
|
+
module PEFile
|
3
|
+
module Scanner
|
4
|
+
require 'rgl/path'
|
5
|
+
|
6
|
+
def self.scan_section(section, regex)
|
7
|
+
index = 0
|
8
|
+
|
9
|
+
hits = []
|
10
|
+
|
11
|
+
while index < section.size && (index = section.index(regex, index)) != nil
|
12
|
+
|
13
|
+
idx = index
|
14
|
+
buf = ''
|
15
|
+
mat = nil
|
16
|
+
|
17
|
+
while (!(mat = buf.match(regex)))
|
18
|
+
buf << section.read(idx, 1)
|
19
|
+
idx += 1
|
20
|
+
end
|
21
|
+
|
22
|
+
rva = section.offset_to_rva(index)
|
23
|
+
|
24
|
+
hits << [rva, buf.unpack("H*")]
|
25
|
+
index += buf.length
|
26
|
+
end
|
27
|
+
|
28
|
+
return hits
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.scan_all_sections(pe, regex)
|
32
|
+
result = []
|
33
|
+
|
34
|
+
pe.all_sections.each do |section|
|
35
|
+
Scanner.scan_section(section, regex).each do |r|
|
36
|
+
result << r
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def self.data_section?(section)
|
42
|
+
if section.flags & 0x20000000 != 0 #IMAGE_SCN_MEM_EXECUTE
|
43
|
+
return false
|
44
|
+
end
|
45
|
+
|
46
|
+
unless section.flags & 0x40000000 != 0 #IMAGE_SCN_MEM_READ
|
47
|
+
return false
|
48
|
+
end
|
49
|
+
|
50
|
+
return true
|
51
|
+
end
|
52
|
+
|
53
|
+
def has_path?(dasm, addr1, addr2, dg=nil)
|
54
|
+
dg = draw_xrefs_dg(dasm, addr1) unless dg
|
55
|
+
|
56
|
+
v1 = dasm.get_label_at(addr1) || addr1.to_s
|
57
|
+
v2 = dasm.get_label_at(addr2) || addr2.to_s
|
58
|
+
dg.path?(v1, v2)
|
59
|
+
end
|
60
|
+
|
61
|
+
def draw_xrefs_dg(dasm, addr1)
|
62
|
+
g = dasm.function_graph_from(addr1)
|
63
|
+
dg = RGL::DirectedAdjacencyGraph.new
|
64
|
+
|
65
|
+
(g.keys + g.values).flatten.uniq.each do |e|
|
66
|
+
label = dasm.get_label_at(e) || e.to_s
|
67
|
+
dg.add_vertex label
|
68
|
+
end
|
69
|
+
|
70
|
+
g.each do |k, v|
|
71
|
+
kl = dasm.get_label_at(k) || k.to_s
|
72
|
+
v.each do |e|
|
73
|
+
el = dasm.get_label_at(e) || e.to_s
|
74
|
+
dg.add_edge(kl, el)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
dg
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
@@ -0,0 +1,321 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module TurboRex
|
4
|
+
module Utils
|
5
|
+
def self.get_all_subdir(root_path)
|
6
|
+
require 'find'
|
7
|
+
paths = []
|
8
|
+
Find.find(root_path) do |path|
|
9
|
+
if FileTest.directory?(path)
|
10
|
+
if File.basename(path)[0] == '.'
|
11
|
+
Find.prune
|
12
|
+
else
|
13
|
+
paths << path
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
paths
|
19
|
+
end
|
20
|
+
|
21
|
+
module DisassemblerHelper
|
22
|
+
# https://github.com/jjyg/metasm/blob/master/samples/dasm-plugins/imm2off.rb
|
23
|
+
def addrtolabel(dasm)
|
24
|
+
bp = dasm.prog_binding.invert
|
25
|
+
dasm.decoded.each_value do |di|
|
26
|
+
next unless di.is_a?(Metasm::DecodedInstruction)
|
27
|
+
|
28
|
+
di.each_expr do |e|
|
29
|
+
next unless e.is_a?(Metasm::Expression)
|
30
|
+
|
31
|
+
if l = bp[e.lexpr]
|
32
|
+
dasm.add_xref(e.lexpr, Metasm::Xref.new(:addr, di.address))
|
33
|
+
e.lexpr = Metasm::Expression[l]
|
34
|
+
end
|
35
|
+
if l = bp[e.rexpr]
|
36
|
+
dasm.add_xref(e.rexpr, Metasm::Xref.new(:addr, di.address))
|
37
|
+
e.rexpr = (e.lexpr ? Metasm::Expression[l] : l)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
nil
|
42
|
+
end
|
43
|
+
|
44
|
+
def add_dasm_all_method(dasm)
|
45
|
+
dasm.instance_eval %(
|
46
|
+
def dasm_all(addrstart, length, method=:disassemble_fast_deep)
|
47
|
+
s = get_section_at(addrstart)
|
48
|
+
return if not s
|
49
|
+
s = s[0]
|
50
|
+
boff = s.ptr
|
51
|
+
off = 0
|
52
|
+
while off < length
|
53
|
+
if di = di_at(addrstart + off)
|
54
|
+
off += di.bin_length
|
55
|
+
elsif @decoded[addrstart+off]
|
56
|
+
off += 1
|
57
|
+
else
|
58
|
+
s.ptr = boff+off
|
59
|
+
maydi = cpu.decode_instruction(s, 0)
|
60
|
+
if not maydi
|
61
|
+
off += 1
|
62
|
+
elsif maydi.instruction.to_s =~ /nop|lea (.*), \[\1(?:\+0)?\]|mov (.*), \2|int 3/
|
63
|
+
off += maydi.bin_length
|
64
|
+
else
|
65
|
+
send(method, addrstart+off)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
count = 0
|
71
|
+
off = 0
|
72
|
+
while off < length
|
73
|
+
addr = addrstart+off
|
74
|
+
if di = di_at(addr)
|
75
|
+
if di.block_head?
|
76
|
+
b = di.block
|
77
|
+
if not @function[addr] and b.from_subfuncret.to_a.empty? and b.from_normal.to_a.empty?
|
78
|
+
l = auto_label_at(addr, 'sub_orph')
|
79
|
+
@function[addrstart+off] = Metasm::DecodedFunction.new
|
80
|
+
@function[addrstart+off].finalized = true
|
81
|
+
detect_function_thunk(addr)
|
82
|
+
count += 1
|
83
|
+
end
|
84
|
+
end
|
85
|
+
off += di.bin_length
|
86
|
+
else
|
87
|
+
off += 1
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
end
|
92
|
+
)
|
93
|
+
|
94
|
+
dasm
|
95
|
+
end
|
96
|
+
|
97
|
+
def _disassemble_executable_sections(pe, method=:disassemble_fast_deep)
|
98
|
+
dasm = pe.disassembler
|
99
|
+
executable_sections = pe.section_info.select {|s| s.last.to_s.split(',').include?('MEM_EXECUTE')}
|
100
|
+
unless executable_sections.empty?
|
101
|
+
add_dasm_all_method(dasm)
|
102
|
+
executable_sections.each do |name, address, len|
|
103
|
+
dasm.dasm_all(address, len, method)
|
104
|
+
end
|
105
|
+
|
106
|
+
addrtolabel(dasm)
|
107
|
+
dasm
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
# https://github.com/jjyg/metasm/blob/2a088ff85e5b873570bc284a97ddd9f8b3b0a03a/metasm/gui/dasm_main.rb#L413
|
112
|
+
def backtrace(addr, dasm, e, narg={})
|
113
|
+
bd = {}
|
114
|
+
expr = Metasm::IndExpression.parse_string(e)
|
115
|
+
registers = (begin
|
116
|
+
dasm.cpu.dbg_register_list.map(&:to_s)
|
117
|
+
rescue StandardError
|
118
|
+
[]
|
119
|
+
end)
|
120
|
+
expr.externals.grep(String).each do |w|
|
121
|
+
bd[w] = w.downcase.to_sym if registers.include? w.downcase
|
122
|
+
end
|
123
|
+
|
124
|
+
expr = expr.bind(bd).reduce do |e_|
|
125
|
+
e_.len ||= dasm.cpu.size / 8 if e_.is_a? Metasm::Indirection; nil
|
126
|
+
end
|
127
|
+
|
128
|
+
log = []
|
129
|
+
found = []
|
130
|
+
bt_opts = { log: log }
|
131
|
+
bt_opts.merge!(narg)
|
132
|
+
dasm.backtrace(expr, addr, bt_opts)
|
133
|
+
if found_log = log.assoc(:found)
|
134
|
+
found_log[1].each do |expr|
|
135
|
+
found << dasm.resolve(expr)
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
[found, log]
|
140
|
+
end
|
141
|
+
|
142
|
+
def solve_cppobj_call(dasm, di)
|
143
|
+
return unless di.opcode.props[:saveip]
|
144
|
+
fptr = dasm.get_xrefs_x(di)
|
145
|
+
return if fptr.to_a.length != 1
|
146
|
+
fptr = ::Metasm::Expression[fptr.first].reduce_rec
|
147
|
+
return unless fptr.kind_of? ::Metasm::Indirection
|
148
|
+
return unless fptr.pointer.lexpr.kind_of? Symbol
|
149
|
+
return unless fptr.pointer.rexpr.kind_of? Integer
|
150
|
+
log = []
|
151
|
+
vtbl = dasm.backtrace(fptr.pointer.lexpr, di.address, log: log)
|
152
|
+
vtbl.delete ::Metasm::Expression::Unknown
|
153
|
+
|
154
|
+
if vtbl.empty?
|
155
|
+
r = log.reverse_each.detect {|l| l[0] != :found && l[2] != ::Metasm::Expression[:unknown]}
|
156
|
+
vtbl = r[2].reduce_rec
|
157
|
+
else
|
158
|
+
vtbl = vtbl.first
|
159
|
+
end
|
160
|
+
|
161
|
+
vtbl = ::Metasm::Expression[vtbl].reduce_rec
|
162
|
+
return unless vtbl.kind_of? ::Metasm::Indirection
|
163
|
+
obj = vtbl.pointer
|
164
|
+
ptr_size = @dasm.program.cpu.size / 8
|
165
|
+
[obj, vtbl, fptr.pointer.rexpr / ptr_size]
|
166
|
+
end
|
167
|
+
|
168
|
+
def solve_guard_icall(dasm, di)
|
169
|
+
return unless di.opcode.props[:saveip]
|
170
|
+
fptr = dasm.get_xrefs_x(di)
|
171
|
+
return if fptr.to_a.length != 1
|
172
|
+
fptr = ::Metasm::Expression[fptr.first].reduce_rec
|
173
|
+
return unless fptr.kind_of? ::Metasm::Indirection
|
174
|
+
|
175
|
+
v = case dasm.cpu.size
|
176
|
+
when 32
|
177
|
+
dasm.program.decode_loadconfig.guard_check_icall
|
178
|
+
when 64
|
179
|
+
dasm.program.decode_loadconfig.guard_dispatch_icall
|
180
|
+
end
|
181
|
+
|
182
|
+
#f = dasm.decode_dword(dasm.normalize(dasm.prog_binding[v.to_s])).to_s
|
183
|
+
if v == fptr.pointer
|
184
|
+
case dasm.cpu.size
|
185
|
+
when 32
|
186
|
+
expr = :ecx
|
187
|
+
when 64
|
188
|
+
expr = :rax
|
189
|
+
end
|
190
|
+
|
191
|
+
log = []
|
192
|
+
res = dasm.backtrace(expr, di.address, log: log)
|
193
|
+
res.delete ::Metasm::Expression::Unknown
|
194
|
+
if res.empty?
|
195
|
+
r = log.reverse_each.detect {|l| l[0] != :found && l[2] != ::Metasm::Expression[:unknown]}
|
196
|
+
return r[2].reduce_rec
|
197
|
+
end
|
198
|
+
|
199
|
+
return res.first
|
200
|
+
end
|
201
|
+
end
|
202
|
+
end
|
203
|
+
|
204
|
+
module COMApiBacktraceHelper
|
205
|
+
include DisassemblerHelper
|
206
|
+
|
207
|
+
def bt_cocreateinstance(dasm, addr, filter={})
|
208
|
+
case dasm.cpu.size
|
209
|
+
when 32
|
210
|
+
expr_rclsid = '[esp]'
|
211
|
+
expr_context = '[esp+8]'
|
212
|
+
expr_riid = '[esp+12]'
|
213
|
+
expr_pv = '[[esp+16]]'
|
214
|
+
when 64
|
215
|
+
expr_rclsid = 'rcx'
|
216
|
+
expr_context = 'r8'
|
217
|
+
expr_riid = 'r9'
|
218
|
+
expr_pv = '[[rsp+32]]'
|
219
|
+
end
|
220
|
+
|
221
|
+
rclsid, context, riid, pv = [:unknown]*4
|
222
|
+
# rclsid
|
223
|
+
found, _ = backtrace(addr, dasm, expr_rclsid)
|
224
|
+
unless found.empty?
|
225
|
+
raw_rclsid = dasm.read_raw_data(found.first, 16)
|
226
|
+
rclsid = TurboRex::MSRPC::Utils.raw_to_guid_str(raw_rclsid)
|
227
|
+
if filter[:rclsid]
|
228
|
+
return unless rclsid == filter[:rclsid]
|
229
|
+
end
|
230
|
+
end
|
231
|
+
|
232
|
+
#context
|
233
|
+
found, _ = backtrace(addr, dasm, expr_context)
|
234
|
+
unless found.empty?
|
235
|
+
context = found.first
|
236
|
+
if filter[:context]
|
237
|
+
return unless context == filter[:context]
|
238
|
+
end
|
239
|
+
end
|
240
|
+
|
241
|
+
# riid
|
242
|
+
found, _ = backtrace(addr, dasm, expr_riid)
|
243
|
+
unless found.empty?
|
244
|
+
raw_riid = dasm.read_raw_data(found.first, 16)
|
245
|
+
riid = TurboRex::MSRPC::Utils.raw_to_guid_str(raw_riid)
|
246
|
+
if filter[:riid]
|
247
|
+
return unless riid == filter[:riid]
|
248
|
+
end
|
249
|
+
end
|
250
|
+
|
251
|
+
# pv
|
252
|
+
log = []
|
253
|
+
found, _ = backtrace(addr, dasm, expr_pv, log: log)
|
254
|
+
found.delete ::Metasm::Expression::Unknown
|
255
|
+
if found.empty?
|
256
|
+
r = log.reverse_each.detect {|l| l[0] != :found && l[2] != ::Metasm::Expression[:unknown]}
|
257
|
+
pv = r[2].reduce_rec
|
258
|
+
else
|
259
|
+
pv = found.first
|
260
|
+
end
|
261
|
+
|
262
|
+
|
263
|
+
{rclsid: rclsid, context: context, riid: riid, pv: pv}
|
264
|
+
end
|
265
|
+
|
266
|
+
# TODO: Backtrace ServerInfo
|
267
|
+
def bt_cocreateinstanceex(dasm, addr, filter={})
|
268
|
+
case dasm.cpu.size
|
269
|
+
when 32
|
270
|
+
expr_rclsid = '[esp]'
|
271
|
+
expr_context = '[esp+8]'
|
272
|
+
expr_count = '[esp+16]'
|
273
|
+
expr_results = '[esp+20]'
|
274
|
+
when 64
|
275
|
+
expr_rclsid = 'rcx'
|
276
|
+
expr_context = 'r8'
|
277
|
+
expr_count = 'dword ptr [rsp+32]'
|
278
|
+
expr_results = '[rsp+40]'
|
279
|
+
end
|
280
|
+
|
281
|
+
rclsid, context, iids = [:unknown]*3
|
282
|
+
|
283
|
+
# rclsid
|
284
|
+
found, _ = backtrace(addr, dasm, expr_rclsid)
|
285
|
+
unless found.empty?
|
286
|
+
raw_rclsid = dasm.read_raw_data(found.first, 16)
|
287
|
+
rclsid = TurboRex::MSRPC::Utils.raw_to_guid_str(raw_rclsid)
|
288
|
+
if filter[:rclsid]
|
289
|
+
return unless rclsid == filter[:rclsid]
|
290
|
+
end
|
291
|
+
end
|
292
|
+
|
293
|
+
#context
|
294
|
+
found, _ = backtrace(addr, dasm, expr_context)
|
295
|
+
unless found.empty?
|
296
|
+
context = found.first
|
297
|
+
if filter[:context]
|
298
|
+
return unless context == filter[:context]
|
299
|
+
end
|
300
|
+
end
|
301
|
+
|
302
|
+
# results and count
|
303
|
+
found, _ = backtrace(addr, dasm, expr_count)
|
304
|
+
unless found.empty?
|
305
|
+
count = found.first
|
306
|
+
iids = []
|
307
|
+
size = dasm.alloc_c_struct('MULTI_QI').sizeof
|
308
|
+
count.times do |i|
|
309
|
+
expr_iid = "[#{expr_results}+#{i*size}]"
|
310
|
+
found, _ = backtrace(addr, dasm, expr_iid)
|
311
|
+
unless found.empty?
|
312
|
+
iids << found.first
|
313
|
+
end
|
314
|
+
end
|
315
|
+
end
|
316
|
+
|
317
|
+
{rclsid: rclsid, context: context, iids: iids}
|
318
|
+
end
|
319
|
+
end
|
320
|
+
end
|
321
|
+
end
|