From a0523407039434fc693c5b7329b4615d0fc862b6 Mon Sep 17 00:00:00 2001 From: Joshua Drake Date: Wed, 3 Feb 2010 20:30:09 +0000 Subject: [PATCH] a few fixes to sunrpc code this fixes a couple of errors handling error messages also, some whitespace/indenting adjustments git-svn-id: file:///home/svn/framework3/trunk@8365 4d416f70-5f16-0410-b530-b9f4589650da --- lib/msf/core/exploit/sunrpc.rb | 36 +++++++++++++------------ lib/rex/proto/sunrpc/client.rb | 48 +++++++++++++++++----------------- 2 files changed, 43 insertions(+), 41 deletions(-) diff --git a/lib/msf/core/exploit/sunrpc.rb b/lib/msf/core/exploit/sunrpc.rb index 4264a27064..34cfe12986 100644 --- a/lib/msf/core/exploit/sunrpc.rb +++ b/lib/msf/core/exploit/sunrpc.rb @@ -6,9 +6,9 @@ module Msf # # This mixin provides utility methods for interacting with a SunRPC service on # a remote machine. These methods may generally be useful in the context of -# exploitation. This mixin extends the Tcp exploit mixin. Only one SunRPC +# exploitation. This mixin extends the Tcp exploit mixin. Only one SunRPC # service can be accessed at a time using this class. -# +# # http://www.ietf.org/rfc/rfc1057.txt # ### @@ -16,7 +16,7 @@ module Exploit::Remote::SunRPC include Exploit::Remote::Tcp XDR = Rex::Encoder::XDR - + MSG_ACCEPTED = 0 SUCCESS = 0 # RPC executed successfully PROG_UMAVAIL = 1 # Remote hasn't exported program @@ -55,8 +55,8 @@ module Exploit::Remote::SunRPC end ret = rpcobj.create - return print_error("#{rhost} - No response to SunRPC PortMap request") unless ret - + return print_error("#{rhost} - No response to SunRPC PortMap request") unless ret + arr = XDR.decode!(ret, Integer, Integer, Integer, String, Integer, Integer) if arr[1] != MSG_ACCEPTED || arr[4] != SUCCESS || arr[5] == 0 err = "#{rhost} - SunRPC PortMap request failed: " @@ -65,7 +65,7 @@ module Exploit::Remote::SunRPC err << 'Program not available' if arr[5] == 0 print_error(err) end - + rpcobj.pport = arr[5] end @@ -75,7 +75,8 @@ module Exploit::Remote::SunRPC arr = Rex::Encoder::XDR.decode!(ret, Integer, Integer, Integer, String, Integer) if arr[1] != MSG_ACCEPTED || arr[4] != SUCCESS - err = "SunRPC call for program #{program} [#{progresolv(program)}], procedure #{procedure}, failed: " + progname = progresolv(rpcobj.program) + err = "SunRPC call for program #{rpcobj.program} [#{progname}], procedure #{proc}, failed: " case arr[4] when PROG_UMAVAIL then err << "Program Unavailable" when PROG_MISMATCH then err << "Program Version Mismatch" @@ -100,13 +101,14 @@ module Exploit::Remote::SunRPC def sunrpc_authunix(*args) rpcobj.authunix_create(*args) end - + # XXX: Incomplete. Just moved from Rex::Proto::SunRPC::Client def portmap_qry() - ret = portmap_req() + ret = portmap_req() arr = Rex::Encoder::XDR.decode!(ret, Integer, Integer, Integer, String, Integer) if arr[1] != MSG_ACCEPTED || arr[4] != SUCCESS || arr[5] == 0 - err = "SunRPC call for program #{program} [#{progresolv(program)}], procedure #{procedure}, failed: " + progname = progresolv(rpcobj.program) + err = "SunRPC query for program #{rpcobj.program} [#{progname}] failed: " case arr[4] when PROG_UMAVAIL then err << "Program Unavailable" when PROG_MISMATCH then err << "Program Version Mismatch" @@ -116,25 +118,25 @@ module Exploit::Remote::SunRPC end print_error("#{rhost} - #{err}") end - + return ret end - + def progresolv(number) - names = File.join(Msf::Config.install_root, "data", "wordlists", "rpc_names.txt") + names = File.join(Msf::Config.install_root, "data", "wordlists", "rpc_names.txt") File.open(names,"r").each_line do |line| next if line.empty? || line =~ /^\s*#/ - + if line =~ /^(\S+?)\s+(\d+)/ && number == $2.to_i return $1 end end - + return "UNKNOWN-#{number}" end - # Used to track the last SunRPC context + # Used to track the last SunRPC context attr_accessor :rpcobj end -end \ No newline at end of file +end diff --git a/lib/rex/proto/sunrpc/client.rb b/lib/rex/proto/sunrpc/client.rb index 18e81464c3..b3e56ab2fb 100644 --- a/lib/rex/proto/sunrpc/client.rb +++ b/lib/rex/proto/sunrpc/client.rb @@ -16,16 +16,16 @@ class RPCTimeout < ::Interrupt end # XXX: CPORT! -class Client +class Client AUTH_NULL = 0 AUTH_UNIX = 1 - + PMAP_PROG = 100000 PMAP_VERS = 2 PMAP_GETPORT = 3 - + CALL = 0 - + attr_reader :rhost, :rport, :proto, :program, :version attr_accessor :pport @@ -40,13 +40,13 @@ class Client rhost, rport, program, version, proto.downcase @pport = nil - + @auth_type = AUTH_NULL @auth_data = '' - + @call_sock = nil end - + # XXX: Add optional parameter to have proto be something else def create() proto_num = 0 @@ -60,7 +60,7 @@ class Client Rex::Encoder::XDR.encode(CALL, 2, PMAP_PROG, PMAP_VERS, PMAP_GETPORT, @auth_type, [@auth_data, 400], AUTH_NULL, '', @program, @version, proto_num, 0) - + sock = make_rpc(@proto, @rhost, @rport) send_rpc(sock, buf) ret = recv_rpc(sock) @@ -73,46 +73,46 @@ class Client buf = Rex::Encoder::XDR.encode(CALL, 2, @program, @version, procedure, @auth_type, [@auth_data, 400], AUTH_NULL, '')+ - buffer - + buffer + if !@call_sock @call_sock = make_rpc(@proto, @rhost, @pport) end send_rpc(@call_sock, buf) - recv_rpc(@call_sock, timeout) + recv_rpc(@call_sock, timeout) end - + def destroy close_rpc(@call_sock) if @call_sock @call_sock = nil end - + def authnull_create @auth_type = AUTH_NULL @auth_data = '' end - + def authunix_create(host, uid, gid, groupz) raise ::Rex::ArgumentError, 'Hostname length is too long' if host.length > 255 # 10? raise ::Rex::ArgumentError, 'Too many groups' if groupz.length > 10 - + @auth_type = AUTH_UNIX @auth_data = Rex::Encoder::XDR.encode(0, host, uid, gid, groupz) # XXX: TIME! GROUPZ?! end - + # XXX: Dirty, integrate some sort of request system into create/call? def portmap_req(host, port, rpc_vers, procedure, buffer) buf = Rex::Encoder::XDR.encode(CALL, 2, PMAP_PROG, rpc_vers, procedure, AUTH_NULL, '', AUTH_NULL, '') + buffer - + sock = make_rpc('tcp', host, port) send_rpc(sock, buf) ret = recv_rpc(sock) close_rpc(sock) - + return ret end @@ -128,11 +128,11 @@ class Client if !self.should_fragment return Rex::Encoder::XDR.encode(0x80000000 | buf.length) + buf end - + str = buf.dup fragmented = '' - + while (str.size > 0) frag = str.slice!(0, rand(3) + 1) len = frag.size @@ -153,7 +153,7 @@ class Client end sock.write(buf) end - + def recv_rpc(sock, timeout=60) buf = sock.get(timeout) buf.slice!(0..3) @@ -163,11 +163,11 @@ class Client return buf if buf.length > 1 return nil end - + def close_rpc(sock) sock.close end - + def gen_xid return Rex::Encoder::XDR.encode(rand(0xffffffff) + 1) end @@ -175,4 +175,4 @@ end end end -end \ No newline at end of file +end