确定Windows进程是否具有创建符号链接的权限
发布时间:2020-12-14 02:27:16 所属栏目:Windows 来源:网络整理
导读:我想以编程方式确定当前用户(或进程)是否有权创建符号链接.在 Windows(Vista和更高版本)中,如果没有SeCreateSymbolicLinkPrivilege,则无法创建符号链接,默认情况下,此操作仅分配给管理员.如果尝试创建没有此权限的符号链接,则会发生Windows错误1314(客户端未
我想以编程方式确定当前用户(或进程)是否有权创建符号链接.在
Windows(Vista和更高版本)中,如果没有SeCreateSymbolicLinkPrivilege,则无法创建符号链接,默认情况下,此操作仅分配给管理员.如果尝试创建没有此权限的符号链接,则会发生Windows错误1314(客户端未保留所需的权限).
为了演示此限制,我创建了一个Windows的全新安装,以初始管理员帐户登录(通过UAC限制),并且无法在主目录中创建符号链接. 以管理员身份运行命令提示符或禁用UAC后,该命令将无错执行. 根据this article,“代表用户执行的每个进程都有[访问]令牌的副本”. 所以我创建了a Python script to query for the permissions.为了方便和后人,我在下面添加了一段摘录. 该脚本背后的想法是枚举所有特权并确定该进程是否具有所需的特权.不幸的是,我发现当前进程实际上并没有所需的权限,即使它可以创建符号链接. 我怀疑问题在于即使当前用户的权限没有明确包含该权限,他的组成员资格确实提供了该权限. 简而言之,我如何确定给定进程是否有权创建符号链接(而不尝试创建符号链接)?最好使用C或C或Python中的示例,但使用Windows API的任何内容都是合适的. def get_process_token(): token = wintypes.HANDLE() TOKEN_ALL_ACCESS = 0xf01ff res = OpenProcessToken(GetCurrentProcess(),TOKEN_ALL_ACCESS,token) if not res > 0: raise RuntimeError("Couldn't get process token") return token def get_privilege_information(): # first call with zero length to determine what size buffer we need return_length = wintypes.DWORD() params = [ get_process_token(),TOKEN_INFORMATION_CLASS.TokenPrivileges,None,return_length,] res = GetTokenInformation(*params) # assume we now have the necessary length in return_length buffer = ctypes.create_string_buffer(return_length.value) params[2] = buffer params[3] = return_length.value res = GetTokenInformation(*params) assert res > 0,"Error in second GetTokenInformation (%d)" % res privileges = ctypes.cast(buffer,ctypes.POINTER(TOKEN_PRIVILEGES)).contents return privileges privileges = get_privilege_information() print("found {0} privileges".format(privileges.count)) map(print,privileges) 解决方法
我找到了解决方案.以下Python代码是Python 2.6或3.1下的全功能脚本,演示了如何确定创建符号链接的权限.在管理员帐户下运行此响应成功,并在Guest帐户下运行它会响应失败.
请注意,脚本的前3/4主要是API定义.这部小说的工作始于get_process_token(). from __future__ import print_function import ctypes from ctypes import wintypes GetCurrentProcess = ctypes.windll.kernel32.GetCurrentProcess GetCurrentProcess.restype = wintypes.HANDLE OpenProcessToken = ctypes.windll.advapi32.OpenProcessToken OpenProcessToken.argtypes = (wintypes.HANDLE,wintypes.DWORD,ctypes.POINTER(wintypes.HANDLE)) OpenProcessToken.restype = wintypes.BOOL class LUID(ctypes.Structure): _fields_ = [ ('low_part',wintypes.DWORD),('high_part',wintypes.LONG),] def __eq__(self,other): return ( self.high_part == other.high_part and self.low_part == other.low_part ) def __ne__(self,other): return not (self==other) LookupPrivilegeValue = ctypes.windll.advapi32.LookupPrivilegeValueW LookupPrivilegeValue.argtypes = ( wintypes.LPWSTR,# system name wintypes.LPWSTR,# name ctypes.POINTER(LUID),) LookupPrivilegeValue.restype = wintypes.BOOL class TOKEN_INFORMATION_CLASS: TokenUser = 1 TokenGroups = 2 TokenPrivileges = 3 # ... see http://msdn.microsoft.com/en-us/library/aa379626%28VS.85%29.aspx SE_PRIVILEGE_ENABLED_BY_DEFAULT = (0x00000001) SE_PRIVILEGE_ENABLED = (0x00000002) SE_PRIVILEGE_REMOVED = (0x00000004) SE_PRIVILEGE_USED_FOR_ACCESS = (0x80000000) class LUID_AND_ATTRIBUTES(ctypes.Structure): _fields_ = [ ('LUID',LUID),('attributes',] def is_enabled(self): return bool(self.attributes & SE_PRIVILEGE_ENABLED) def enable(self): self.attributes |= SE_PRIVILEGE_ENABLED def get_name(self): size = wintypes.DWORD(10240) buf = ctypes.create_unicode_buffer(size.value) res = LookupPrivilegeName(None,self.LUID,buf,size) if res == 0: raise RuntimeError return buf[:size.value] def __str__(self): res = self.get_name() if self.is_enabled(): res += ' (enabled)' return res LookupPrivilegeName = ctypes.windll.advapi32.LookupPrivilegeNameW LookupPrivilegeName.argtypes = ( wintypes.LPWSTR,# lpSystemName ctypes.POINTER(LUID),# lpLuid wintypes.LPWSTR,# lpName ctypes.POINTER(wintypes.DWORD),#cchName ) LookupPrivilegeName.restype = wintypes.BOOL class TOKEN_PRIVILEGES(ctypes.Structure): _fields_ = [ ('count',('privileges',LUID_AND_ATTRIBUTES*0),] def get_array(self): array_type = LUID_AND_ATTRIBUTES*self.count privileges = ctypes.cast(self.privileges,ctypes.POINTER(array_type)).contents return privileges def __iter__(self): return iter(self.get_array()) PTOKEN_PRIVILEGES = ctypes.POINTER(TOKEN_PRIVILEGES) GetTokenInformation = ctypes.windll.advapi32.GetTokenInformation GetTokenInformation.argtypes = [ wintypes.HANDLE,# TokenHandle ctypes.c_uint,# TOKEN_INFORMATION_CLASS value ctypes.c_void_p,# TokenInformation wintypes.DWORD,# TokenInformationLength ctypes.POINTER(wintypes.DWORD),# ReturnLength ] GetTokenInformation.restype = wintypes.BOOL # http://msdn.microsoft.com/en-us/library/aa375202%28VS.85%29.aspx AdjustTokenPrivileges = ctypes.windll.advapi32.AdjustTokenPrivileges AdjustTokenPrivileges.restype = wintypes.BOOL AdjustTokenPrivileges.argtypes = [ wintypes.HANDLE,# TokenHandle wintypes.BOOL,# DisableAllPrivileges PTOKEN_PRIVILEGES,# NewState (optional) wintypes.DWORD,# BufferLength of PreviousState PTOKEN_PRIVILEGES,# PreviousState (out,optional) ctypes.POINTER(wintypes.DWORD),# ReturnLength ] def get_process_token(): """ Get the current process token """ token = wintypes.HANDLE() TOKEN_ALL_ACCESS = 0xf01ff res = OpenProcessToken(GetCurrentProcess(),token) if not res > 0: raise RuntimeError("Couldn't get process token") return token def get_symlink_luid(): """ Get the LUID for the SeCreateSymbolicLinkPrivilege """ symlink_luid = LUID() res = LookupPrivilegeValue(None,"SeCreateSymbolicLinkPrivilege",symlink_luid) if not res > 0: raise RuntimeError("Couldn't lookup privilege value") return symlink_luid def get_privilege_information(): """ Get all privileges associated with the current process. """ # first call with zero length to determine what size buffer we need return_length = wintypes.DWORD() params = [ get_process_token(),ctypes.POINTER(TOKEN_PRIVILEGES)).contents return privileges def report_privilege_information(): """ Report all privilege information assigned to the current process. """ privileges = get_privilege_information() print("found {0} privileges".format(privileges.count)) tuple(map(print,privileges)) def enable_symlink_privilege(): """ Try to assign the symlink privilege to the current process token. Return True if the assignment is successful. """ # create a space in memory for a TOKEN_PRIVILEGES structure # with one element size = ctypes.sizeof(TOKEN_PRIVILEGES) size += ctypes.sizeof(LUID_AND_ATTRIBUTES) buffer = ctypes.create_string_buffer(size) tp = ctypes.cast(buffer,ctypes.POINTER(TOKEN_PRIVILEGES)).contents tp.count = 1 tp.get_array()[0].enable() tp.get_array()[0].LUID = get_symlink_luid() token = get_process_token() res = AdjustTokenPrivileges(token,False,tp,None) if res == 0: raise RuntimeError("Error in AdjustTokenPrivileges") ERROR_NOT_ALL_ASSIGNED = 1300 return ctypes.windll.kernel32.GetLastError() != ERROR_NOT_ALL_ASSIGNED def main(): assigned = enable_symlink_privilege() msg = ['failure','success'][assigned] print("Symlink privilege assignment completed with {0}".format(msg)) if __name__ == '__main__': main() (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |