提升权限令牌

提权相关函数:

GetCurrentProcess() 介绍:

功能:检索当前进程的伪句柄。

函数原型:HANDLE GetCurrentProcess();

返回值:返回值是当前进程的伪句柄。

 

OpenProcessToken() 介绍:
功能:打开与进程相关联的访问令牌。

函数原型:BOOL WINAPI OpenProcessToken(

                  HANDLE  ProcessHandle,   // 要修改访问权限的进程句柄。
                  DWORD   DesiredAccess, // 指定你要进行的操作类型。
                  PHANDLE TokenHandle  // 返回的访问令牌的指针。
                  );

参数

DesiredAccess

常用值:

TOKEN_ADJUST_PRIVILEGES TOKEN_ADJUST_GROUPS TOKEN_ADJUST_DEFAULT TOKEN_EXECUTE
TOKEN_QUERY TOKEN_READ TOKEN_WRITE TOKEN_ALL_ACCESS

 

如要修改访问令牌的特权,我们要指定第二个参数为 TOKEN_ADJUST_PRIVILEGES

返回值:非零表示成功,零表示失败。

 

AdjustTokenPrivileges() 介绍:

功能:用于启用或禁止,指定访问令牌的特权。

函数原型:BOOL WINAPI AdjustTokenPrivileges(
                  HANDLE   TokenHandle,  // 要修改的权限的访问令牌的句柄。
                  BOOL  DisableAllPrivileges, // 指定函数是否禁用所有标记的权限。
                  PTOKEN_PRIVILEGES  NewState, // 指向 TOKEN_PRIVILEGES 结构的指针, 它指定特权数组及其属性。
                  DWORD  BufferLength, // 指定由 PreviousState 参数指向的缓冲区的大小 (以字节为单位)。
                  PTOKEN_PRIVILEGES  PreviousState, // 一个指向缓冲区的指针。
                  PDWORD  ReturnLength // 一个指针, 该变量接收 PreviousState 参数指向的缓冲区所需的大小 (以字节为单位)。
                  );

参数

TokenHandle

包含要修改的权限的访问令牌的句柄。句柄必须具有对令牌的 TOKEN_ADJUST_PRIVILEGES 访问权限。

如果 PreviousState 参数不是 NULL, 则句柄还必须具有 TOKEN_QUERY 访问权限。

DisableAllPrivileges

指定函数是否禁用所有标记的权限。如果此值为 TRUE, 则该函数将禁用所有权限并忽略 NewState 参数。

如果是 FALSE, 则该函数根据 NewState 参数指向的信息修改权限。

NewState

指向 TOKEN_PRIVILEGES 结构的指针, 它指定特权数组及其属性。

如果 DisableAllPrivileges 参数为 FALSE, 则 AdjustTokenPrivileges 函数启用、禁用或删除令牌的这些特权。

它的值有这三个:SE_PRIVILEGE_ENABLED,SE_PRIVILEGE_REMOVED,None

BufferLength

指定由 PreviousState 参数指向的缓冲区的大小 (以字节为单位)。如果 PreviousState 参数为 NULL, 则此参数可以为零。

PreviousState

一个指向缓冲区的指针, 该函数用包含该函数修改的任何特权的以前状态的 TOKEN_PRIVILEGES 结构填充。

即, 如果此函数修改了权限, 则该特权及其以前的状态将包含在 PreviousState 引用的 TOKEN_PRIVILEGES 结构中。

如果 TOKEN_PRIVILEGES 的 PrivilegeCount 成员为零, 则此函数不更改任何特权。此参数可以为 NULL。

ReturnLength

一个指针, 该变量接收 PreviousState 参数指向的缓冲区所需的大小 (以字节为单位)。

返回值:如果函数成功, 则返回值为非零。如果失败,则可以是:ERROR_SUCCESS,ERROR_NOT_ALL_ASSIGNED。

 

TOKEN_PRIVLEGES 结构体:

typedef struct _TOKEN_PRIVILEGES {
  DWORD               PrivilegeCount; // 这必须设置为权限数组中的项数。
  LUID_AND_ATTRIBUTES Privileges[ANYSIZE_ARRAY]; // ANYSIZE_ARRAY 宏定义为 1
  } TOKEN_PRIVILEGES, *PTOKEN_PRIVILEGES;

LUID_AND_ATTRIBUTES 结构体:

typedef struct _LUID_AND_ATTRIBUTES {
  LUID  Luid; 
  DWORD Attributes; // 指定 LUID 的属性。此值最多包含32个单比特标志。它的意思取决于 LUID 的定义和用途。
  } LUID_AND_ATTRIBUTES, *PLUID_AND_ATTRIBUTES;

 

属性
描述
SE_PRIVILEGE_ENABLED_BY_DEFAULT
特权默认启用
SE_PRIVILEGE_ENABLED
特权启用.
SE_PRIVILEGE_REMOVED
删除特权
SE_PRIVILEGE_USED_FOR_ACCESS
特权被用来访问一个对象或服务。
这个标志 被用于 标识有关特权,因为
通过一组客户端应用程序,可能包含不必要的特权

 

LUDI 结构体:

typedef struct _LUID {
  DWORD LowPart; // 低阶位。
  LONG  HighPart; // 高阶位。
  } LUID, *PLUID;

本地唯一标识符 (LUID) 是仅在生成它的系统上保证唯一的64位值。只有在系统重新启动之前, 才能保证 LUID 的唯一性。

LUID 不是直接操纵的。驱动程序必须使用支持例程和结构来操作 LUID 值。

若要获取与 LUID 关联的特权的名称, 请调用 LookupPrivilegeName():

 

LookupPrivilegeName() 介绍:

功能:检索与指定的本地唯一标识符 (LUID) 在特定系统上表示的权限相对应的名称。

函数原型:BOOL LookupPrivilegeName(
                  LPCSTR  lpSystemName,  // 一个指针, 它指定检索特权名称的系统的名称。本地系统为 NULL。
                  PLUID   lpLuid, // 指向目标系统上已知权限的 LUID 的指针。
                  LPSTR   lpName, // 一个指向缓冲区的指针, 它接收表示特权名称的以 NULL 结尾的字符串。
                  LPDWORD cchName // 一个指针, 该变量指定 lpName 缓冲区的大小。
                  ); 

https://docs.microsoft.com/zh-cn/windows/desktop/SecAuthZ/privilege-constants

返回值:非零表示成功,零表示失败。

 

LookupPrivilegeValue() 介绍:

功能:查看系统权限的特权值,返回信息到一个LUID结构体里。

函数原型:BOOL LookupPrivilegeValue(
                  LPCSTR lpSystemName, // 一个指针, 它指定检索特权名称的系统的名称。本地系统为 NULL。
                  LPCSTR lpName, // 一个指针, 指定特权的名称.
                  PLUID  lpLuid // 一个指向一个变量的指针, 它接收到由 lpSystemName 参数指定的系统上已知权限的 LUID。
                   );

参数 lpName:

返回值:非零表示成功,零表示失败。

 

DEMOCODE:

BOOL PreProcess()
{
    HANDLE hToken;
    TOKEN_PRIVILEGES TKP;
    //PTOKEN_PRIVILEGES TKP = (PTOKEN_PRIVILEGES)malloc(sizeof(TOKEN_PRIVILEGES) + N * sizeof(LUID_AND_ATTRIBUTES));
    if (OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken) == 0)
    {
        return FALSE;
    }

    if (LookupPrivilegeValue(NULL, SE_SHUTDOWN_NAME, &TKP.Privileges->Luid) == 0)
    {
        return FALSE;
    }

/*    if (LookupPrivilegeValue(NULL, SE_SHUTDOWN_NAME, &TKP->Privileges[0].Luid) == 0 ||
          LookupPrivilegeValue(NULL, SE_SECURITY_NAME, &TKP->Privileges[1].Luid) == 0
          ......)
    {
        return FALSE;
    }
*/
    TKP.PrivilegeCount = 1;
    TKP.Privileges->Attributes = SE_PRIVILEGE_ENABLED;
/*    TKP->PrivilegeCount = N+1;
    for ( i = 0; i <= N; i++)
    {
        TKP->Privileges[i].Attributes = SE_PRIVILEGE_ENABLED;
    }
*/
    if (AdjustTokenPrivileges(hToken, FALSE, &TKP, 0, NULL, 0) == 0)
    {
        return FALSE;
    }
CloseHandle(hToken);
return TRUE; } BOOL ShutDown() { if (ExitWindowsEx(EWX_SHUTDOWN | EWX_FORCE, 0) == 0) return FALSE; return TRUE; }

步骤应该很清楚了......

posted @ 2018-08-13 09:15  M-Anonymous  阅读(1093)  评论(0编辑  收藏  举报