Прямой доступ к диску для записи в Windows 7


Прямой доступ к диску для записи в Windows 7

При разработке программы для защиты флешек от вирусов возникла необходимость записи секторов напрямую на диск. Прямой доступ к диску осуществлялся через функцию CreateFile. Под Windows XP все работало нормально, а под Windows 7 при попытке записи сектора возвращалась ошибка Access Denied, при том, что при открытии диска на запись никаких ошибок не возникало. После длительных поисков причины было выяснено следующее: еще в самом начале разработки в Windows 7 была обнаружена критическая уязвимость. Если не вдаваться в нудные технические подробности, то смысл ее заключался в том, что злоумышленник мог открыть системный диск напрямую для записи и поместить любой злонамеренный код в файл подкачки. В Microsoft решили проблему с присущей им дубовой прямолинейностью - просто взяли и запретили прямую запись на диски. Но поскольку нельзя, но было очень нужно, то способ обхода защиты нашелся очень быстро. Оказывается, что запись на диски запрещена не полностью, система разрешает записывать данные в нулевую дорожку диска и в неразмеченные области. Такое поведение вполне объяснимо: надо же как-то форматировать диски штатными средствами без дополнительных танцев с бубнами. Значит для того, чтобы система разрешила запись в произвольное место диска, она сперва должна определить его как неразмеченный. А это достигается уничтожением нулевого сектора диска перед записью. Естественно, что перед уничтожением надо сохранить все данные из нулевого сектора в сухом прохладном месте, а потом вернуть их обратно.

Порядок действий следующий: открыть диск для чтения-записи, попробовать записать нужный сектор. Если произошла ошибка Access Denied, то надо прочитать нулевой сектор, записать вместо него нули, после этого обязательно закрыть диск. Это нужно, чтобы система при повторном обращении посчитала диск неразмеченным и разрешила запись в любой сектор. Затем снова открываем диск для чтения-записи. После записи нужных данных восстанавливаем нулевой сектор и закрываем диск. Все, наша задача выполнена, данные записаны, система спокойна. У этого способа есть и минусы. Так, если работа вашей программы по какой-то причине завершилась аварийно до момента, когда она восстановила нулевую дорожку, то данные на диске могут стать недоступны или вообще потеряться. Способ проверен и хорошо работает на съемных дисках с файловой системой FAT/FAT32, на стационарных жестких дисках и других файловых системах я его не проверял.

Вот фрагмент кода на Ассемблере, взятый из рабочего проекта. При необходимости его можно легко портировать на другие языки программирования.
        ; Открыть диск для чтения и записи
        invoke  CreateFile,drvName,GENERIC_READ+GENERIC_WRITE,\
                FILE_SHARE_READ+FILE_SHARE_WRITE,NULL,OPEN_EXISTING,0,NULL
        ; Сохранить хэндл
        mov     [hFile],eax
 
        ; Сразу прочитать нулевую дорожку
        invoke  ReadFile,[hFile],mbr,512,tmp,NULL
 
        ; Установить смещение на нужный сектор
        invoke  SetFilePointer,[hFile],512*numberofsector,0,FILE_BEGIN
 
        ; Попытаться записать нужный сектор
        invoke  WriteFile,[hFile],new_sector,512,tmp,NULL
        or      eax,eax
        ; Ошибок записи не произошло
        jnz     close_drive_and_exit
 
        ; Получить код последней ошибки
        invoke  GetLastError
        ; Ошибка Access Denied?
        cmp     eax,5
        ; Произошла какая-то другая критическая ошибка
        jne     close_drive_and_exit
 
        ; Уничтожить нулевую дорожку
        invoke  SetFilePointer,[hFile],0,0,FILE_BEGIN
        invoke  WriteFile,[hFile],zerobuff,512,tmp,NULL
        ; Закрыть диск
        invoke  CloseHandle,[hFile]
 
        ; Открыть заново диск с уничтоженной дорожкой
        invoke  CreateFile,drvName,GENERIC_READ+GENERIC_WRITE,\
                FILE_SHARE_READ+FILE_SHARE_WRITE,NULL,OPEN_EXISTING,0,NULL
        ; Сохранить хэндл
        mov     [hFile],eax
 
        ; Установить смещение на нужный сектор
        invoke  SetFilePointer,[hFile],512*numberofsector,0,FILE_BEGIN
 
        ; Записать нужный сектор
        invoke  WriteFile,[hFile],new_sector,512,tmp,NULL
 
        ; Записать нулевую дорожку обратно
        invoke  SetFilePointer,[hFile],0,0,FILE_BEGIN
        invoke  WriteFile,[hFile],mbr,512,tmp,NULL
 
close_drive_and_exit:
        ; Закрыть диск
        invoke  CloseHandle,[hFile]

Код приведен минимально необходимый, без дополнительной обработки возможных ошибок. В реальной ситуации, конечно, надо позаботиться о лучшей сохранности прочитанной нулевой дорожки, об обработке ситуации в случае ошибки записи данных на диск с уничтоженной нулевой дорожкой и т.д. Все это вы можете сделать самостоятельно.

Не зря говорится: "Что бы русский ни делал - все равно получается автомат Калашникова". Хотел как лучше, а в результате нашел способ как лишний раз наклонить защиту системы :)
Теги:
защита, взлом, флешка
Добавлено: 21 Сентября 2013 01:30:09 Добавил: Андрей Ковальчук Нравится 0
Добавить
Комментарии:
Нету комментариев для вывода...