Skip to content

Commit 35db51a

Browse files
authored
Merge pull request #885 from crass/win-file-opts-16bit
Add windows 16bit compatibility file api
2 parents cb7be68 + 1ddbe6d commit 35db51a

File tree

4 files changed

+159
-1
lines changed

4 files changed

+159
-1
lines changed

ChangeLog

+1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ This file details the changelog of Qiling Framework.
77
- Added more Posix syscall
88
- Bugfix: GDB server on MIPS binary
99
- Major refactor of Windows DLL
10+
- Add Win32 16bit compatibility file api
1011

1112

1213
------------------------------------

qiling/os/windows/api.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
ACCESS_MASK = INT
2121
BOOLEAN = INT
2222
GROUP = INT
23+
HFILE = INT
2324
OBJECT_INFORMATION_CLASS = INT
2425
PROCESSINFOCLASS = INT
2526
SOCKET = INT
@@ -157,4 +158,4 @@
157158
REFIID = POINTER
158159
REGSAM = POINTER
159160
UINT_PTR = POINTER
160-
ULONG_PTR = POINTER
161+
ULONG_PTR = POINTER

qiling/os/windows/const.py

+19
Original file line numberDiff line numberDiff line change
@@ -687,3 +687,22 @@
687687
# https://docs.microsoft.com/en-us/windows/win32/api/handleapi/nf-handleapi-sethandleinformation
688688
HANDLE_FLAG_INHERIT = 0x1
689689
HANDLE_FLAG_PROTECT_FROM_CLOSE = 0x2
690+
691+
# https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-openfile
692+
OF_READ = 0x00000000
693+
OF_WRITE = 0x00000001
694+
OF_READWRITE = 0x00000002
695+
OF_PARSE = 0x00000100
696+
OF_DELETE = 0x00000200
697+
OF_VERIFY = 0x00000400
698+
OF_CANCEL = 0x00000800
699+
OF_CREATE = 0x00001000
700+
OF_PROMPT = 0x00002000
701+
OF_EXIST = 0x00004000
702+
OF_REOPEN = 0x00008000
703+
704+
OF_SHARE_COMPAT = 0x00000000
705+
OF_SHARE_EXCLUSIVE = 0x00000010
706+
OF_SHARE_DENY_WRITE = 0x00000020
707+
OF_SHARE_DENY_READ = 0x00000030
708+
OF_SHARE_DENY_NONE = 0x00000040

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

+137
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
# Cross Platform and Multi Architecture Advanced Binary Emulation Framework
44
#
55

6+
import os
67
import configparser
78

89
from qiling import Qiling
@@ -13,6 +14,142 @@
1314
from qiling.os.windows.structs import OsVersionInfoExA
1415
from qiling.os.windows.utils import cmp
1516

17+
# HFILE _lclose(
18+
# HFILE hFile
19+
# );
20+
@winsdkapi(cc=STDCALL, params={
21+
'hFile' : HFILE
22+
})
23+
def hook__lclose(ql: Qiling, address: int, params):
24+
fileno = params["hFile"]
25+
26+
if fileno < 0:
27+
return HFILE_ERROR
28+
29+
os.close(fileno)
30+
31+
return fileno
32+
33+
# HFILE _lcreat(
34+
# LPCSTR lpPathName,
35+
# int iAttribute
36+
# );
37+
@winsdkapi(cc=STDCALL, params={
38+
'lpPathName' : LPCSTR,
39+
'iAttribute' : INT
40+
})
41+
def hook__lcreat(ql: Qiling, address: int, params):
42+
s_lpPathName = params["lpPathName"]
43+
iAttribute = params["iAttribute"]
44+
45+
# There are 4 access bits, we don't care about hidden or system
46+
mode = "w+b"
47+
if iAttribute & 2:
48+
mode += "r+b"
49+
50+
try:
51+
f = ql.os.fs_mapper.open(s_lpPathName, mode)
52+
except FileNotFoundError:
53+
ql.os.last_error = ERROR_FILE_NOT_FOUND
54+
return -1
55+
56+
# The file obj will be closed, dup the file handle to keep open
57+
return os.dup(f.fileno())
58+
59+
# HFILE _lopen(
60+
# LPCSTR lpPathName,
61+
# int iReadWrite
62+
# );
63+
@winsdkapi(cc=STDCALL, params={
64+
'lpPathName' : LPCSTR,
65+
'iReadWrite' : INT
66+
})
67+
def hook__lopen(ql: Qiling, address: int, params):
68+
s_lpPathName = params["lpPathName"]
69+
iReadWrite = params["iReadWrite"]
70+
71+
# access mask DesiredAccess
72+
mode = ""
73+
if iReadWrite & (OF_WRITE | OF_READWRITE):
74+
mode += "wb"
75+
else:
76+
mode += "r"
77+
78+
try:
79+
f = ql.os.fs_mapper.open(s_lpPathName, mode)
80+
except FileNotFoundError:
81+
ql.os.last_error = ERROR_FILE_NOT_FOUND
82+
return -1
83+
84+
# The file obj will be closed, dup the file handle to keep open
85+
return os.dup(f.fileno())
86+
87+
# UINT _lread(
88+
# HFILE hFile,
89+
# LPVOID lpBuffer,
90+
# UINT uBytes
91+
# );
92+
@winsdkapi(cc=STDCALL, params={
93+
'hFile' : HFILE,
94+
'lpBuffer' : LPVOID,
95+
'uBytes' : UINT
96+
})
97+
def hook__lread(ql: Qiling, address: int, params):
98+
fileno = params["hFile"]
99+
lpBuffer = params["lpBuffer"]
100+
uBytes = params["uBytes"]
101+
102+
if fileno < 0:
103+
return HFILE_ERROR
104+
105+
data = os.read(fileno, uBytes)
106+
ql.mem.write(lpBuffer, data)
107+
108+
return len(data)
109+
110+
# LONG _llseek(
111+
# HFILE hFile,
112+
# LONG lOffset,
113+
# int iOrigin
114+
# );
115+
@winsdkapi(cc=STDCALL, params={
116+
'hFile' : HFILE,
117+
'lOffset' : LONG,
118+
'iOrigin' : INT
119+
})
120+
def hook__llseek(ql: Qiling, address: int, params):
121+
fileno = params["hFile"]
122+
lOffset = params["lOffset"]
123+
iOrigin = params["iOrigin"]
124+
125+
if fileno < 0:
126+
return HFILE_ERROR
127+
128+
return os.lseek(fileno, lOffset, iOrigin)
129+
130+
# UINT _lwrite(
131+
# HFILE hFile,
132+
# LPCCH lpBuffer,
133+
# UINT uBytes
134+
# );
135+
@winsdkapi(cc=STDCALL, params={
136+
'hFile' : HFILE,
137+
'lpBuffer' : LPCCH,
138+
'uBytes' : UINT
139+
})
140+
def hook__lwrite(ql: Qiling, address: int, params):
141+
fileno = params["hFile"]
142+
lpBuffer = params["lpBuffer"]
143+
uBytes = params["uBytes"]
144+
145+
if fileno < 0:
146+
return HFILE_ERROR
147+
148+
wbuf = ql.mem.read(lpBuffer, uBytes)
149+
len = os.write(fileno, wbuf)
150+
151+
return len
152+
16153
# __analysis_noreturn VOID FatalExit(
17154
# int ExitCode
18155
# );

0 commit comments

Comments
 (0)