windows权限提升(-)

简述

  • SeDebugPrivilege 允许用户attach任何进程进行调试。
  • 调试过程中运行读、写内存以及改变任何进程的属性(包括本地系统进程、管理员所创建的进程等)。

    Detail

  • 还是直接看代码吧,我们直接使用如下的代码进行线程所加载模块的查看。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    //powershell 获取进程所加载的dll方法 https://stackoverflow.com/questions/9041062/retrieving-dll-path-of-a-running-process
    //
    #include <windows.h>
    #include <tlhelp32.h>
    #include <tchar.h>
    #include <stdio.h>
    // Forward declarations:
    BOOL ListProcessModules(DWORD dwPID);
    void printError(TCHAR* msg);
    int _tmain(int argc, TCHAR* argv[])
    {
    if (argc != 2)
    {
    printf("\n Usage : GetProcessDll.exe <processid> \n\n");
    return 1;
    }
    //ListProcessModules(GetCurrentProcessId());
    DWORD pid = wcstod(argv[1], _T('\0'));
    ListProcessModules(pid);
    return 0;
    }
    BOOL ListProcessModules(DWORD dwPID)
    {
    HANDLE hModuleSnap = INVALID_HANDLE_VALUE;
    MODULEENTRY32 me32;
    // Take a snapshot of all modules in the specified process.
    hModuleSnap = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, dwPID);
    if (hModuleSnap == INVALID_HANDLE_VALUE)
    {
    printError(TEXT("CreateToolhelp32Snapshot (of modules)"));
    return(FALSE);
    }
    // Set the size of the structure before using it.
    me32.dwSize = sizeof(MODULEENTRY32);
    // Retrieve information about the first module,
    // and exit if unsuccessful
    if (!Module32First(hModuleSnap, &me32))
    {
    printError(TEXT("Module32First")); // Show cause of failure
    CloseHandle(hModuleSnap); // Must clean up the snapshot object!
    return(FALSE);
    }
    // Now walk the module list of the process,
    // and display information about each module
    do
    {
    _tprintf(TEXT("\n\n MODULE NAME: %s"), me32.szModule);
    _tprintf(TEXT("\n executable = %s"), me32.szExePath);
    _tprintf(TEXT("\n process ID = 0x%08X"), me32.th32ProcessID);
    _tprintf(TEXT("\n ref count (g) = 0x%04X"), me32.GlblcntUsage);
    _tprintf(TEXT("\n ref count (p) = 0x%04X"), me32.ProccntUsage);
    _tprintf(TEXT("\n base address = 0x%08X"), (DWORD)me32.modBaseAddr);
    _tprintf(TEXT("\n base size = %d"), me32.modBaseSize);
    } while (Module32Next(hModuleSnap, &me32));
    _tprintf(TEXT("\n"));
    // Do not forget to clean up the snapshot object.
    CloseHandle(hModuleSnap);
    return(TRUE);
    }
    void printError(TCHAR* msg)
    {
    DWORD eNum;
    TCHAR sysMsg[256];
    TCHAR* p;
    eNum = GetLastError();
    FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
    NULL, eNum,
    MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
    sysMsg, 256, NULL);
    // Trim the end of the line and terminate it with a null
    p = sysMsg;
    while ((*p > 31) || (*p == 9))
    ++p;
    do { *p-- = 0; } while ((p >= sysMsg) &&
    ((*p == '.') || (*p < 33)));
    // Display the message
    _tprintf(TEXT("\n WARNING: %s failed with error %d (%s)"), msg, eNum, sysMsg);
    }
  • 如下图所示

    我们可以看到,当我们查看notepad.exe进程中的dll时是可以成功的,但是要查看svhost.exe(pid=4620)的时候,程序报错了( CreateToolhelp32Snapshot (of modules) failed with error 5 (?????)),即在查看进程所属的用户相同的时候是可以正常查看的,如果是所属不同用户的话就会失败。

  • 这个时候我们添加如下的函数并调用它
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    VOID DebugPrivilege()
    {
    HANDLE hToken = NULL;
    BOOL bRet = OpenProcessToken(GetCurrentProcess(),
    TOKEN_ALL_ACCESS, &hToken);
    if (bRet == TRUE)
    {
    TOKEN_PRIVILEGES tp;
    tp.PrivilegeCount = 1;
    LookupPrivilegeValue(NULL,
    SE_DEBUG_NAME,
    &tp.Privileges[0].Luid);
    tp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
    AdjustTokenPrivileges(hToken,
    FALSE, &tp, sizeof(tp),
    NULL, NULL);
    CloseHandle(hToken);
    }
    }

以上代码的作用是将运行的程序的权限提升至“SeDebugPrivilege“,拥有该权限以后,当前进程可以访问一些受限的系统资源。

调整进程权限的步骤如下:

1.使用OpenProcessToken函数打开当前进程的访问令牌。

2.使用LookupPrivilegeValue函数取得描述权限的LUID。

3.使用AdjustTokenPrivilege函数调整访问令牌的权限。

Reference