Ejemplo n.º 1
0
def winerror(code):
    global _WINERROR_BY_VALUE
    if not _WINERROR_BY_VALUE: # Lazy init
        _WINERROR_BY_VALUE = gdef.FlagMapper(*(getattr(gdef, error) for error in gdef.meta.errors))
    val = _WINERROR_BY_VALUE[code]
    if val is code: # Not found
        val = _WINERROR_BY_VALUE[code & 0xffff] # Hresult: extract code (https://en.wikipedia.org/wiki/HRESULT)
    return val
Ejemplo n.º 2
0
class LogicalDrive(AutoHandle):
    DRIVE_TYPE = gdef.FlagMapper(DRIVE_UNKNOWN, DRIVE_NO_ROOT_DIR, DRIVE_REMOVABLE,
                    DRIVE_FIXED, DRIVE_REMOTE, DRIVE_CDROM, DRIVE_RAMDISK)

    def __init__(self, name):
        self.name = name

    @property
    def type(self):
        """The type of drive, values are:

            * DRIVE_UNKNOWN(0x0L)
            * DRIVE_NO_ROOT_DIR(0x1L)
            * DRIVE_REMOVABLE(0x2L)
            * DRIVE_FIXED(0x3L)
            * DRIVE_REMOTE(0x4L)
            * DRIVE_CDROM(0x5L)
            * DRIVE_RAMDISK(0x6L)

        :type: :class:`long` or :class:`int` (or subclass)
        """
        t = winproxy.GetDriveTypeA(self.name)
        return self.DRIVE_TYPE.get(t,t)

    @property
    def path(self):
        """The target path of the device

        :type: :class:`str`"""
        res = query_dos_device(self.name.strip("\\"))
        if len(res) != 1:
            raise ValueError("[Unexpected result] query_dos_device(logicaldrive) returned multiple path")
        return res[0]

    def query_info(self, info):
        return windows.utils.query_volume_information(self.handle, info)

    @property
    def volume_info(self):
        return self.query_info(gdef.FileFsVolumeInformation)

    @property
    def serial(self):
        return self.volume_info.VolumeSerialNumber

    def _get_handle(self):
        nt_name = windows.utils.dospath_to_ntpath(self.name)
        handle = windows.winproxy.CreateFileA(nt_name, gdef.GENERIC_READ,
                                                gdef.FILE_SHARE_READ, None, gdef.OPEN_EXISTING, gdef.FILE_FLAG_BACKUP_SEMANTICS , None)
        return handle

    def __repr__(self):
        return """<{0} "{1}" ({2})>""".format(type(self).__name__, self.name, self.type.name)
Ejemplo n.º 3
0
import ctypes
import windows

from collections import namedtuple
from contextlib import contextmanager

from windows import utils
import windows.generated_def as gdef
from windows.generated_def import *


SERVICE_TYPE = gdef.FlagMapper(SERVICE_KERNEL_DRIVER, SERVICE_FILE_SYSTEM_DRIVER, SERVICE_WIN32_OWN_PROCESS, SERVICE_WIN32_SHARE_PROCESS, SERVICE_INTERACTIVE_PROCESS)
SERVICE_STATE = gdef.FlagMapper(SERVICE_STOPPED, SERVICE_START_PENDING, SERVICE_STOP_PENDING, SERVICE_RUNNING, SERVICE_CONTINUE_PENDING, SERVICE_PAUSE_PENDING, SERVICE_PAUSED)
SERVICE_CONTROLE_ACCEPTED = gdef.FlagMapper()
SERVICE_FLAGS = gdef.FlagMapper(SERVICE_RUNS_IN_SYSTEM_PROCESS)


ServiceStatus = namedtuple("ServiceStatus", ["type", "state", "control_accepted", "flags"])
"""
``type`` might be one of:

    * ``SERVICE_KERNEL_DRIVER(0x1L)``
    * ``SERVICE_FILE_SYSTEM_DRIVER(0x2L)``
    * ``SERVICE_WIN32_OWN_PROCESS(0x10L)``
    * ``SERVICE_WIN32_SHARE_PROCESS(0x20L)``
    * ``SERVICE_INTERACTIVE_PROCESS(0x100L)``

``state`` might be one of:

    * ``SERVICE_STOPPED(0x1L)``
    * ``SERVICE_START_PENDING(0x2L)``
Ejemplo n.º 4
0
class System(object):
    """The state of the current ``Windows`` system ``Python`` is running on"""

    # Setup these in a fixedproperty ?
    network = network.Network()
    """Object of class :class:`windows.winobject.network.Network`"""
    registry = registry.Registry()
    """Object of class :class:`windows.winobject.registry.Registry`"""

    @property
    def processes(self):
        """The list of running processes

        :type: [:class:`~windows.winobject.process.WinProcess`] -- A list of Process
		"""
        return self.enumerate_processes()

    @property
    def threads(self):
        """The list of running threads

        :type: [:class:`~windows.winobject.process.WinThread`] -- A list of Thread
		"""
        return self.enumerate_threads_setup_owners()

    @property
    def logicaldrives(self):
        """List of logical drives [C:\, ...]

        :type: [:class:`~windows.winobject.volume.LogicalDrive`] -- A list of LogicalDrive
        """
        return volume.enum_logical_drive()

    @utils.fixedpropety
    def services(self):
        """The list of services

        :type: [:class:`~windows.winobject.service.ServiceA`] -- A list of Service"""
        return service.ServiceManager()

    @property
    def handles(self):
        """The list of system handles

        :type: [:class:`~windows.winobject.handle.Handle`] -- A list of Hanlde"""
        return handle.enumerate_handles()

    @property
    def modules(self):
        """The list of system modules

        :type: [:class:`~windows.winobject.system_module.SystemModule`] -- A list of :class:`~windows.winobject.system_module.SystemModule` or :class:`~windows.winobject.system_module.SystemModuleWow64`
        """
        return system_module.enumerate_kernel_modules()

    @utils.fixedpropety
    def bitness(self):
        """The bitness of the system

        :type: :class:`int` -- 32 or 64
		"""
        if os.environ["PROCESSOR_ARCHITECTURE"].lower() != "x86":
            return 64
        if "PROCESSOR_ARCHITEW6432" in os.environ:
            return 64
        return 32

    @utils.fixedpropety
    def wmi(self):
        r"""An object to perform wmi requests to various namespaces

        :type: :class:`~windows.winobject.wmi.WmiManager`"""
        return wmi.WmiManager()


    @utils.fixedpropety
    def event_log(self):
        return event_log.EvtlogManager()

    @utils.fixedpropety
    def etw(self):
        return event_trace.EtwManager()


    @utils.fixedpropety
    def task_scheduler(self):
        """An object able to manage scheduled tasks on the local system

        :type: :class:`~windows.winobject.task_scheduler.TaskService`
        """
        windows.com.init()
        clsid_task_scheduler = gdef.IID.from_string("0f87369f-a4e5-4cfc-bd3e-73e6154572dd")
        task_service = task_scheduler.TaskService()
        # What is non-implemented (WinXP)
        # Raise (NotImplementedError?) ? Return NotImplemented ?
        windows.com.create_instance(clsid_task_scheduler, task_service)
        task_service.connect()
        return task_service

    @utils.fixedpropety
    def object_manager(self):
        """An object to query the objects in the kernel object manager.

        :type: :class:`~windows.winobject.object_manager.ObjectManager`
        """
        return windows.winobject.object_manager.ObjectManager()

    @utils.fixedpropety
    def bits(self):
        return bits.create_manager()

    #TODO: use GetComputerNameExA ? and recover other names ?
    @utils.fixedpropety
    def computer_name(self):
        """The name of the computer

        :type: :class:`str`
        """
        size = gdef.DWORD(0x1000)
        # For now I don't know what is best as A vs W APIs...
        if windows.pycompat.is_py3:
            buf = ctypes.create_unicode_buffer(size.value)
            winproxy.GetComputerNameW(buf, ctypes.byref(size))
        else:
            buf = ctypes.create_string_buffer(size.value)
            winproxy.GetComputerNameA(buf, ctypes.byref(size))
        return buf[:size.value]

    @utils.fixedpropety
    def version(self):
        """The version of the system

        :type: (:class:`int`, :class:`int`) -- (Major, Minor)
        """
        data = self.get_version()
        result = data.dwMajorVersion, data.dwMinorVersion
        if result == (6,2):
            result_str = self.get_file_version("kernel32")
            result_tup = [int(x) for x in result_str.split(".")]
            result = tuple(result_tup[:2])
        return result

    @utils.fixedpropety
    def version_name(self):
        """The name of the system version,  values are:

            * Windows Server 2016
            * Windows 10
            * Windows Server 2012 R2
            * Windows 8.1
            * Windows Server 2012
            * Windows 8
            * Windows Server 2008
            * Windows 7
            * Windows Server 2008
            * Windows Vista
            * Windows XP Professional x64 Edition
            * TODO: version (5.2) + is_workstation + bitness == 32 (don't even know if possible..)
            * Windows Server 2003 R2
            * Windows Server 2003
            * Windows XP
            * Windows 2000
            * "Unknow Windows <version={0} | is_workstation={1}>".format(version, is_workstation)

        :type: :class:`str`
        """
        version = self.version
        is_workstation = self.product_type == gdef.VER_NT_WORKSTATION
        if version == (10, 0):
            return ["Windows Server 2016", "Windows 10"][is_workstation]
        elif version == (6, 3):
            return  ["Windows Server 2012 R2", "Windows 8.1"][is_workstation]
        elif version == (6, 2):
            return ["Windows Server 2012", "Windows 8"][is_workstation]
        elif version == (6, 1):
            return ["Windows Server 2008 R2", "Windows 7"][is_workstation]
        elif version == (6, 0):
            return ["Windows Server 2008", "Windows Vista"][is_workstation]
        elif version == (5, 2):
            metric = winproxy.GetSystemMetrics(gdef.SM_SERVERR2)
            if is_workstation:
                if self.bitness == 64:
                    return "Windows XP Professional x64 Edition"
                else:
                    return "TODO: version (5.2) + is_workstation + bitness == 32"
            elif metric != 0:
                return "Windows Server 2003 R2"
            else:
                return "Windows Server 2003"
        elif version == (5, 1):
            return "Windows XP"
        elif version == (5, 0):
            return "Windows 2000"
        else:
            return "Unknow Windows <version={0} | is_workstation={1}>".format(version, is_workstation)

    VERSION_MAPPER = gdef.FlagMapper(gdef.VER_NT_WORKSTATION, gdef.VER_NT_DOMAIN_CONTROLLER, gdef.VER_NT_SERVER)
    @utils.fixedpropety
    def product_type(self):
        """The product type, value might be:

            * VER_NT_WORKSTATION(0x1L)
            * VER_NT_DOMAIN_CONTROLLER(0x2L)
            * VER_NT_SERVER(0x3L)

        :type: :class:`long` or :class:`int` (or subclass)
        """
        version = self.get_version()
        return self.VERSION_MAPPER[version.wProductType]


    EDITION_MAPPER = gdef.FlagMapper(gdef.PRODUCT_UNDEFINED,
        gdef.PRODUCT_ULTIMATE,
        gdef.PRODUCT_HOME_BASIC,
        gdef.PRODUCT_HOME_PREMIUM,
        gdef.PRODUCT_ENTERPRISE,
        gdef.PRODUCT_HOME_BASIC_N,
        gdef.PRODUCT_BUSINESS,
        gdef.PRODUCT_STANDARD_SERVER,
        gdef.PRODUCT_DATACENTER_SERVER,
        gdef.PRODUCT_SMALLBUSINESS_SERVER,
        gdef.PRODUCT_ENTERPRISE_SERVER,
        gdef.PRODUCT_STARTER,
        gdef.PRODUCT_DATACENTER_SERVER_CORE,
        gdef.PRODUCT_STANDARD_SERVER_CORE,
        gdef.PRODUCT_ENTERPRISE_SERVER_CORE,
        gdef.PRODUCT_ENTERPRISE_SERVER_IA64,
        gdef.PRODUCT_BUSINESS_N,
        gdef.PRODUCT_WEB_SERVER,
        gdef.PRODUCT_CLUSTER_SERVER,
        gdef.PRODUCT_HOME_SERVER,
        gdef.PRODUCT_STORAGE_EXPRESS_SERVER,
        gdef.PRODUCT_STORAGE_STANDARD_SERVER,
        gdef.PRODUCT_STORAGE_WORKGROUP_SERVER,
        gdef.PRODUCT_STORAGE_ENTERPRISE_SERVER,
        gdef.PRODUCT_SERVER_FOR_SMALLBUSINESS,
        gdef.PRODUCT_SMALLBUSINESS_SERVER_PREMIUM,
        gdef.PRODUCT_HOME_PREMIUM_N,
        gdef.PRODUCT_ENTERPRISE_N,
        gdef.PRODUCT_ULTIMATE_N,
        gdef.PRODUCT_WEB_SERVER_CORE,
        gdef.PRODUCT_MEDIUMBUSINESS_SERVER_MANAGEMENT,
        gdef.PRODUCT_MEDIUMBUSINESS_SERVER_SECURITY,
        gdef.PRODUCT_MEDIUMBUSINESS_SERVER_MESSAGING,
        gdef.PRODUCT_SERVER_FOUNDATION,
        gdef.PRODUCT_HOME_PREMIUM_SERVER,
        gdef.PRODUCT_SERVER_FOR_SMALLBUSINESS_V,
        gdef.PRODUCT_STANDARD_SERVER_V,
        gdef.PRODUCT_DATACENTER_SERVER_V,
        gdef.PRODUCT_ENTERPRISE_SERVER_V,
        gdef.PRODUCT_DATACENTER_SERVER_CORE_V,
        gdef.PRODUCT_STANDARD_SERVER_CORE_V,
        gdef.PRODUCT_ENTERPRISE_SERVER_CORE_V,
        gdef.PRODUCT_HYPERV,
        gdef.PRODUCT_STORAGE_EXPRESS_SERVER_CORE,
        gdef.PRODUCT_STORAGE_STANDARD_SERVER_CORE,
        gdef.PRODUCT_STORAGE_WORKGROUP_SERVER_CORE,
        gdef.PRODUCT_STORAGE_ENTERPRISE_SERVER_CORE,
        gdef.PRODUCT_STARTER_N,
        gdef.PRODUCT_PROFESSIONAL,
        gdef.PRODUCT_PROFESSIONAL_N,
        gdef.PRODUCT_SB_SOLUTION_SERVER,
        gdef.PRODUCT_SERVER_FOR_SB_SOLUTIONS,
        gdef.PRODUCT_STANDARD_SERVER_SOLUTIONS,
        gdef.PRODUCT_STANDARD_SERVER_SOLUTIONS_CORE,
        gdef.PRODUCT_SB_SOLUTION_SERVER_EM,
        gdef.PRODUCT_SERVER_FOR_SB_SOLUTIONS_EM,
        gdef.PRODUCT_SOLUTION_EMBEDDEDSERVER,
        gdef.PRODUCT_SOLUTION_EMBEDDEDSERVER_CORE,
        gdef.PRODUCT_SMALLBUSINESS_SERVER_PREMIUM_CORE,
        gdef.PRODUCT_ESSENTIALBUSINESS_SERVER_MGMT,
        gdef.PRODUCT_ESSENTIALBUSINESS_SERVER_ADDL,
        gdef.PRODUCT_ESSENTIALBUSINESS_SERVER_MGMTSVC,
        gdef.PRODUCT_ESSENTIALBUSINESS_SERVER_ADDLSVC,
        gdef.PRODUCT_CLUSTER_SERVER_V,
        gdef.PRODUCT_EMBEDDED,
        gdef.PRODUCT_STARTER_E,
        gdef.PRODUCT_HOME_BASIC_E,
        gdef.PRODUCT_HOME_PREMIUM_E,
        gdef.PRODUCT_PROFESSIONAL_E,
        gdef.PRODUCT_ENTERPRISE_E,
        gdef.PRODUCT_ULTIMATE_E,
        gdef.PRODUCT_ENTERPRISE_EVALUATION,
        gdef.PRODUCT_MULTIPOINT_STANDARD_SERVER,
        gdef.PRODUCT_MULTIPOINT_PREMIUM_SERVER,
        gdef.PRODUCT_STANDARD_EVALUATION_SERVER,
        gdef.PRODUCT_DATACENTER_EVALUATION_SERVER,
        gdef.PRODUCT_ENTERPRISE_N_EVALUATION,
        gdef.PRODUCT_STORAGE_WORKGROUP_EVALUATION_SERVER,
        gdef.PRODUCT_STORAGE_STANDARD_EVALUATION_SERVER,
        gdef.PRODUCT_CORE_ARM,
        gdef.PRODUCT_CORE_N,
        gdef.PRODUCT_CORE_COUNTRYSPECIFIC,
        gdef.PRODUCT_CORE_LANGUAGESPECIFIC,
        gdef.PRODUCT_CORE,
        gdef.PRODUCT_PROFESSIONAL_WMC,
        gdef.PRODUCT_UNLICENSED)

    @utils.fixedpropety
    def edition(self): # Find a better name ?
        version = self.get_version()
        edition = gdef.DWORD()
        try:
            winproxy.GetProductInfo(version.dwMajorVersion,
                                        version.dwMinorVersion,
                                        version.wServicePackMajor,
                                        version.wServicePackMinor,
                                        edition)
        except winproxy.ExportNotFound as e:
            # Windows XP does not implem GetProductInfo
            assert version.dwMajorVersion, version.dwMinorVersion == (5,1)
            return self._edition_windows_xp()
        return self.EDITION_MAPPER[edition.value]

    def _edition_windows_xp(self):
        # Emulate standard response from IsOS(gdef.OS_PROFESSIONAL)
        if winproxy.IsOS(gdef.OS_PROFESSIONAL):
            return gdef.PRODUCT_PROFESSIONAL
        return gdef.PRODUCT_HOME_BASIC

    @utils.fixedpropety
    def windir(self):
        buffer = ctypes.c_buffer(0x100)
        reslen = winproxy.GetWindowsDirectoryA(buffer)
        return buffer[:reslen]

    def get_version(self):
        data = gdef.OSVERSIONINFOEXA()
        data.dwOSVersionInfoSize = ctypes.sizeof(data)
        winproxy.GetVersionExA(ctypes.cast(ctypes.pointer(data), ctypes.POINTER(gdef.OSVERSIONINFOA)))
        return data

    def get_file_version(self, name):
        size = winproxy.GetFileVersionInfoSizeA(name)
        buf = ctypes.c_buffer(size)
        winproxy.GetFileVersionInfoA(name, 0, size, buf)

        bufptr = gdef.PVOID()
        bufsize = gdef.UINT()
        winproxy.VerQueryValueA(buf, "\\VarFileInfo\\Translation", ctypes.byref(bufptr), ctypes.byref(bufsize))
        bufstr = ctypes.cast(bufptr, gdef.LPCSTR)
        tup = struct.unpack("<HH", bufstr.value[:4])
        req = "{0:04x}{1:04x}".format(*tup)
        winproxy.VerQueryValueA(buf, "\\StringFileInfo\\{0}\\ProductVersion".format(req), ctypes.byref(bufptr), ctypes.byref(bufsize))
        bufstr = ctypes.cast(bufptr, gdef.LPCSTR)
        return bufstr.value

    @utils.fixedpropety
    def build_number(self):
        # Best effort. use get_file_version if registry code fails
        try:
            # Does not works on Win7..
            # Missing CurrentMajorVersionNumber/CurrentMinorVersionNumber/UBR
            # We have CurrentVersion instead
            # Use this code and get_file_version as a backup ?
            curver_key = windows.system.registry(r"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion")
            try:
                major = curver_key["CurrentMajorVersionNumber"].value
                minor = curver_key["CurrentMinorVersionNumber"].value
            except WindowsError as e:
                version = curver_key["CurrentVersion"].value
                # May raise ValueError if no "."
                major, minor = version.split(".")
            build = curver_key["CurrentBuildNumber"].value
            # Update Build Revision
            try:
                ubr = curver_key["UBR"].value
            except WindowsError as e:
                ubr = 0 # Not present on Win7
            return "{0}.{1}.{2}.{3}".format(major, minor, build, ubr)
        except (WindowsError, ValueError):
            return self.get_file_version("ntdll")


    @staticmethod
    def enumerate_processes():
        dbgprint("Enumerating processes with CreateToolhelp32Snapshot", "SLOW")
        process_entry = gdef.PROCESSENTRY32()
        process_entry.dwSize = ctypes.sizeof(process_entry)
        snap = winproxy.CreateToolhelp32Snapshot(gdef.TH32CS_SNAPPROCESS, 0)
        winproxy.Process32First(snap, process_entry)
        res = []
        res.append(process.WinProcess._from_PROCESSENTRY32(process_entry))
        while winproxy.Process32Next(snap, process_entry):
            res.append(process.WinProcess._from_PROCESSENTRY32(process_entry))
        winproxy.CloseHandle(snap)
        return res

    @staticmethod
    def enumerate_threads_generator():
        # Ptet dangereux, parce que on yield la meme THREADENTRY32 a chaque fois
        dbgprint("Enumerating threads with CreateToolhelp32Snapshot <generator>", "SLOW")
        thread_entry = gdef.THREADENTRY32()
        thread_entry.dwSize = ctypes.sizeof(thread_entry)
        snap = winproxy.CreateToolhelp32Snapshot(gdef.TH32CS_SNAPTHREAD, 0)
        dbgprint("New handle CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD) <generator> | {0:#x}".format(snap), "HANDLE")
        try:
            winproxy.Thread32First(snap, thread_entry)
            yield thread_entry
            while winproxy.Thread32Next(snap, thread_entry):
                yield thread_entry
        finally:
            winproxy.CloseHandle(snap)
        dbgprint("CLOSE CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD) <generator> | {0:#x}".format(snap), "HANDLE")


    @staticmethod
    def enumerate_threads():
        return [WinThread._from_THREADENTRY32(th) for th in System.enumerate_threads_generator()]


    def enumerate_threads_setup_owners(self):
        # Enumerating threads is a special operation concerning the owner process.
        # We may not be able to retrieve the name of the owning process by normal way
        # (as we need to get a handle on the process)
        # So, this implementation of enumerate_thread also setup the owner with the result of enumerate_processes
        dbgprint("Enumerating threads with CreateToolhelp32Snapshot and setup owner", "SLOW")

        # One snap for both enum to be prevent race
        snap = winproxy.CreateToolhelp32Snapshot(gdef.TH32CS_SNAPTHREAD | gdef.TH32CS_SNAPPROCESS, 0)

        process_entry = gdef.PROCESSENTRY32()
        process_entry.dwSize = ctypes.sizeof(process_entry)
        winproxy.Process32First(snap, process_entry)
        processes = []
        processes.append(process.WinProcess._from_PROCESSENTRY32(process_entry))
        while winproxy.Process32Next(snap, process_entry):
            processes.append(process.WinProcess._from_PROCESSENTRY32(process_entry))

        # Forge a dict pid -> process
        proc_dict = {proc.pid: proc for proc in processes}

        thread_entry = gdef.THREADENTRY32()
        thread_entry.dwSize = ctypes.sizeof(thread_entry)
        threads = []
        winproxy.Thread32First(snap, thread_entry)
        parent = proc_dict[thread_entry.th32OwnerProcessID]
        threads.append(process.WinThread._from_THREADENTRY32(thread_entry, owner=parent))
        while winproxy.Thread32Next(snap, thread_entry):
            parent = proc_dict[thread_entry.th32OwnerProcessID]
            threads.append(process.WinThread._from_THREADENTRY32(thread_entry, owner=parent))
        winproxy.CloseHandle(snap)
        return threads
Ejemplo n.º 5
0
class Token(utils.AutoHandle):
    """Represent a Windows Token.
    The attributes only documented by a type are from the :class:`~windows.generated_def.winstructs.TOKEN_INFORMATION_CLASS`, such return values may be improved version of the structure.

    .. note::

        see `[MSDN] TOKEN_INFORMATION_CLASS <https://docs.microsoft.com/en-us/windows/desktop/api/winnt/ne-winnt-_token_information_class>`_
    """
    def __init__(self, handle):
        self._handle = handle

    def _get_required_token_information_size(self, infos_class):
        cbsize = gdef.DWORD()
        try:
            winproxy.GetTokenInformation(self.handle, infos_class, None, 0, ctypes.byref(cbsize))
        except winproxy.WinproxyError as e:
             if not e.winerror in (gdef.ERROR_INSUFFICIENT_BUFFER, gdef.ERROR_BAD_LENGTH):
                raise
        return cbsize.value

    def get_token_infomations(self, infos_class, rtype):
        required_size = self._get_required_token_information_size(infos_class)
        requested_size = max(required_size, ctypes.sizeof(rtype))
        buffer = utils.BUFFER(rtype, 1)(size=requested_size)
        cbsize = gdef.DWORD()
        winproxy.GetTokenInformation(self.handle, infos_class, buffer, buffer.real_size, cbsize)
        return buffer[0]


    def set_informations(self, info_type, infos):
        return winproxy.SetTokenInformation(self.handle, info_type, ctypes.byref(infos), ctypes.sizeof(infos))


    craft = meta_craft(get_token_infomations)
    # https://docs.microsoft.com/en-us/windows/desktop/api/winnt/ne-winnt-_token_information_class
    TokenUser = craft(gdef.TokenUser, gdef.TOKEN_USER) #: :class:`~windows.generated_def.winstructs.TOKEN_USER`
    TokenGroups = craft(gdef.TokenGroups , TokenGroupsType) #: :class:`TokenGroups`
    TokenPrivileges = craft(gdef.TokenPrivileges , TokenPrivilegesType) #: :class:`TokenPrivileges`
    TokenOwner = craft(gdef.TokenOwner, gdef.TOKEN_OWNER) #: :class:`~windows.generated_def.winstructs.TOKEN_OWNER`
    TokenPrimaryGroup = craft(gdef.TokenPrimaryGroup, gdef.TOKEN_PRIMARY_GROUP) #: :class:`~windows.generated_def.winstructs.TOKEN_PRIMARY_GROUP`
    TokenDefaultDacl = craft(gdef.TokenDefaultDacl, gdef.TOKEN_DEFAULT_DACL) #: :class:`~windows.generated_def.winstructs.TOKEN_DEFAULT_DACL`
    TokenSource = craft(gdef.TokenSource, gdef.TOKEN_SOURCE) #: :class:`~windows.generated_def.winstructs.TOKEN_SOURCE`
    TokenType = craft(gdef.TokenType, gdef.TOKEN_TYPE) #: :class:`~windows.generated_def.winstructs.TOKEN_TYPE`
    TokenImpersonationLevel = craft(gdef.TokenImpersonationLevel, gdef.SECURITY_IMPERSONATION_LEVEL) #: :class:`~windows.generated_def.winstructs.SECURITY_IMPERSONATION_LEVEL`
    TokenStatistics = craft(gdef.TokenStatistics, gdef.TOKEN_STATISTICS) #: :class:`~windows.generated_def.winstructs.TOKEN_STATISTICS`
    TokenRestrictedSids = craft(gdef.TokenRestrictedSids, TokenGroupsType) #: :class:`~windows.generated_def.winstructs.TokenGroups`
    TokenSessionId = craft(gdef.TokenSessionId, gdef.DWORD) #: :class:`~windows.generated_def.winstructs.DWORD`
    TokenGroupsAndPrivileges = craft(gdef.TokenGroupsAndPrivileges, gdef.TOKEN_GROUPS_AND_PRIVILEGES) #: :class:`~windows.generated_def.winstructs.TOKEN_GROUPS_AND_PRIVILEGES`
    # TokenSessionReference = craft(gdef.TokenSessionReference, ???) # Reserved.
    TokenSandBoxInert = craft(gdef.TokenSandBoxInert, gdef.DWORD) #: :class:`~windows.generated_def.winstructs.DWORD`
    # TokenAuditPolicy = craft(gdef.TokenAuditPolicy, ???) # Reserved.
    TokenOrigin = craft(gdef.TokenOrigin, gdef.TOKEN_ORIGIN) #: :class:`~windows.generated_def.winstructs.TOKEN_ORIGIN`
    TokenElevationType = craft(gdef.TokenElevationType, gdef.TOKEN_ELEVATION_TYPE) #: :class:`~windows.generated_def.winstructs.TOKEN_ELEVATION_TYPE`
    TokenLinkedToken = craft(gdef.TokenLinkedToken, gdef.TOKEN_LINKED_TOKEN) #: :class:`~windows.generated_def.winstructs.TOKEN_LINKED_TOKEN`
    TokenElevation = craft(gdef.TokenElevation, gdef.TOKEN_ELEVATION) #: :class:`~windows.generated_def.winstructs.TOKEN_ELEVATION`
    TokenHasRestrictions = craft(gdef.TokenHasRestrictions, gdef.DWORD) #: :class:`~windows.generated_def.winstructs.DWORD`
    TokenAccessInformation = craft(gdef.TokenAccessInformation, gdef.TOKEN_ACCESS_INFORMATION) #: :class:`~windows.generated_def.winstructs.TOKEN_ACCESS_INFORMATION`
    TokenVirtualizationAllowed = craft(gdef.TokenVirtualizationAllowed, gdef.DWORD) #: :class:`~windows.generated_def.winstructs.DWORD`
    TokenVirtualizationEnabled = craft(gdef.TokenVirtualizationEnabled, gdef.DWORD) #: :class:`~windows.generated_def.winstructs.DWORD`
    TokenIntegrityLevel = craft(gdef.TokenIntegrityLevel, gdef.TOKEN_MANDATORY_LABEL) #: :class:`~windows.generated_def.winstructs.TOKEN_MANDATORY_LABEL`
    TokenUIAccess = craft(gdef.TokenUIAccess, gdef.DWORD) #: :class:`~windows.generated_def.winstructs.DWORD`
    TokenMandatoryPolicy = craft(gdef.TokenMandatoryPolicy, gdef.TOKEN_MANDATORY_POLICY) #: :class:`~windows.generated_def.winstructs.TOKEN_MANDATORY_POLICY`
    TokenLogonSid = craft(gdef.TokenLogonSid, TokenGroupsType) #: :class:`TokenGroups`
    TokenIsAppContainer = craft(gdef.TokenIsAppContainer, gdef.DWORD) #: :class:`~windows.generated_def.winstructs.DWORD`
    TokenCapabilities = craft(gdef.TokenCapabilities, TokenGroupsType) #: :class:`TokenGroups`
    TokenAppContainerSid = craft(gdef.TokenAppContainerSid, gdef.TOKEN_APPCONTAINER_INFORMATION) #: :class:`~windows.generated_def.winstructs.TOKEN_APPCONTAINER_INFORMATION`
    TokenAppContainerNumber = craft(gdef.TokenAppContainerNumber, gdef.DWORD) #: :class:`~windows.generated_def.winstructs.DWORD`
    TokenUserClaimAttributes = craft(gdef.TokenUserClaimAttributes, gdef.CLAIM_SECURITY_ATTRIBUTES_INFORMATION) #: :class:`~windows.generated_def.winstructs.CLAIM_SECURITY_ATTRIBUTES_INFORMATION`
    TokenDeviceClaimAttributes = craft(gdef.TokenDeviceClaimAttributes, gdef.CLAIM_SECURITY_ATTRIBUTES_INFORMATION) #: :class:`~windows.generated_def.winstructs.CLAIM_SECURITY_ATTRIBUTES_INFORMATION`
    # TokenRestrictedUserClaimAttributes = craft(gdef.TokenRestrictedUserClaimAttributes, ???) # Reserved.
    # TokenRestrictedDeviceClaimAttributes = craft(gdef.TokenRestrictedDeviceClaimAttributes, ???) # Reserved.
    TokenDeviceGroups = craft(gdef.TokenDeviceGroups, TokenGroupsType) #: :class:`TokenGroups`
    TokenRestrictedDeviceGroups = craft(gdef.TokenRestrictedDeviceGroups, gdef.TOKEN_GROUPS) #: :class:`~windows.generated_def.winstructs.TOKEN_GROUPS`
    # Reserved.
    # Structure found in ntseapi.h (thx internet)
    TokenSecurityAttributes = craft(gdef.TokenSecurityAttributes, TokenSecurityAttributesInformation) #: :class:`TokenSecurityAttributesInformation`
    # Help would be appreciated for the structures of the following query type

    # TokenIsRestricted = craft(gdef.TokenIsRestricted, ???) # Reserved.
    TokenProcessTrustLevel = craft(gdef.TokenProcessTrustLevel, gdef.PSID) #: :class:`~windows.generated_def.winstructs.PSID`
    # TokenPrivateNameSpace = craft(gdef.TokenPrivateNameSpace, gdef.ULONG) # Reserved.
    # TokenSingletonAttributes = craft(gdef.TokenSingletonAttributes, ???) # Reserved.
    # TokenBnoIsolation = craft(gdef.TokenBnoIsolation, ???) # Reserved.
    # TokenChildProcessFlags = craft(gdef.TokenChildProcessFlags, ???) # Reserved.
    # TokenIsLessPrivilegedAppContainer = craft(gdef.TokenIsLessPrivilegedAppContainer, ???) # Reserved.

    # High level properties

    @property
    def user(self):
        """The user sid of the token

        :type: :class:`~windows.generated_def.winstructs.PSID`
        """
        return self.TokenUser.User.Sid

    @property
    def username(self):
        """The username of the token

        :type: :class:`str`
        """
        return self._user_and_computer_name()[1]

    @property
    def computername(self):
        """The computername of the token

        :type: :class:`str`
        """
        return self._user_and_computer_name()[0]

    def _user_and_computer_name(self):
        return windows.utils.lookup_sid(self.user)


    groups = TokenGroups #: Alias for TokenGroups (type may change in the future for improved struct)

    @property
    def owner(self):
        """The owner sid of the token

        :type: :class:`~windows.generated_def.winstructs.PSID`
        """
        return self.TokenOwner.Owner

    @property
    def primary_group(self):
        """The sid of the primary group of the token

        :type: :class:`~windows.generated_def.winstructs.PSID`
        """
        return self.TokenPrimaryGroup.PrimaryGroup

    @property
    def default_dacl(self):
        """The defaul DACL of the token

        :type: :class:`windows.security.Acl`
        """
        import window.security # Beuk move token.py & in a security/ directory ?
        return self.get_token_infomations(gdef.TokenDefaultDacl, windows.security.PAcl)[0]

    # def source(self): (tok.TokenSource) ??

    @property
    def type(self):
        """The type (Primary / Impersonation) of the token


        """
        return self.TokenType.value

    @property
    def impersonation_level(self):
        """The impersonation level of a ``TokenImpersonation`` token.

        :raises: :class:`WindowsError` if token is not a ``TokenImpersonation``
        :type: :class:`int` -- Enum value from :class:`~windows.generated_def.winstructs.SECURITY_IMPERSONATION_LEVEL`
        """
        try:
            return self.TokenImpersonationLevel.value
        except WindowsError as e:
            if (e.winerror == gdef.ERROR_INVALID_PARAMETER and
                    self.type != gdef.TokenImpersonation):
                # raise ValueError ?
                e.strerror += " This Token is not an Impersonation token"
            raise

    statistics = TokenStatistics #: Alias for TokenStatistics (type may change in the future for improved struct)

    @property
    def id(self):
        """The TokenId Specifies an unique identifier that identifies this instance of the token object.

        :type: :class:`int`
        """
        return int(self.TokenStatistics.TokenId)

    @property
    def authentication_id(self):
        """The AuthenticationId Specifies an unique identifier assigned to the session this token represents.
        There can be many tokens representing a single logon session.

        :type: :class:`int`
        """
        return int(self.TokenStatistics.AuthenticationId)

    @property
    def modified_id(self):
        """The ModifiedId Specifies an unique identifier that changes each time the token is modified.

        :type: :class:`int`
        """
        return int(self.TokenStatistics.ModifiedId)

    restricted_sids = TokenRestrictedSids #: Alias for TokenRestrictedSids (type may change in the future for improved struct)
    session_id = TokenSessionId #: Alias for TokenSessionId (type may change in the future for improved struct)

    @property
    def groups_and_privileges(self):
        """Alias for TokenGroupsAndPrivileges (type may change in the future for improved struct)"""
        # Return enhanced 'TOKEN_GROUPS_AND_PRIVILEGES' ?
        return self.TokenGroupsAndPrivileges

    @property
    def privileges(self):
        """Alias for ``TokenPrivileges``

        :type: :class:`TokenPrivileges`
        """
        return self.TokenPrivileges

    sandbox_inert = TokenSandBoxInert #: Alias for TokenSandBoxInert (type may change in the future for improved struct)

    # def audit_policy(self):
        # raise NotImplementedError("Need to find the type of TokenAuditPolicy")

    @property
    def origin(self):
        """The originating logon session of the token.

        :type: :class:`int`
        """
        origin_logon_session = self.TokenOrigin.OriginatingLogonSession
        return int(origin_logon_session) # improved LUID implem __int__ :)

    @property
    def elevation_type(self):
        """The elevation type of the token.

        :type: :class:`int` -- Enum value from :class:`~windows.generated_def.winstructs.TOKEN_ELEVATION_TYPE`
        """
        return self.TokenElevationType.value

    @property
    def linked_token(self):
        """The token linked to our token if present (may raise else)

        :type: :class:`Token`
        """
        # TODO: return None if not present ?
        return Token(self.TokenLinkedToken.LinkedToken)

    @property
    def elevated(self):
        """``True`` if token is an elevated token"""
        return bool(self.TokenElevation.TokenIsElevated)

    is_elevated = elevated #: Alias for ``elevated`` deprecated and may disapear
    has_restriction = TokenHasRestrictions #: Alias for TokenHasRestrictions (type may change in the future for improved struct)

    @property
    def access_information(self):
        """Alias for TokenAccessInformation (type may change in the future for improved struct)"""
        # Return enhanced subclass ?
        return self.TokenAccessInformation

    @property
    def trust_level(self):
        """The trust level of the process if present else ``None``.

        :type: :class:`~windows.generated_def.winstructs.PSID`
        """
        tl = self.TokenProcessTrustLevel
        if not tl: # NULL:
            return None
        return tl

    virtualization_allowed = TokenVirtualizationAllowed #: Alias for TokenVirtualizationAllowed (type may change in the future for improved struct)
    virtualization_enabled = TokenVirtualizationEnabled #: Alias for TokenVirtualizationEnabled (type may change in the future for improved struct)

    @property
    def integrity_level(self):
        """The integrity level and attributes of the token

        :type: :class:`windows.generated_def.winstructs.SID_AND_ATTRIBUTES`
        """
        return self.TokenIntegrityLevel.Label # SID_AND_ATTRIBUTES

    def get_integrity(self):
        """Return the integrity level of the token

        :type: :class:`int`
		"""
        sid = self.integrity_level.Sid
        count = winproxy.GetSidSubAuthorityCount(sid)
        integrity = winproxy.GetSidSubAuthority(sid, count[0] - 1)[0]
        return KNOW_INTEGRITY_LEVEL[integrity]

    def set_integrity(self, integrity):
        """Set the integrity level of a token

        :param type: :class:`int`
		"""
        mandatory_label = gdef.TOKEN_MANDATORY_LABEL()
        mandatory_label.Label.Attributes = 0x60
        # cast integrity to int to accept SECURITY_MANDATORY_LOW_RID & other Flags
        mandatory_label.Label.Sid = gdef.PSID.from_string("S-1-16-{0}".format(int(integrity)))
        return self.set_informations(gdef.TokenIntegrityLevel, mandatory_label)

    _INTEGRITY_PROPERTY_DOC = """The integrity of the token as an int (extracted from integrity PSID)

    :getter: :func:`get_integrity`
    :setter: :func:`set_integrity`
    """

    integrity = property(get_integrity, set_integrity, doc=_INTEGRITY_PROPERTY_DOC)

    ui_access = TokenUIAccess #: Alias for TokenUIAccess (type may change in the future for improved struct)

    VALID_TOKEN_POLICIES = gdef.FlagMapper(
        gdef.TOKEN_MANDATORY_POLICY_OFF,
        gdef.TOKEN_MANDATORY_POLICY_NO_WRITE_UP,
        gdef.TOKEN_MANDATORY_POLICY_NEW_PROCESS_MIN,
        gdef.TOKEN_MANDATORY_POLICY_VALID_MASK,
    )

    @property
    def mandatory_policy(self):
        """mandatory integrity access policy for the associated token

        :type: :class:`int` -- see `[MSDN] mandatory policy <https://docs.microsoft.com/en-us/windows/desktop/api/winnt/ns-winnt-_token_mandatory_policy>`_
        """
        return self.VALID_TOKEN_POLICIES[self.TokenMandatoryPolicy.Policy]

    @property
    def logon_sid(self):
        """The logon sid of the token. (Case of multiple logon sid not handled and will raise AssertionError)

        :type: :class:`windows.generated_def.winstructs.SID_AND_ATTRIBUTES`
        """
        rgroups = self.TokenLogonSid
        assert rgroups.GroupCount == 1, "More than 1 TokenLogonSid"
        return rgroups.Groups[0]

    is_appcontainer = TokenIsAppContainer #: Alias for TokenIsAppContainer (type may change in the future for improved struct)
    capabilities = TokenCapabilities #: Alias for TokenCapabilities (type may change in the future for improved struct)

    @property
    def appcontainer_sid(self):
        """The sid of the TokenAppContainerSid if present else ``None``

        :type: :class:`~windows.generated_def.winstructs.PSID`
        """
        sid = self.TokenAppContainerSid.TokenAppContainer
        if not sid: # NULL
            return None
        return sid

    appcontainer_number = TokenAppContainerNumber #: Alias for TokenAppContainerNumber (type may change in the future for improved struct)

    @property
    def security_attributes(self):
        """The security attributes of the token

        :type: [:class:`TokenSecurityAttributeV1`] - A list of token security attributes
        """
        return self.TokenSecurityAttributes.attributes


    ## Token Methods
    def duplicate(self, access_rigth=gdef.MAXIMUM_ALLOWED, attributes=None, type=None, impersonation_level=None):
        """Duplicate the token into a new :class:`Token`.

        :param type: The type of token: ``TokenPrimary(0x1L)`` or ``TokenImpersonation(0x2L)``
        :param impersonation_level: The :class:`~windows.generated_def.winstructs.SECURITY_IMPERSONATION_LEVEL` for a ``TokenImpersonation(0x2L)``:

            - If ``type`` is ``TokenPrimary(0x1L)`` this parameter is ignored if ``None`` or used as-is.
            - If ``type`` is ``TokenImpersonation(0x2L)`` and this parameter is None, ``self.impersonation_level`` is used.
            - If ``type`` is ``TokenImpersonation(0x2L)`` and our Token is a ``TokenPrimary(0x1L)`` this parameter MUST be provided

        :returns: :class:`Token` - The duplicate token

        Example:

            >>> tok
            <Token TokenId=0x39d6dde5 Type=TokenPrimary(0x1L)>
            >>> tok.duplicate()
            <Token TokenId=0x39d7b206 Type=TokenPrimary(0x1L)>
            >>> tok.duplicate(type=gdef.TokenImpersonation)
            ...
            ValueError: Duplicating a PrimaryToken as a TokenImpersonation require explicit <impersonation_level> parameter
            >>> tok.duplicate(type=gdef.TokenImpersonation, impersonation_level=gdef.SecurityImpersonation)
            <Token TokenId=0x39dadbf8 Type=TokenImpersonation(0x2L) ImpersonationLevel=SecurityImpersonation(0x2L)>
        """
        newtoken = gdef.HANDLE()
        if type is None:
            type = self.type
        if impersonation_level is None:
            if self.type == gdef.TokenImpersonation:
                impersonation_level = self.impersonation_level
            elif type != gdef.TokenImpersonation:
                impersonation_level = 0 #: ignored
            else:
                raise ValueError("Duplicating a PrimaryToken as a TokenImpersonation require explicit <impersonation_level> parameter")
        winproxy.DuplicateTokenEx(self.handle, access_rigth, attributes, impersonation_level, type, newtoken)
        return bltn_type(self)(newtoken.value)

    def adjust_privileges(self, privileges):
        """Adjust the token privileges according to ``privileges``.
        This API is the `complex one` to adjust multiple privileges at once.

        To simply enable one privilege see :func:`enable_privilege`.

        :param privileges: :class:`~windows.generated_def.winstructs.TOKEN_PRIVILEGES` (or subclass as :class:`TokenPrivileges`). To easily update your token privileges use the result of :data:`privileges`.

        Example:

            >>> tok = windows.current_process.token
            >>> privs = tok.privileges
            >>> privs["SeShutdownPrivilege"] = gdef.SE_PRIVILEGE_ENABLED
            >>> privs["SeUndockPrivilege"] = gdef.SE_PRIVILEGE_ENABLED
            >>> tok.adjust_privileges(privs)

        """
        buffsize = None
        if isinstance(privileges, TokenPrivilegesType):
            # The TokenPrivilegesType should come from a PTR via Improved buffer
            try:
                buffsize = privileges._b_base_.real_size
            except AttributeError as e:
                pass
        if buffsize is None:
            buffsize = ctypes.sizeof(privileges)
        winproxy.AdjustTokenPrivileges(self.handle, False, privileges, buffsize, None, None)
        if winproxy.GetLastError() == gdef.ERROR_NOT_ALL_ASSIGNED:
            # Transform this in a real WindowsError
            raise WindowsError(gdef.ERROR_NOT_ALL_ASSIGNED, "Failed to adjust all privileges")

    def enable_privilege(self, name):
        """Enable privilege ``name`` in the token

        :raises: :class:`ValueError` if :class:`Token` has no privilege ``name``
        """
        privs = self.privileges
        try:
            privs[name] = gdef.SE_PRIVILEGE_ENABLED
        except KeyError as e:
            # Emulate the WindowsError that would be triggered in 'adjust_privileges' ?
            raise ValueError("{0} has no privilege <{1}>".format(self, name))
        return self.adjust_privileges(privs)

    def __repr__(self):
        flag_repr = gdef.Flag.__repr__
        tid_int = int(self.TokenStatistics.TokenId)
        toktype = self.type
        if toktype == gdef.TokenPrimary:
            return "<{0} TokenId={1:#x} Type={2}>".format(type(self).__name__, tid_int, flag_repr(toktype))
        return "<{0} TokenId={1:#x} Type={2} ImpersonationLevel={3}>".format(type(self).__name__, tid_int, flag_repr(toktype), flag_repr(self.impersonation_level))
Ejemplo n.º 6
0
import ctypes
import functools

import windows
from windows import utils
from windows import winproxy
import windows.generated_def as gdef

bltn_type = type

KNOW_INTEGRITY_LEVEL = gdef.FlagMapper(
    gdef.SECURITY_MANDATORY_UNTRUSTED_RID,
    gdef.SECURITY_MANDATORY_LOW_RID,
    gdef.SECURITY_MANDATORY_MEDIUM_RID,
    gdef.SECURITY_MANDATORY_MEDIUM_PLUS_RID,
    gdef.SECURITY_MANDATORY_HIGH_RID,
    gdef.SECURITY_MANDATORY_SYSTEM_RID,
    gdef.SECURITY_MANDATORY_PROTECTED_PROCESS_RID
)

# Voodoo to fix lookup-strangeness in class declaration
def meta_craft(x):
    def partial_applier(infos_class, rtype):
        return property(functools.partial(x, infos_class=infos_class, rtype=rtype))
    return partial_applier


class TokenGroups(gdef.TOKEN_GROUPS):
    @property
    def _groups(self):
        return windows.utils.resized_array(self.Groups, self.GroupCount)
Ejemplo n.º 7
0
import ctypes
import sys

import windows
import windows.generated_def as gdef
from windows import winproxy
from windows.pycompat import basestring

from windows.winobject.token import Token, KNOW_INTEGRITY_LEVEL

# Specific access right

FILE_ACCESS_RIGHT = gdef.FlagMapper(gdef.FILE_READ_DATA, gdef.FILE_WRITE_DATA,
                                    gdef.FILE_APPEND_DATA, gdef.FILE_READ_EA,
                                    gdef.FILE_WRITE_EA, gdef.FILE_EXECUTE,
                                    gdef.FILE_READ_ATTRIBUTES,
                                    gdef.FILE_WRITE_ATTRIBUTES)

DIRECTORY_ACCESS_RIGHT = gdef.FlagMapper(
    gdef.FILE_LIST_DIRECTORY,
    gdef.FILE_ADD_FILE,
    gdef.FILE_ADD_SUBDIRECTORY,
    gdef.FILE_READ_EA,
    gdef.FILE_WRITE_EA,
    gdef.FILE_TRAVERSE,
    gdef.FILE_DELETE_CHILD,
    gdef.FILE_READ_ATTRIBUTES,
    gdef.FILE_WRITE_ATTRIBUTES,
)
NAMED_PIPE_ACCESS_RIGHT = gdef.FlagMapper(
    gdef.FILE_READ_DATA,
Ejemplo n.º 8
0
    CERT_E_MALFORMED,
    CERT_E_UNTRUSTEDROOT,
    CERT_E_CHAINING,
    TRUST_E_FAIL,
    CERT_E_REVOKED,
    CERT_E_UNTRUSTEDTESTROOT,
    CERT_E_REVOCATION_FAILURE,
    CERT_E_CN_NO_MATCH,
    CERT_E_WRONG_USAGE,
    TRUST_E_EXPLICIT_DISTRUST,
    CERT_E_UNTRUSTEDCA,
    CERT_E_INVALID_POLICY,
    CERT_E_INVALID_NAME,
    CRYPT_E_FILE_ERROR,
]
wintrust_return_value_mapper = gdef.FlagMapper(*wintrust_know_return_value)


def check_signature(filename):
    """Check if ``filename`` embeds a valid signature.

        :return: :class:`int`: ``0`` if ``filename`` have a valid signature else the error
    """
    file_data = WINTRUST_FILE_INFO()
    file_data.cbStruct = ctypes.sizeof(WINTRUST_FILE_INFO)
    file_data.pcwszFilePath = filename
    file_data.hFile = None
    file_data.pgKnownSubject = None

    WVTPolicyGUID = WINTRUST_ACTION_GENERIC_VERIFY_V2
Ejemplo n.º 9
0
    def get_datalen(self):
        return self.u1.s1.DataLength

    datalen = property(get_datalen, set_datalen)
    """The length of the data"""


KNOWN_ALPC_ATTRIBUTES = (gdef.ALPC_MESSAGE_SECURITY_ATTRIBUTE,
                         gdef.ALPC_MESSAGE_VIEW_ATTRIBUTE,
                         gdef.ALPC_MESSAGE_CONTEXT_ATTRIBUTE,
                         gdef.ALPC_MESSAGE_HANDLE_ATTRIBUTE,
                         gdef.ALPC_MESSAGE_TOKEN_ATTRIBUTE,
                         gdef.ALPC_MESSAGE_DIRECT_ATTRIBUTE,
                         gdef.ALPC_MESSAGE_WORK_ON_BEHALF_ATTRIBUTE)

KNOWN_ALPC_ATTRIBUTES_MAPPING = gdef.FlagMapper(*KNOWN_ALPC_ATTRIBUTES)


class MessageAttribute(gdef.ALPC_MESSAGE_ATTRIBUTES):
    """The attributes of an ALPC message"""
    ATTRIBUTE_BY_FLAG = [
        (gdef.ALPC_MESSAGE_SECURITY_ATTRIBUTE, gdef.ALPC_SECURITY_ATTR),
        (gdef.ALPC_MESSAGE_VIEW_ATTRIBUTE, gdef.ALPC_DATA_VIEW_ATTR),
        (gdef.ALPC_MESSAGE_CONTEXT_ATTRIBUTE, gdef.ALPC_CONTEXT_ATTR),
        (gdef.ALPC_MESSAGE_HANDLE_ATTRIBUTE, gdef.ALPC_HANDLE_ATTR),
        (gdef.ALPC_MESSAGE_TOKEN_ATTRIBUTE, gdef.ALPC_TOKEN_ATTR),
        (gdef.ALPC_MESSAGE_DIRECT_ATTRIBUTE, gdef.ALPC_DIRECT_ATTR),
        (gdef.ALPC_MESSAGE_WORK_ON_BEHALF_ATTRIBUTE,
         gdef.ALPC_WORK_ON_BEHALF_ATTR),
    ]
Ejemplo n.º 10
0
import ctypes
import struct

import windows.alpc as alpc
import windows.com
import windows.generated_def as gdef

if windows.pycompat.is_py3:
    buffer = bytes


KNOW_REQUEST_TYPE = gdef.FlagMapper(gdef.RPC_REQUEST_TYPE_CALL, gdef.RPC_REQUEST_TYPE_BIND)
KNOW_RESPONSE_TYPE = gdef.FlagMapper(gdef.RPC_RESPONSE_TYPE_FAIL, gdef.RPC_RESPONSE_TYPE_SUCCESS, gdef.RPC_RESPONSE_TYPE_BIND_OK)
KNOWN_RPC_ERROR_CODE = gdef.FlagMapper(
        gdef.ERROR_INVALID_HANDLE,
        gdef.RPC_X_BAD_STUB_DATA,
        gdef.RPC_S_UNKNOWN_IF,
        gdef.RPC_S_PROTOCOL_ERROR,
        gdef.RPC_S_UNSUPPORTED_TRANS_SYN,
        gdef.RPC_S_PROCNUM_OUT_OF_RANGE)

NOT_USED = 0xBAADF00D

class ALPC_RPC_BIND(ctypes.Structure):
    _pack_ = 1
    _fields_ = [
        ("request_type", gdef.DWORD),
        ("UNK1", gdef.DWORD),
        ("UNK2", gdef.DWORD),
        ("target", gdef.RPC_IF_ID),
        ("flags", gdef.DWORD),
Ejemplo n.º 11
0
CFGMGR32_ERRORS = gdef.FlagMapper(
    gdef.CR_SUCCESS,
    gdef.CR_DEFAULT,
    gdef.CR_OUT_OF_MEMORY,
    gdef.CR_INVALID_POINTER,
    gdef.CR_INVALID_FLAG,
    gdef.CR_INVALID_DEVNODE,
    gdef.CR_INVALID_DEVINST,
    gdef.CR_INVALID_RES_DES,
    gdef.CR_INVALID_LOG_CONF,
    gdef.CR_INVALID_ARBITRATOR,
    gdef.CR_INVALID_NODELIST,
    gdef.CR_DEVNODE_HAS_REQS,
    gdef.CR_DEVINST_HAS_REQS,
    gdef.CR_INVALID_RESOURCEID,
    gdef.CR_DLVXD_NOT_FOUND,
    gdef.CR_NO_SUCH_DEVNODE,
    gdef.CR_NO_SUCH_DEVINST,
    gdef.CR_NO_MORE_LOG_CONF,
    gdef.CR_NO_MORE_RES_DES,
    gdef.CR_ALREADY_SUCH_DEVNODE,
    gdef.CR_ALREADY_SUCH_DEVINST,
    gdef.CR_INVALID_RANGE_LIST,
    gdef.CR_INVALID_RANGE,
    gdef.CR_FAILURE,
    gdef.CR_NO_SUCH_LOGICAL_DEV,
    gdef.CR_CREATE_BLOCKED,
    gdef.CR_NOT_SYSTEM_VM,
    gdef.CR_REMOVE_VETOED,
    gdef.CR_APM_VETOED,
    gdef.CR_INVALID_LOAD_TYPE,
    gdef.CR_BUFFER_SMALL,
    gdef.CR_NO_ARBITRATOR,
    gdef.CR_NO_REGISTRY_HANDLE,
    gdef.CR_REGISTRY_ERROR,
    gdef.CR_INVALID_DEVICE_ID,
    gdef.CR_INVALID_DATA,
    gdef.CR_INVALID_API,
    gdef.CR_DEVLOADER_NOT_READY,
    gdef.CR_NEED_RESTART,
    gdef.CR_NO_MORE_HW_PROFILES,
    gdef.CR_DEVICE_NOT_THERE,
    gdef.CR_NO_SUCH_VALUE,
    gdef.CR_WRONG_TYPE,
    gdef.CR_INVALID_PRIORITY,
    gdef.CR_NOT_DISABLEABLE,
    gdef.CR_FREE_RESOURCES,
    gdef.CR_QUERY_VETOED,
    gdef.CR_CANT_SHARE_IRQ,
    gdef.CR_NO_DEPENDENT,
    gdef.CR_SAME_RESOURCES,
    gdef.CR_NO_SUCH_REGISTRY_KEY,
    gdef.CR_INVALID_MACHINENAME,
    gdef.CR_REMOTE_COMM_FAILURE,
    gdef.CR_MACHINE_UNAVAILABLE,
    gdef.CR_NO_CM_SERVICES,
    gdef.CR_ACCESS_DENIED,
    gdef.CR_CALL_NOT_IMPLEMENTED,
    gdef.CR_INVALID_PROPERTY,
    gdef.CR_DEVICE_INTERFACE_ACTIVE,
    gdef.CR_NO_SUCH_DEVICE_INTERFACE,
    gdef.CR_INVALID_REFERENCE_STRING,
    gdef.CR_INVALID_CONFLICT_LIST,
    gdef.CR_INVALID_INDEX,
    gdef.CR_INVALID_STRUCTURE_SIZE
)
Ejemplo n.º 12
0
        :type: [:class:`ResourceDescriptor`] -- A list of [:class:`ResourceDescriptor`]
        """
        return list(self.get_resources_for_type(gdef.ResType_All))

    def __repr__(self):
        return "<{0}>".format(type(self).__name__)


ResType_Mapper = gdef.FlagMapper(
    gdef.ResType_None,
    gdef.ResType_Mem,
    gdef.ResType_IO,
    gdef.ResType_DMA,
    gdef.ResType_IRQ,
    gdef.ResType_BusNumber,
    gdef.ResType_MemLarge,
    gdef.ResType_ClassSpecific,
    gdef.ResType_DevicePrivate,
    gdef.ResType_MfCardConfig,
    gdef.ResType_PcCardConfig,
)


class ResourceDescriptor(gdef.HANDLE):
    """Describe a resource allocated or reserved by a device instance.
    This class is a base class, all resources returned by :class:`LogicalConfiguration` should be one of the following:

        * :class:`ResourceNoType`
        * :class:`MemoryResource`
        * :class:`IoResource`
Ejemplo n.º 13
0
import ctypes
import sys

import windows
import windows.generated_def as gdef
from windows import winproxy

from windows.winobject.token import Token

# Specific access right

FILE_ACCESS_RIGHT = gdef.FlagMapper(gdef.FILE_READ_DATA, gdef.FILE_WRITE_DATA,
                                    gdef.FILE_APPEND_DATA, gdef.FILE_READ_EA,
                                    gdef.FILE_WRITE_EA, gdef.FILE_EXECUTE,
                                    gdef.FILE_READ_ATTRIBUTES,
                                    gdef.FILE_WRITE_ATTRIBUTES)

DIRECTORY_ACCESS_RIGHT = gdef.FlagMapper(
    gdef.FILE_LIST_DIRECTORY,
    gdef.FILE_ADD_FILE,
    gdef.FILE_ADD_SUBDIRECTORY,
    gdef.FILE_READ_EA,
    gdef.FILE_WRITE_EA,
    gdef.FILE_TRAVERSE,
    gdef.FILE_DELETE_CHILD,
    gdef.FILE_READ_ATTRIBUTES,
    gdef.FILE_WRITE_ATTRIBUTES,
)
NAMED_PIPE_ACCESS_RIGHT = gdef.FlagMapper(
    gdef.FILE_READ_DATA,
    gdef.FILE_WRITE_DATA,
Ejemplo n.º 14
0
class Certificate(gdef.CERT_CONTEXT):
    """Represent a Certificate """
    @property
    def raw_serial(self):
        """The raw serial number of the certificate.

        :type: [:class:`int`]: A list of int ``0 <= x <= 255``"""
        serial_number = self.pCertInfo[0].SerialNumber
        return [(c & 0xff)
                for c in serial_number.pbData[:serial_number.cbData][::-1]]

    @property
    def serial(self):
        """The string representation of the certificate's serial.

        :type: :class:`str`
        """
        serial_bytes = self.raw_serial
        return " ".join("{:02x}".format(x) for x in serial_bytes)

    def get_name(self,
                 nametype=gdef.CERT_NAME_SIMPLE_DISPLAY_TYPE,
                 param_type=0,
                 flags=0):
        """Retrieve the subject or issuer name of the certificate.
        See `CertGetNameStringA <https://msdn.microsoft.com/en-us/library/windows/desktop/aa376086(v=vs.85).aspx>`_

        :returns: :class:`str`
        """
        if nametype == gdef.CERT_NAME_RDN_TYPE:
            param_type = gdef.DWORD(param_type)
            param_type = gdef.LPDWORD(param_type)
        size = winproxy.CertGetNameStringA(self, nametype, flags, param_type,
                                           None, 0)
        namebuff = ctypes.c_buffer(size)
        size = winproxy.CertGetNameStringA(self, nametype, flags, param_type,
                                           namebuff, size)
        return namebuff[:-1]

    name = property(get_name)
    """The name of the certificate.

    :type: :class:`str`"""

    def raw_hash(self):
        size = gdef.DWORD(100)
        buffer = ctypes.c_buffer(size.value)
        winproxy.CryptHashCertificate(None, 0, 0, self.pbCertEncoded,
                                      self.cbCertEncoded,
                                      ctypes.cast(buffer, gdef.LPBYTE), size)
        return buffer[:size.value]

    @property
    def thumbprint(self):
        """The thumbprint of the certificate (which is the sha1 of the encoded cert).

        Example:

            >>> x
            <Certificate "YOLO2" serial="6f 1d 3e 7d d9 77 59 a9 4c 1c 53 dc 80 db 0c fe">
            >>> x.thumbprint
            'E2 A2 DB 76 A1 DD 8E 70 0D C6 9F CB 71 CF 29 12 C6 D9 78 97'

        :type: :class:`str`
        """
        return " ".join("{:02X}".format(x) for x in bytearray(self.raw_hash()))

    @property
    def distinguished_name(self):
        """The distinguished name (DN) of the certificate.

        Example:

            >>> x
            <Certificate "Microsoft Windows Production PCA 2011" serial="61 07 76 56 00 00 00 00 00 08">
            >>> x.distinguished_name
            'C=US, S=Washington, L=Redmond, O=Microsoft Corporation, CN=Microsoft Windows Production PCA 2011'

        :type: :class:`str`
        """
        return self.get_name(gdef.CERT_NAME_RDN_TYPE, gdef.CERT_X500_NAME_STR)

    @property
    def issuer(self):
        """The name of the certificate's issuer.

        :type: :class:`str`"""
        return self.get_name(flags=gdef.CERT_NAME_ISSUER_FLAG)

    @property
    def store(self):
        """The certificate store that contains the certificate

        :type: :class:`CertificateStore`
        """
        return CertificateStore(self.hCertStore)

    def get_raw_certificate_chains(self):  # Rename to all_chains ?
        chain_context = EPCCERT_CHAIN_CONTEXT()

        enhkey_usage = gdef.CERT_ENHKEY_USAGE()
        enhkey_usage.cUsageIdentifier = 0
        enhkey_usage.rgpszUsageIdentifier = None

        cert_usage = gdef.CERT_USAGE_MATCH()
        cert_usage.dwType = gdef.USAGE_MATCH_TYPE_AND
        cert_usage.Usage = enhkey_usage

        chain_para = gdef.CERT_CHAIN_PARA()
        chain_para.cbSize = ctypes.sizeof(chain_para)
        chain_para.RequestedUsage = cert_usage

        winproxy.CertGetCertificateChain(None, self, None, self.hCertStore,
                                         ctypes.byref(chain_para), 0, None,
                                         ctypes.byref(chain_context))
        # Lower chains ?
        # winproxy.CertGetCertificateChain(None, self, None, self[0].hCertStore, ctypes.byref(chain_para), 0x80, None, ctypes.byref(chain_context))
        #return CertficateChain(chain_context)
        return chain_context

    @property  # fixedproperty ?
    def chains(self):
        """The list of chain context available for this certificate. Each elements of this list is a list of ``Certificate`` that should
        go from the ``self`` certificate to a trusted certificate.

        :type: [[:class:`Certificate`]] -- A list of chain (list) of :class:`Certificate`
        """
        chain_context = self.get_raw_certificate_chains()
        res = []
        for chain in chain_context.chains:
            chain_res = [elt.cert for elt in chain.elements]
            res.append(chain_res)
        return res

    # API Arround CertSelectCertificateChains ?
    # https://msdn.microsoft.com/en-us/library/windows/desktop/dd433797(v=vs.85).aspx

    def duplicate(self):
        """Duplicate the certificate by incrementing the internal refcount. (see `CertDuplicateCertificateContext <https://msdn.microsoft.com/en-us/library/windows/desktop/aa376045(v=vs.85).aspx>`_)

        note: The object returned is ``self``

        :return: :class:`Certificate`
        """
        res = winproxy.CertDuplicateCertificateContext(self)
        # Check what the doc says: the pointer returned is actually the PCERT in parameter
        # Only the refcount is incremented
        # This postulate allow us to return 'self' directly
        # https://msdn.microsoft.com/en-us/library/windows/desktop/aa376045(v=vs.85).aspx
        if not ctypes.addressof(res[0]) == ctypes.addressof(self):
            raise ValueError(
                "CertDuplicateCertificateContext did not returned the argument (check doc)"
            )
        return self

    def view(self, title=None):
        return windows.winproxy.CryptUIDlgViewContext(
            gdef.CERT_STORE_CERTIFICATE_CONTEXT, ctypes.byref(self), None,
            title, 0, None)

    KNOWN_PROPERTIES_VALUES = gdef.FlagMapper(
        gdef.CERT_KEY_PROV_HANDLE_PROP_ID, gdef.CERT_KEY_PROV_INFO_PROP_ID,
        gdef.CERT_SHA1_HASH_PROP_ID, gdef.CERT_MD5_HASH_PROP_ID,
        gdef.CERT_HASH_PROP_ID, gdef.CERT_KEY_CONTEXT_PROP_ID,
        gdef.CERT_KEY_SPEC_PROP_ID, gdef.CERT_IE30_RESERVED_PROP_ID,
        gdef.CERT_PUBKEY_HASH_RESERVED_PROP_ID, gdef.CERT_ENHKEY_USAGE_PROP_ID,
        gdef.CERT_CTL_USAGE_PROP_ID, gdef.CERT_NEXT_UPDATE_LOCATION_PROP_ID,
        gdef.CERT_FRIENDLY_NAME_PROP_ID, gdef.CERT_PVK_FILE_PROP_ID,
        gdef.CERT_DESCRIPTION_PROP_ID, gdef.CERT_ACCESS_STATE_PROP_ID,
        gdef.CERT_SIGNATURE_HASH_PROP_ID, gdef.CERT_SMART_CARD_DATA_PROP_ID,
        gdef.CERT_EFS_PROP_ID, gdef.CERT_FORTEZZA_DATA_PROP_ID,
        gdef.CERT_ARCHIVED_PROP_ID, gdef.CERT_KEY_IDENTIFIER_PROP_ID,
        gdef.CERT_AUTO_ENROLL_PROP_ID, gdef.CERT_PUBKEY_ALG_PARA_PROP_ID,
        gdef.CERT_CROSS_CERT_DIST_POINTS_PROP_ID,
        gdef.CERT_ISSUER_PUBLIC_KEY_MD5_HASH_PROP_ID,
        gdef.CERT_SUBJECT_PUBLIC_KEY_MD5_HASH_PROP_ID,
        gdef.CERT_ENROLLMENT_PROP_ID, gdef.CERT_DATE_STAMP_PROP_ID,
        gdef.CERT_ISSUER_SERIAL_NUMBER_MD5_HASH_PROP_ID,
        gdef.CERT_SUBJECT_NAME_MD5_HASH_PROP_ID,
        gdef.CERT_EXTENDED_ERROR_INFO_PROP_ID, gdef.CERT_RENEWAL_PROP_ID,
        gdef.CERT_ARCHIVED_KEY_HASH_PROP_ID,
        gdef.CERT_AUTO_ENROLL_RETRY_PROP_ID,
        gdef.CERT_AIA_URL_RETRIEVED_PROP_ID,
        gdef.CERT_AUTHORITY_INFO_ACCESS_PROP_ID, gdef.CERT_BACKED_UP_PROP_ID,
        gdef.CERT_OCSP_RESPONSE_PROP_ID, gdef.CERT_REQUEST_ORIGINATOR_PROP_ID,
        gdef.CERT_SOURCE_LOCATION_PROP_ID)

    def enum_properties(self):
        prop = 0
        res = []
        while True:
            prop = winproxy.CertEnumCertificateContextProperties(self, prop)
            if not prop:
                return res
            res.append(self.KNOWN_PROPERTIES_VALUES[prop])
        raise RuntimeError("Unreachable code")

    properties = property(enum_properties)
    """The properties of the certificate

    :type: [:class:`int` or :class:`~windows.generated_def.Flag`] -- A list of property ID
    """

    #def get_property(self):
    # https://msdn.microsoft.com/en-us/library/windows/desktop/aa376079(v=vs.85).aspx
    # - Usefull:
    # CERT_SHA1_HASH_PROP_ID

    def get_property(self, prop):
        "TODO: DOC :D + auto-type ?"
        datasize = gdef.DWORD()
        windows.winproxy.CertGetCertificateContextProperty(
            self, prop, None, datasize)
        buf = (gdef.BYTE * datasize.value)()
        windows.winproxy.CertGetCertificateContextProperty(
            self, prop, buf, datasize)
        return bytearray(buf)

    @property
    def encoded(self):
        """The encoded certificate.

        :type: :class:`bytearray`"""
        return bytearray(self.pbCertEncoded[:self.cbCertEncoded])

    @property
    def version(self):
        """The version number of the certificate

        :type: :class:`int`
        """
        return self.pCertInfo[0].dwVersion

    @classmethod
    def from_file(cls, filename):
        """Create a :class:`Certificate` from the file ``filename``

        :return: :class:`Certificate`
        """
        with open(filename, "rb") as f:
            data = f.read()
            buf = (ctypes.c_ubyte * len(data))(*bytearray(data))
            pcert = windows.winproxy.CertCreateCertificateContext(
                windows.crypto.DEFAULT_ENCODING, buf, len(data))
            return cls.from_pointer(pcert)

    @classmethod
    def from_buffer(cls, data):
        """Create a :class:`Certificate` from the buffer ``data``

        :return: :class:`Certificate`
        """
        buf = (ctypes.c_ubyte * len(data))(*bytearray(data))
        pcert = windows.winproxy.CertCreateCertificateContext(
            windows.crypto.DEFAULT_ENCODING, buf, len(data))
        return cls.from_pointer(pcert)

    @classmethod
    def from_pointer(self, ptr):
        return ctypes.cast(ptr, ctypes.POINTER(Certificate))[0]

    def __eq__(self, other):
        if not isinstance(other, Certificate):
            return NotImplemented
        return windows.winproxy.CertCompareCertificate(DEFAULT_ENCODING,
                                                       self.pCertInfo,
                                                       other.pCertInfo)

    def __repr__(self):
        return '<{0} "{1}" serial="{2}">'.format(
            type(self).__name__, self.name, self.serial)
Ejemplo n.º 15
0
CRYPT_OBJECT_FORMAT_TYPE = [
    gdef.CERT_QUERY_OBJECT_FILE, gdef.CERT_QUERY_OBJECT_BLOB,
    gdef.CERT_QUERY_CONTENT_CERT, gdef.CERT_QUERY_CONTENT_CTL,
    gdef.CERT_QUERY_CONTENT_CRL, gdef.CERT_QUERY_CONTENT_SERIALIZED_STORE,
    gdef.CERT_QUERY_CONTENT_SERIALIZED_CERT,
    gdef.CERT_QUERY_CONTENT_SERIALIZED_CTL,
    gdef.CERT_QUERY_CONTENT_SERIALIZED_CRL,
    gdef.CERT_QUERY_CONTENT_PKCS7_SIGNED,
    gdef.CERT_QUERY_CONTENT_PKCS7_UNSIGNED,
    gdef.CERT_QUERY_CONTENT_PKCS7_SIGNED_EMBED, gdef.CERT_QUERY_CONTENT_PKCS10,
    gdef.CERT_QUERY_CONTENT_PFX, gdef.CERT_QUERY_CONTENT_CERT_PAIR,
    gdef.CERT_QUERY_CONTENT_PFX_AND_LOAD
]

CRYPT_OBJECT_FORMAT_TYPE_DICT = gdef.FlagMapper(*CRYPT_OBJECT_FORMAT_TYPE)

## Move CryptObject to new .py ?


class CryptObject(object):
    """Extract information from an CryptoAPI object.
    (see `CryptQueryObject <https://msdn.microsoft.com/en-us/library/windows/desktop/aa380264(v=vs.85).aspx>`_)

    Current main use is extracting the signers certificates from a PE file.
    """
    MSG_PARAM_KNOW_TYPES = {
        gdef.CMSG_SIGNER_INFO_PARAM: gdef.CMSG_SIGNER_INFO,
        gdef.CMSG_SIGNER_COUNT_PARAM: gdef.DWORD,
        gdef.CMSG_CERT_COUNT_PARAM: gdef.DWORD
    }
Ejemplo n.º 16
0
class System(object):
    """The state of the current ``Windows`` system ``Python`` is running on"""

    network = network.Network()
    """Object of class :class:`windows.winobject.network.Network`"""
    registry = registry.Registry()
    """Object of class :class:`windows.winobject.registry.Registry`"""
    @property
    def processes(self):
        """The list of running processes

        :type: [:class:`~windows.winobject.process.WinProcess`] -- A list of Process
		"""
        return self.enumerate_processes()

    @property
    def threads(self):
        """The list of running threads

        :type: [:class:`~windows.winobject.process.WinThread`] -- A list of Thread
		"""
        return self.enumerate_threads_setup_owners()

    @property
    def logicaldrives(self):
        """List of logical drives [C:\, ...]

        :type: [:class:`~windows.winobject.volume.LogicalDrive`] -- A list of LogicalDrive
        """
        return volume.enum_logical_drive()

    @property
    def services(self):
        """The list of services

        :type: [:class:`~windows.winobject.service.ServiceA`] -- A list of Service"""
        return service.enumerate_services()

    @property
    def handles(self):
        """The list of system handles

        :type: [:class:`~windows.winobject.handle.Handle`] -- A list of Hanlde"""
        return handle.enumerate_handles()

    @utils.fixedpropety
    def bitness(self):
        """The bitness of the system

        :type: :class:`int` -- 32 or 64
		"""
        if os.environ["PROCESSOR_ARCHITECTURE"].lower() != "x86":
            return 64
        if "PROCESSOR_ARCHITEW6432" in os.environ:
            return 64
        return 32

    @utils.fixedpropety
    def wmi(self):
        r"""An object to perform wmi requests to various namespaces

        :type: :class:`~windows.winobject.wmi.WmiManager`"""
        return wmi.WmiManager()

    #TODO: use GetComputerNameExA ? and recover other names ?
    @utils.fixedpropety
    def computer_name(self):
        """The name of the computer

        :type: :class:`str`
        """
        size = DWORD(0x1000)
        buf = ctypes.c_buffer(size.value)
        winproxy.GetComputerNameA(buf, ctypes.byref(size))
        return buf[:size.value]

    @utils.fixedpropety
    def version(self):
        """The version of the system

        :type: (:class:`int`, :class:`int`) -- (Major, Minor)
        """
        data = self.get_version()
        result = data.dwMajorVersion, data.dwMinorVersion
        if result == (6, 2):
            result_str = self.get_file_version("kernel32")
            result_tup = [int(x) for x in result_str.split(".")]
            result = tuple(result_tup[:2])
        return result

    @utils.fixedpropety
    def version_name(self):
        """The name of the system version,  values are:

            * Windows Server 2016
            * Windows 10
            * Windows Server 2012 R2
            * Windows 8.1
            * Windows Server 2012
            * Windows 8
            * Windows Server 2008
            * Windows 7
            * Windows Server 2008
            * Windows Vista
            * Windows XP Professional x64 Edition
            * TODO: version (5.2) + is_workstation + bitness == 32 (don't even know if possible..)
            * Windows Server 2003 R2
            * Windows Server 2003
            * Windows XP
            * Windows 2000
            * "Unknow Windows <version={0} | is_workstation={1}>".format(version, is_workstation)

        :type: :class:`str`
        """
        version = self.version
        is_workstation = self.product_type == VER_NT_WORKSTATION
        if version == (10, 0):
            return ["Windows Server 2016", "Windows 10"][is_workstation]
        elif version == (6, 3):
            return ["Windows Server 2012 R2", "Windows 8.1"][is_workstation]
        elif version == (6, 2):
            return ["Windows Server 2012", "Windows 8"][is_workstation]
        elif version == (6, 1):
            return ["Windows Server 2008 R2", "Windows 7"][is_workstation]
        elif version == (6, 0):
            return ["Windows Server 2008", "Windows Vista"][is_workstation]
        elif version == (5, 2):
            metric = winproxy.GetSystemMetrics(SM_SERVERR2)
            if is_workstation:
                if self.bitness == 64:
                    return "Windows XP Professional x64 Edition"
                else:
                    return "TODO: version (5.2) + is_workstation + bitness == 32"
            elif metric != 0:
                return "Windows Server 2003 R2"
            else:
                return "Windows Server 2003"
        elif version == (5, 1):
            return "Windows XP"
        elif version == (5, 0):
            return "Windows 2000"
        else:
            return "Unknow Windows <version={0} | is_workstation={1}>".format(
                version, is_workstation)

    VERSION_MAPPER = gdef.FlagMapper(VER_NT_WORKSTATION,
                                     VER_NT_DOMAIN_CONTROLLER, VER_NT_SERVER)

    @utils.fixedpropety
    def product_type(self):
        """The product type, value might be:

            * VER_NT_WORKSTATION(0x1L)
            * VER_NT_DOMAIN_CONTROLLER(0x2L)
            * VER_NT_SERVER(0x3L)

        :type: :class:`long` or :class:`int` (or subclass)
        """
        version = self.get_version()
        return self.VERSION_MAPPER[version.wProductType]

    @utils.fixedpropety
    def windir(self):
        buffer = ctypes.c_buffer(0x100)
        reslen = winproxy.GetWindowsDirectoryA(buffer)
        return buffer[:reslen]

    def get_version(self):
        data = windows.generated_def.OSVERSIONINFOEXA()
        data.dwOSVersionInfoSize = ctypes.sizeof(data)
        winproxy.GetVersionExA(
            ctypes.cast(ctypes.pointer(data),
                        ctypes.POINTER(windows.generated_def.OSVERSIONINFOA)))
        return data

    def get_file_version(self, name):
        size = winproxy.GetFileVersionInfoSizeA(name)
        buf = ctypes.c_buffer(size)
        winproxy.GetFileVersionInfoA(name, 0, size, buf)

        bufptr = PVOID()
        bufsize = UINT()
        winproxy.VerQueryValueA(buf, "\\VarFileInfo\\Translation",
                                ctypes.byref(bufptr), ctypes.byref(bufsize))
        bufstr = ctypes.cast(bufptr, LPCSTR)
        tup = struct.unpack("<HH", bufstr.value[:4])
        req = "{0:04x}{1:04x}".format(*tup)
        winproxy.VerQueryValueA(
            buf, "\\StringFileInfo\\{0}\\ProductVersion".format(req),
            ctypes.byref(bufptr), ctypes.byref(bufsize))
        bufstr = ctypes.cast(bufptr, LPCSTR)
        return bufstr.value

    @utils.fixedpropety
    def build_number(self):
        # This returns the last version where ntdll was updated
        # Should look at HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion
        # values:  CurrentBuild + UBR
        return self.get_file_version("comctl32")

    @staticmethod
    def enumerate_processes():
        dbgprint("Enumerating processes with CreateToolhelp32Snapshot", "SLOW")
        process_entry = PROCESSENTRY32()
        process_entry.dwSize = ctypes.sizeof(process_entry)
        snap = winproxy.CreateToolhelp32Snapshot(gdef.TH32CS_SNAPPROCESS, 0)
        winproxy.Process32First(snap, process_entry)
        res = []
        res.append(process.WinProcess._from_PROCESSENTRY32(process_entry))
        while winproxy.Process32Next(snap, process_entry):
            res.append(process.WinProcess._from_PROCESSENTRY32(process_entry))
        winproxy.CloseHandle(snap)
        return res

    @staticmethod
    def enumerate_threads_generator():
        # Ptet dangereux, parce que on yield la meme THREADENTRY32 a chaque fois
        dbgprint(
            "Enumerating threads with CreateToolhelp32Snapshot <generator>",
            "SLOW")
        thread_entry = THREADENTRY32()
        thread_entry.dwSize = ctypes.sizeof(thread_entry)
        snap = winproxy.CreateToolhelp32Snapshot(gdef.TH32CS_SNAPTHREAD, 0)
        dbgprint(
            "New handle CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD) <generator> | {0:#x}"
            .format(snap), "HANDLE")
        try:
            winproxy.Thread32First(snap, thread_entry)
            yield thread_entry
            while winproxy.Thread32Next(snap, thread_entry):
                yield thread_entry
        finally:
            winproxy.CloseHandle(snap)
        dbgprint(
            "CLOSE CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD) <generator> | {0:#x}"
            .format(snap), "HANDLE")

    @staticmethod
    def enumerate_threads():
        return [
            WinThread._from_THREADENTRY32(th)
            for th in System.enumerate_threads_generator()
        ]

    def enumerate_threads_setup_owners(self):
        # Enumerating threads is a special operation concerning the owner process.
        # We may not be able to retrieve the name of the owning process by normal way
        # (as we need to get a handle on the process)
        # So, this implementation of enumerate_thread also setup the owner with the result of enumerate_processes
        dbgprint(
            "Enumerating threads with CreateToolhelp32Snapshot and setup owner",
            "SLOW")

        # One snap for both enum to be prevent race
        snap = winproxy.CreateToolhelp32Snapshot(
            gdef.TH32CS_SNAPTHREAD | gdef.TH32CS_SNAPPROCESS, 0)

        process_entry = PROCESSENTRY32()
        process_entry.dwSize = ctypes.sizeof(process_entry)
        winproxy.Process32First(snap, process_entry)
        processes = []
        processes.append(
            process.WinProcess._from_PROCESSENTRY32(process_entry))
        while winproxy.Process32Next(snap, process_entry):
            processes.append(
                process.WinProcess._from_PROCESSENTRY32(process_entry))

        # Forge a dict pid -> process
        proc_dict = {proc.pid: proc for proc in processes}

        thread_entry = THREADENTRY32()
        thread_entry.dwSize = ctypes.sizeof(thread_entry)
        threads = []
        winproxy.Thread32First(snap, thread_entry)
        parent = proc_dict[thread_entry.th32OwnerProcessID]
        threads.append(
            process.WinThread._from_THREADENTRY32(thread_entry, owner=parent))
        while winproxy.Thread32Next(snap, thread_entry):
            parent = proc_dict[thread_entry.th32OwnerProcessID]
            threads.append(
                process.WinThread._from_THREADENTRY32(thread_entry,
                                                      owner=parent))
        winproxy.CloseHandle(snap)
        return threads