提权相关函数:
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; }
步骤应该很清楚了......