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

Add windows 16bit compatibility file api #885

Merged
merged 1 commit into from
Aug 21, 2021
Merged
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
1 change: 1 addition & 0 deletions ChangeLog
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ This file details the changelog of Qiling Framework.
- Added more Posix syscall
- Bugfix: GDB server on MIPS binary
- Major refactor of Windows DLL
- Add Win32 16bit compatibility file api


------------------------------------
Expand Down
3 changes: 2 additions & 1 deletion qiling/os/windows/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
ACCESS_MASK = INT
BOOLEAN = INT
GROUP = INT
HFILE = INT
OBJECT_INFORMATION_CLASS = INT
PROCESSINFOCLASS = INT
SOCKET = INT
Expand Down Expand Up @@ -155,4 +156,4 @@
REFIID = POINTER
REGSAM = POINTER
UINT_PTR = POINTER
ULONG_PTR = POINTER
ULONG_PTR = POINTER
19 changes: 19 additions & 0 deletions qiling/os/windows/const.py
Original file line number Diff line number Diff line change
Expand Up @@ -687,3 +687,22 @@
# https://docs.microsoft.com/en-us/windows/win32/api/handleapi/nf-handleapi-sethandleinformation
HANDLE_FLAG_INHERIT = 0x1
HANDLE_FLAG_PROTECT_FROM_CLOSE = 0x2

# https://docs.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-openfile
OF_READ = 0x00000000
OF_WRITE = 0x00000001
OF_READWRITE = 0x00000002
OF_PARSE = 0x00000100
OF_DELETE = 0x00000200
OF_VERIFY = 0x00000400
OF_CANCEL = 0x00000800
OF_CREATE = 0x00001000
OF_PROMPT = 0x00002000
OF_EXIST = 0x00004000
OF_REOPEN = 0x00008000

OF_SHARE_COMPAT = 0x00000000
OF_SHARE_EXCLUSIVE = 0x00000010
OF_SHARE_DENY_WRITE = 0x00000020
OF_SHARE_DENY_READ = 0x00000030
OF_SHARE_DENY_NONE = 0x00000040
137 changes: 137 additions & 0 deletions qiling/os/windows/dlls/kernel32/winbase.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
# Cross Platform and Multi Architecture Advanced Binary Emulation Framework
#

import os
import configparser

from qiling import Qiling
Expand All @@ -13,6 +14,142 @@
from qiling.os.windows.structs import OsVersionInfoExA
from qiling.os.windows.utils import cmp

# HFILE _lclose(
# HFILE hFile
# );
@winsdkapi(cc=STDCALL, params={
'hFile' : HFILE
})
def hook__lclose(ql: Qiling, address: int, params):
fileno = params["hFile"]

if fileno < 0:
return HFILE_ERROR

os.close(fileno)

return fileno

# HFILE _lcreat(
# LPCSTR lpPathName,
# int iAttribute
# );
@winsdkapi(cc=STDCALL, params={
'lpPathName' : LPCSTR,
'iAttribute' : INT
})
def hook__lcreat(ql: Qiling, address: int, params):
s_lpPathName = params["lpPathName"]
iAttribute = params["iAttribute"]

# There are 4 access bits, we don't care about hidden or system
mode = "w+b"
if iAttribute & 2:
mode += "r+b"

try:
f = ql.os.fs_mapper.open(s_lpPathName, mode)
except FileNotFoundError:
ql.os.last_error = ERROR_FILE_NOT_FOUND
return -1

# The file obj will be closed, dup the file handle to keep open
return os.dup(f.fileno())

# HFILE _lopen(
# LPCSTR lpPathName,
# int iReadWrite
# );
@winsdkapi(cc=STDCALL, params={
'lpPathName' : LPCSTR,
'iReadWrite' : INT
})
def hook__lopen(ql: Qiling, address: int, params):
s_lpPathName = params["lpPathName"]
iReadWrite = params["iReadWrite"]

# access mask DesiredAccess
mode = ""
if iReadWrite & (OF_WRITE | OF_READWRITE):
mode += "wb"
else:
mode += "r"

try:
f = ql.os.fs_mapper.open(s_lpPathName, mode)
except FileNotFoundError:
ql.os.last_error = ERROR_FILE_NOT_FOUND
return -1

# The file obj will be closed, dup the file handle to keep open
return os.dup(f.fileno())

# UINT _lread(
# HFILE hFile,
# LPVOID lpBuffer,
# UINT uBytes
# );
@winsdkapi(cc=STDCALL, params={
'hFile' : HFILE,
'lpBuffer' : LPVOID,
'uBytes' : UINT
})
def hook__lread(ql: Qiling, address: int, params):
fileno = params["hFile"]
lpBuffer = params["lpBuffer"]
uBytes = params["uBytes"]

if fileno < 0:
return HFILE_ERROR

data = os.read(fileno, uBytes)
ql.mem.write(lpBuffer, data)

return len(data)

# LONG _llseek(
# HFILE hFile,
# LONG lOffset,
# int iOrigin
# );
@winsdkapi(cc=STDCALL, params={
'hFile' : HFILE,
'lOffset' : LONG,
'iOrigin' : INT
})
def hook__llseek(ql: Qiling, address: int, params):
fileno = params["hFile"]
lOffset = params["lOffset"]
iOrigin = params["iOrigin"]

if fileno < 0:
return HFILE_ERROR

return os.lseek(fileno, lOffset, iOrigin)

# UINT _lwrite(
# HFILE hFile,
# LPCCH lpBuffer,
# UINT uBytes
# );
@winsdkapi(cc=STDCALL, params={
'hFile' : HFILE,
'lpBuffer' : LPCCH,
'uBytes' : UINT
})
def hook__lwrite(ql: Qiling, address: int, params):
fileno = params["hFile"]
lpBuffer = params["lpBuffer"]
uBytes = params["uBytes"]

if fileno < 0:
return HFILE_ERROR

wbuf = ql.mem.read(lpBuffer, uBytes)
len = os.write(fileno, wbuf)

return len

# __analysis_noreturn VOID FatalExit(
# int ExitCode
# );
Expand Down