100 lines
		
	
	
		
			2.7 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			100 lines
		
	
	
		
			2.7 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| import argparse
 | |
| import ctypes
 | |
| import os.path
 | |
| from pathlib import Path
 | |
| 
 | |
| import win32file
 | |
| 
 | |
| 
 | |
| class FILE_DIRECTORY_INFORMATION(ctypes.Structure):
 | |
|     _fields_ = [
 | |
|         ("NextEntryOffset", ctypes.c_uint32),
 | |
|         ("FileIndex", ctypes.c_uint32),
 | |
|         ("CreationTime", ctypes.c_int64),
 | |
|         ("LastAccessTime", ctypes.c_int64),
 | |
|         ("LastWriteTime", ctypes.c_int64),
 | |
|         ("ChangeTime", ctypes.c_int64),
 | |
|         ("EndOfFile", ctypes.c_int64),
 | |
|         ("AllocationSize", ctypes.c_int64),
 | |
|         ("FileAttributes", ctypes.c_uint32),
 | |
|         ("FileNameLength", ctypes.c_uint32),
 | |
|         ("FileName", ctypes.c_wchar),
 | |
|     ]
 | |
| 
 | |
| 
 | |
| def main():
 | |
|     parser = argparse.ArgumentParser("list directory using NtQueryOpenFile")
 | |
|     parser.add_argument("-r", "--recurse", action="store_true", help="list recursively")
 | |
|     parser.add_argument("directory", type=Path, help="directory to list")
 | |
| 
 | |
|     args = parser.parse_args()
 | |
|     recursive: bool = args.recurse
 | |
|     directory: Path = args.directory
 | |
| 
 | |
|     kernel32 = ctypes.windll.LoadLibrary("kernel32.dll")
 | |
|     ntdll = ctypes.windll.LoadLibrary("ntdll.dll")
 | |
| 
 | |
|     h = kernel32.CreateFileW(
 | |
|         os.path.expanduser(str(directory)),
 | |
|         win32file.GENERIC_READ,
 | |
|         win32file.FILE_SHARE_READ | win32file.FILE_SHARE_WRITE,
 | |
|         0,
 | |
|         3,
 | |
|         win32file.FILE_FLAG_BACKUP_SEMANTICS,
 | |
|         0,
 | |
|     )
 | |
| 
 | |
|     if h == -1:
 | |
|         print("failed to open directory")
 | |
|         exit(1)
 | |
| 
 | |
|     print(f"handle={h}")
 | |
| 
 | |
|     io_status_block = ctypes.create_string_buffer(64)
 | |
|     length = 1024
 | |
|     file_information_buffer = ctypes.create_string_buffer(length)
 | |
| 
 | |
|     while (
 | |
|         ntdll.NtQueryDirectoryFile(
 | |
|             h,
 | |
|             0,
 | |
|             0,
 | |
|             0,
 | |
|             io_status_block,
 | |
|             file_information_buffer,
 | |
|             length,
 | |
|             1,
 | |
|             False,
 | |
|             0,
 | |
|             False,
 | |
|         )
 | |
|         == 0
 | |
|     ):
 | |
|         index = 0
 | |
|         while index < length:
 | |
|             file_information = FILE_DIRECTORY_INFORMATION.from_buffer(
 | |
|                 file_information_buffer, index
 | |
|             )
 | |
|             print(
 | |
|                 "{name} ({length}) -> {offset}".format(
 | |
|                     offset=file_information.NextEntryOffset,
 | |
|                     length=file_information.FileNameLength,
 | |
|                     name=ctypes.wstring_at(
 | |
|                         ctypes.addressof(file_information)
 | |
|                         + FILE_DIRECTORY_INFORMATION.FileName.offset,
 | |
|                         file_information.FileNameLength // 2,
 | |
|                     ),
 | |
|                 )
 | |
|             )
 | |
| 
 | |
|             if file_information.NextEntryOffset == 0:
 | |
|                 break
 | |
| 
 | |
|             index += file_information.NextEntryOffset
 | |
| 
 | |
|     kernel32.CloseHandle(h)
 | |
| 
 | |
| 
 | |
| if __name__ == "__main__":
 | |
|     main()
 |