# -*- coding: binary -*- require 'msf/core' module Msf ### # # This module exposes methods for talking to WDBRPC daemons # ### module Exploit::Remote::WDBRPC_Client include Exploit::Remote::WDBRPC include Auxiliary::Report attr_accessor :wdbrpc_info, :udp_sock def initialize(info = {}) super register_options( [ Opt::RHOST, Opt::RPORT(17185), ], Msf::Exploit::Remote::WDBRPC_Client) end def wdbrpc_client_connect self.wdbrpc_info = {} wdbrpc_client_disconnect() self.udp_sock = Rex::Socket::Udp.create( { 'Context' => {'Msf' => framework, 'MsfExploit' => self} } ) add_socket(self.udp_sock) wdbrpc_client_send_disconnect() udp_sock.sendto(wdbrpc_request_connect(rhost), rhost, rport, 0) res,src = udp_sock.recvfrom(65535, 5) if not res print_error("No response to TARGET_CONNECT (WDB4)") return end if res.length > 0 and res.length < 80 print_status("#{rhost}: Unknown response: '#{res.unpack("H*")[0]}'") return end if res.empty? print_error("#{rhost}: No response from the target") return end self.wdbrpc_info = wdbrpc_parse_connect_reply(res) print_status("#{rhost} Connected to #{self.wdbrpc_info[:rt_vers]} - #{self.wdbrpc_info[:rt_bsp_name]} (#{self.wdbrpc_info[:rt_bootline]})") report_note( :host => rhost, :port => rport, :proto => 'udp', :type => 'vxworks.target_info', :data => res, :update => :unique ) end def wdbrpc_client_connect2 self.wdbrpc_info = {} wdbrpc_client_disconnect() self.udp_sock = Rex::Socket::Udp.create( { 'Context' => {'Msf' => framework, 'MsfExploit' => self} } ) add_socket(self.udp_sock) wdbrpc_client_send_disconnect() udp_sock.sendto(wdbrpc_request_connect2(rhost), rhost, rport, 0) res,src = udp_sock.recvfrom(65535, 5) if not res print_error("No response to TARGET_CONNECT2") return end if res.length < 80 print_status("#{rhost}: Unknown response: '#{res.unpack("H*")[0]}'") return end self.wdbrpc_info = wdbrpc_parse_connect_reply(res) print_status("#{rhost} Connected to #{self.wdbrpc_info[:rt_vers]} - #{self.wdbrpc_info[:rt_bsp_name]} (#{self.wdbrpc_info[:rt_bootline]})") report_note( :host => rhost, :port => rport, :proto => 'udp', :type => 'vxworks.target_info', :data => res, :update => :unique ) end def wdbrpc_client_memread(offset, length, params=0) pkt = wdbrpc_request_memread(offset, length, params) cnt = 0 res = nil begin udp_sock.sendto(pkt, rhost, rport, 0) res,src = udp_sock.recvfrom(65535, 0.5) if not res and src raise RuntimeError, "no reply" end if res.length <= 48 raise RuntimeError, "short read" end rescue ::Interrupt raise $! rescue ::Exception if cnt < 120 cnt += 1 retry end end res[48,res.length-48] end def wdbrpc_client_memwrite(offset, buffer, params=0) pkt = wdbrpc_request_memwrite(offset, buffer, params) cnt = 0 res = nil udp_sock.sendto(pkt, rhost, rport, 0) res,src = udp_sock.recvfrom(65535, 5.0) if not res and src raise RuntimeError, "no reply" end res[-4,4].unpack("N")[0] end def wdbrpc_client_memscan(offset, depth, buffer, params=0) pkt = wdbrpc_request_memscan(offset, depth, buffer, params) cnt = 0 res = nil udp_sock.sendto(pkt, rhost, rport, 0) res,src = udp_sock.recvfrom(65535, 5.0) if not res and src raise RuntimeError, "no reply" end p res res end def wdbrpc_client_context_kill(ctx_type=0, ctx=0) pkt = wdbrpc_request_context_kill(ctx_type, ctx) res = nil begin udp_sock.sendto(pkt, rhost, rport, 0) res,src = udp_sock.recvfrom(65535, 0.5) rescue ::Interrupt raise $! rescue ::Exception end res end def wdbrpc_client_send_disconnect pkt = wdbrpc_request_disconnect begin if self.udp_sock self.udp_sock.sendto(pkt, rhost, rport, 0) self.udp_sock.recvfrom(65535, 5) end rescue ::Interrupt raise $! rescue ::Exception end end def wdbrpc_client_disconnect wdbrpc_client_send_disconnect if self.udp_sock self.udp_sock.close rescue nil end self.udp_sock = nil end def rhost datastore['RHOST'] end def rport datastore['RPORT'].to_i end end end