class TurboRex::MSRPC::RPCFinder::ImageFinder
Attributes
client_interfaces[R]
client_routines[R]
dasm[R]
dispatch_funcs[R]
midl_server_infos[R]
midl_stubless_proxy_infos[R]
midl_syntax_infos[R]
ndr_decompiler[R]
pe[R]
server_interfaces[R]
server_routines[R]
Public Class Methods
glob(path, suffixes = nil) { |filename| ... }
click to toggle source
# File lib/turborex/msrpc/rpcfinder.rb, line 403 def self.glob(path, suffixes = nil) pattern = [] suffixes&.each { |suffix| pattern << File.join(path, '*') + suffix } if block_given? Dir.glob(pattern) do |filename| yield(filename) end else Dir.glob(pattern) end end
glob_all(root)
click to toggle source
# File lib/turborex/msrpc/rpcfinder.rb, line 399 def self.glob_all(root) Dir.glob(root + '/**/*') end
new(pe, _opts = {})
click to toggle source
# File lib/turborex/msrpc/rpcfinder.rb, line 381 def initialize(pe, _opts = {}) open_file(pe) @server_interfaces = [] @midl_server_infos = [] @midl_stub_descs = [] @midl_syntax_infos = [] @midl_stubless_proxy_infos = [] @server_routines = [] @dispatch_funcs = [] @client_interfaces = [] @dasm = new_dasm @collection_proxy = _opts[:collection_proxy] arch = @pe.ptr_32? ? 'x86' : 'x64' @ndr_decompiler = TurboRex::MSRPC::Decompiler.new(arch: arch) end
Public Instance Methods
auto_find(&block)
click to toggle source
# File lib/turborex/msrpc/rpcfinder.rb, line 436 def auto_find(&block) default = TurboRex::MSRPC::RPCFinder::ImageFinder::AutoFindConf.new config = if block_given? Docile.dsl_eval(default, &block).build else default.build end internal_auto_find(config) end
close()
click to toggle source
# File lib/turborex/msrpc/rpcfinder.rb, line 427 def close unless @pe.nil? @pe.close @pe = nil end true end
decompile_func(addr)
click to toggle source
# File lib/turborex/msrpc/rpcfinder.rb, line 997 def decompile_func(addr) dasm = disassemble_fast(addr)[0] dasm.decompiler.decompile(addr) # Metasm::C::Parser end
disassemble(addr, dasm = nil)
click to toggle source
# File lib/turborex/msrpc/rpcfinder.rb, line 979 def disassemble(addr, dasm = nil) dasm ||= (@dasm || new_dasm) res = dasm.disassemble addr [dasm, res] end
disassemble_executable_sections(dasm = nil)
click to toggle source
# File lib/turborex/msrpc/rpcfinder.rb, line 1002 def disassemble_executable_sections(dasm = nil) exe_sections = @pe.executable_sections unless exe_sections.empty? dasm ||= (@dasm || new_dasm) add_dasm_all_method(dasm) exe_sections.each do |s| dasm.dasm_all(@pe.rva_to_vma(s.base_rva), s.raw_size) end addrtolabel(dasm) dasm end end
disassemble_fast(addr, dasm = nil)
click to toggle source
# File lib/turborex/msrpc/rpcfinder.rb, line 991 def disassemble_fast(addr, dasm = nil) dasm ||= (@dasm || new_dasm) res = dasm.disassemble_fast(addr) [dasm, res] end
disassemble_fast_deep(addr, dasm = nil)
click to toggle source
# File lib/turborex/msrpc/rpcfinder.rb, line 985 def disassemble_fast_deep(addr, dasm = nil) dasm ||= (@dasm || new_dasm) res = dasm.disassemble_fast_deep(addr) [dasm, res] end
draw_ifs_xrefs()
click to toggle source
Xrefs in the same binary file
# File lib/turborex/msrpc/rpcfinder.rb, line 956 def draw_ifs_xrefs @server_interfaces.each do |si| @client_interfaces.each do |ci| calls = [] ci.routines.each do |cr| unless (res = si.func_in_server_routines(cr.addr)).empty? calls << { caller: res, called: cr } end end next if calls.empty? si.xrefs_from << [ci, calls] ci.xrefs_to << [si, calls] si.xrefs_from.uniq! si.xrefs_to.uniq! end end end
find_client_disp_functions(va, dasm, expr, *funcs) { |addr, dasm| ... }
click to toggle source
# File lib/turborex/msrpc/rpcfinder.rb, line 587 def find_client_disp_functions(va, dasm, expr, *funcs) disassemble_executable_sections(dasm) # addrtolabel(dasm) dispatch_funcs = [] if expr.nil? case dasm.cpu.size when 64 expr = 'rcx' when 32 expr = '[esp]' end end funcs.each do |func| callers = dasm.call_sites(Metasm::Expression[func]) callers.each do |addr| found, log = backtrace(addr, dasm, expr) next unless found.include?(va) # Finding proc number proc_num = nil case func when 'NdrClientCall' # Oi, conflict with 64-bit platform expr_procnum = '[esp+4]' switch = :Oi when 'NdrClientCall2' # Oicf expr_procnum = dasm.cpu.size == 64 ? 'rdx' : '[esp+4]' switch = :Oicf when 'NdrClientCall3' expr_procnum = 'rdx' when 'NdrClientCall4' # ? expr_procnum = dasm.cpu.size == 64 ? 'rdx' : '[esp+4]' end _found, _log = backtrace(addr, dasm, expr_procnum) unless _found.empty? if func == 'NdrClientCall3' proc_num = _found.first else _dasm = dasm.dup _dasm.c_parser = @ndr_decompiler.parser fs_header, header_len = @ndr_decompiler.parse_proc_fs_header_dasm(_dasm, _found[0]) proc_num = fs_header.oi_header.common.ProcNum end end yield(addr, dasm) if block_given? func_start = dasm.find_function_start(addr) dispatch_funcs << { dispatch_func: func_start, backtrace: [func, va, log], proc_num: proc_num } end end dispatch_funcs end
find_client_routines(client_if, client_if_addr, dasm = nil)
click to toggle source
# File lib/turborex/msrpc/rpcfinder.rb, line 648 def find_client_routines(client_if, client_if_addr, dasm = nil) dasm = @dasm || (@dasm = new_dasm) disp_funcs = [] if has_proxy_info?(client_if) # stubless proxy, no dispatch table and thunk table if proxy_info = get_stubless_pinfo_from_client_if(client_if) pi_obj = TurboRex::MSRPC::RPCBase::MIDL_STUBLESS_PROXY_INFO_Klass.new(proxy_info) pinterpreter_info = client_if.InterpreterInfo_Value @midl_stubless_proxy_infos << pi_obj client_if.midl_switches << %w[all win64 amd64 ia64] client_if.link_to pi_obj disp_funcs = find_client_disp_functions(pinterpreter_info, dasm, nil, 'NdrClientCall3') end else xrefs = scan_xrefs_immediate(client_if_addr, dasm) xrefs.each do |xref| midl_stub_desc = make_midl_stub_desc(@pe) reconstruct_struct_from_pe(@pe, @pe.vma_to_rva(xref), midl_stub_desc) next unless validate_midl_stub_desc(@pe, midl_stub_desc) stub_desc_obj = MIDL_STUB_DESC_Klass.new(midl_stub_desc) stub_desc_obj.link_to client_if @midl_stub_descs << stub_desc_obj disp_funcs = find_client_disp_functions(xref, dasm, nil, 'NdrClientCall', 'NdrClientCall2', 'NdrClientCall4') # TODO: detect switches when using NdrClientCall4 next unless b = disp_funcs[0]&.fetch(:backtrace) { } client_if.midl_switches << %w[Oi Oic] if b[0] == 'NdrClientCall' if b[0] == 'NdrClientCall2' client_if.midl_switches << %w[Oif Oicf] end end end disp_funcs.map do |m| r = TurboRex::MSRPC::RPCBase::CLIENT_ROUTINE_Klass.new(m[:dispatch_func]) r.proc_num = m[:proc_num] r end.uniq(&:addr) end
find_rpc_server_interface(opts = {}) { |rpc_server_interface, r| ... }
click to toggle source
# File lib/turborex/msrpc/rpcfinder.rb, line 553 def find_rpc_server_interface(opts = {}) rpc_server_interface = make_rpc_server_interface(@pe) regexp = Regexp.new [rpc_server_interface.slength].pack('V') res = [] opts[:only_data_section] ||= true if opts[:only_data_section] @pe.data_sections.each do |s| TurboRex::PEFile::Scanner.scan_section(s, regexp).each do |r| rpc_server_interface = make_rpc_server_interface(@pe) next unless reconstruct_struct_from_pe(@pe, r[0], rpc_server_interface) > 0 if validate_rpc_server_interface(@pe, rpc_server_interface) yield(rpc_server_interface, r[0]) if block_given? res << rpc_server_interface end end end else addr_info = TurboRex::PEFile::Scanner.scan_all_sections(@pe, regexp) unless addr_info.empty? addr_info.each do |addr| rpc_server_interface = make_rpc_server_interface(@pe) if reconstruct_struct_from_pe(@pe, addr[0], rpc_server_interface) > 0 yield(rpc_server_interface, addr[0]) if block_given? res << rpc_server_interface end end end end res end
get_disp_functions(rpc_dispatch_table)
click to toggle source
# File lib/turborex/msrpc/rpcfinder.rb, line 535 def get_disp_functions(rpc_dispatch_table) reconstruct_disp_functions(@pe, rpc_dispatch_table) end
get_dispatch_table(rpc_server_if)
click to toggle source
# File lib/turborex/msrpc/rpcfinder.rb, line 519 def get_dispatch_table(rpc_server_if) reconstruct_disptbl_for_server_interface(@pe, rpc_server_if) end
get_endpoint_info(rpc_server_if)
click to toggle source
# File lib/turborex/msrpc/rpcfinder.rb, line 531 def get_endpoint_info(rpc_server_if) reconstruct_endpoint_info(@pe, rpc_server_if) end
get_midl_server_info(rpc_server_if)
click to toggle source
# File lib/turborex/msrpc/rpcfinder.rb, line 503 def get_midl_server_info(rpc_server_if) reconstruct_midl_server_info(@pe, rpc_server_if) end
get_midl_stub_desc(midl_server_info)
click to toggle source
# File lib/turborex/msrpc/rpcfinder.rb, line 507 def get_midl_stub_desc(midl_server_info) reconstruct_midl_stub_desc(@pe, midl_server_info) end
get_midl_syntax_info(midl_server_info)
click to toggle source
# File lib/turborex/msrpc/rpcfinder.rb, line 515 def get_midl_syntax_info(midl_server_info) reconstruct_midl_syntax_info(@pe, midl_server_info) end
get_offset_table(rpc_server_if)
click to toggle source
# File lib/turborex/msrpc/rpcfinder.rb, line 523 def get_offset_table(rpc_server_if) reconstruct_offset_table(@pe, rpc_server_if) end
get_offset_table2(disptbl, midl_server_info)
click to toggle source
# File lib/turborex/msrpc/rpcfinder.rb, line 527 def get_offset_table2(disptbl, midl_server_info) reconstruct_offset_table2(@pe, disptbl, midl_server_info) end
get_routines_from_server_interface(rpc_server_interface)
click to toggle source
# File lib/turborex/msrpc/rpcfinder.rb, line 543 def get_routines_from_server_interface(rpc_server_interface) if has_interpreter_info?(rpc_server_interface) disptbl = get_dispatch_table(rpc_server_interface) midl_server_info = get_midl_server_info(rpc_server_interface) count = disptbl['dispatchTableCount'].value get_rpc_server_routines(midl_server_info, count) if count > 0 end end
get_rpc_server_routines(midl_server_info, count)
click to toggle source
# File lib/turborex/msrpc/rpcfinder.rb, line 539 def get_rpc_server_routines(midl_server_info, count) reconstruct_disptbl_for_midl_server_info(@pe, midl_server_info, count) end
get_stubless_pinfo_from_client_if(rpc_client_if)
click to toggle source
# File lib/turborex/msrpc/rpcfinder.rb, line 511 def get_stubless_pinfo_from_client_if(rpc_client_if) reconstruct_stubless_pinfo(@pe, rpc_client_if) end
make_midl_server_info(pe)
click to toggle source
# File lib/turborex/msrpc/rpcfinder.rb, line 455 def make_midl_server_info(pe) if pe.ptr_32? TurboRex::MSRPC::RPCBase::MIDL_SERVER_INFO32.make else TurboRex::MSRPC::RPCBase::MIDL_SERVER_INFO64.make end end
make_midl_stub_desc(pe)
click to toggle source
# File lib/turborex/msrpc/rpcfinder.rb, line 495 def make_midl_stub_desc(pe) if pe.ptr_32? TurboRex::MSRPC::RPCBase::MIDL_STUB_DESC.make(pack: 4, align: true) else TurboRex::MSRPC::RPCBase::MIDL_STUB_DESC64.make(pack: 8, align: true) end end
make_midl_stubless_proxy_info(pe)
click to toggle source
# File lib/turborex/msrpc/rpcfinder.rb, line 463 def make_midl_stubless_proxy_info(pe) if pe.ptr_32? TurboRex::MSRPC::RPCBase::MIDL_STUBLESS_PROXY_INFO32.make(pack: 4, align: true) else TurboRex::MSRPC::RPCBase::MIDL_STUBLESS_PROXY_INFO64.make(pack: 8, align: true) end end
make_midl_syntax_info(pe)
click to toggle source
# File lib/turborex/msrpc/rpcfinder.rb, line 471 def make_midl_syntax_info(pe) if pe.ptr_32? TurboRex::MSRPC::RPCBase::MIDL_SYNTAX_INFO32.make(pack: 4, align: true) else TurboRex::MSRPC::RPCBase::MIDL_SYNTAX_INFO64.make(pack: 8, align: true) end end
make_rpc_dispatch_table_t(pe)
click to toggle source
# File lib/turborex/msrpc/rpcfinder.rb, line 479 def make_rpc_dispatch_table_t(pe) if pe.ptr_32? TurboRex::MSRPC::RPCBase::RPC_DISPATCH_TABLE_T.make(pack: 4, align: true) else TurboRex::MSRPC::RPCBase::RPC_DISPATCH_TABLE_T64.make(pack: 8, align: true) end end
make_rpc_protseq_endpoint(pe)
click to toggle source
# File lib/turborex/msrpc/rpcfinder.rb, line 487 def make_rpc_protseq_endpoint(pe) if pe.ptr_32? TurboRex::MSRPC::RPCBase::RPC_PROTSEQ_ENDPOINT32.make(pack: 4, align: true) else TurboRex::MSRPC::RPCBase::RPC_PROTSEQ_ENDPOINT64.make(pack: 8, align: true) end end
make_rpc_server_interface(pe)
click to toggle source
# File lib/turborex/msrpc/rpcfinder.rb, line 447 def make_rpc_server_interface(pe) if pe.ptr_32? TurboRex::MSRPC::RPCBase::RPC_SERVER_INTERFACE32.make(pack: 4, align: true) else TurboRex::MSRPC::RPCBase::RPC_SERVER_INTERFACE64.make(pack: 8, align: true) end end
new_dasm()
click to toggle source
# File lib/turborex/msrpc/rpcfinder.rb, line 930 def new_dasm exe = Metasm::PE.decode_file @pe.image_path.to_s exe.disassembler end
open_file(filename)
click to toggle source
# File lib/turborex/msrpc/rpcfinder.rb, line 416 def open_file(filename) begin @pe = TurboRex::PEFile::PE.new_from_file(filename) @pe.image_path = Pathname.new(filename) rescue FileHeaderError return false end pe end
reconstruct_disp_functions(pe, rpc_dispatch_table)
click to toggle source
# File lib/turborex/msrpc/rpcfinder.rb, line 882 def reconstruct_disp_functions(pe, rpc_dispatch_table) count = rpc_dispatch_table['dispatchTableCount'].value pdispatch_table = pe.vma_to_rva(rpc_dispatch_table['dispatchTable'].value) dispatch_funcs = [] if pe.ptr_32? ptr_len = 4 format = 'V' func_name = 'read_dword' else ptr_len = 8 format = 'Q<' func_name = 'read_qword' end unless pdispatch_table == 0 count.times do |i| code = "#{func_name}(pe._isource, pe.rva_to_file_offset(pdispatch_table + #{i * ptr_len})).unpack('#{format}')[0]" begin dispatch_funcs << eval(code) rescue StandardError next end end end dispatch_funcs end
reconstruct_disptbl_for_midl_server_info(pe, midl_server_info, count)
click to toggle source
# File lib/turborex/msrpc/rpcfinder.rb, line 911 def reconstruct_disptbl_for_midl_server_info(pe, midl_server_info, count) rva = pe.vma_to_rva(midl_server_info['dispatchTable'].value) server_routines = [] if pe.ptr_32? count.times do server_routines << read_dword(pe._isource, pe.rva_to_file_offset(rva)).unpack('V')[0] rva += 4 end else count.times do server_routines << read_qword(pe._isource, pe.rva_to_file_offset(rva)).unpack('Q<')[0] rva += 8 end end server_routines end
reconstruct_disptbl_for_server_interface(pe, rpc_server_interface)
click to toggle source
# File lib/turborex/msrpc/rpcfinder.rb, line 870 def reconstruct_disptbl_for_server_interface(pe, rpc_server_interface) rva = pe.vma_to_rva(rpc_server_interface['dispatchTable'].value) reconstruct_disptbl_from_addr(pe, rva) end
reconstruct_disptbl_from_addr(pe, addr)
click to toggle source
# File lib/turborex/msrpc/rpcfinder.rb, line 875 def reconstruct_disptbl_from_addr(pe, addr) rpc_dispatch_table = make_rpc_dispatch_table_t(pe) reconstruct_struct_from_pe(pe, addr, rpc_dispatch_table) rpc_dispatch_table end
reconstruct_endpoint_info(pe, server_if)
click to toggle source
# File lib/turborex/msrpc/rpcfinder.rb, line 794 def reconstruct_endpoint_info(pe, server_if) endpoints = [] if (count = server_if['rpcProtseqEndpointCount'].value) > 0 rva = pe.vma_to_rva(server_if['rpcProtseqEndpoint'].value) count.times do |i| ep = make_rpc_protseq_endpoint(pe) reconstruct_struct_from_pe(pe, rva+i*ep.slength, ep) pprotseq = pe.vma_to_file_offset(ep['rpcProtocolSequence'].value) pendpoint = pe.vma_to_file_offset(ep['endpoint'].value) protseq = TurboRex::MSRPC::Utils.read_cstring(pe._isource, pprotseq)[0] ep_name = TurboRex::MSRPC::Utils.read_cstring(pe._isource, pendpoint)[0] endpoints << {protseq: protseq, ep_name: ep_name} i+=ep.slength end end endpoints end
reconstruct_midl_server_info(pe, rpc_server_interface)
click to toggle source
# File lib/turborex/msrpc/rpcfinder.rb, line 851 def reconstruct_midl_server_info(pe, rpc_server_interface) if validate_rpc_server_interface(pe, rpc_server_interface) && has_interpreter_info?(rpc_server_interface) rva = pe.vma_to_rva(rpc_server_interface['interpreterInfo'].value) midl_server_info = make_midl_server_info(pe) reconstruct_struct_from_pe(pe, rva, midl_server_info) midl_server_info end end
reconstruct_midl_stub_desc(pe, midl_server_info)
click to toggle source
# File lib/turborex/msrpc/rpcfinder.rb, line 861 def reconstruct_midl_stub_desc(pe, midl_server_info) unless midl_server_info['pStubDesc'].value == 0 rva = pe.vma_to_rva(midl_server_info['pStubDesc'].value) midl_stub_desc = make_midl_stub_desc(@pe) reconstruct_struct_from_pe(pe, rva, midl_stub_desc) midl_stub_desc if validate_midl_stub_desc(pe, midl_stub_desc) end end
reconstruct_midl_syntax_info(pe, midl_server_info)
click to toggle source
# File lib/turborex/msrpc/rpcfinder.rb, line 825 def reconstruct_midl_syntax_info(pe, midl_server_info) pSyntaxInfo = midl_server_info['pSyntaxInfo'].value count = midl_server_info['nCount'].value return nil if count < 0 syntax_infos = [] if pe.ptr_32? len = TurboRex::MSRPC::RPCBase::MIDL_SYNTAX_INFO32.make(pack: 4, align: true).slength else len = TurboRex::MSRPC::RPCBase::MIDL_SYNTAX_INFO64.make(pack: 8, align: true).slength end unless pSyntaxInfo == 0 count.times do |i| rva = pe.vma_to_rva(pSyntaxInfo + i * len) midl_syntax_info = make_midl_syntax_info(pe) reconstruct_struct_from_pe(pe, rva, midl_syntax_info) syntax_infos << midl_syntax_info end end syntax_infos end
reconstruct_offset_table(pe, server_if)
click to toggle source
# File lib/turborex/msrpc/rpcfinder.rb, line 775 def reconstruct_offset_table(pe, server_if) if server_if['interpreterInfo'].value != 0 server_info = reconstruct_midl_server_info(pe, server_if) unless server_info.nil? pdisptbl = pe.vma_to_rva(server_if['dispatchTable'].value) disptbl = reconstruct_disptbl_from_addr(pe, pdisptbl) reconstruct_offset_table2(pe, disptbl, server_info) end end end
reconstruct_offset_table2(pe, disptbl, midl_server_info)
click to toggle source
# File lib/turborex/msrpc/rpcfinder.rb, line 788 def reconstruct_offset_table2(pe, disptbl, midl_server_info) poffset_table = pe.vma_to_file_offset(midl_server_info['fmtStringOffset'].value) count = disptbl['dispatchTableCount'].value pe._isource.read(poffset_table, count).unpack('C'*count) end
reconstruct_struct_from_pe(pe, rva, cstruct)
click to toggle source
# File lib/turborex/msrpc/rpcfinder.rb, line 769 def reconstruct_struct_from_pe(pe, rva, cstruct) length = cstruct.slength data = pe._isource.read(pe.rva_to_file_offset(rva), length) cstruct.from_s data end
reconstruct_stubless_pinfo(pe, client_if)
click to toggle source
# File lib/turborex/msrpc/rpcfinder.rb, line 817 def reconstruct_stubless_pinfo(pe, client_if) proxy_info = make_midl_stubless_proxy_info(pe) pinterpreter_info = client_if.InterpreterInfo_Value rva = pe.vma_to_rva(pinterpreter_info) reconstruct_struct_from_pe(pe, rva, proxy_info) proxy_info if validate_stubless_proxy_info(pe, proxy_info) end
scan_xrefs_immediate(addr, dasm = nil)
click to toggle source
# File lib/turborex/msrpc/rpcfinder.rb, line 936 def scan_xrefs_immediate(addr, dasm = nil) dasm ||= (@dasm || new_dasm) cpu_size = dasm.cpu.size mask = (1 << cpu_size) - 1 format = (cpu_size == 64 ? 'q' : 'V') res = [] dasm.sections.sort.each do |start_addr, encoded_data| raw = encoded_data.data.to_str (0..raw.length - cpu_size / 8).each do |offset| data = raw[offset, cpu_size / 8].unpack(format).first res << (start_addr + offset) if data == addr end end res end
validate_midl_stub_desc(pe, struct)
click to toggle source
# File lib/turborex/msrpc/rpcfinder.rb, line 727 def validate_midl_stub_desc(pe, struct) pfnAllocate = struct['pfnAllocate'].value pfnFree = struct['pfnFree'].value phandle = struct['implicit_handle_info'].value bounds_flag = struct['fCheckBounds'].value # TODO: more check(version) pointer_check = pe.valid_vma?(pfnAllocate) && pe.valid_vma?(pfnFree) # && pe.valid_vma?(phandle) # Rex library valid_vma? method make a mistake here. bounds_flag_check = (bounds_flag == 1 || bounds_flag == 0) pointer_check && bounds_flag end
validate_rpc_server_interface(pe, rpc_server_interface)
click to toggle source
# File lib/turborex/msrpc/rpcfinder.rb, line 695 def validate_rpc_server_interface(pe, rpc_server_interface) length = rpc_server_interface.slength return false unless rpc_server_interface['length'].value == length unless validate_transfer_syntax(rpc_server_interface['transferSyntax']) return false end itpInfo = rpc_server_interface['interpreterInfo'].value # vma if itpInfo == 0 # TODO: Inline stub check else section = pe._find_section_by_rva(pe.vma_to_rva(itpInfo)) return false if section.nil? return false unless TurboRex::PEFile::Scanner.data_section?(section) end dispTable = rpc_server_interface['dispatchTable'].value unless dispTable == 0 section = pe._find_section_by_rva(pe.vma_to_rva(dispTable)) return false if section.nil? return false unless TurboRex::PEFile::Scanner.data_section?(section) end true end
validate_server_interface_from_pe(pe, address)
click to toggle source
# File lib/turborex/msrpc/rpcfinder.rb, line 721 def validate_server_interface_from_pe(pe, address) make_rpc_server_interface(pe) reconstruct_struct_from_pe(pe, address, rpc_server_interface) validate_rpc_server_interface(pe, rpc_server_interface) end
validate_stubless_proxy_info(pe, stubless_proxy_info, strict_check = true)
click to toggle source
The “strict_check” option will use the algorithm of NdrClientCall3
# File lib/turborex/msrpc/rpcfinder.rb, line 743 def validate_stubless_proxy_info(pe, stubless_proxy_info, strict_check = true) pTransferSyntax = stubless_proxy_info['pTransferSyntax'].value pSyntaxInfo = stubless_proxy_info['pSyntaxInfo'].value nCount = stubless_proxy_info['nCount'].value dce_transfer = DCE_TransferSyntax.to_s ndr64_transfer = NDR64_TransferSyntax.to_s len = make_midl_syntax_info(pe).slength return false if pTransferSyntax == 0 transfer_syntax = pe._isource.read(pe.vma_to_file_offset(pTransferSyntax), DCE_TransferSyntax.slength) unless transfer_syntax == dce_transfer || transfer_syntax == ndr64_transfer return false end if strict_check nCount.times do |i| syntaxinfo_trans = pe._isource.read(pe.vma_to_file_offset(pSyntaxInfo + i * len), DCE_TransferSyntax.slength) break if syntaxinfo_trans == transfer_syntax return false if i + 1 == nCount end end true end
validate_transfer_syntax(transfer_syntax)
click to toggle source
# File lib/turborex/msrpc/rpcfinder.rb, line 691 def validate_transfer_syntax(transfer_syntax) transfer_syntax.to_s == DCE_TransferSyntax.to_s || transfer_syntax.to_s == NDR64_TransferSyntax.to_s end
Private Instance Methods
has_interpreter_info?(rpc_server_interface)
click to toggle source
# File lib/turborex/msrpc/rpcfinder.rb, line 1027 def has_interpreter_info?(rpc_server_interface) # Don't assume when flag is set. Must check if InterpreterInfo is a null pointer. (rpc_server_interface['flags'].value & 0x4000000) == 0x4000000 && \ rpc_server_interface['interpreterInfo'].value != 0 end
has_proxy_info?(rpc_server_interface)
click to toggle source
# File lib/turborex/msrpc/rpcfinder.rb, line 1033 def has_proxy_info?(rpc_server_interface) flags = (begin rpc_server_interface['flags'].value rescue StandardError rpc_server_interface.Flags end) interpreter_info = (begin rpc_server_interface['interpreterInfo'].value rescue StandardError rpc_server_interface.InterpreterInfo end) (flags & 0x2000000) == 0x2000000 && \ interpreter_info != 0 end
internal_auto_find(config = {})
click to toggle source
# File lib/turborex/msrpc/rpcfinder.rb, line 1048 def internal_auto_find(config = {}) @server_interfaces = [] @dispatch_funcs = [] @server_routines = [] @client_routines = [] @client_interfaces = [] @midl_stub_descs = [] find_rpc_server_interface do |r, s_addr| next if r.nil? si_obj = TurboRex::MSRPC::RPCBase::RPC_SERVER_INTERFACE_Klass.new(r) interface = InterfaceModel.new si_obj, self interface.endpoints = get_endpoint_info(r) if interface.dispatch_table_nullptr? # maybe client next unless config[:include_client] @client_interfaces << interface @collection_proxy&.push_client(interface) if config[:find_client_routines] cr = find_client_routines(interface, @pe.rva_to_vma(s_addr)) @client_routines |= cr interface.routines = cr end else # server next if config[:only_client] @server_interfaces << interface @collection_proxy&.push_server(interface) disp_table = get_dispatch_table(r) disp_func = get_disp_functions(disp_table) @dispatch_funcs |= disp_func disp_table_obj = TurboRex::MSRPC::RPCBase::RPC_DISPATCH_TABLE_Klass.new(disp_table) disp_table_obj.link_to disp_func interface.link_to disp_table_obj msi = get_midl_server_info(r) if msi.nil? # Inline stub(-Os mode) @dispatch_funcs |= disp_func else msi_obj = TurboRex::MSRPC::RPCBase::MIDL_SERVER_INFO_Klass.new(msi) @midl_server_infos << msi_obj interface.link_to msi_obj # find all server routines routines = get_routines_from_server_interface(r) unless routines.nil? r_objs = routines.map { |r| TurboRex::MSRPC::RPCBase::SERVER_ROUTINE_Klass.new(r) } @server_routines |= r_objs interface.routines = r_objs msi_obj.link_to r_objs end # reconstruct MIDL_SYNTAX_INFO midl_syntax_info = get_midl_syntax_info(msi) unless midl_syntax_info.nil? || midl_syntax_info.empty? objs = [] midl_syntax_info.each do |m| syntax_info_obj = TurboRex::MSRPC::RPCBase::MIDL_SYNTAX_INFO_Klass.new(m) pdisp_tbl = syntax_info_obj.DispatchTable unless pdisp_tbl == 0 disptbl = reconstruct_disptbl_from_addr(@pe, @pe.vma_to_rva(pdisp_tbl)) disp_funcs = reconstruct_disp_functions(@pe, disptbl) disptbl_obj = RPC_DISPATCH_TABLE_Klass.new(disptbl) disptbl_obj.link_to disp_funcs syntax_info_obj.link_to disptbl_obj end @midl_syntax_infos << syntax_info_obj objs << syntax_info_obj end msi_obj.link_to objs end # reconstruct MIDL_STUB_DESC midl_stub_desc = get_midl_stub_desc(msi) unless midl_stub_desc.nil? stub_desc_obj = TurboRex::MSRPC::RPCBase::MIDL_STUB_DESC_Klass.new(midl_stub_desc) msi_obj.link_to stub_desc_obj end # reconstruct offset_table interface.offset_table = get_offset_table2(disp_table, msi) end end interface.analysis_midl_switches if config[:analysis_switches] end end
read_dword(isource, address)
click to toggle source
# File lib/turborex/msrpc/rpcfinder.rb, line 1019 def read_dword(isource, address) isource.read(address, 4) end
read_qword(isource, address)
click to toggle source
# File lib/turborex/msrpc/rpcfinder.rb, line 1023 def read_qword(isource, address) isource.read(address, 8) end