#!/usr/bin/env python

#This little script displays Bios Information Block entries
#from a FAT bootsector.

#Author: Seth de l'Isle <szoth@ubertechnique.com> 
#(c) 2004 GE Security -- Supra

#The GNU GPL is available here: http://www.gnu.org/copyleft/gpl.html

#This program is free software; you can redistribute it and/or
#modify it under the terms of the GNU General Public License
#as published by the Free Software Foundation; either version 2
#of the License, or (at your option) any later version.
#
#This program is distributed in the hope that it will be useful,
#but WITHOUT ANY WARRANTY; without even the implied warranty of
#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#GNU General Public License for more details.

#You should have received a copy of the GNU General Public License
#along with this program; if not, write to the Free Software
#Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

import struct, sys

TARGET=sys.argv[1]

bootInfoConstants = {  "OEM ID": (0x03, 8),
           "BytesPerSector": (0x0b, 2),
	   "SectorsPerCluster": (0x0d, 1),
	   "ReservedSectors": (0x0e, 2),
	   "NumberOfFats": (0x10, 1),
	   "RootEntries": (0x11, 2),
	   "NumberOfSectors": (0x13,2),
	   "MediaDescriptor": (0x15, 1),
	   "SectorsPerFAT": (0x16, 2),
	   "SectorsPerHead": (0x18, 2),
	   "HeadsPerCylinder": (0x1a, 2),
	   "HiddenSectors": (0x1c, 4),
	   "BigNumberOfSectors": (0x20, 4),
	   "BigSectorsPerFAT": (0x24, 4),
	   "ExtFlags": (0x28, 2),
	   "FSVersion": (0x2a, 2),
	   "RootDirectoryStart": (0x2c, 4),
	   "FSInfoSector": (0x30, 2),
	   "BackupBootSector": (0x32, 2),
	   }



class BootInfoTable:
    def __init__(self, bootSectorFile="bootsect.bin"):
	self.bootSector = open(bootSectorFile).read()

    def _get_raw_item(self, constantName):
	offset, length = bootInfoConstants[constantName]
	return self.bootSector[offset:offset + length]

    def _set_raw_item(self, constantName, value):
	offset, length = bootInfoConstants[constantName]
	newBootSector = ( self.bootSector[:offset] + value +
	                  self.bootSector[offset+length:] )

	self.bootSector = newBootSector 

    def __getitem__(self, constantName):
	rawItem = self._get_raw_item(constantName)

	if len(rawItem) == 1:
	    return ord(rawItem)

	elif len(rawItem) == 2:
	    return struct.unpack("h", rawItem)[0]

	elif len(rawItem) == 4:
	    return struct.unpack("l", rawItem)[0]

	elif len(rawItem) == 8:
	    return rawItem

	else:
	    raise "reading: alien constant size"

    def __setitem__(self, constantName, value):
	rawItem = self._get_raw_item(constantName)

	if len(rawItem) == 1:
	    newRawItem = chr(value) 

	elif len(rawItem) == 2:
	    newRawItem = struct.pack("h", value)

	elif len(rawItem) == 4:
	    newRawItem =  struct.pack("l", value)

	elif len(rawItem) == 8:
	    newRawItem = value

	else:
	    raise "setting: alien constant size"

	self._set_raw_item(constantName, newRawItem)

if __name__ == '__main__':

    bit = BootInfoTable(TARGET)

    for key in bootInfoConstants.keys():
	    print key, ':',  bit[key] 
