# windows_tools
## Collection of useful python functions around Microsoft Windows
[![License](https://img.shields.io/badge/License-BSD%203--Clause-blue.svg)](https://opensource.org/licenses/BSD-3-Clause)
[![Percentage of issues still open](http://isitmaintained.com/badge/open/netinvent/windows_tools.svg)](http://isitmaintained.com/project/netinvent/ofunctions "Percentage of issues still open")
[![Maintainability](https://api.codeclimate.com/v1/badges/0d9732260019ec390649/maintainability)](https://codeclimate.com/github/netinvent/windows_tools/maintainability)
[![codecov](https://codecov.io/gh/netinvent/windows_tools/branch/master/graph/badge.svg?token=6Z03XTQU8G)](https://codecov.io/gh/netinvent/windows_tools)
[![windows-tests](https://github.com/netinvent/windows_tools/actions/workflows/windows.yaml/badge.svg)](https://github.com/netinvent/windows_tools/actions/workflows/windows.yaml)
[![GitHub Release](https://img.shields.io/github/release/netinvent/windows_tools.svg?label=Latest)](https://github.com/netinvent/windows_tools/releases/latest)
windows_tools is a set of various recurrent functions amongst
- antivirus: antivirus state and list of installed AV engines
- bitlocker: drive encryption status and protector key retrieval
- bitness: simple bitness identification
- file_utils: file ownership handling, NTFS & ReFS ACL handling, file listing with permission fixes
- impersonate: python Runas implementation
- installed_software: list of installed software from registry, 32 and 64 bits
- logical_disk: logical disk listing
- misc: basic time related functions to convert windows ticks into epoch / date strings
- office: microsoft Office version identification, works for click & run, O365 and legacy
- powershell: powershell wrapper to identify interpreter and run scripts or commands
- product_key: windows product key retrieval
- registry: registry 32 and 64 bit API
- securityprivilege: enable / disable various security privileges for user
- server: windows server identification
- signtool: Easily sign executables with Authenticode
- updates: get all installed windows updates based on COM, WMI and registry retrieval methods
- users: user lookup for SID/PySID/username
- virtualization: virtualization platform identification for guest
- windows_firewall: windows firewall state retrieval
- wmi_queries: windows WMI query wrapper, wmi timezone converters
It is compatible with Python 3.5+ and is tested on Windows only (obviously).
## Setup
You may install the whole `windows_tools` package or any subpackage using the following commands
```
pip install windows_tools
pip install windows_tools.<subpackage>
```
## Usage
### antivirus
The antivirus package tries to list installed Antivirus products via the SecurityCenter API (using WMI calls).
Since SecurityCenter API does not exist on Windows Servers, we also need to check for installed antivirus software using the uninstall registry keys.
These checks are more fuzzy, but allow to detect the following products:
- avast
- avira
- avg technologies
- bitdefender
- dr web
- eset
- f-secure
- g data software
- kaspersky
- mcafee
- panda security
- sophos
- trend micro
- malwarebytes
- vipre
- sentinel one
On top of that list, it will detect any installed software containing "antivirus/antiviral/antimalware" in the name.
Please report back if your antivirus is not detected, so we can improve the fuzzy detection here.
Usage
```
import windows_tools.antivirus
result = windows_tools.antivirus.get_installed_antivirus_software()
```
`result` will contain a list of dict like
```
[{
'name': 'Windows Defender',
'version': None,
'publisher': None,
'enabled': False,
'is_up_to_date': True,
'type': 'Windows Defender / Security Essentials'
}, {
'name': 'Malwarebytes version 4.4.6.132',
'version': '4.4.6.132',
'publisher': 'Malwarebytes',
'enabled': None,
'is_up_to_date': None,
'type': None
}
]
```
**Warning**
Keys `enabled`, `is_up_to_date` and `type` are only filled via securityCenter API*.
Keys `version` and `publisher` are only filled via installed software list.
The only guaranteed filled key will always be `name`
### bitlocker
Bitlocker can only work on NTFS or ReFS formatted disks.
Bitlocker keys can only be retrieved on local disks.
#### Usage
```
import windows_tools.bitlocker
result = windows_tools.bitlocker.get_bitlocker_full_status()
```
`result` will contain a dict as follows containing raw strings from `manage-bde` windows tool:
```
{
'C:': {
'status': 'Chiffrement de lecteur BitLocker\xa0: outil de configuration version 10.0.19041\nCopyright (C) 2013 Microsoft Corporation. Tous droits réservés.\n\nVolume C: [Windows ]\n[Volume du système d?exploitation]\n\n Taille : 855,14 Go\n Version de BitLocker : Aucun\n État de la conversion : Intégralement déchiffré\n Pourcentage chiffré : 0,0%\n Méthode de chiffrement : Aucun\n État de la protection\xa0: Protection désactivée\n État du verrouillage : Déverrouillé\n Champ d?identification : Aucun\n Protecteurs de clés : Aucun trouvé\n\n',
'protectors': None
},
'D:': {
'status': 'Chiffrement de lecteur BitLocker\xa0: outil de configuration version 10.0.19041\nCopyright (C) 2013 Microsoft Corporation. Tous droits réservés.\n\nVolume D: [Étiquette inconnue]\n[Volume de données]\n\n Taille : Inconnu Go\n Version de BitLocker : 2.0\n État de la conversion : Inconnu\n Pourcentage chiffré : Inconnu%\n Méthode de chiffrement : XTS-AES 128\n État de la protection\xa0: Inconnu\n État du verrouillage : Verrouillé\n Champ d?identification : Inconnu\n Déverrouillage automatique : Désactivé\n Protecteurs de clés\xa0:\n Password\n Mot de passe numérique\n\n',
'protectors': 'Chiffrement de lecteur BitLocker\xa0: outil de configuration version 10.0.19041\nCopyright (C) 2013 Microsoft Corporation. Tous droits réservés.\n\nVolume D: [Étiquette inconnue]\nTous les protecteurs de clés\n\n Password :\n ID : {SOMEPASS-WORD-ICAN-NNOT-REMEMBERWELL}\n\n Mot de passe numérique :\n ID : {SOMEPASS-GUID-ICAN-NNOT-REMEMBERWELL}\n\n'
}
}
```
You may parse those or simply pretty print since print will not interpret special characters from a dict or multiple variables at once:
```
result = windows_tools.bitlocker.get_bitlocker_full_status()
result = get_bitlocker_full_status()
for drive in result:
for designation, content in result[drive].items():
print(designation, content)
```
**Warning** bitlocker needs to be run as admin.
Running as non administrator will produce the following logs
```
Don't have permission to get bitlocker drive status for C:.
Don't have permission to get bitlocker drive protectors for C:.
Don't have permission to get bitlocker drive status for D:.
Don't have permission to get bitlocker drive protectors for D:.
```
Output shall be
```
{
'C:': {
'status': None,
'protectors': None
},
'D:': {
'status': None,
'protectors': None
}
}
```
You can check that you have administrator rights with `windows_utils.users` module
### bitness
### file_utils
### impersonate
### installed_software
### logical_disk
### misc
### office
### powershell
### product_key
### registry
### securityprivilege
### server
### signtool
signtool is designed to make the windows executable signature as simple as possible.
Once the Windows SDK is installed on your machine, you can sign any executable with the following commands:
```
from windows_tools.signtool import SignTool
signer = SignTool()
signer.sign(r"c:\path\to\executable", bitness=64)
```
Note that current versions of `signtool.exe` that come with Windows 10 SDK automagically detect hardware EV certificate tokens like Safenet.
When using former certificate files in order to sign an executable, one should use the following syntax:
```
from windows_tools.signtool import SignTool
signer = SignTool(certificate=r"c:\path\to\cert.pfx", pkcs12_password="the_certificate_file_password")
signer.sign(r"c:\path\to\executable", bitness=64)
```
If the wrong certificate is used to sign, please open `certmgr.msc`, go to Private > Certificates and remove the certificate you don't want.
### updates
Windows updates can be retrieved via a COM object that talks to Windows Update service, via WMI requests or via registry entries.
All methods can return different results, so they are combined into one function.
Usage
```
import windows_tools.updates
result = windows_tools.updates.get_windows_updates(filter_duplicates=True, include_all_states=False)
```
`result` will contain a list of dict like
```
[{
'kb': 'KB123456',
'date': '2021-01-01 00:01:02',
'title': 'Some update title',
'description': 'Some update description',
'supporturl': 'https://support.microsoft.com/someID',
'operation': 'Installation'
'result': 'Installed'
}, {
'kb': None,
'date': '2021-01-01 00:01:02',
'title': 'Windows 10 20H1 update',
'description': 'Pretty big system update',
'supporturl': 'https://support.microsoft.com/someID',
'operation': 'Installation'
'result': 'Installed'
}
]
```
Using `filter_duplicates` will avoid returning multiple times the same KB from different sources.
This setting is enabled by default.
The parameter `include_all_states` set to True will include all updates, even those who failed to install or are superseeded.
### users
### virtualization
### windows_firewall
### wmi_queries
Raw data
{
"_id": null,
"home_page": "https://github.com/netinvent/windows_tools",
"name": "windows-tools",
"maintainer": "",
"docs_url": null,
"requires_python": ">=3.5",
"maintainer_email": "",
"keywords": "wmi,virtualization,file,acl,ntfs,refs,antivirus,security,firewall,office",
"author": "NetInvent - Orsiris de Jong",
"author_email": "contact@netinvent.fr",
"download_url": "https://files.pythonhosted.org/packages/2a/67/8222a5d7efa51c118b70ffa389c271885316b8b0953f2b715830435037aa/windows_tools-2.4.0.tar.gz",
"platform": null,
"description": "# windows_tools\r\n## Collection of useful python functions around Microsoft Windows\r\n\r\n[![License](https://img.shields.io/badge/License-BSD%203--Clause-blue.svg)](https://opensource.org/licenses/BSD-3-Clause)\r\n[![Percentage of issues still open](http://isitmaintained.com/badge/open/netinvent/windows_tools.svg)](http://isitmaintained.com/project/netinvent/ofunctions \"Percentage of issues still open\")\r\n[![Maintainability](https://api.codeclimate.com/v1/badges/0d9732260019ec390649/maintainability)](https://codeclimate.com/github/netinvent/windows_tools/maintainability)\r\n[![codecov](https://codecov.io/gh/netinvent/windows_tools/branch/master/graph/badge.svg?token=6Z03XTQU8G)](https://codecov.io/gh/netinvent/windows_tools)\r\n[![windows-tests](https://github.com/netinvent/windows_tools/actions/workflows/windows.yaml/badge.svg)](https://github.com/netinvent/windows_tools/actions/workflows/windows.yaml)\r\n[![GitHub Release](https://img.shields.io/github/release/netinvent/windows_tools.svg?label=Latest)](https://github.com/netinvent/windows_tools/releases/latest)\r\n\r\n\r\nwindows_tools is a set of various recurrent functions amongst\r\n\r\n- antivirus: antivirus state and list of installed AV engines\r\n- bitlocker: drive encryption status and protector key retrieval\r\n- bitness: simple bitness identification\r\n- file_utils: file ownership handling, NTFS & ReFS ACL handling, file listing with permission fixes\r\n- impersonate: python Runas implementation\r\n- installed_software: list of installed software from registry, 32 and 64 bits\r\n- logical_disk: logical disk listing\r\n- misc: basic time related functions to convert windows ticks into epoch / date strings\r\n- office: microsoft Office version identification, works for click & run, O365 and legacy\r\n- powershell: powershell wrapper to identify interpreter and run scripts or commands\r\n- product_key: windows product key retrieval\r\n- registry: registry 32 and 64 bit API\r\n- securityprivilege: enable / disable various security privileges for user\r\n- server: windows server identification\r\n- signtool: Easily sign executables with Authenticode\r\n- updates: get all installed windows updates based on COM, WMI and registry retrieval methods\r\n- users: user lookup for SID/PySID/username\r\n- virtualization: virtualization platform identification for guest\r\n- windows_firewall: windows firewall state retrieval\r\n- wmi_queries: windows WMI query wrapper, wmi timezone converters\r\n\r\nIt is compatible with Python 3.5+ and is tested on Windows only (obviously).\r\n\r\n## Setup\r\n\r\nYou may install the whole `windows_tools` package or any subpackage using the following commands\r\n```\r\npip install windows_tools\r\npip install windows_tools.<subpackage>\r\n\r\n```\r\n\r\n## Usage\r\n\r\n### antivirus\r\n\r\nThe antivirus package tries to list installed Antivirus products via the SecurityCenter API (using WMI calls).\r\nSince SecurityCenter API does not exist on Windows Servers, we also need to check for installed antivirus software using the uninstall registry keys.\r\nThese checks are more fuzzy, but allow to detect the following products:\r\n\r\n- avast\r\n- avira\r\n- avg technologies\r\n- bitdefender\r\n- dr web\r\n- eset\r\n- f-secure\r\n- g data software\r\n- kaspersky\r\n- mcafee\r\n- panda security\r\n- sophos\r\n- trend micro\r\n- malwarebytes\r\n- vipre\r\n- sentinel one\r\n\r\nOn top of that list, it will detect any installed software containing \"antivirus/antiviral/antimalware\" in the name.\r\n\r\nPlease report back if your antivirus is not detected, so we can improve the fuzzy detection here.\r\n\r\nUsage\r\n```\r\nimport windows_tools.antivirus\r\n\r\nresult = windows_tools.antivirus.get_installed_antivirus_software()\r\n```\r\n\r\n`result` will contain a list of dict like\r\n\r\n```\r\n[{\r\n 'name': 'Windows Defender',\r\n 'version': None,\r\n 'publisher': None,\r\n 'enabled': False,\r\n 'is_up_to_date': True,\r\n 'type': 'Windows Defender / Security Essentials'\r\n }, {\r\n 'name': 'Malwarebytes version 4.4.6.132',\r\n 'version': '4.4.6.132',\r\n 'publisher': 'Malwarebytes',\r\n 'enabled': None,\r\n 'is_up_to_date': None,\r\n 'type': None\r\n }\r\n]\r\n```\r\n\r\n**Warning**\r\nKeys `enabled`, `is_up_to_date` and `type` are only filled via securityCenter API*.\r\nKeys `version` and `publisher` are only filled via installed software list.\r\nThe only guaranteed filled key will always be `name`\r\n\r\n### bitlocker\r\n\r\nBitlocker can only work on NTFS or ReFS formatted disks.\r\nBitlocker keys can only be retrieved on local disks.\r\n\r\n#### Usage\r\n\r\n```\r\nimport windows_tools.bitlocker\r\n\r\nresult = windows_tools.bitlocker.get_bitlocker_full_status()\r\n```\r\n\r\n`result` will contain a dict as follows containing raw strings from `manage-bde` windows tool:\r\n\r\n```\r\n{\r\n\t'C:': {\r\n\t\t'status': 'Chiffrement de lecteur BitLocker\\xa0: outil de configuration version 10.0.19041\\nCopyright (C) 2013 Microsoft Corporation. Tous droits r\u00e9serv\u00e9s.\\n\\nVolume C: [Windows ]\\n[Volume du syst\u00e8me d?exploitation]\\n\\n Taille : 855,14 Go\\n Version de BitLocker : Aucun\\n \u00c9tat de la conversion : Int\u00e9gralement d\u00e9chiffr\u00e9\\n Pourcentage chiffr\u00e9 : 0,0%\\n M\u00e9thode de chiffrement : Aucun\\n \u00c9tat de la protection\\xa0: Protection d\u00e9sactiv\u00e9e\\n \u00c9tat du verrouillage : D\u00e9verrouill\u00e9\\n Champ d?identification : Aucun\\n Protecteurs de cl\u00e9s : Aucun trouv\u00e9\\n\\n', \r\n\t\t'protectors': None\r\n\t},\r\n\t'D:': {\r\n\t\t'status': 'Chiffrement de lecteur BitLocker\\xa0: outil de configuration version 10.0.19041\\nCopyright (C) 2013 Microsoft Corporation. Tous droits r\u00e9serv\u00e9s.\\n\\nVolume D: [\u00c9tiquette inconnue]\\n[Volume de donn\u00e9es]\\n\\n Taille : Inconnu Go\\n Version de BitLocker : 2.0\\n \u00c9tat de la conversion : Inconnu\\n Pourcentage chiffr\u00e9 : Inconnu%\\n M\u00e9thode de chiffrement : XTS-AES 128\\n \u00c9tat de la protection\\xa0: Inconnu\\n \u00c9tat du verrouillage : Verrouill\u00e9\\n Champ d?identification : Inconnu\\n D\u00e9verrouillage automatique : D\u00e9sactiv\u00e9\\n Protecteurs de cl\u00e9s\\xa0:\\n Password\\n Mot de passe num\u00e9rique\\n\\n',\r\n\t\t'protectors': 'Chiffrement de lecteur BitLocker\\xa0: outil de configuration version 10.0.19041\\nCopyright (C) 2013 Microsoft Corporation. Tous droits r\u00e9serv\u00e9s.\\n\\nVolume D: [\u00c9tiquette inconnue]\\nTous les protecteurs de cl\u00e9s\\n\\n Password :\\n ID : {SOMEPASS-WORD-ICAN-NNOT-REMEMBERWELL}\\n\\n Mot de passe num\u00e9rique :\\n ID : {SOMEPASS-GUID-ICAN-NNOT-REMEMBERWELL}\\n\\n'\r\n\t}\r\n}\r\n```\r\n\r\nYou may parse those or simply pretty print since print will not interpret special characters from a dict or multiple variables at once:\r\n\r\n```\r\nresult = windows_tools.bitlocker.get_bitlocker_full_status()\r\n\r\n\r\nresult = get_bitlocker_full_status()\r\nfor drive in result:\r\n for designation, content in result[drive].items():\r\n print(designation, content)\r\n\r\n```\r\n\r\n**Warning** bitlocker needs to be run as admin.\r\nRunning as non administrator will produce the following logs\r\n\r\n```\r\nDon't have permission to get bitlocker drive status for C:.\r\nDon't have permission to get bitlocker drive protectors for C:.\r\nDon't have permission to get bitlocker drive status for D:.\r\nDon't have permission to get bitlocker drive protectors for D:.\r\n```\r\n\r\nOutput shall be\r\n```\r\n{\r\n 'C:': {\r\n 'status': None,\r\n 'protectors': None\r\n },\r\n 'D:': {\r\n 'status': None,\r\n 'protectors': None\r\n }\r\n}\r\n```\r\n\r\nYou can check that you have administrator rights with `windows_utils.users` module\r\n\r\n\r\n### bitness\r\n\r\n### file_utils\r\n\r\n### impersonate\r\n\r\n### installed_software\r\n\r\n### logical_disk\r\n\r\n### misc\r\n\r\n### office\r\n\r\n### powershell\r\n\r\n### product_key\r\n\r\n### registry\r\n\r\n### securityprivilege\r\n\r\n### server\r\n\r\n### signtool\r\n\r\nsigntool is designed to make the windows executable signature as simple as possible. \r\nOnce the Windows SDK is installed on your machine, you can sign any executable with the following commands:\r\n\r\n```\r\nfrom windows_tools.signtool import SignTool\r\nsigner = SignTool()\r\nsigner.sign(r\"c:\\path\\to\\executable\", bitness=64)\r\n```\r\n\r\nNote that current versions of `signtool.exe` that come with Windows 10 SDK automagically detect hardware EV certificate tokens like Safenet.\r\n\r\nWhen using former certificate files in order to sign an executable, one should use the following syntax:\r\n\r\n```\r\nfrom windows_tools.signtool import SignTool\r\nsigner = SignTool(certificate=r\"c:\\path\\to\\cert.pfx\", pkcs12_password=\"the_certificate_file_password\")\r\nsigner.sign(r\"c:\\path\\to\\executable\", bitness=64)\r\n```\r\n\r\nIf the wrong certificate is used to sign, please open `certmgr.msc`, go to Private > Certificates and remove the certificate you don't want.\r\n\r\n\r\n### updates\r\n\r\nWindows updates can be retrieved via a COM object that talks to Windows Update service, via WMI requests or via registry entries.\r\nAll methods can return different results, so they are combined into one function.\r\n\r\nUsage\r\n```\r\nimport windows_tools.updates\r\n\r\nresult = windows_tools.updates.get_windows_updates(filter_duplicates=True, include_all_states=False)\r\n```\r\n\r\n`result` will contain a list of dict like\r\n\r\n```\r\n[{\r\n 'kb': 'KB123456',\r\n 'date': '2021-01-01 00:01:02',\r\n 'title': 'Some update title',\r\n 'description': 'Some update description',\r\n 'supporturl': 'https://support.microsoft.com/someID',\r\n 'operation': 'Installation'\r\n 'result': 'Installed'\r\n }, {\r\n 'kb': None,\r\n 'date': '2021-01-01 00:01:02',\r\n 'title': 'Windows 10 20H1 update',\r\n 'description': 'Pretty big system update',\r\n 'supporturl': 'https://support.microsoft.com/someID',\r\n 'operation': 'Installation'\r\n 'result': 'Installed'\r\n }\r\n]\r\n```\r\n\r\nUsing `filter_duplicates` will avoid returning multiple times the same KB from different sources.\r\nThis setting is enabled by default.\r\n\r\nThe parameter `include_all_states` set to True will include all updates, even those who failed to install or are superseeded.\r\n\r\n### users\r\n\r\n### virtualization\r\n\r\n### windows_firewall\r\n\r\n### wmi_queries\r\n",
"bugtrack_url": null,
"license": "BSD",
"summary": "Toolset for antivirus, NTFS/ReFS ACLs, file ownership, registry, user handling...Well a lot of stuff",
"version": "2.4.0",
"project_urls": {
"Homepage": "https://github.com/netinvent/windows_tools"
},
"split_keywords": [
"wmi",
"virtualization",
"file",
"acl",
"ntfs",
"refs",
"antivirus",
"security",
"firewall",
"office"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "f8870d06270b7bacbd4f8deb067dd29420505d8cf0a2820a26d825ad616b3934",
"md5": "a7c72fb6407ce32f28a6153e2699c108",
"sha256": "287e0b195700097126e465abf096741e0273b5d2f0910ef8f6440b8ff24e526b"
},
"downloads": -1,
"filename": "windows_tools-2.4.0-py3-none-any.whl",
"has_sig": false,
"md5_digest": "a7c72fb6407ce32f28a6153e2699c108",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.5",
"size": 47970,
"upload_time": "2023-08-29T08:26:37",
"upload_time_iso_8601": "2023-08-29T08:26:37.862886Z",
"url": "https://files.pythonhosted.org/packages/f8/87/0d06270b7bacbd4f8deb067dd29420505d8cf0a2820a26d825ad616b3934/windows_tools-2.4.0-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "2a678222a5d7efa51c118b70ffa389c271885316b8b0953f2b715830435037aa",
"md5": "e99db4db5151889e380ba3690a5df80b",
"sha256": "f8c91ea36dc81c97628a5d6b11dde08890b5476a4e5a46e0a28b420eec8860aa"
},
"downloads": -1,
"filename": "windows_tools-2.4.0.tar.gz",
"has_sig": false,
"md5_digest": "e99db4db5151889e380ba3690a5df80b",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.5",
"size": 42296,
"upload_time": "2023-08-29T08:26:57",
"upload_time_iso_8601": "2023-08-29T08:26:57.053348Z",
"url": "https://files.pythonhosted.org/packages/2a/67/8222a5d7efa51c118b70ffa389c271885316b8b0953f2b715830435037aa/windows_tools-2.4.0.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2023-08-29 08:26:57",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "netinvent",
"github_project": "windows_tools",
"travis_ci": false,
"coveralls": false,
"github_actions": true,
"lcname": "windows-tools"
}