diff --git a/TODO b/TODO index 32e034c..4b26f8f 100644 --- a/TODO +++ b/TODO @@ -6,6 +6,14 @@ TODO: - Document / fix / release: - windows.bits - window +- WMI + - verif samples + - add create_process sample to doc + - rewrite / check doc + samples +- Token + - Finish code + - samples + - doc :) ====== @@ -42,9 +50,8 @@ TODO: - winobject\exception.py - large part could be rewritten with ctypes-generation extended-def - - add winobject/window.py + winobject/kernobj.py to System() - - Some test/doc on both - + - add winobject/window.py + - Some test/doc - wintrust doc: add : https://blogs.msdn.microsoft.com/winsdk/2016/01/05/why-cryptcatadmincalchashfromfilehandle-fails-with-a-seemingly-unexpected-error-code/ diff --git a/windows/utils/__init__.py b/windows/utils/__init__.py index 5f666fc..32bb007 100644 --- a/windows/utils/__init__.py +++ b/windows/utils/__init__.py @@ -1,2 +1,3 @@ from pythonutils import * from winutils import * +from improved_buffer import * diff --git a/windows/utils/improved_buffer.py b/windows/utils/improved_buffer.py new file mode 100644 index 0000000..46b1875 --- /dev/null +++ b/windows/utils/improved_buffer.py @@ -0,0 +1,127 @@ +import ctypes +import _ctypes +import windows.generated_def as gdef + +## TESTING Improved Buffer code ### +## This code is not stable and WILL CHANGE ## +## Do not use for now :) ## + +# Uses cases: + # Simple buffer + # String / Wstring / Bytes + # Resize array in struct + # Typed buffer : filed call & contains X struct S + # Having a ptr on struct with a buffer > sizeof(struct) + # Autocreate a good-typed buffer from a tuple of ctypes objects + + # On peut vouloir creer un buffer avec 12 elts de type X + # Ou creer un buffer avec 12 elt de type X mais une sub-size de 1000 + +class ImprovedCtypesBufferBase(object): + def cast(self, type): + return ctypes.cast(self, type) + + def as_string(self): + return ctypes.cast(self, gdef.LPCSTR).value + + def as_wstring(self): + return ctypes.cast(self, gdef.LPWSTR).value + + def as_pvoid(self): + return self.cast(gdef.PVOID) + + # Constructor + @classmethod + def from_size(cls, size): + raw_buffer = ctypes.c_buffer(size) + buffer = cls.from_buffer(raw_buffer) + buffer._raw_buffer_ = raw_buffer + return buffer + + @property + def real_size(self): + real_buffer = getattr(self, "_raw_buffer_", self) + return ctypes.sizeof(real_buffer) + + def __new__(cls, *args, **kwargs): + if "size" in kwargs: + buff = ctypes.create_string_buffer(kwargs["size"]) + self = cls.from_buffer(buff) + self._raw_buffer_ = buff + return self + # Add a '_raw_buffer_' even when no explicit size ? + return super(ImprovedCtypesBufferBase, cls).__new__(cls, *args, **kwargs) + + +# Used in windows.crypto.sign_verify for test +class PartialBufferType(object): + def __init__(self, type, nbelt=None): + self.type = type + self.nbelt = None + + @staticmethod + def create_real_implem(item_type, nbelt): + if isinstance(nbelt, long): + nbelt = int(nbelt) + assert isinstance(nbelt, int) + cls_name = "TypedBuffer<{0}><{1}>".format(item_type.__name__, nbelt) + + class TmpImplemArrayName(ImprovedCtypesBufferBase, ctypes.Array): + _type_ = item_type + _length_ = nbelt + + TmpImplemArrayName.__name__ = cls_name + return TmpImplemArrayName + + def from_buffer(self, buffer): # size as kwargs ? + if len(buffer) % ctypes.sizeof(self.type): + raise NotImplementedError("Buffer size of not a multiple of sizeof({0})".format(self.type.__name__)) + nbelt = len(buffer) / ctypes.sizeof(self.type) + return self.create_real_implem(self.type, nbelt).from_buffer(buffer) + + def from_buffer_copy(self, buffer): # size as kwargs ? + if len(buffer) % ctypes.sizeof(self.type): + raise NotImplementedError("Buffer size of not a multiple of sizeof({0})".format(self.type.__name__)) + nbelt = len(buffer) / ctypes.sizeof(self.type) + return self.create_real_implem(self.type, nbelt).from_buffer_copy(buffer) + + def create(self, nbelt): + return self.create_real_implem(self.type, nbelt) + + def __mul__(self, nbelt): + return self.create_real_implem(self.type, nbelt) + + def __call__(self, *args, **kwargs): + if len(args) == 1: # String magic: explode string as arg + if isinstance(args[0], basestring): + args = args[0] + nbelt = kwargs.get("nbelt", max(len(args), 1)) + return self.create_real_implem(self.type, nbelt)(*args, **kwargs) + +# # Expose these predefined types ? +# CharBuffer = PartialBufferType(gdef.CHAR) +# WCharBuffer = PartialBufferType(gdef.WCHAR) +# ByteBuffer = PartialBufferType(gdef.BYTE) + + +def BUFFER(type, nbelt=None): + if nbelt is None: + return PartialBufferType(type) # Allow user to create custom sized buffer + return PartialBufferType.create_real_implem(type, int(nbelt)) + +def buffer(obj, eltclass=None): + if eltclass is None: # Guess + obj = list(obj) + item = obj[0] + eltclass = type(item) # All object must have the same type + dlen = len(obj) + return BUFFER(eltclass, dlen)(*obj) + +def resized_array(array, newnbelt): + btype = buffer_type(array._type_, newnbelt) + new_array = btype.from_address(ctypes.addressof(array)) + new_array._base_array_ = array # Keep a ref to prevent some gc + return new_array + + + diff --git a/windows/utils/pythonutils.py b/windows/utils/pythonutils.py index 0cd19f9..03444da 100644 --- a/windows/utils/pythonutils.py +++ b/windows/utils/pythonutils.py @@ -8,86 +8,6 @@ from windows.dbgprint import dbgprint from windows import winproxy -## TESTING Improved Buffer code ### - -class ImprovedCtypesBufferBase(object): - def cast(self, type): - return ctypes.cast(self, type) - - def as_string(self): - return ctypes.cast(self, LPCSTR).value - - def as_wstring(self): - return ctypes.cast(self, LPWSTR).value - - def as_pvoid(self): - return self.cast(gdef.PVOID) - -def buffer(size): # Test: DONT USE - raise NotImplementedError("utils.buffer") - buf = ctypes.create_string_buffer(size) - buf.size = size - buf.address = ctypes.addressof(buf) - - class ImprovedCtypesBufferImpl(ctypes.Array): - _length_ = size - _type_ = ctypes.c_char - def lol(self): - return "lol" - - return ImprovedCtypesBufferImpl() - - -def wbuffer(size): # Test: DONT USE - raise NotImplementedError("utils.buffer") - buf = ctypes.create_string_buffer(size) - buf.size = size - buf.address = ctypes.addressof(buf) - - class ImprovedCtypesBufferImpl(ctypes.Array): - _length_ = size - _type_ = ctypes.c_wchar - def lol(self): - return "lol" - - return ImprovedCtypesBufferImpl() - -# Used in windows.crypto.sign_verify for test -class PartialBufferType(object): - def __init__(self, type, size=None): - self.type = type - self.size = None - - @staticmethod - def create_real_implem(item_type, size): - cls_name = "YOLO<{0}><{1}>".format(item_type.__name__, size) - - class TmpImplemArrayName(ctypes.Array, ImprovedCtypesBufferBase): - _type_ = item_type - _length_ = size - - TmpImplemArrayName.__name__ = cls_name - return TmpImplemArrayName - - def from_buffer(self, buffer): - return self.create_real_implem(self.type, len(buffer)).from_buffer(buffer) - - def from_buffer_copy(self, buffer): - return self.create_real_implem(self.type, len(buffer)).from_buffer_copy(buffer) - - def __call__(self, *args): - return self.create_real_implem(self.type, len(args))(*args) - -CharBuffer = PartialBufferType(gdef.CHAR) -# CharBuffer vs CharString that append the +1 ? - -def buffer(type, size=None): - if size is None: - return PartialBufferType(type) - return PartialBufferType.create_real_implem(type, size) - - -### Other utils ### def fixedpropety(f): cache_name = "_" + f.__name__ @@ -106,7 +26,15 @@ def transform_ctypes_fields(struct, replacement): return [(name, replacement.get(name, type)) for name, type in struct._fields_] -def print_ctypes_struct(struct, name="", ident=0, hexa=False): +def print_ctypes_struct(struct, name="", hexa=False): + sprint_method = getattr(struct, "__sprint__", None) + if sprint_method is not None: + # Allow function to accept 'hexa' param + # But handle function that don't, So we can just do: + # __sprint__ = __repr__ + print("{0} -> {1}".format(name, sprint_method())) + return + if isinstance(struct, _ctypes._Pointer): if ctypes.cast(struct, ctypes.c_void_p).value is None: print("{0} -> NULL".format(name))