Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix wchar array encoding in structs #1348

Open
wants to merge 5 commits into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions qiling/os/struct.py
Original file line number Diff line number Diff line change
Expand Up @@ -122,15 +122,18 @@ 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)

# 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()

Expand Down
38 changes: 29 additions & 9 deletions qiling/os/windows/structs.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down Expand Up @@ -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),
Expand Down Expand Up @@ -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_ = (
Expand All @@ -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
Expand All @@ -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_ = (
Expand All @@ -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),
Expand Down Expand Up @@ -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_ = (
Expand All @@ -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)
Expand Down