Skip to content

Commit 9977863

Browse files
committed
Redefine WIN32_FIND_DATA as a BaseStruct
1 parent d0f477e commit 9977863

2 files changed

Lines changed: 67 additions & 108 deletions

File tree

qiling/os/windows/dlls/kernel32/fileapi.py

Lines changed: 43 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
from qiling.os.windows.const import *
1616
from qiling.os.windows.fncc import *
1717
from qiling.os.windows.handle import Handle
18-
from qiling.os.windows.structs import Win32FindData
18+
from qiling.os.windows.structs import FILETIME, make_win32_find_data
1919

2020
# DWORD GetFileType(
2121
# HANDLE hFile
@@ -46,50 +46,67 @@ def hook_FindFirstFileA(ql: Qiling, address: int, params):
4646
filename = params['lpFileName']
4747
pointer = params['lpFindFileData']
4848

49-
if filename == 0:
49+
if not filename:
5050
return INVALID_HANDLE_VALUE
51-
elif len(filename) >= MAX_PATH:
51+
52+
if len(filename) >= MAX_PATH:
5253
return ERROR_INVALID_PARAMETER
5354

54-
target_dir = os.path.join(ql.rootfs, filename.replace("\\", os.sep))
55-
ql.log.info('TARGET_DIR = %s' % target_dir)
56-
real_path = ql.os.path.transform_to_real_path(filename)
55+
host_path = ql.os.path.virtual_to_host_path(filename)
5756

5857
# Verify the directory is in ql.rootfs to ensure no path traversal has taken place
59-
if not os.path.exists(real_path):
58+
if not ql.os.path.is_safe_host_path(host_path):
6059
ql.os.last_error = ERROR_FILE_NOT_FOUND
60+
6161
return INVALID_HANDLE_VALUE
6262

6363
# Check if path exists
6464
filesize = 0
65+
6566
try:
66-
f = ql.os.fs_mapper.open(real_path, "r")
67-
filesize = os.path.getsize(real_path)
67+
f = ql.os.fs_mapper.open(host_path, "r")
68+
69+
filesize = os.path.getsize(host_path)
6870
except FileNotFoundError:
6971
ql.os.last_error = ERROR_FILE_NOT_FOUND
70-
return INVALID_HANDLE_VALUE
7172

72-
# Get size of the file
73-
file_size_low = filesize & 0xffffff
74-
file_size_high = filesize >> 32
73+
return INVALID_HANDLE_VALUE
7574

7675
# Create a handle for the path
7776
new_handle = Handle(obj=f)
7877
ql.os.handle_manager.append(new_handle)
7978

80-
# Spoof filetime values
81-
filetime = ql.pack64(datetime.now().microsecond)
82-
83-
find_data = Win32FindData(
84-
ql,
85-
FILE_ATTRIBUTE_NORMAL,
86-
filetime, filetime, filetime,
87-
file_size_high, file_size_low,
88-
0, 0,
89-
filename,
90-
0, 0, 0, 0,)
91-
92-
find_data.write(pointer)
79+
# calculate file time
80+
epoch = datetime(1601, 1, 1)
81+
elapsed = datetime.now() - epoch
82+
83+
# number of 100-nanosecond intervals since Jan 1, 1601 utc
84+
# where: (10 ** 9) / 100 -> (10 ** 7)
85+
hnano = int(elapsed.total_seconds() * (10 ** 7))
86+
87+
mask = (1 << 32) - 1
88+
89+
ftime = FILETIME(
90+
(hnano >> 0) & mask,
91+
(hnano >> 32) & mask
92+
)
93+
94+
fdata_struct = make_win32_find_data(ql.arch.bits, wide=False)
95+
96+
with fdata_struct.ref(ql.mem, pointer) as fdata_obj:
97+
fdata_obj.dwFileAttributes = FILE_ATTRIBUTE_NORMAL
98+
fdata_obj.ftCreationTime = ftime
99+
fdata_obj.ftLastAccessTime = ftime
100+
fdata_obj.ftLastWriteTime = ftime
101+
fdata_obj.nFileSizeHigh = (filesize >> 32) & mask
102+
fdata_obj.nFileSizeLow = (filesize >> 0) & mask
103+
fdata_obj.dwReserved0 = 0
104+
fdata_obj.dwReserved1 = 0
105+
fdata_obj.cFileName = filename
106+
fdata_obj.cAlternateFileName = 0
107+
fdata_obj.dwFileType = 0
108+
fdata_obj.dwCreatorType = 0
109+
fdata_obj.wFinderFlags = 0
93110

94111
return new_handle.id
95112

qiling/os/windows/structs.py

Lines changed: 24 additions & 82 deletions
Original file line numberDiff line numberDiff line change
@@ -1634,85 +1634,27 @@ class OBJECT_ALL_TYPES_INFORMATION(Struct):
16341634
return OBJECT_ALL_TYPES_INFORMATION
16351635

16361636

1637-
# typedef struct _WIN32_FIND_DATAA {
1638-
# DWORD dwFileAttributes;
1639-
# FILETIME ftCreationTime;
1640-
# FILETIME ftLastAccessTime;
1641-
# FILETIME ftLastWriteTime;
1642-
# DWORD nFileSizeHigh;
1643-
# DWORD nFileSizeLow;
1644-
# DWORD dwReserved0;
1645-
# DWORD dwReserved1;
1646-
# CHAR cFileName[MAX_PATH];
1647-
# CHAR cAlternateFileName[14];
1648-
# DWORD dwFileType;
1649-
# DWORD dwCreatorType;
1650-
# WORD wFinderFlags;
1651-
# } WIN32_FIND_DATAA, *PWIN32_FIND_DATAA, *LPWIN32_FIND_DATAA;
1652-
class Win32FindData(WindowsStruct):
1653-
def write(self, addr):
1654-
super().generic_write(addr,
1655-
[
1656-
self.file_attributes, self.creation_time,
1657-
self.last_acces_time, self.last_write_time,
1658-
self.file_size_high, self.file_size_low,
1659-
self.reserved_0, self.reserved_1, self.file_name,
1660-
self.alternate_file_name, self.file_type,
1661-
self.creator_type, self.finder_flags
1662-
])
1663-
1664-
def read(self, addr):
1665-
super().generic_read(addr,
1666-
[
1667-
self.file_attributes, self.creation_time,
1668-
self.last_acces_time, self.last_write_time,
1669-
self.file_size_high, self.file_size_low,
1670-
self.reserved_0, self.reserved_1, self.file_name,
1671-
self.alternate_file_name, self.file_type,
1672-
self.creator_type, self.finder_flags
1673-
])
1674-
1675-
def __init__(self,
1676-
ql,
1677-
file_attributes=None,
1678-
creation_time=None,
1679-
last_acces_time=None,
1680-
last_write_time=None,
1681-
file_size_high=None,
1682-
file_size_low=None,
1683-
reserved_0=None,
1684-
reserved_1=None,
1685-
file_name=None,
1686-
alternate_filename=None,
1687-
file_type=None,
1688-
creator_type=None,
1689-
finder_flags=None):
1690-
super().__init__(ql)
1691-
1692-
# Size of FileTime == 2*(DWORD)
1693-
self.size = (
1694-
self.DWORD_SIZE # dwFileAttributes
1695-
+ (3 * (2 * self.DWORD_SIZE)) # ftCreationTime, ftLastAccessTime, ftLastWriteTime
1696-
+ self.DWORD_SIZE # nFileSizeHigh
1697-
+ self.DWORD_SIZE # nFileSizeLow
1698-
+ self.DWORD_SIZE # dwReservered0
1699-
+ self.DWORD_SIZE # dwReservered1
1700-
+ (self.BYTE_SIZE * 260) # cFileName[MAX_PATH]
1701-
+ (self.BYTE_SIZE * 14) # cAlternateFileName[14]
1702-
+ self.DWORD_SIZE # dwFileType
1703-
+ self.DWORD_SIZE # dwCreatorType
1704-
+ self.WORD_SIZE) # wFinderFlags
1705-
1706-
self.file_attributes = file_attributes
1707-
self.creation_time = creation_time
1708-
self.last_acces_time = last_acces_time
1709-
self.last_write_time = last_write_time
1710-
self.file_size_high = file_size_high
1711-
self.file_size_low = file_size_low
1712-
self.reserved_0 = reserved_0
1713-
self.reserved_1 = reserved_1
1714-
self.file_name = file_name
1715-
self.alternate_file_name = alternate_filename
1716-
self.file_type = file_type
1717-
self.creator_type = creator_type
1718-
self.finder_flags = finder_flags
1637+
# https://docs.microsoft.com/en-us/windows/win32/api/minwinbase/ns-minwinbase-win32_find_dataw
1638+
def make_win32_find_data(archbits: int, *, wide: bool):
1639+
Struct = struct.get_aligned_struct(archbits)
1640+
1641+
char_type = (ctypes.c_wchar if wide else ctypes.c_char)
1642+
1643+
class WIN32_FIND_DATA(Struct):
1644+
_fields_ = (
1645+
('dwFileAttributes', ctypes.c_uint32),
1646+
('ftCreationTime', FILETIME),
1647+
('ftLastAccessTime', FILETIME),
1648+
('ftLastWriteTime', FILETIME),
1649+
('nFileSizeHigh', ctypes.c_uint32),
1650+
('nFileSizeLow', ctypes.c_uint32),
1651+
('dwReserved0', ctypes.c_uint32),
1652+
('dwReserved1', ctypes.c_uint32),
1653+
('cFileName', char_type * MAX_PATH),
1654+
('cAlternateFileName', char_type * 14),
1655+
('dwFileType', ctypes.c_uint32),
1656+
('dwCreatorType', ctypes.c_uint32),
1657+
('wFinderFlags', ctypes.c_uint16)
1658+
)
1659+
1660+
return WIN32_FIND_DATA

0 commit comments

Comments
 (0)