diff --git a/qiling/os/struct.py b/qiling/os/struct.py index c723eb172..777443e06 100644 --- a/qiling/os/struct.py +++ b/qiling/os/struct.py @@ -122,7 +122,7 @@ def __setattr__(self, name: str, value: Any) -> None: ftype = _fields[name] # transform value into field bytes and write them to memory - fvalue = ftype(*value) if hasattr(ftype, '_length_') else ftype(value) + fvalue = ftype(*value) if hasattr(ftype, '_length_') and not hasattr(ftype, 'is_wrapper') else ftype(value) data = bytes(fvalue) mem.write(address + field.offset, data) @@ -130,7 +130,10 @@ def __setattr__(self, name: str, value: Any) -> None: # proceed to set the value to the structure in order to maintain consistency with ctypes.Structure # set attribute value - super().__setattr__(name, value) + if hasattr(ftype, 'is_wrapper'): + super().__setattr__(name, ftype(value)) + else: + super().__setattr__(name, value) return VolatileStructRef() diff --git a/qiling/os/windows/structs.py b/qiling/os/windows/structs.py index 71aed2d74..6f157c0df 100644 --- a/qiling/os/windows/structs.py +++ b/qiling/os/windows/structs.py @@ -14,11 +14,30 @@ from qiling.exception import QlErrorNotImplemented from .wdk_const import IRP_MJ_MAXIMUM_FUNCTION, PROCESSOR_FEATURE_MAX +class c_wchar_14(ctypes.c_ubyte * 30): + is_wrapper = True + def __init__(self, string: str): + null_terminated_bytes = [x for x in string.encode('utf-16le')] + null_terminated_bytes.extend([0, 0]) + super().__init__(*null_terminated_bytes) + +class c_wchar_128(ctypes.c_ubyte * 258): + is_wrapper = True + def __init__(self, string: str): + null_terminated_bytes = [x for x in string.encode('utf-16le')] + null_terminated_bytes.extend([0, 0]) + super().__init__(*null_terminated_bytes) + +class c_wchar_max_path(ctypes.c_ubyte * (MAX_PATH * 2 + 2)): + is_wrapper = True + def __init__(self, string: str): + null_terminated_bytes = [x for x in string.encode('utf-16le')] + null_terminated_bytes.extend([0, 0]) + super().__init__(*null_terminated_bytes) def make_teb(archbits: int): """Generate a TEB structure class. """ - native_type = struct.get_native_type(archbits) Struct = struct.get_aligned_struct(archbits) @@ -202,7 +221,7 @@ class KUSER_SHARED_DATA(struct.BaseStructEL): ('TimeZoneBias', KSYSTEM_TIME), ('ImageNumberLow', ctypes.c_uint16), ('ImageNumberHigh', ctypes.c_uint16), - ('NtSystemRoot', ctypes.c_wchar * MAX_PATH), + ('NtSystemRoot', c_wchar_max_path), ('MaxStackTraceDepth', ctypes.c_uint32), ('CryptoExponent', ctypes.c_uint32), ('TimeZoneId', ctypes.c_uint32), @@ -1050,7 +1069,7 @@ class PROCESS_BASIC_INFORMATION(Struct): def make_os_version_info(archbits: int, *, wide: bool): Struct = struct.get_aligned_struct(archbits) - char_type = (ctypes.c_wchar if wide else ctypes.c_char) + char_type = (c_wchar_128 if wide else ctypes.c_char * 128) class OSVERSIONINFO(Struct): _fields_ = ( @@ -1059,7 +1078,7 @@ class OSVERSIONINFO(Struct): ('dwMinorVersion', ctypes.c_uint32), ('dwBuildNumber', ctypes.c_uint32), ('dwPlatformId', ctypes.c_uint32), - ('szCSDVersion', char_type * 128) + ('szCSDVersion', char_type) ) return OSVERSIONINFO @@ -1069,7 +1088,7 @@ class OSVERSIONINFO(Struct): def make_os_version_info_ex(archbits: int, *, wide: bool): Struct = struct.get_aligned_struct(archbits) - char_type = (ctypes.c_wchar if wide else ctypes.c_char) + char_type = (c_wchar_128 if wide else ctypes.c_char * 128) class OSVERSIONINFOEX(Struct): _fields_ = ( @@ -1078,7 +1097,7 @@ class OSVERSIONINFOEX(Struct): ('dwMinorVersion', ctypes.c_uint32), ('dwBuildNumber', ctypes.c_uint32), ('dwPlatformId', ctypes.c_uint32), - ('szCSDVersion', char_type * 128), + ('szCSDVersion', char_type), ('wServicePackMajor', ctypes.c_uint16), ('wServicePackMinor', ctypes.c_uint16), ('wSuiteMask', ctypes.c_uint16), @@ -1521,7 +1540,8 @@ class OBJECT_ALL_TYPES_INFORMATION(Struct): def make_win32_find_data(archbits: int, *, wide: bool): Struct = struct.get_aligned_struct(archbits) - char_type = (ctypes.c_wchar if wide else ctypes.c_char) + filename = c_wchar_max_path if wide else ctypes.c_char * MAX_PATH + alternateFileName = c_wchar_14 if wide else ctypes.c_char * 14 class WIN32_FIND_DATA(Struct): _fields_ = ( @@ -1533,8 +1553,8 @@ class WIN32_FIND_DATA(Struct): ('nFileSizeLow', ctypes.c_uint32), ('dwReserved0', ctypes.c_uint32), ('dwReserved1', ctypes.c_uint32), - ('cFileName', char_type * MAX_PATH), - ('cAlternateFileName', char_type * 14), + ('cFileName', filename), + ('cAlternateFileName', alternateFileName), ('dwFileType', ctypes.c_uint32), ('dwCreatorType', ctypes.c_uint32), ('wFinderFlags', ctypes.c_uint16)