Чтение загрузочного сектора в Windows

Я создал небольшую программу на питоне, которая читает загрузочный сектор на низком уровне, чтобы не повредить устройство. Вчера я успешно запустил эту программу в Linux, и мне пришла в голову идея сделать то же самое в Windows. Но единственная проблема, которая пришло то, что я не смог прочитать, например: \Device\Harddisk0\Partition1, загрузочный раздел или \Device\Harddisk0\DR0, необработанный диск 0. Каждый раз, когда я пытаюсь, он говорит мне: No such a file or a directory

Что я делаю неправильно?


person Zeiad Badawy    schedule 31.12.2016    source источник
comment
Вы пробовали с префиксом \\.? Это open("\\\\.\\Device\\Harddisk0\\Partition1")   -  person selbie    schedule 01.01.2017
comment
вы не можете использовать тот же метод: загрузочный сектор не отображается в файле. Где вы прочитали, что на винде так можно было?   -  person Jean-François Fabre    schedule 01.01.2017
comment
Это дает мне ту же ошибку   -  person Zeiad Badawy    schedule 01.01.2017
comment
\Device\Harddisk0\DR0 находится в пространстве имен объектов. API Windows выборочно использует это пространство имен, например. глобальные символические ссылки на устройства создаются в \GLOBAL??, например. C: =› \Device\HarddiskVolume2. Устаревшее пространство имен DOS позволяет вам использовать здесь некоторые ссылки на устройства, такие как буквы дисков и устаревшие устройства DOS, такие как CON, но для доступа ко всему, что вам нужно, один из префиксов устройств WinAPI, либо \\.\ (некоторая обработка пути и косая черта разрешена, но ограничена MAX_PATH символами) или \\?\ (без обработки пути; должен быть Unicode и использовать обратную косую черту).   -  person Eryk Sun    schedule 01.01.2017
comment
Вы ищете ссылку \\.\PhysicalDrive0, которая открывает \Device\Harddisk0\DR0. Аналогично \\.\PhysicalDrive1 открывает \Device\Harddisk1\DR1. Другой, \Device\Harddisk0\Partition1, является томом, а не диском. Вы можете просто открыть букву тома или точку подключения GUID, например. \\.\C:. Но вы не можете жестко закодировать это. Вы должны использовать API для сопоставления тома по букве диска, имени тома GUID или точке подключения NTFS с номером физического диска.   -  person Eryk Sun    schedule 01.01.2017
comment
Я попробовал t = open(r"\\.\PhysicalDrive0") и получил ошибку: Permission Denied. Поэтому я сделал это в своей командной строке от имени администратора, и это дало мне: OSError: [WinError 1] Incorrect Function   -  person Zeiad Badawy    schedule 01.01.2017
comment
Высокоуровневый ввод-вывод Python пытается определить файл, но это не удается. Используйте disk_fd = os.open( r"\\.\PhysicalDrive0", os.O_RDONLY | os.O_BINARY); data = os.read(disk_fd, 512); os.close(disk_fd).   -  person Eryk Sun    schedule 01.01.2017
comment
Что именно вы читаете в Linux? Нам нужно знать, пытаетесь ли вы прочитать основную загрузочную запись / таблицу разделов GUID на диске или загрузочную запись тома на томе. Если вы хотите прочитать VBR для системного диска, откройте '\\.\%s' % os.environ['SystemDrive']. Это почти всегда будет \\.\C:.   -  person Eryk Sun    schedule 01.01.2017


Ответы (2)


Правильный способ сделать это:

import os
disk_fd = os.open( r"\\.\PhysicalDrive0", os.O_RDONLY | os.O_BINARY)
data = os.read(disk_fd, 512)
os.close(disk_fd)

Спасибо @eryksun

person Zeiad Badawy    schedule 10.03.2017

все зависит от NT или WIN32 API, который вы используете. ZwOpenFile или CreateFileW ?

\Device\Harddisk0\Partition1 является форматом имени NT и должен использоваться только в ZwOpenFile или ZwCreateFile.

для использования этого имени в CreateFileW вы должны добавить к нему префикс \\?\globalroot

поэтому пример кода - (с использованием вызовов NT и win32 в одной функции)

void xxx()
{
    HANDLE hFile;
    IO_STATUS_BLOCK iosb;
    UNICODE_STRING ObjectName;
    OBJECT_ATTRIBUTES oa = { sizeof(oa), 0, &ObjectName, OBJ_CASE_INSENSITIVE };
    RtlInitUnicodeString(&ObjectName, L"\\Device\\Harddisk0\\Partition1");

    UCHAR buf[0x200];
    if (0 <= ZwOpenFile(&hFile, FILE_GENERIC_READ, &oa, &iosb, FILE_SHARE_VALID_FLAGS, FILE_SYNCHRONOUS_IO_NONALERT))
    {
        LARGE_INTEGER ByteOffset = {};
        ZwReadFile(hFile, 0, 0, 0, &iosb, buf, sizeof(buf), &ByteOffset, 0);
        ZwClose(hFile);
    }

    hFile = CreateFile(L"\\\\?\\globalroot\\Device\\Harddisk0\\Partition1", FILE_GENERIC_READ, FILE_SHARE_VALID_FLAGS,
        0, OPEN_EXISTING, 0, 0);

    if (hFile != INVALID_HANDLE_VALUE)
    {
        OVERLAPPED ov = {};
        ULONG n;
        ReadFile(hFile, buf, sizeof(buf), &n, &ov);
        CloseHandle(hFile);
    }
}

также вы можете использовать следующие SymbolicLinks с CreateFileW :

  • \\?\Harddisk<X>Partition<Y> - для раздела (1,2,..) на жестком диске (0,1,..)
  • \\?\PhysicalDrive<X> для жесткого диска (0,1,..)

все зависит от того, как вы получили эти пути? или вы просто жестко кодируете это?

person RbMm    schedule 31.12.2016
comment
Это просто ссылка на том, например. \Device\HarddiskVolume1, так почему бы вам просто не открыть обычную букву диска, имя тома GUID или точку монтирования NTFS? Например, \\.\C:. В противном случае, если вы хотите открыть базовые диски, вам придется открыть том и получить экстенты диска через IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS и откройте соответствующий файл \\.\PhysicalDrive[N]. И все это без необходимости обращаться к собственному пространству имен объектов, чего следует избегать при программировании для Windows. Майкрософт не поддерживает его. - person Eryk Sun; 01.01.2017
comment
@eryksun - о том, как / какие имена используются - зависит от того, как OP получил (или вычислил) \Device\Harddisk0\Partition1, или он просто жестко закодировал это? я не пытаюсь рассказать здесь, как нужно перечислять/открывать диски, разделы, тома. в чем разница между этими объектами. я только объясняю разницу в формате имени для конкретного жестко заданного имени - person RbMm; 01.01.2017
comment
Я просто объясняю, что эти нативные пути к объектам не должны использоваться в программировании пользовательского режима Windows, если нет другого способа что-то сделать. В данном случае это не нужно. - person Eryk Sun; 01.01.2017
comment
@eryksun - да, я слушаю это уже много раз :) у меня нет конкретных советов по использованию (nt или win32 api), просто покажите код как для случая, так и для разных имен (префикс \\?\globalroot), однако главный вопрос здесь - какова цель OP, как правильно перечислять диски или разделы (тома).. я не освещаю это. может быть лучше вообще удалить мой ответ? - person RbMm; 01.01.2017