Martin Matysiak Martin Matysiak - 1 year ago 194
Python Question

Is it possible to get writing access to raw devices using python with windows?

This is sort of a follow-up to this question. I want to know if you can access raw devices (i.e.

) in writing mode and if this should be the case, how.

Using Linux, write access can simply be achieved by using e.g.
open("/dev/sdd", "w+")
(provided that the script is running with root permissions). I assume that Mac OS behaves similar (with
as input file).

When trying the same command under Windows (with the corresponding path), it fails with the following error:

IOError: [Errno 22] invalid mode ('w+') or filename: '\\\\.\\PhysicalDrive3'

However, when trying to read from the PhysicalDrive, it does work (even the correct data is read). The shell is running with administrator permissions under Windows 7.

Is there any other way to accomplish this task using python while still keeping the script as platform-independent as possible?


I looked a bit further into what methods python provides for file handling and stumbled across Opening the PhysicalDrive using, os.O_WRONLY|os.O_BINARY)
returns no error. So far, so good. Now I have either the choice to write directly to this file-descriptor using os.write, or use os.fdopen to get a file-object and write to it in the regular way.
Sadly, none of these possibilities works. In the first case (
), I get this:

>>> os.write("\\\\.\\PhysicalDrive3", os.O_WRONLY|os.O_BINARY), "test")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
OSError: [Errno 22] Invalid argument

In the second case, I can create a file object with write permissions, but the writing itself fails (well, after enforcing its execution using

>>> g = os.fdopen("\\\\.\\PhysicalDrive3", os.O_WRONLY|os.O_BINARY), "wb")
>>> g.write("test")
>>> g.flush()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
IOError: [Errno 22] Invalid argument

Answer Source

As eryksun and agf pointed out in the comments (but I didn't really get it at first), the solution is rather simple: you have to open the device in the rb+ mode, which opens the device for updating (as I have found out now..) without trying to replace it with a new file (which wouldn't work because the file is in fact a physical drive).

When writing, you have to write always a whole sector at a time (i.e. multiples of 512-byte), otherwise it fails.

In addition, the .seek() command can also jump only sector-wise. If you try to seek a position inside a sector (e.g. position 621), the file object will jump to the beginning of the sector where your requested position is (i.e. to the beginning of the second sector, byte 512).