This recipe will display a hex dump of the disk specified on the command line. As the last two arguments, the program takes the first sector and last sector that should be displayed by this utility. The size of the sectors is stored in a variable created right after the imports executed by this script. The main feature of this recipe is its cross OS capabilities as demonstrated in get_data.
| Python |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 | import os
import sys
SECTOR_SIZE = 512
def main():
try:
if len(sys.argv) != 4:
raise Exception('Not Enough Arguments')
else:
program(sys.argv[1], int(sys.argv[2]), int(sys.argv[3]))
except Exception, error:
print os.path.basename(sys.argv[0]), '<drive> <first> <last>'
print 'Note:', error
def program(drive, first, last):
if first > last:
first, last = last, first
data = get_data(drive, first, last)
sectors = partition(data, SECTOR_SIZE)
show_hex(first, last, sectors)
def get_data(drive, first, last):
if os.name == 'posix':
drive = file('/dev/' + drive)
elif os.name == 'nt':
drive = file(r'\\.\%s:' % drive)
else:
raise Exception('Do Not Know How To Access Drives')
return read_all(drive, first, last - first + 1)
def read_all(drive, start_sector, sectors_to_read):
start = start_sector * SECTOR_SIZE
end = sectors_to_read * SECTOR_SIZE
all_data = ''
while start > 0:
temp = drive.read(start)
if not temp:
temp = drive.read(start)
if not temp:
raise Exception('Cannot Read First Sector')
start -= len(temp)
assert start == 0
while end > 0:
temp = drive.read(end)
if not temp:
temp = drive.read(end)
if not temp:
if not all_data:
raise Exception('Cannot Find Requested Data')
return all_data
all_data += temp
end -= len(temp)
assert end == 0
return all_data
def partition(string, size):
if len(string) % size:
parts = len(string) / size + 1
else:
parts = len(string) / size
return [string[index*size:index*size+size] for index in range(parts)]
def show_hex(first, last, sectors):
print '=' * 77
for index in range(len(sectors)):
print 'SECTOR', index + first
print '=' * 77
engine(sectors[index], index + first)
print '=' * 77
def engine(string, sector):
parts = partition(string, 16)
rule = printable()
for index in range(len(parts)):
print ' | '.join([hex(index + sector * 32)[2:].upper().zfill(7)[-7:] + '0', \
pad_right(convert_hex(parts[index]), 47), \
convert_print(parts[index], rule)])
def printable():
return ''.join([chr(byte) for byte in range(256) \
if len(repr(chr(byte))) == 3 or byte == ord('\\')])
def pad_right(string, length, padding=' '):
return string + padding[0] * (length - len(string))
def convert_hex(string):
return ' '.join([hex(ord(character))[2:].upper().zfill(2) \
for character in string])
def convert_print(string, rule):
return ''.join([character in rule and character \
or '.' for character in string])
if __name__ == '__main__':
main()
|
Discussion
If you are wondering what is on a disk, then this recipe can be very helpful in getting you an answer.


Comments
While I likely won't be using your recipe specifically, knowing how to open the raw disk on Windows is terribly convenient.
I had had an interest in looking at boot sectors, and this was a great place to start. I did have to change the file open mode to 'rb' to get things to work properly. And I later discovered how to open the physical drive (windows) using a filename such as:
r"\.\PhysicalDrive0"
in addition to example's r"\.\C:" form for opening a logical drive.
Sign in to comment