fixed bug and python3 compat in vnc_login

pull/4/merge
lanjelot 12 years ago
parent 87c29fa7ac
commit 4f67d02e7f

@ -589,7 +589,7 @@ logger.addHandler(handler)
import re import re
import os import os
from sys import stdin, exc_info, exit from sys import stdin, exc_info, exit, version_info
from time import localtime, strftime, sleep, time from time import localtime, strftime, sleep, time
from functools import reduce from functools import reduce
from threading import Thread, active_count from threading import Thread, active_count
@ -2403,74 +2403,72 @@ class VNC_Error(Exception): pass
class VNC: class VNC:
def connect(self, host, port): def connect(self, host, port):
self.fp = socket.create_connection((host, port)) self.fp = socket.create_connection((host, port))
resp = self.fp.recv(1024) # banner resp = self.fp.recv(99) # banner
self.version = resp[:11]
logger.debug('banner: %s' % repr(resp))
self.version = resp[:11].decode('ascii')
if len(resp) > 12: if len(resp) > 12:
raise VNC_Error(self.version + ' ' + resp[20:]) raise VNC_Error('%s %s' % (self.version, resp[12:].decode('ascii', 'ignore')))
return self.version return self.version
def login(self, password): def login(self, password):
logger.debug("Remote version: %s" % self.version) logger.debug('Remote version: %s' % self.version)
major, minor = self.version[6], self.version[10] major, minor = self.version[6], self.version[10]
if major == '3' and minor == '8': if (major, minor) in [('3', '8'), ('4', '1')]:
proto = 'RFB 003.008\n' proto = b'RFB 003.008\n'
elif major == '3' and minor == '7': elif (major, minor) == ('3', '7'):
proto = 'RFB 003.007\n' proto = b'RFB 003.007\n'
else: else:
proto = 'RFB 003.003\n' proto = b'RFB 003.003\n'
logger.debug('Client version: %s' % proto[:-1]) logger.debug('Client version: %s' % proto[:-1])
self.fp.sendall(proto) self.fp.sendall(proto)
if minor in ('7', '8'): sleep(0.5)
# send security type
resp = self.fp.recv(1024)
logger.debug("Security types supported: %s" % repr(resp))
self.fp.sendall('\x02') # always use classic VNC authentication
# read server challenge resp = self.fp.recv(99)
resp = self.fp.recv(1024) logger.debug('Security types supported: %s' % repr(resp))
logger.debug('Remote challenge: %s' % repr(resp))
if minor == '3': if minor in ('7', '8'):
if len(resp) < 4: code = ord(resp[0:1])
raise VNC_Error('Unexpected response size (%d > 4): %s' % (len(resp), repr(resp)))
code = ord(resp[3])
if code == 0: if code == 0:
raise VNC_Error('Session setup failed: %s' % repr(resp)) raise VNC_Error('Session setup failed: %s' % resp.decode('ascii', 'ignore'))
elif code == 1: self.fp.sendall(b'\x02') # always use classic VNC authentication
raise VNC_Error('No authentication required: %s' % repr(resp)) resp = self.fp.recv(99)
elif code == 2: else: # minor == '3':
if len(resp) != 20: code = ord(resp[3:4])
raise VNC_Error('Unexpected challenge size (unsupported authentication type ?): %s' % repr(resp)) if code != 2:
raise VNC_Error('Session setup failed: %s' % resp.decode('ascii', 'ignore'))
resp = resp[4:20] resp = resp[-16:]
else: if len(resp) != 16:
raise VNC_Error('Session setup unknown response') raise VNC_Error('Unexpected challenge size (unsupported authentication type ?)')
logger.debug('challenge: %s' % repr(resp))
pw = password.ljust(8, '\x00')[:8] # make sure it is 8 chars long, zero padded
pw = (password + '\0' * 8)[:8] # make sure it is 8 chars long, zero padded
key = self.gen_key(pw) key = self.gen_key(pw)
logger.debug('key: %s' % repr(key)) logger.debug('key: %s' % repr(key))
des = DES.new(key, DES.MODE_ECB) des = DES.new(key, DES.MODE_ECB)
enc = des.encrypt(resp) enc = des.encrypt(resp)
logger.debug('enc: %s' % repr(enc))
logger.debug('enc: %s' % repr(enc))
self.fp.sendall(enc) self.fp.sendall(enc)
resp = self.fp.recv(1024)
resp = self.fp.recv(99)
logger.debug('resp: %s' % repr(resp)) logger.debug('resp: %s' % repr(resp))
code = ord(resp[3]) code = ord(resp[3:4])
mesg = resp[8:] mesg = resp[8:].decode('ascii', 'ignore')
if code == 1: if code == 1:
return code, mesg or 'Authentication failure' return code, mesg or 'Authentication failure'
@ -2490,15 +2488,19 @@ class VNC:
for i in range(8): for i in range(8):
if bsrc & (1 << i): if bsrc & (1 << i):
btgt = btgt | (1 << 7-i) btgt = btgt | (1 << 7-i)
newkey.append(chr(btgt)) newkey.append(btgt)
return ''.join(newkey)
if version_info[0] == 2:
return ''.join(chr(c) for c in newkey)
else:
return bytes(newkey)
class VNC_login: class VNC_login:
'''Brute-force VNC authentication''' '''Brute-force VNC authentication'''
usage_hints = ( usage_hints = (
"""%prog host=10.0.0.1 password=FILE0 0=passwords.txt -x retry:fgrep!='Authentication failure' --max-retries -1 -x quit:code=0""", """%prog host=10.0.0.1 password=FILE0 0=passwords.txt -t 1 -x retry:fgrep!='Authentication failure' --max-retries -1 -x quit:code=0""",
) )
available_options = ( available_options = (
@ -2514,13 +2516,13 @@ class VNC_login:
self.m = VNC() self.m = VNC()
def execute(self, host, port=None, password=None): def execute(self, host, port=None, password=None):
try: try:
code, mesg = '0', self.m.connect(host, int(port or 5900)) code, mesg = 0, self.m.connect(host, int(port or 5900))
if password is not None: if password is not None:
code, mesg = self.m.login(password) code, mesg = self.m.login(password)
except VNC_Error as e: except VNC_Error as e:
code, mesg = '2', str(e) code, mesg = 2, str(e)
logger.debug('VNC_Error: %s' % mesg) logger.debug('VNC_Error: %s' % mesg)
return self.Response(code, mesg) return self.Response(code, mesg)
@ -3037,4 +3039,4 @@ Available modules:
# }}} # }}}
# vim: ts=2 sw=2 sts=2 et fdm=marker # vim: ts=2 sw=2 sts=2 et fdm=marker bg=dark

Loading…
Cancel
Save