Last active
March 23, 2023 08:45
-
-
Save UserUnknownFactor/96d3d3246ce89e0c54feef3f2ee05243 to your computer and use it in GitHub Desktop.
Python Windows utility to check what NTFS files correspond to what bad sectors on disk that showed up as failed in System Log (also corresponds to bad physical sector reads in low-level disk checking tools that use native Windows API).
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import win32evtlog # requires pywin32 pre-installed (`pip install pywin32`) | |
import os, sys, platform, tempfile, subprocess, base64, hashlib | |
from struct import unpack | |
import ctypes | |
from ctypes.wintypes import HANDLE | |
from ctypes.wintypes import BOOL | |
from ctypes.wintypes import HWND | |
from ctypes.wintypes import DWORD | |
from ctypes.wintypes import ULONG | |
from ctypes.wintypes import USHORT | |
from ctypes.wintypes import LPVOID | |
from ctypes.wintypes import LPWSTR | |
if ctypes.windll.shell32.IsUserAnAdmin() == 0: | |
print('This script requires Administrator privileges...') | |
sys.exit() | |
NULL = 0 | |
HDEVINFO = ctypes.c_void_p | |
LPCTSTR = ctypes.c_wchar_p | |
PCTSTR = ctypes.c_wchar_p | |
PTSTR = ctypes.c_wchar_p | |
LPDWORD = PDWORD = ctypes.POINTER(DWORD) | |
LPBYTE = PBYTE = ctypes.c_void_p | |
ULONG_PTR = ctypes.POINTER(ULONG) | |
CHAR = ctypes.c_ubyte | |
LPOVERLAPPED = LPVOID | |
LPSECURITY_ATTRIBUTES = LPVOID | |
GENERIC_READ = 0x80000000 | |
FILE_SHARE_READ = 1 | |
GENERIC_ALL = 0x10000000 | |
OPEN_EXISTING = 3 | |
FILE_ATTRIBUTE_NORMAL = 0x00000080 | |
DIGCF_PRESENT = 2 | |
DIGCF_DEVICEINTERFACE = 0x10 | |
IOCTL_STORAGE_GET_DEVICE_NUMBER = 0x002D1080 | |
SPDRP_PHYSICAL_DEVICE_OBJECT_NAME = 0x0000000E | |
INVALID_HANDLE_VALUE = -1 | |
ERROR_PATH_NOT_FOUND = 3 | |
ERROR_INSUFFICIENT_BUFFER = 122 | |
SCSI_OP_IOCTL = 0x0F | |
class STORAGE_DEVICE_NUMBER(ctypes.Structure): | |
_fields_ = [ | |
('DeviceType', DWORD), | |
('DeviceNumber', DWORD), | |
('PartitionNumber', DWORD) | |
] | |
class GUID(ctypes.Structure): | |
_fields_ = [ | |
("data1", ULONG), | |
("data2", USHORT), | |
("data3", USHORT), | |
("data4", CHAR * 8) | |
] | |
def __init__(self, dw=0, w1=0, w2=0, b1=0, b2=0, b3=0, b4=0, b5=0, b6=0, | |
b7=0, b8=0): | |
self.data1 = dw | |
self.data2 = w1 | |
self.data3 = w2 | |
self.data4[0] = b1 | |
self.data4[1] = b2 | |
self.data4[2] = b3 | |
self.data4[3] = b4 | |
self.data4[4] = b5 | |
self.data4[5] = b6 | |
self.data4[6] = b7 | |
self.data4[7] = b8 | |
class SP_DEVICE_INTERFACE_DATA(ctypes.Structure): | |
_fields_ = [ | |
('cbSize', DWORD), | |
('InterfaceClassGuid', GUID), | |
('Flags', DWORD), | |
('Reserved', ULONG_PTR), | |
] | |
def __str__(self): | |
return "InterfaceClassGuid:%s Flags:%s" % (self.InterfaceClassGuid, self.Flags) | |
PSP_DEVICE_INTERFACE_DETAIL_DATA = ctypes.c_void_p | |
PSP_DEVICE_INTERFACE_DATA = ctypes.POINTER(SP_DEVICE_INTERFACE_DATA) | |
class SP_DEVICE_INTERFACE_DETAIL_DATA_W(ctypes.Structure): | |
_fields_ = [ | |
('cbSize', DWORD), | |
('DevicePath', CHAR * 2) | |
] | |
class SP_DEVINFO_DATA(ctypes.Structure): | |
_fields_ = [ | |
('cbSize', DWORD), | |
('ClassGuid', GUID), | |
('DevInst', DWORD), | |
('Reserved', ULONG_PTR), | |
] | |
def __str__(self): | |
return "ClassGuid:%s DevInst:%s" % (self.ClassGuid, self.DevInst) | |
PSP_DEVINFO_DATA = ctypes.POINTER(SP_DEVINFO_DATA) | |
def ValidHandle(value, func, arguments): | |
if value == 0: | |
raise ctypes.WinError() | |
return value | |
GUID_DEVINTERFACE_DISK = GUID(0x53f56307, 0xb6bf, 0x11d0, 0x94, 0xf2, | |
0x00, 0xa0, 0xc9, 0x1e, 0xfb, 0x8b) | |
GUID_DEVINTERFACE_VOLUME = GUID(0x53F5630D, 0xB6BF, 0x11D0, 0x94, 0xF2, | |
0x00, 0xA0, 0xC9, 0x1E, 0xFB, 0x8B) | |
setupapi = ctypes.windll.LoadLibrary("setupapi") | |
kernel32 = ctypes.windll.kernel32 | |
SetupDiGetClassDevs = setupapi.SetupDiGetClassDevsW | |
SetupDiGetClassDevs.argtypes = [ctypes.POINTER(GUID), PCTSTR, HWND, DWORD] | |
SetupDiGetClassDevs.restype = HDEVINFO | |
SetupDiGetClassDevs.errcheck = ValidHandle | |
SetupDiEnumDeviceInfo = setupapi.SetupDiEnumDeviceInfo | |
SetupDiEnumDeviceInfo.argtypes = [HDEVINFO, DWORD, PSP_DEVINFO_DATA] | |
SetupDiEnumDeviceInfo.restype = BOOL | |
SetupDiGetDeviceRegistryProperty = setupapi.SetupDiGetDeviceRegistryPropertyW | |
SetupDiGetDeviceRegistryProperty.argtypes = [HDEVINFO, PSP_DEVINFO_DATA, DWORD, PDWORD, PBYTE, DWORD, PDWORD] | |
SetupDiGetDeviceRegistryProperty.restype = BOOL | |
SetupDiDestroyDeviceInfoList = setupapi.SetupDiDestroyDeviceInfoList | |
SetupDiDestroyDeviceInfoList.argtypes = [HDEVINFO] | |
SetupDiDestroyDeviceInfoList.restype = BOOL | |
def _DeviceIoControl(devhandle, ioctl, inbuf, inbufsiz, outbuf, outbufsiz): | |
DeviceIoControl_Fn = kernel32.DeviceIoControl | |
DeviceIoControl_Fn.argtypes = [ | |
HANDLE, # _In_ HANDLE hDevice | |
DWORD, # _In_ DWORD dwIoControlCode | |
LPVOID, # _In_opt_ LPVOID lpInBuffer | |
DWORD, # _In_ DWORD nInBufferSize | |
LPVOID, # _Out_opt_ LPVOID lpOutBuffer | |
DWORD, # _In_ DWORD nOutBufferSize | |
LPDWORD, # _Out_opt_ LPDWORD lpBytesReturned | |
LPOVERLAPPED] # _Inout_opt_ LPOVERLAPPED lpOverlapped | |
DeviceIoControl_Fn.restype = BOOL | |
# allocate a DWORD, and take its reference | |
dwBytesReturned = DWORD(0) | |
lpBytesReturned = ctypes.byref(dwBytesReturned) | |
status = DeviceIoControl_Fn(devhandle, | |
ioctl, | |
inbuf, | |
inbufsiz, | |
outbuf, | |
outbufsiz, | |
lpBytesReturned, | |
None) | |
return status, dwBytesReturned | |
def _CreateFile(filename, access, mode, creation, flags): | |
CreateFile_Fn = kernel32.CreateFileW | |
CreateFile_Fn.argtypes = [ | |
LPWSTR, # _In_ LPCTSTR lpFileName | |
DWORD, # _In_ DWORD dwDesiredAccess | |
DWORD, # _In_ DWORD dwShareMode | |
LPSECURITY_ATTRIBUTES, # _In_opt_ LPSECURITY_ATTRIBUTES lpSecurityAttributes | |
DWORD, # _In_ DWORD dwCreationDisposition | |
DWORD, # _In_ DWORD dwFlagsAndAttributes | |
HANDLE] # _In_opt_ HANDLE hTemplateFile | |
CreateFile_Fn.restype = HANDLE | |
return HANDLE(CreateFile_Fn(filename, access, mode, NULL, creation, flags, NULL)) | |
class DeviceIoControl(object): | |
def __init__(self, path): | |
self.path = path | |
self._fhandle = None | |
def _validate_handle(self): | |
if self._fhandle is None: | |
raise Exception('No file handle') | |
if self._fhandle.value == HANDLE(INVALID_HANDLE_VALUE).value: | |
ecode = kernel32.GetLastError() | |
if ecode == ERROR_PATH_NOT_FOUND: | |
ecode = 'ERROR_PATH_NOT_FOUND' | |
raise Exception(f'Failed to open {self.path}. Error: {ecode}') | |
def ioctl(self, ctl, inbuf, inbufsiz, outbuf, outbufsiz): | |
res = (None, None) | |
self._validate_handle() | |
res = _DeviceIoControl(self._fhandle, ctl, inbuf, inbufsiz, outbuf, outbufsiz) | |
return res | |
def __enter__(self): | |
self._fhandle = _CreateFile(self.path, FILE_SHARE_READ, 0, OPEN_EXISTING, 0) | |
self._validate_handle() | |
return self | |
def __exit__(self, typ, val, tb): | |
try: | |
self._validate_handle() | |
except Exception: | |
pass | |
else: | |
kernel32.CloseHandle(self._fhandle) | |
map_disks = dict() | |
def get_device_for_nfi(winpath): | |
global map_disks | |
found = None | |
if winpath in map_disks: | |
return map_disks[winpath] | |
disk_guid = GUID_DEVINTERFACE_DISK | |
g_hdi = SetupDiGetClassDevs(ctypes.byref(disk_guid), None, None, | |
DIGCF_PRESENT | DIGCF_DEVICEINTERFACE) | |
if g_hdi == INVALID_HANDLE_VALUE: | |
raise Exception | |
try: | |
szHardwareID = ctypes.create_unicode_buffer(1024) | |
lenHardwareID = ctypes.sizeof(szHardwareID) - 1 | |
devinfo = SP_DEVINFO_DATA() | |
devinfo.cbSize = ctypes.sizeof(SP_DEVINFO_DATA) | |
index = 0 | |
while SetupDiEnumDeviceInfo(g_hdi, index, ctypes.byref(devinfo)): | |
ret = SetupDiGetDeviceRegistryProperty( | |
g_hdi, | |
ctypes.byref(devinfo), | |
SPDRP_PHYSICAL_DEVICE_OBJECT_NAME, | |
None, | |
ctypes.byref(szHardwareID), | |
lenHardwareID, None) | |
if not ret: continue | |
disk = f'\\Device\\Harddisk{index}\\DR{index}' | |
sdn = STORAGE_DEVICE_NUMBER() | |
try: | |
with DeviceIoControl('\\\\.\\GLOBALROOT' + szHardwareID.value) as dev: | |
status, _ = dev.ioctl(IOCTL_STORAGE_GET_DEVICE_NUMBER, None, 0, | |
ctypes.pointer(sdn), ctypes.sizeof(STORAGE_DEVICE_NUMBER)) | |
# not always working? | |
if status: | |
disk = f'\\Device\\Harddisk{sdn.DeviceNumber}\\DR{sdn.DeviceNumber}' | |
except: | |
print(f'Error detecting harddisk device {szHardwareID.value} number...') | |
index += 1 | |
if winpath == disk: | |
found = szHardwareID.value | |
map_disks[winpath] = found | |
break | |
except: | |
print(f'Error detecting device ID for {winpath}...') | |
finally: | |
SetupDiDestroyDeviceInfoList(g_hdi) | |
return found | |
def call_with_output(command): | |
success = False | |
output = None | |
try: | |
output = subprocess.check_output(command).decode() | |
success = True | |
except subprocess.CalledProcessError as e: | |
output = e.output.decode() | |
except Exception as e: | |
#output = str(e) | |
pass | |
return(success, output) | |
def get_disk_errors(tolerance=200): | |
server = platform.node() # name of the current computer to get event logs | |
logtype = 'System' # 'Application' # 'Security' | |
hlog = win32evtlog.OpenEventLog(server, logtype) | |
flags = win32evtlog.EVENTLOG_FORWARDS_READ|win32evtlog.EVENTLOG_SEQUENTIAL_READ | |
total = win32evtlog.GetNumberOfEventLogRecords(hlog) | |
error_sectors = [] | |
sector = 0 | |
for i in range(total): #while True: | |
events = win32evtlog.ReadEventLog(hlog, flags,0) | |
if events: | |
for event in events: | |
if event.SourceName == "disk": | |
data = event.StringInserts | |
disk = '' | |
sector_tmp = '' | |
nsectors = '' | |
if (event.Data and len(event.Data) > 139 and event.Data[0] != SCSI_OP_IOCTL): | |
sector_tmp = unpack('>L', event.Data[130:134])[0] # LBA | |
nsectors = unpack('>L', event.Data[134:138])[0] # length | |
if event.EventType == 2: #windows 8 | |
if (len(data > 1)): | |
sector_tmp = int(data[1], 0) | |
disk = data[3] | |
else: # windows 10? | |
disk = get_device_for_nfi(data[0]) | |
if not disk or not sector_tmp: | |
#print(f"{disk}/{sector_tmp}/+{nsectors}") | |
continue | |
if sector_tmp - sector > tolerance or sector_tmp < sector: | |
sector = sector_tmp | |
error_sectors.append((disk, str(sector), str(nsectors))) | |
win32evtlog.CloseEventLog(hlog) | |
return error_sectors | |
# nfi.exe: unofficial Microsoft's NTFS File Sector Information Utility. | |
nfi_exe = "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ZQAAAHMAZQBjADIAZgBpAGwAZQAuAGUAeABlAAAAAAB0ACgAAQBMAGUAZwBhAGwAQwBvAHAAeQByAGkAZwBoAHQAAABDAG8AcAB5AHIAaQBnAGgAdAAgACgAQwApACAATQBpAGMAcgBvAHMAbwBmAHQAIABDAG8AcgBwAC4AIAAxADkAOQA4AC0AMQA5ADkAOQAAAEIADQABAE8AcgBpAGcAaQBuAGEAbABGAGkAbABlAG4AYQBtAGUAAABzAGUAYwAyAGYAaQBsAGUALgBlAHgAZQAAAAAARAASAAEAUAByAG8AZAB1AGMAdABOAGEAbQBlAAAAAABNAGkAYwByAG8AcwBvAGYAdAAgAFcAaQBuAGQAbwB3AHMAAAA8AAwAAQBQAHIAbwBkAHUAYwB0AFYAZQByAHMAaQBvAG4AAAAzAC4AMAAwAC4AMgAwADkAMwAuADEAAABEAAAAAQBWAGEAcgBGAGkAbABlAEkAbgBmAG8AAAAAACQABAAAAFQAcgBhAG4AcwBsAGEAdABpAG8AbgAAAAAACQSwBAAAAAAFAAAAAQAAAA0AAABAAAAAjAAAAIwAAABsDwAAlQAAAJYAAAA0EAAALAEAAC0BAABUEQAAXAEAAHABAABgEgAA2AABAE4AVABGAFMAIABGAGkAbABlACAAUwBlAGMAdABvAHIAIABJAG4AZgBvAHIAbQBhAHQAaQBvAG4AIABVAHQAaQBsAGkAdAB5AC4ADQAKAEMAbwBwAHkAcgBpAGcAaAB0ACAAKABDACkAIABNAGkAYwByAG8AcwBvAGYAdAAgAEMAbwByAHAAbwByAGEAdABpAG8AbgAgADEAOQA5ADkALgAgAEEAbABsACAAcgBpAGcAaAB0AHMAIAByAGUAcwBlAHIAdgBlAGQALgANAAoADQAKAAAAMAoBAEQAdQBtAHAAcwAgAGkAbgBmAG8AcgBtAGEAdABpAG8AbgAgAGEAYgBvAHUAdAAgAGEAbgAgAE4AVABGAFMAIAB2AG8AbAB1AG0AZQAsACAAYQBuAGQAIABvAHAAdABpAG8AbgBhAGwAbAB5ACAAZABlAHQAZQByAG0AaQBuAGUAcwANAAoAdwBoAGkAYwBoACAAdgBvAGwAdQBtAGUAIABhAG4AZAAgAGYAaQBsAGUAIABjAG8AbgB0AGEAaQBuAHMAIABhACAAcABhAHIAdABpAGMAdQBsAGEAcgAgAHMAZQBjAHQAbwByAC4ADQAKAA0ACgBVAHMAYQBnAGUAOgAgACUAMQAgAGQAcgBpAHYAZQAtAGwAZQB0AHQAZQByACAAWwBsAG8AZwBpAGMAYQBsAC0AcwBlAGMAdABvAHIALQBuAHUAbQBiAGUAcgBdAA0ACgANAAoAIAAgACAAIAAgACAAIAAgACAAIAAgACAARAByAGkAdgBlAC0AbABlAHQAdABlAHIAIABjAGEAbgAgAGIAZQAgAGEAIABzAGkAbgBnAGwAZQAgAGMAaABhAHIAYQBjAHQAZQByACAAbwByACAAYQAgAGMAaABhAHIAYQBjAHQAZQByACAAZgBvAGwAbABvAHcAZQBkAA0ACgAgACAAIAAgACAAIAAgACAAIAAgACAAIABiAHkAIABhACAAYwBvAGwAbwBuACAAKABpAC4AZQAuACwAIABDACAAbwByACAAQwA6ACAAYQByAGUAIABhAGMAYwBlAHAAdABhAGIAbABlACkALgANAAoADQAKACAAIAAgACAAIAAgACAAIAAgACAAIAAgAEwAbwBnAGkAYwBhAGwALQBzAGUAYwB0AG8AcgAtAG4AdQBtAGIAZQByACAAaQBzACAAYQAgAGQAZQBjAGkAbQBhAGwAIABvAHIAIAAwAHgALQBwAHIAZQBmAGkAeABlAGQAIABoAGUAeAANAAoAIAAgACAAIAAgACAAIAAgACAAIAAgACAAbgB1AG0AYgBlAHIALAAgAHMAcABlAGMAaQBmAHkAaQBuAGcAIABhACAAcwBlAGMAdABvAHIAIABuAHUAbQBiAGUAcgAgAHIAZQBsAGEAdABpAHYAZQAgAHQAbwAgAHQAaABlACAAdgBvAGwAdQBtAGUADQAKACAAIAAgACAAIAAgACAAIAAgACAAIAAgAHcAaABvAHMAZQAgAGQAcgBpAHYAZQAgAGwAZQB0AHQAZQByACAAaQBzACAAZwBpAHYAZQBuACAAYgB5ACAAZAByAGkAdgBlAC0AbABlAHQAdABlAHIALgAgAEkAZgAgAG4AbwB0AA0ACgAgACAAIAAgACAAIAAgACAAIAAgACAAIABzAHAAZQBjAGkAZgBpAGUAZAAsACAAdABoAGUAbgAgAGkAbgBmAG8AcgBtAGEAdABpAG8AbgAgAGEAYgBvAHUAdAAgAGUAdgBlAHIAeQAgAGYAaQBsAGUAIABvAG4AIAB0AGgAZQAgAHYAbwBsAHUAbQBlAA0ACgAgACAAIAAgACAAIAAgACAAIAAgACAAIABpAHMAIABkAHUAbQBwAGUAZAAuAA0ACgANAAoAIAAgACAAIAAgACAAIAAlADEAIABOAFQALQBkAGUAdgBpAGMAZQAtAHAAYQB0AGgAIABwAGgAeQBzAGkAYwBhAGwALQBzAGUAYwB0AG8AcgAtAG4AdQBtAGIAZQByAA0ACgANAAoAIAAgACAAIAAgACAAIAAgACAAIAAgACAARABlAHQAZQByAG0AaQBuAGUAcwAgAHcAaABpAGMAaAAgAHYAbwBsAHUAbQBlACAAYQAgAGcAaQB2AGUAbgAgAHAAaAB5AHMAaQBjAGEAbAAgAHMAZQBjAHQAbwByACAAbwBuACAAYQAgAGQAcgBpAHYAZQAgAGkAcwANAAoAIAAgACAAIAAgACAAIAAgACAAIAAgACAAdwBpAHQAaABpAG4ALAAgAGEAbgBkACAAdABoAGUAbgAgAHcAaABpAGMAaAAgAGYAaQBsAGUAIABvAG4AIAB0AGgAZQAgAHYAbwBsAHUAbQBlACAAaQB0ACAAaQBzACAAaQBuAC4ADQAKAA0ACgAgACAAIAAgACAAIAAgACAAIAAgACAAIABOAFQALQBkAGUAdgBpAGMAZQAtAHAAYQB0AGgAIABpAHMAIAB0AGgAZQAgAE4AVAAtAHMAdAB5AGwAZQAgAHAAYQB0AGgAIAB0AG8AIABhACAAcABoAHkAcwBpAGMAYQBsACAAZABlAHYAaQBjAGUALgANAAoAIAAgACAAIAAgACAAIAAgACAAIAAgACAASQB0ACAAbQB1AHMAdAAgAG4AbwB0ACAAaQBuAGMAbAB1AGQAZQAgAGEAIABwAGEAcgB0AGkAdABpAG8AbgAgAHMAcABlAGMAaQBmAGkAYwBhAHQAaQBvAG4ALgANAAoADQAKACAAIAAgACAAIAAgACAAIAAgACAAIAAgAFAAaAB5AHMAaQBjAGEAbAAtAHMAZQBjAHQAbwByAC0AbgB1AG0AYgBlAHIAIABpAHMAIABhACAAZABlAGMAaQBtAGEAbAAgAG8AcgAgADAAeAAtAHAAcgBlAGYAaQB4AGUAZAAgAGgAZQB4AA0ACgAgACAAIAAgACAAIAAgACAAIAAgACAAIABuAHUAbQBiAGUAcgAsACAAcwBwAGUAYwBpAGYAeQBpAG4AZwAgAGEAIABzAGUAYwB0AG8AcgAgAG4AdQBtAGIAZQByACAAcgBlAGwAYQB0AGkAdgBlACAAdABvACAAdABoAGUAIABwAGgAeQBzAGkAYwBhAGwADQAKACAAIAAgACAAIAAgACAAIAAgACAAIAAgAGQAcgBpAHYAZQAgAHcAaABvAHMAZQAgAGQAZQB2AGkAYwBlACAAcABhAHQAaAAgAGkAcwAgAGcAaQB2AGUAbgAgAGIAeQAgAE4AVAAtAGQAZQB2AGkAYwBlAC0AcABhAHQAaAAuAA0ACgANAAoAIAAgACAAIAAgACAAIAAgACUAMQAgAGYAdQBsAGwALQB3AGkAbgAzADIALQBwAGEAdABoAA0ACgANAAoAIAAgACAAIAAgACAAIAAgACAAIAAgACAARAB1AG0AcABzACAAaQBuAGYAbwByAG0AYQB0AGkAbwBuACAAYQBiAG8AdQB0ACAAYQAgAHAAYQByAHQAaQBjAHUAbABhAHIAIABmAGkAbABlAC4AIABmAHUAbABsAC0AdwBpAG4AMwAyAC0AcABhAHQAaAANAAoAIAAgACAAIAAgACAAIAAgACAAIAAgACAAbQB1AHMAdAAgAHMAdABhAHIAdAAgAHcAaQB0AGgAIABhACAAZAByAGkAdgBlACAAbABlAHQAdABlAHIAIABhAG4AZAAgAGEAIABjAG8AbABvAG4ALgANAAoAAAAAAEAAAQBVAG4AYQBiAGwAZQAgAHQAbwAgAG8AcABlAG4AIABkAHIAaQB2AGUAIAAlADEAIQBjACEALgANAAoAAAB4AAEAVQBuAGEAYgBsAGUAIAB0AG8AIAByAGUAdAByAGkAZQB2AGUAIAB2AG8AbAB1AG0AZQAgAGkAbgBmAG8AcgBtAGEAdABpAG8AbgAgAGYAbwByACAAZAByAGkAdgBlACAAJQAxACEAYwAhAC4ADQAKAAAAAACcAAEARAByAGkAdgBlACAAJQAxACEAYwAhACAAaQBzACAAbgBvAHQAIABOAFQARgBTAC4AIABPAG4AbAB5ACAATgBUAEYAUwAgAGQAcgBpAHYAZQBzACAAYQByAGUAIABzAHUAcABwAG8AcgB0AGUAZAAgAGIAeQAgAHQAaABpAHMAIABwAHIAbwBnAHIAYQBtAC4ADQAKAAAAAAB4AAEASQBuAHMAdQBmAGYAaQBjAGkAZQBuAHQAIABtAGUAbQBvAHIAeQAgACgAYQAgAHIAZQBxAHUAZQBzAHQAIABmAG8AcgAgACUAMQAhAHUAIQAgAGIAeQB0AGUAcwAgAGYAYQBpAGwAZQBkACkALgANAAoAAABYAAEAVQBuAGEAYgBsAGUAIAB0AG8AIABzAGUAZQBrACAAdABvACAAcwBlAGMAdABvAHIAIAAwAHgAJQAxACEAeAAhACUAMgAhAHgAIQAuAA0ACgAAAAAAhAABAFUAbgBhAGIAbABlACAAdABvACAAcgBlAGEAZAAgACUAMwAhAHUAIQAgAHMAZQBjAHQAbwByAHMAIABzAHQAYQByAHQAaQBuAGcAIABhAHQAIABzAGUAYwB0AG8AcgAgADAAeAAlADEAIQB4ACEAJQAyACEAeAAhAC4ADQAKAAAADAABAA0ACgAAAAAAFAABACUAMQAlADAADQAKAAAAAAAwAAEAKAB1AG4AawBuAG8AdwBuAC8AdQBuAG4AYQBtAGUAZAApACUAMAANAAoAAABcAAEARgBpAGwAZQAgAG4AbwB0ACAAZgBvAHUAbgBkACAAbwByACAAdQBuAGEAYgBsAGUAIAB0AG8AIABhAGMAYwBlAHMAcwAgAGYAaQBsAGUALgANAAoAAAAAANAAAQAqACoAKgBXAGEAcgBuAGkAbgBnADoAIABWAG8AbAB1AG0AZQBzACAAbwBuACAAZAB5AG4AYQBtAGkAYwAgAGQAaQBzAGsAcwAgACgAbwB0AGgAZQByACAAdABoAGEAbgAgAHMAaQBtAHAAbABlACAAdgBvAGwAdQBtAGUAcwApAA0ACgAgACAAIAAgACAAIAAgACAAIAAgACAAIABhAHIAZQAgAG4AbwB0ACAAcwB1AHAAcABvAHIAdABlAGQALgANAAoADQAKAAAAAADIAAEAKgAqACoAUABoAHkAcwBpAGMAYQBsACAAcwBlAGMAdABvAHIAIAAlADEAIAAoADAAeAAlADIAKQAgAGkAcwAgAG4AbwB0ACAAaQBuACAAYQBuAHkAIABwAGEAcgB0AGkAdABpAG8AbgAgAG8AbgAgACUAMwAsAA0ACgBvAHIAIAAlADMAIABpAHMAIABuAG8AdAAgAGEAIABsAGUAZwBhAGwAIABkAGUAdgBpAGMAZQAgAG4AYQBtAGUALgANAAoAAAAAAJgAAQAqACoAKgBQAGgAeQBzAGkAYwBhAGwAIABzAGUAYwB0AG8AcgAgACUAMQAgACgAMAB4ACUAMgApACAAaQBzACAAaQBuACAAZAByAGkAdgBlACAAJQAzACEAYwAhACAAYgB1AHQAIABpAHMADQAKAG4AbwB0ACAAaQBuACAAYQBuAHkAIABmAGkAbABlAC4ADQAKAAAAiAABACoAKgAqAEwAbwBnAGkAYwBhAGwAIABzAGUAYwB0AG8AcgAgACUAMQAgACgAMAB4ACUAMgApACAAbwBuACAAZAByAGkAdgBlACAAJQAzACEAYwAhACAAaQBzACAAbgBvAHQAIABpAG4AIABhAG4AeQAgAGYAaQBsAGUALgANAAoAAAAAAKgAAQBUAGgAZQAgAG0AYQBzAHQAZQByACAAZgBpAGwAZQAgAHQAYQBiAGwAZQAgAGEAcABwAGUAYQByAHMAIAB0AG8AIABiAGUAIABkAGEAbQBhAGcAZQBkAC4AIABUAGgAZQAgAGQAaQBzAGsAIABtAGEAeQAgAGIAZQANAAoAcwBlAHYAZQByAGUAbAB5ACAAZABhAG0AYQBnAGUAZAAuAA0ACgAAAGQAAQBUAGgAZQAgAE0ARgBUACAAaQBzACAAZABhAG0AYQBnAGUAZAAgAGEAdAAgAGYAaQBsAGUAIAByAGUAYwBvAHIAZAAgAHMAZQBnAG0AZQBuAHQAIAAlADEALgANAAoAAABQAAEAcABoAHkAcwBpAGMAYQBsACAAcwBlAGMAdABvAHIAcwAgACUAMQAtACUAMgAgACgAMAB4ACUAMwAtADAAeAAlADQAKQANAAoAAAAAAIwAAQAqACoAKgBQAGgAeQBzAGkAYwBhAGwAIABzAGUAYwB0AG8AcgAgACUAMQAgACgAMAB4ACUAMgApACAAaQBzACAAaQBuACAAZgBpAGwAZQAgAG4AdQBtAGIAZQByACAAJQAzACAAbwBuACAAZAByAGkAdgBlACAAJQA0ACEAYwAhAC4ADQAKAAAAjAABACoAKgAqAEwAbwBnAGkAYwBhAGwAIABzAGUAYwB0AG8AcgAgACUAMQAgACgAMAB4ACUAMgApACAAbwBuACAAZAByAGkAdgBlACAAJQA0ACEAYwAhACAAaQBzACAAaQBuACAAZgBpAGwAZQAgAG4AdQBtAGIAZQByACAAJQAzAC4ADQAKAAAAAAAYAAEARgBpAGwAZQAgACUAMQANAAoAAAAgAAEAIAAoAHIAZQBzAGkAZABlAG4AdAApAA0ACgAAACgAAQAgACgAbgBvAG4AcgBlAHMAaQBkAGUAbgB0ACkADQAKAAAAAABMAAEAbABvAGcAaQBjAGEAbAAgAHMAZQBjAHQAbwByAHMAIAAlADEALQAlADIAIAAoADAAeAAlADMALQAwAHgAJQA0ACkADQAKAAAAPAABAEEAdAB0AHIAaQBiAHUAdABlACAAVAB5AHAAZQAgADAAeAAlADEAIQB4ACEAJQAwAA0ACgAAAAAAQAABAE0AYQBzAHQAZQByACAARgBpAGwAZQAgAFQAYQBiAGwAZQAgACgAJABNAGYAdAApACUAMAANAAoAAAAAAFQAAQBNAGEAcwB0AGUAcgAgAEYAaQBsAGUAIABUAGEAYgBsAGUAIABNAGkAcgByAG8AcgAgACgAJABNAGYAdABNAGkAcgByACkAJQAwAA0ACgAAADQAAQBMAG8AZwAgAEYAaQBsAGUAIAAoACQATABvAGcARgBpAGwAZQApACUAMAANAAoAAAAsAAEARABBAFMARAAgACgAJABWAG8AbAB1AG0AZQApACUAMAANAAoAAAAAAFgAAQBBAHQAdAByAGkAYgB1AHQAZQAgAEQAZQBmAGkAbgBpAHQAaQBvAG4AIABUAGEAYgBsAGUAIAAoACQAQQB0AHQAcgBEAGUAZgApACUAMAANAAoAAAAsAAEAUgBvAG8AdAAgAEQAaQByAGUAYwB0AG8AcgB5ACUAMAANAAoAAAAAADwAAQBWAG8AbAB1AG0AZQAgAEIAaQB0AG0AYQBwACAAKAAkAEIAaQB0AE0AYQBwACkAJQAwAA0ACgAAADgAAQBCAG8AbwB0ACAAUwBlAGMAdABvAHIAcwAgACgAJABCAG8AbwB0ACkAJQAwAA0ACgAAAAAARAABAEIAYQBkACAAQwBsAHUAcwB0AGUAcgAgAEwAaQBzAHQAIAAoACQAQgBhAGQAQwBsAHUAcwApACUAMAANAAoAAAAsAAEAUQB1AG8AdABhACAAKAAkAFEAdQBvAHQAYQApACUAMAANAAoAAAAAADwAAQBVAHAAYwBhAHMAZQAgAFQAYQBiAGwAZQAgACgAJABVAHAAQwBhAHMAZQApACUAMAANAAoAAAAAADwAAQBFAHgAdABlAG4AZAAgAFQAYQBiAGwAZQAgACgAJABFAHgAdABlAG4AZAApACUAMAANAAoAAAAAADQAAQBTAGUAYwB1AHIAaQB0AHkAIAAoACQAUwBlAGMAdQByAGUAKQAlADAADQAKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAQAQAAAAAAAG5maS5kYmcAMzg2XG5maS5leGUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYBQAAFIAAAAAAAAABQAAAMAUAADcAQAARQAAAAUAABSgFgAAeQMAAL8BAAAFAAAUIBoAAOAAAAATAAAAAwAAAgAbAAAZAQAAGgAAAAMAAAMgHAAAGgAAAAAAAAABAAACQBwAADMGAACRAAAABwAAFIAiAACUAQAANgAAAAUAABQgJAAAWwEAAA4AAAAEAAADgCUAAHwAAAABAAAAAQAAAwAmAABjAAAAAAAAAAEAAANwJgAAeAAAAAIAAAADAAAD8CYAAFwBAACAAAAAAwAAFFAoAACcAQAA8AQAAAQAABTwKQAAtwEAAAAAAAAEAAAAsCsAAKUCAAAAAAAAAQAAAGAuAADaAAAACgQAAAQAAANALwAAiwEAAB0AAAACAAAD0DAAACIAAAAAAAAAAQAAAQAxAAAkAAAAAAAAAAUAAAAwMQAAHwAAAAAAAAAEAAAAUDEAAL8AAAAAAAAAAwAAAxAyAAAfAAAAAQAAAAIAAAAwMgAAMwAAAAEAAAACAAAAcDIAACACAAA2AAAAAgAAFJA0AADqAAAAAAAAAAIAABSANQAAzAAAAAAAAAACAAAU4DcAABMAAAAAAAAAAAAAAAA4AAADAAAAAAAAAAEAAAAQOAAAAQAAAAAAAAAAAAAA" | |
error_sectors = get_disk_errors() | |
path = 'nfi.exe' | |
temp = False | |
if not os.path.exists(path): | |
fd, path = tempfile.mkstemp(suffix='_nfi.exe') | |
code = base64.b64decode(nfi_exe) | |
os.write(fd, code) | |
#print(f"nfi.exe temporary written as {path}") | |
os.close(fd) | |
temp = True | |
result = '' | |
check_duplicates = {} | |
try: | |
for disk, sect, _ in error_sectors: | |
if not sect or not disk: | |
continue | |
_, text = call_with_output([path, disk, sect]) | |
if not text or "Usage: nfi drive-letter" in text: | |
print(f'Something went wrong! Disk: {disk}, sector: {sect}') | |
break | |
text = text.replace('\r', '').replace('\n\n', '\n') | |
lines = text.split("\n")[3:] | |
lines = [ | |
line[4:] if line[:4] == " " else line for line in lines if ( | |
"$STANDARD_INFORMATION (resident)" not in line and "$FILE_NAME (resident)" not in line) | |
] | |
md5 = hashlib.md5(lines[2].encode("utf-8")).hexdigest() #file path should be in lines[2] | |
if md5 not in check_duplicates: | |
check_duplicates[md5] = True | |
text = '\n'.join(lines) + '\n' | |
result += text | |
finally: | |
if temp: | |
os.remove(path) | |
if result.strip(): | |
with open("errors.txt", "w") as f: f.write(result) | |
# or maybe instead | |
print(result) # to use >errors.txt operator to output into a file | |
else: | |
print("No bad sectors reported") |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment