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:`process.WinProcess`] -- A list of Process """ return self.enumerate_processes() @property def threads(self): """The list of running threads :type: [:class:`process.WinThread`] -- A list of Thread """ return self.enumerate_threads() @property def logicaldrives(self): """List of logical drives [C:\, ...] :type: [:class:`volume.LogicalDrive`] -- A list of LogicalDrive """ return volume.enum_logical_drive() @property def services(self): """The list of services :type: [:class:`service.ServiceA`] -- A list of Service""" return service.enumerate_services() @property def handles(self): """The list of system handles :type: [:class:`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 request to "root\\cimv2" :type: :class:`windows.winobject.wmi.WmiRequester`""" return wmi.WmiRequester() #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) @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_map = {x:x for x in [VER_NT_WORKSTATION, VER_NT_DOMAIN_CONTROLLER, VER_NT_SERVER]} version = self.get_version() return version_map.get(version.wProductType, version.wProductType) 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 @staticmethod def enumerate_processes(): process_entry = PROCESSENTRY32() process_entry.dwSize = ctypes.sizeof(process_entry) snap = winproxy.CreateToolhelp32Snapshot(windef.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)) return res @staticmethod def enumerate_threads(): thread_entry = process.WinThread() thread_entry.dwSize = ctypes.sizeof(thread_entry) snap = winproxy.CreateToolhelp32Snapshot(windef.TH32CS_SNAPTHREAD, 0) threads = [] winproxy.Thread32First(snap, thread_entry) threads.append(copy.copy(thread_entry)) while winproxy.Thread32Next(snap, thread_entry): threads.append(copy.copy(thread_entry)) return threads
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
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:`process.WinProcess`] -- A list of Process """ return self.enumerate_processes() @property def threads(self): """The list of running threads :type: [:class:`process.WinThread`] -- A list of Thread """ return self.enumerate_threads_setup_owners() @property def logicaldrives(self): """List of logical drives [C:\, ...] :type: [:class:`volume.LogicalDrive`] -- A list of LogicalDrive """ return volume.enum_logical_drive() @property def services(self): """The list of services :type: [:class:`service.ServiceA`] -- A list of Service""" return service.enumerate_services() @property def handles(self): """The list of system handles :type: [:class:`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 request to "root\\cimv2" :type: :class:`windows.winobject.wmi.WmiRequester`""" return wmi.WmiRequester() #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) @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_map = { x: x for x in [VER_NT_WORKSTATION, VER_NT_DOMAIN_CONTROLLER, VER_NT_SERVER] } version = self.get_version() return version_map.get(version.wProductType, 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): return self.get_file_version("ntdll") @staticmethod def enumerate_processes(): dbgprint("Enumerating processes with CreateToolhelp32Snapshot", "SLOW") process_entry = PROCESSENTRY32() process_entry.dwSize = ctypes.sizeof(process_entry) snap = winproxy.CreateToolhelp32Snapshot(windef.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(windef.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( windef.TH32CS_SNAPTHREAD | windef.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