Too many changes to list

This commit is contained in:
David Maisonave
2024-09-13 10:10:37 -04:00
parent 5b34502963
commit 452c08df03
18 changed files with 1645 additions and 353 deletions

View File

@@ -17,7 +17,7 @@ Example Usage:
of.closeFile(r"B:\V\V\testdup\deleme2.mp4")
"""
import ctypes, os, sys, psutil, argparse, traceback, logging, numbers, string
import ctypes, os, sys, argparse, traceback, logging, numbers, string
from ctypes import wintypes
# from StashPluginHelper import StashPluginHelper
# Look at the following links to enhance this code:
@@ -30,8 +30,8 @@ from ctypes import wintypes
# getPid is the only function which does NOT require elevated admin privileges.
class openedFile():
# generic strings and constants
ntdll = ctypes.WinDLL('ntdll')
kernel32 = ctypes.WinDLL('kernel32', use_last_error=True)
ntdll = None
kernel32 = None
NTSTATUS = wintypes.LONG
INVALID_HANDLE_VALUE = wintypes.HANDLE(-1).value
FILE_READ_ATTRIBUTES = 0x80
@@ -51,57 +51,62 @@ class openedFile():
self.stash = stash
if handleExe == None or handleExe == "" or not os.path.isfile(handleExe):
raise Exception(f"handleExe requires a valid path to Sysinternals 'handle.exe' or 'handle64.exe' executable. Can be downloaded from following link:\nhttps://learn.microsoft.com/en-us/sysinternals/downloads/handle")
# create handle on concerned file with dwDesiredAccess == self.FILE_READ_ATTRIBUTES
self.kernel32.CreateFileW.restype = wintypes.HANDLE
self.kernel32.CreateFileW.argtypes = (
wintypes.LPCWSTR, # In lpFileName
wintypes.DWORD, # In dwDesiredAccess
wintypes.DWORD, # In dwShareMode
self.LPSECURITY_ATTRIBUTES, # In_opt lpSecurityAttributes
wintypes.DWORD, # In dwCreationDisposition
wintypes.DWORD, # In dwFlagsAndAttributes
wintypes.HANDLE) # In_opt hTemplateFile
if self.stash != None and self.stash.IS_WINDOWS:
self.ntdll = ctypes.WinDLL('ntdll')
self.kernel32 = ctypes.WinDLL('kernel32', use_last_error=True)
# create handle on concerned file with dwDesiredAccess == self.FILE_READ_ATTRIBUTES
self.kernel32.CreateFileW.restype = wintypes.HANDLE
self.kernel32.CreateFileW.argtypes = (
wintypes.LPCWSTR, # In lpFileName
wintypes.DWORD, # In dwDesiredAccess
wintypes.DWORD, # In dwShareMode
self.LPSECURITY_ATTRIBUTES, # In_opt lpSecurityAttributes
wintypes.DWORD, # In dwCreationDisposition
wintypes.DWORD, # In dwFlagsAndAttributes
wintypes.HANDLE) # In_opt hTemplateFile
def getPid(self, path):
self.lastPath = path
hFile = self.kernel32.CreateFileW(
path, self.FILE_READ_ATTRIBUTES, self.FILE_SHARE_READ, None, self.OPEN_EXISTING,
self.FILE_FLAG_BACKUP_SEMANTICS, None)
if hFile == self.INVALID_HANDLE_VALUE:
raise ctypes.WinError(ctypes.get_last_error())
# prepare data types for system call
class IO_STATUS_BLOCK(ctypes.Structure):
class _STATUS(ctypes.Union):
_fields_ = (('Status', self.NTSTATUS),
('Pointer', wintypes.LPVOID))
_anonymous_ = '_Status',
_fields_ = (('_Status', _STATUS),
('Information', self.ULONG_PTR))
iosb = IO_STATUS_BLOCK()
class FILE_PROCESS_IDS_USING_FILE_INFORMATION(ctypes.Structure):
_fields_ = (('NumberOfProcessIdsInList', wintypes.LARGE_INTEGER),
('ProcessIdList', wintypes.LARGE_INTEGER * 64))
info = FILE_PROCESS_IDS_USING_FILE_INFORMATION()
PIO_STATUS_BLOCK = ctypes.POINTER(IO_STATUS_BLOCK)
self.ntdll.NtQueryInformationFile.restype = self.NTSTATUS
self.ntdll.NtQueryInformationFile.argtypes = (
wintypes.HANDLE, # In FileHandle
PIO_STATUS_BLOCK, # Out IoStatusBlock
wintypes.LPVOID, # Out FileInformation
wintypes.ULONG, # In Length
self.FILE_INFORMATION_CLASS) # In FileInformationClass
# system call to retrieve list of PIDs currently using the file
status = self.ntdll.NtQueryInformationFile(hFile, ctypes.byref(iosb),
ctypes.byref(info),
ctypes.sizeof(info),
self.FileProcessIdsUsingFileInformation)
pidList = info.ProcessIdList[0:info.NumberOfProcessIdsInList]
if len(pidList) > 0:
return pidList
# ToDo: Add Linux implementation
if self.stash != None and self.stash.IS_WINDOWS:
hFile = self.kernel32.CreateFileW(
path, self.FILE_READ_ATTRIBUTES, self.FILE_SHARE_READ, None, self.OPEN_EXISTING,
self.FILE_FLAG_BACKUP_SEMANTICS, None)
if hFile == self.INVALID_HANDLE_VALUE:
raise ctypes.WinError(ctypes.get_last_error())
# prepare data types for system call
class IO_STATUS_BLOCK(ctypes.Structure):
class _STATUS(ctypes.Union):
_fields_ = (('Status', self.NTSTATUS),
('Pointer', wintypes.LPVOID))
_anonymous_ = '_Status',
_fields_ = (('_Status', _STATUS),
('Information', self.ULONG_PTR))
iosb = IO_STATUS_BLOCK()
class FILE_PROCESS_IDS_USING_FILE_INFORMATION(ctypes.Structure):
_fields_ = (('NumberOfProcessIdsInList', wintypes.LARGE_INTEGER),
('ProcessIdList', wintypes.LARGE_INTEGER * 64))
info = FILE_PROCESS_IDS_USING_FILE_INFORMATION()
PIO_STATUS_BLOCK = ctypes.POINTER(IO_STATUS_BLOCK)
self.ntdll.NtQueryInformationFile.restype = self.NTSTATUS
self.ntdll.NtQueryInformationFile.argtypes = (
wintypes.HANDLE, # In FileHandle
PIO_STATUS_BLOCK, # Out IoStatusBlock
wintypes.LPVOID, # Out FileInformation
wintypes.ULONG, # In Length
self.FILE_INFORMATION_CLASS) # In FileInformationClass
# system call to retrieve list of PIDs currently using the file
status = self.ntdll.NtQueryInformationFile(hFile, ctypes.byref(iosb),
ctypes.byref(info),
ctypes.sizeof(info),
self.FileProcessIdsUsingFileInformation)
pidList = info.ProcessIdList[0:info.NumberOfProcessIdsInList]
if len(pidList) > 0:
return pidList
return None
def isAdmin(self):
if os.name=='nt':
if self.stash != None and self.stash.IS_WINDOWS:
try:
return ctypes.windll.shell32.IsUserAnAdmin()
except:
@@ -112,7 +117,7 @@ class openedFile():
def runMeAsAdmin(self):
if self.isAdmin() == True:
return
if os.name=='nt':
if self.stash != None and self.stash.IS_WINDOWS:
# Below is a Windows only method which does NOT popup a console.
import win32com.shell.shell as shell # Requires: pip install pywin32
script = os.path.abspath(sys.argv[0])
@@ -130,6 +135,7 @@ class openedFile():
return filename
def getFilesOpen(self, pid:int): # Requires running with admin privileges.
import psutil # Requires: pip install psutil
p = psutil.Process(pid1)
return p.open_files()