2010-01-19 27 views
5

Tôi muốn xác định theo chương trình nếu người dùng hiện tại (hoặc quy trình) có quyền truy cập để tạo liên kết tượng trưng. Trong Windows (Vista và lớn hơn), người ta không thể tạo ra một liên kết tượng trưng mà không có SeCreateSymbolicLinkPrivilege và theo mặc định, điều này chỉ được gán cho các quản trị viên. Nếu một trong những cố gắng để tạo ra một liên kết tượng trưng mà không có đặc quyền này, một lỗi Windows 1314 (Một đặc quyền cần thiết không được tổ chức bởi khách hàng) xảy ra.Xác định xem quy trình Windows có đặc quyền để tạo liên kết tượng trưng

Để chứng minh hạn chế này, tôi đã tạo cài đặt Windows sạch, đăng nhập bằng tài khoản Quản trị viên ban đầu (bị giới hạn thông qua UAC) và không thể tạo liên kết tượng trưng trong thư mục chính.

Command Prompt demonstrates mklink fails due to insufficient privilege

Sau khi chạy Command Prompt as Administrator hoặc vô hiệu hóa UAC, lệnh đó thực hiện mà không có lỗi.

Theo this article, "mọi quá trình được thực hiện thay mặt cho người dùng đều có bản sao mã thông báo [truy cập]".

Vì vậy, tôi đã tạo a Python script to query for the permissions. Để thuận tiện và áp phích, tôi bao gồm một đoạn trích dưới đây.

Ý tưởng đằng sau tập lệnh là liệt kê tất cả các đặc quyền và xác định xem quy trình có đặc quyền bắt buộc hay không. Thật không may, tôi thấy rằng quá trình hiện tại không thực sự có đặc quyền mong muốn, ngay cả khi nó có thể tạo các liên kết tượng trưng.

Tôi nghi ngờ vấn đề là mặc dù các đặc quyền của người dùng hiện tại không bao gồm rõ ràng đặc quyền, tư cách thành viên nhóm của anh ta đủ khả năng đặc quyền đó.

Tóm lại, làm thế nào tôi có thể xác định xem một quy trình cụ thể có đặc quyền tạo liên kết tượng trưng (không cố gắng tạo liên kết) không? Một ví dụ trong C hoặc C++ hoặc Python được ưa thích, mặc dù bất cứ điều gì sử dụng Windows API sẽ phù hợp.

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, 
     0, 
     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) 
+0

Windows có liên kết tượng trưng? –

+2

Bạn đang cố gắng tạo loại liên kết tượng trưng nào? Có rất nhiều thứ khác nhau có thể được coi là liên kết tượng trưng trong Windows - các điểm kết nối hệ thống tập tin, liên kết cứng hệ thống tập tin, liên kết tượng trưng quản lý đối tượng, v.v .. Tôi tin rằng bạn chỉ cần đặc quyền SeCreateSymbolicLink để tạo các liên kết tượng trưng cho người quản lý đối tượng. –

+0

Tôi đang cố gắng tạo liên kết tượng trưng dựa trên điểm nối hệ thống tệp, chẳng hạn như liên kết được tạo bởi CreateSymbolicLink. –

Trả lời

4

Tôi đã tìm được giải pháp. Mã Python sau đây là một tập lệnh đầy đủ chức năng trong Python 2.6 hoặc 3.1 thể hiện cách một người có thể xác định đặc quyền để tạo các liên kết tượng trưng. Chạy tài khoản này dưới tài khoản Administrator sẽ đáp ứng thành công và chạy nó trong tài khoản Guest sẽ trả lời với lỗi.

Lưu ý, 3/4 đầu tiên của tập lệnh chủ yếu là định nghĩa API. Tác phẩm tiểu thuyết bắt đầu với 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', wintypes.DWORD), 
     ] 

    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', wintypes.DWORD), 
     ('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_ALL_ACCESS, 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(), 
     TOKEN_INFORMATION_CLASS.TokenPrivileges, 
     None, 
     0, 
     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 

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, 0, None, 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() 
Các vấn đề liên quan