mirror of
https://github.com/hakril/PythonForWindows
synced 2026-06-08 14:31:45 +00:00
Added some docstrings
This commit is contained in:
+14
-3
@@ -890,6 +890,17 @@ class SecurityDescriptor(gdef.PSECURITY_DESCRIPTOR):
|
||||
flags |= gdef.SACL_SECURITY_INFORMATION
|
||||
winproxy.SetNamedSecurityInfoW(filename, gdef.SE_FILE_OBJECT, flags, self.owner, self.group, self.dacl, self.sacl)
|
||||
|
||||
def to_handle(self, handle, flags=0):
|
||||
if not flags:
|
||||
if self.owner:
|
||||
flags |= gdef.OWNER_SECURITY_INFORMATION
|
||||
if self.group:
|
||||
flags |= gdef.GROUP_SECURITY_INFORMATION
|
||||
if self.dacl:
|
||||
flags |= gdef.DACL_SECURITY_INFORMATION
|
||||
if self.sacl:
|
||||
flags |= gdef.SACL_SECURITY_INFORMATION
|
||||
self._apply_to_handle_and_type(handle, gdef.SE_FILE_OBJECT, flags)
|
||||
|
||||
@classmethod
|
||||
def from_service(cls, filename, query_sacl=False, flags=SERVICE_SECURITY_INFORMATION):
|
||||
@@ -978,11 +989,11 @@ def explain_mask(mask, sdtype):
|
||||
def explain_simple_ace(ace, sdtype):
|
||||
yield u"Type:"
|
||||
yield u" " + str(ace.Header.AceType)
|
||||
yield u"Flags:"
|
||||
yield u" {0:#x}".format(ace.Header.AceFlags)
|
||||
yield u"Flags: {0:#x}".format(ace.Header.AceFlags)
|
||||
yield u" {0}".format(ace.Header.flags)
|
||||
yield u"SID:"
|
||||
yield u" " + explain_sid(ace.sid)
|
||||
yield u"Mask:"
|
||||
yield u"Mask: {0:#x}".format(ace.Mask)
|
||||
mapper = windows.security.SPECIFIC_ACCESS_RIGTH_BY_TYPE[sdtype]
|
||||
yield u" " + str(list(mapper[x] for x in ace.mask))
|
||||
|
||||
|
||||
@@ -214,6 +214,11 @@ class EvtEvent(EvtHandle):
|
||||
"""The provider of the event"""
|
||||
return self.system_values()[gdef.EvtSystemProviderName]
|
||||
|
||||
@property
|
||||
def computer(self):
|
||||
"""The computer that generated the event"""
|
||||
return self.system_values()[gdef.EvtSystemComputer]
|
||||
|
||||
@property
|
||||
def id(self):
|
||||
"""The ID of the Event"""
|
||||
@@ -249,6 +254,16 @@ class EvtEvent(EvtHandle):
|
||||
"""The process ID of the Event"""
|
||||
return self.value("Event/System/Execution/@ThreadID")
|
||||
|
||||
@property
|
||||
def error_payload(self):
|
||||
raw = self.value("Event/ProcessingErrorData/EventPayload")
|
||||
return bytearray(raw) if raw is not None else None
|
||||
|
||||
@property
|
||||
def user(self):
|
||||
"""The User ID associated with the Event"""
|
||||
return self.system_values()[gdef.EvtSystemUserID]
|
||||
|
||||
@property
|
||||
def metadata(self):
|
||||
"""The medata for the current Event
|
||||
@@ -276,6 +291,45 @@ class EvtEvent(EvtHandle):
|
||||
event_data_name = (i["name"] for i in self.metadata.event_data if i["type"] == "data")
|
||||
return {k:v for k,v in zip(event_data_name, self.event_values())}
|
||||
|
||||
def xml_data(self):
|
||||
xmlevt = xml.dom.minidom.parseString(self.render_xml())
|
||||
res = {}
|
||||
|
||||
eventdata = xmlevt.getElementsByTagName("EventData")
|
||||
if eventdata:
|
||||
# <Data Name='FIELD_NAME'>FIELD_VALUE</Data>
|
||||
for i, datanode in enumerate(xmlevt.getElementsByTagName("Data")):
|
||||
name = datanode.getAttribute("Name")
|
||||
if not name:
|
||||
# Some Data in old EVTX have no name (Windows Powershell)
|
||||
# Do the best we can by using the position of the event
|
||||
name = str(i)
|
||||
|
||||
if datanode.hasChildNodes():
|
||||
value = datanode.firstChild.nodeValue
|
||||
else:
|
||||
value = ""
|
||||
if not (name not in res):
|
||||
import pdb;pdb.set_trace()
|
||||
res[name] = value
|
||||
userdata = xmlevt.getElementsByTagName("UserData")
|
||||
if userdata:
|
||||
# <UserData>
|
||||
# <EventXML xmlns="Event_NS">
|
||||
# <FIELD_NAME>FIELD_VALUE</FIELD_NAME>
|
||||
# </EventXML>
|
||||
# </UserData>
|
||||
for datanode in userdata[0].firstChild.childNodes:
|
||||
name = datanode.tagName
|
||||
if datanode.hasChildNodes():
|
||||
value = datanode.firstChild.nodeValue
|
||||
else:
|
||||
value = ""
|
||||
assert name not in res
|
||||
res[name] = value
|
||||
return res
|
||||
|
||||
|
||||
@property
|
||||
def date(self):
|
||||
"""``Event.time_created`` as a :class:``datetime``"""
|
||||
|
||||
@@ -51,6 +51,8 @@ class EventRecord(gdef.EVENT_RECORD):
|
||||
|
||||
@property
|
||||
def context(self):
|
||||
if self.UserContext is None:
|
||||
return None
|
||||
return ctypes.py_object.from_address(self.UserContext).value
|
||||
|
||||
@property
|
||||
@@ -74,12 +76,17 @@ class EventRecord(gdef.EVENT_RECORD):
|
||||
PEventRecord = ctypes.POINTER(EventRecord)
|
||||
|
||||
class EventTraceProperties(gdef.EVENT_TRACE_PROPERTIES):
|
||||
"""Represent an Event Trace session that may exist or now. (https://docs.microsoft.com/en-us/windows/win32/api/evntrace/ns-evntrace-event_trace_properties)
|
||||
|
||||
This class is widly used by :class:`EtwTrace`
|
||||
"""
|
||||
# Test: ascii / Use Wchar ?
|
||||
FULL_SIZE = ctypes.sizeof(gdef.EVENT_TRACE_PROPERTIES) + MAX_SESSION_NAME_LEN_W + MAX_LOGFILE_PATH_LEN_W
|
||||
|
||||
# def alloc(cls, size) ?
|
||||
@classmethod
|
||||
def create(cls):
|
||||
"""Initialize a new :class:`EventTraceProperties`"""
|
||||
buff = windows.utils.BUFFER(cls)(size=cls.FULL_SIZE)
|
||||
# ctypes.memset(buff, "\x00", cls.FULL_SIZE)
|
||||
self = buff[0]
|
||||
@@ -92,14 +99,13 @@ class EventTraceProperties(gdef.EVENT_TRACE_PROPERTIES):
|
||||
assert self.LogFileNameOffset
|
||||
return windows.current_process.read_string(ctypes.addressof(self) + self.LogFileNameOffset)
|
||||
|
||||
|
||||
def set_logfilename(self, filename):
|
||||
assert self.LogFileNameOffset
|
||||
if not filename.endswith("\x00"):
|
||||
filename += "\x00"
|
||||
return windows.current_process.write_memory(ctypes.addressof(self) + self.LogFileNameOffset, filename)
|
||||
|
||||
logfile = property(get_logfilename, set_logfilename)
|
||||
logfile = property(get_logfilename, set_logfilename) #: The logfile associated with the session
|
||||
|
||||
def get_logger_name(self):
|
||||
assert self.LoggerNameOffset
|
||||
@@ -112,17 +118,23 @@ class EventTraceProperties(gdef.EVENT_TRACE_PROPERTIES):
|
||||
filename += "\x00"
|
||||
return windows.current_process.write_memory(ctypes.addressof(self) + self.LoggerNameOffset, filename)
|
||||
|
||||
name = property(get_logger_name, set_logfilename)
|
||||
name = property(get_logger_name, set_logfilename) #: The name of the session
|
||||
|
||||
@property
|
||||
def guid(self):
|
||||
"""The GUID of the Event Trace session (see ``Wnode.Guid``)"""
|
||||
return self.Wnode.Guid
|
||||
|
||||
@property
|
||||
def id(self):
|
||||
"""LoggerId"""
|
||||
"""The LoggerId if the session (see ``Wnode.HistoricalContext``)"""
|
||||
return self.Wnode.HistoricalContext
|
||||
|
||||
|
||||
def __repr__(self):
|
||||
return """<{0} name="{1}" guid={2}>""".format(type(self).__name__, self.name, self.guid)
|
||||
|
||||
|
||||
# GUID setter ?
|
||||
|
||||
class CtxProcess(object):
|
||||
@@ -154,15 +166,17 @@ class CtxProcess(object):
|
||||
|
||||
|
||||
class EtwTrace(object):
|
||||
"""Represent an ETW Trace for tracing/processing events"""
|
||||
def __init__(self, name, logfile=None, guid=None):
|
||||
self.name = windows.pycompat.raw_encode(name)
|
||||
self.logfile = logfile
|
||||
self.name = windows.pycompat.raw_encode(name) #: The name of the trace
|
||||
self.logfile = logfile #: The logging file of the trace (``None`` means real time trace)
|
||||
if guid and isinstance(guid, basestring):
|
||||
guid = gdef.GUID.from_string(guid)
|
||||
self.guid = guid
|
||||
self.guid = guid #: The guid of the trace
|
||||
self.handle = 0
|
||||
|
||||
def exists(self):
|
||||
"""Return ``True`` if the trace already exist (based on its name)"""
|
||||
prop = EventTraceProperties.create()
|
||||
try:
|
||||
windows.winproxy.ControlTraceA(self.handle, self.name, prop, gdef.EVENT_TRACE_CONTROL_QUERY)
|
||||
@@ -173,6 +187,7 @@ class EtwTrace(object):
|
||||
return True
|
||||
|
||||
def start(self, flags=0):
|
||||
"""Start the tracing"""
|
||||
prop = EventTraceProperties.create()
|
||||
prop.NumberOfBuffers = 42
|
||||
prop.EnableFlags = flags
|
||||
@@ -189,6 +204,11 @@ class EtwTrace(object):
|
||||
self.handle = handle
|
||||
|
||||
def stop(self, soft=False): # Change name
|
||||
"""stop the tracing.
|
||||
|
||||
``soft`` will allow to stop a non-existing trace that do not exists/run.
|
||||
This allow for simpler script that stop/start some EtwTrace.
|
||||
"""
|
||||
prop = EventTraceProperties.create()
|
||||
try:
|
||||
windows.winproxy.ControlTraceA(0, self.name, prop, gdef.EVENT_TRACE_CONTROL_STOP)
|
||||
@@ -199,16 +219,19 @@ class EtwTrace(object):
|
||||
return True
|
||||
|
||||
def flush(self):
|
||||
"""Flush the trace"""
|
||||
prop = EventTraceProperties.create()
|
||||
windows.winproxy.ControlTraceA(0, self.name, prop, gdef.EVENT_TRACE_CONTROL_FLUSH)
|
||||
|
||||
|
||||
def enable(self, guid, flags=0xff, level=0xff):
|
||||
"""Enable the specified event trace provider."""
|
||||
if isinstance(guid, basestring):
|
||||
guid = gdef.GUID.from_string(guid)
|
||||
return windows.winproxy.EnableTrace(1, flags, level, guid, self.handle) # EnableTraceEx ?
|
||||
|
||||
def enable_ex(self, guid, flags=0xff, level=0xff, any_keyword = 0xffffffff, all_keyword=0x00):
|
||||
"""Enable the specified event trace provider."""
|
||||
if isinstance(guid, basestring):
|
||||
guid = gdef.GUID.from_string(guid)
|
||||
|
||||
@@ -223,6 +246,17 @@ class EtwTrace(object):
|
||||
|
||||
|
||||
def process(self, callback, begin=None, end=None, context=None):
|
||||
"""Process the event retrieved by the trace.
|
||||
This function will call ``callback`` with any :class:`EventRecord` in the trace.
|
||||
``begin/end`` allow to filter and only process events in a given timeframe.
|
||||
|
||||
.. warning::
|
||||
|
||||
If the trace if ``REALTIME`` (no logfile) this function will hang/process new event until the trace is stopped.
|
||||
|
||||
Using ``logman -ets stop TRACE_NAME`` for exemple.
|
||||
|
||||
"""
|
||||
if end == "now":
|
||||
end = gdef.FILETIME()
|
||||
windows.winproxy.GetSystemTimeAsFileTime(end)
|
||||
@@ -272,11 +306,19 @@ class EtwTrace(object):
|
||||
return """<{0} name={1!r} logfile={2!r}>""".format(type(self).__name__, self.name, self.logfile)
|
||||
|
||||
class TraceProvider(object):
|
||||
"""Represent a ETW provider, which is just a GUID.
|
||||
Corresponding name for a provider may be available trhought WMI.
|
||||
"""
|
||||
def __init__(self, guid):
|
||||
self.guid = guid
|
||||
|
||||
@property
|
||||
def infos(self):
|
||||
"""The :class:`TraceGuidInfo` associated with the provider.
|
||||
Main use is to retrieve the instances of the provider (directly available with ``instances``)
|
||||
|
||||
:type: :class:`TraceGuidInfo`
|
||||
"""
|
||||
size = gdef.DWORD()
|
||||
info_buffer = ctypes.c_buffer(0x1000)
|
||||
try:
|
||||
@@ -293,6 +335,10 @@ class TraceProvider(object):
|
||||
# Our trace providers should be able to directly returns its instances
|
||||
@property
|
||||
def instances(self):
|
||||
"""The instances of the provider.
|
||||
|
||||
:type: [:class:`TraceProviderInstanceInfo`] -- A list of :class:`TraceProviderInstanceInfo`
|
||||
"""
|
||||
return self.infos.instances
|
||||
|
||||
def __repr__(self):
|
||||
@@ -300,6 +346,10 @@ class TraceProvider(object):
|
||||
|
||||
|
||||
class TraceGuidInfo(gdef.TRACE_GUID_INFO):
|
||||
"""Defines the header to the list of sessions that enabled the provider
|
||||
(see https://docs.microsoft.com/en-us/windows/win32/api/evntrace/ns-evntrace-trace_guid_info)
|
||||
"""
|
||||
|
||||
@classmethod
|
||||
def from_raw_buffer(cls, buffer):
|
||||
self = cls.from_buffer(buffer)
|
||||
@@ -317,6 +367,10 @@ class TraceGuidInfo(gdef.TRACE_GUID_INFO):
|
||||
|
||||
@property
|
||||
def instances(self):
|
||||
"""The instances of the provider.
|
||||
|
||||
:type: [:class:`TraceProviderInstanceInfo`] -- A list of :class:`TraceProviderInstanceInfo`
|
||||
"""
|
||||
return [x for x in self._instance_generator()]
|
||||
|
||||
def __repr__(self):
|
||||
@@ -324,6 +378,9 @@ class TraceGuidInfo(gdef.TRACE_GUID_INFO):
|
||||
|
||||
|
||||
class TraceProviderInstanceInfo(gdef.TRACE_PROVIDER_INSTANCE_INFO):
|
||||
"""Defines an instance of the provider
|
||||
(see https://docs.microsoft.com/en-us/windows/win32/api/evntrace/ns-evntrace-trace_provider_instance_info)
|
||||
"""
|
||||
@classmethod
|
||||
def from_raw_buffer(cls, buffer, offset):
|
||||
self = cls.from_buffer(buffer, offset)
|
||||
@@ -340,6 +397,10 @@ class TraceProviderInstanceInfo(gdef.TRACE_PROVIDER_INSTANCE_INFO):
|
||||
|
||||
@property
|
||||
def sessions(self):
|
||||
"""The sessions for the instance
|
||||
|
||||
:type: [:class:`~windows.generated_def.winstructs.TRACE_ENABLE_INFO`] -- A list of session
|
||||
"""
|
||||
return [x for x in self._instance_generator()]
|
||||
|
||||
def __repr__(self):
|
||||
@@ -347,8 +408,14 @@ class TraceProviderInstanceInfo(gdef.TRACE_PROVIDER_INSTANCE_INFO):
|
||||
|
||||
|
||||
class EtwManager(object):
|
||||
"""An object to query ETW session/providers and open new trace"""
|
||||
|
||||
@property
|
||||
def sessions(self):
|
||||
"""The list of currently active ETW session.
|
||||
|
||||
:type: [:class:`EventTraceProperties`] -- A list of :class:`EventTraceProperties`
|
||||
"""
|
||||
# Create a tuple of MAX_ETW_SESSIONS EventTraceProperties ptr
|
||||
t = [EventTraceProperties.create() for _ in range(MAX_ETW_SESSIONS)]
|
||||
# Put this in a ctypes array
|
||||
@@ -362,12 +429,20 @@ class EtwManager(object):
|
||||
|
||||
@property
|
||||
def providers(self):
|
||||
"""The list of currently existing ETW providers.
|
||||
|
||||
:type: [:class:`TraceProvider`] -- A list of ETW providers
|
||||
"""
|
||||
buffer = windows.utils.BUFFER(gdef.GUID, 0x1000)()
|
||||
size = gdef.DWORD()
|
||||
windows.winproxy.EnumerateTraceGuidsEx(gdef.TraceGuidQueryList, None, 0, buffer, buffer.real_size, size)
|
||||
return [TraceProvider(g) for g in buffer[:size.value / ctypes.sizeof(gdef.GUID)]]
|
||||
return [TraceProvider(g) for g in buffer[:size.value // ctypes.sizeof(gdef.GUID)]]
|
||||
|
||||
|
||||
# Temp name / API ?
|
||||
def open_trace(self, name=None, logfile=None, guid=None):
|
||||
"""Open a new ETW Trace
|
||||
|
||||
:return: :class:`EtwTrace`
|
||||
"""
|
||||
return EtwTrace(name, logfile, guid)
|
||||
@@ -107,10 +107,18 @@ class System(object):
|
||||
|
||||
@utils.fixedpropety
|
||||
def event_log(self):
|
||||
"""An object to open Event channel/publisher and evtx file
|
||||
|
||||
:type: :class:`~windows.winobject.event_log.EvtlogManager`
|
||||
"""
|
||||
return event_log.EvtlogManager()
|
||||
|
||||
@utils.fixedpropety
|
||||
def etw(self):
|
||||
"""An object to interact with ETW (Event Tracing for Windows)
|
||||
|
||||
:type: :class:`~windows.winobject.event_trace.EtwManager`
|
||||
"""
|
||||
return event_trace.EtwManager()
|
||||
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ import windows
|
||||
from windows import utils
|
||||
from windows import winproxy
|
||||
import windows.generated_def as gdef
|
||||
# import windows.security # at the end of this file (loop import)
|
||||
|
||||
bltn_type = type
|
||||
|
||||
@@ -308,7 +309,6 @@ class Token(utils.AutoHandle):
|
||||
|
||||
: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) ??
|
||||
@@ -618,3 +618,6 @@ class Token(utils.AutoHandle):
|
||||
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))
|
||||
|
||||
|
||||
import windows.security
|
||||
|
||||
@@ -2,7 +2,7 @@ import ctypes
|
||||
import windows.generated_def as gdef
|
||||
|
||||
from ..apiproxy import ApiProxy, NeededParameter
|
||||
from ..error import fail_on_zero, succeed_on_zero, result_is_error_code, result_is_handle, no_error_check
|
||||
from ..error import fail_on_zero, succeed_on_zero, result_is_error_code, result_is_handle, no_error_check, result_is_ntstatus
|
||||
|
||||
class Advapi32Proxy(ApiProxy):
|
||||
APIDLL = "advapi32"
|
||||
@@ -588,4 +588,41 @@ def TraceEvent(SessionHandle, EventTrace):
|
||||
|
||||
@Advapi32Proxy(error_check=result_is_handle)
|
||||
def GetTraceLoggerHandle(Buffer):
|
||||
return GetTraceLoggerHandle.ctypes_function(Buffer)
|
||||
return GetTraceLoggerHandle.ctypes_function(Buffer)
|
||||
|
||||
|
||||
# Lsa APIs
|
||||
@Advapi32Proxy(error_check=result_is_ntstatus)
|
||||
def LsaOpenPolicy(SystemName=None, ObjectAttributes=None, DesiredAccess=NeededParameter, PolicyHandle=NeededParameter):
|
||||
if ObjectAttributes is None:
|
||||
ObjectAttributes = gdef.LSA_OBJECT_ATTRIBUTES()
|
||||
return LsaOpenPolicy.ctypes_function(SystemName, ObjectAttributes, DesiredAccess, PolicyHandle)
|
||||
|
||||
@Advapi32Proxy(error_check=result_is_ntstatus)
|
||||
def LsaQueryInformationPolicy(PolicyHandle, InformationClass, Buffer):
|
||||
return LsaQueryInformationPolicy.ctypes_function(PolicyHandle, InformationClass, Buffer)
|
||||
|
||||
@Advapi32Proxy(error_check=result_is_ntstatus)
|
||||
def LsaClose(ObjectHandle):
|
||||
return LsaClose.ctypes_function(ObjectHandle)
|
||||
|
||||
@Advapi32Proxy(error_check=result_is_ntstatus)
|
||||
def LsaNtStatusToWinError(Status):
|
||||
return LsaNtStatusToWinError.ctypes_function(Status)
|
||||
|
||||
@Advapi32Proxy(error_check=result_is_ntstatus)
|
||||
def LsaLookupNames(PolicyHandle, Count, Names, ReferencedDomains, Sids):
|
||||
return LsaLookupNames.ctypes_function(PolicyHandle, Count, Names, ReferencedDomains, Sids)
|
||||
|
||||
@Advapi32Proxy(error_check=result_is_ntstatus)
|
||||
def LsaLookupNames2(PolicyHandle, Flags, Count, Names, ReferencedDomains, Sids):
|
||||
return LsaLookupNames2.ctypes_function(PolicyHandle, Flags, Count, Names, ReferencedDomains, Sids)
|
||||
|
||||
@Advapi32Proxy(error_check=result_is_ntstatus)
|
||||
def LsaLookupSids(PolicyHandle, Count, Sids, ReferencedDomains, Names):
|
||||
return LsaLookupSids.ctypes_function(PolicyHandle, Count, Sids, ReferencedDomains, Names)
|
||||
|
||||
@Advapi32Proxy(error_check=result_is_ntstatus)
|
||||
def LsaLookupSids2(PolicyHandle, LookupOptions, Count, Sids, ReferencedDomains, Names):
|
||||
return LsaLookupSids2.ctypes_function(PolicyHandle, LookupOptions, Count, Sids, ReferencedDomains, Names)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user