From 5d7322f5bfece81b9803bafcf4d695a0160fda55 Mon Sep 17 00:00:00 2001 From: thecompu Date: Mon, 8 Feb 2016 19:27:40 -0600 Subject: [PATCH] Added argparse module and rewrote script based upon use. All initial crawls through the DIBs now record strictly decimabls unless output is ascii. At CSV write time, adjustments are made based upon options thrown when you run the script. New options include -rd for all decimal output and -rh for all hex output. Not specifying those arguments will get you more English friendly output. --- Driv3rs.py | 202 ++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 145 insertions(+), 57 deletions(-) diff --git a/Driv3rs.py b/Driv3rs.py index f0a0508..591a2c8 100644 --- a/Driv3rs.py +++ b/Driv3rs.py @@ -1,28 +1,29 @@ # use unpack from struct and argv from sys -from struct import unpack; from sys import argv +from struct import unpack; import argparse import hashlib import os.path - -# setup args as a variable to hold argv -- there will be three -# in total script, input file, output file. -args = argv -usage = """ + +parser = argparse.ArgumentParser( + prog='Driv3rs.py', + formatter_class=argparse.RawDescriptionHelpFormatter, + description='''\ **************************************************************** * Driv3rs.py - A tiny Python script to help catalog drivers on * * imaged Apple /// disks. By Mike Whalen, Michael Sternberg * * and Paul Hagstrom. Please submit pull requests to Github. * * https://github.com/thecompu/Driv3rs * **************************************************************** -\nUsage: python Driv3rs.py [SOS_DRIVER_FILE] [output_file.csv]\n -""" +''') +group = parser.add_mutually_exclusive_group() +group.add_argument("-rh", "--rawhex", action="store_true", help="Store hex values in CSV") +group.add_argument("-rd", "--rawdec", action="store_true", help="Store decimal values in CSV") +parser.add_argument("sosfile", help="sos.driver file to parse") +parser.add_argument("csvfile", help="csv file to create") +args = parser.parse_args() -# check that user passed required number of arguments -if len(args) < 3: - print usage - exit() # stick passed arugments into variables for later -disk_img = args[1] -output_csv = args[2] +disk_img = args.sosfile +output_csv = args.csvfile # this function unpacks several read operations -- # text, binary, and single-byte. Each uses unpack from @@ -120,6 +121,10 @@ while loop : # utilizing the offsets found, we now push through each Device information # Block to log information about a driver. Comments therein. +# For nearly all entries, we write decimal values to our initial dictionaries +# then convert to desired output at csv time. Excluded would be ascii strings +# and the version numbers. + # first deal with comment length and comment text. # comment length is two bytes (either the length in hex or 0x0000) # log both to list/dictionary @@ -165,21 +170,13 @@ for i in range(0,len(drivers_list)): # or shall be loaded on a page boundary. This is set up in # the System Configuration Program flag = readUnpack(1, type = '1') - if flag == 192: - drivers_list[i]['flag'] = 'ACTIVE, Load on Boundary' - elif flag == 128: - drivers_list[i]['flag'] = 'ACTIVE' - else: - drivers_list[i]['flag'] = 'INACTIVE' + drivers_list[i]['flag'] = flag # if the driver is for a card that is loaded into a slot # and that slot has been defined in the SCP and placed into # the current SOS.DRIVER file, we log it here. slot_num = readUnpack(1, type = '1') - if slot_num == 0: - drivers_list[i]['slot_num'] = 'None' - else: - drivers_list[i]['slot_num'] = slot_num + drivers_list[i]['slot_num'] = slot_num # the unit byte is concerned with the device number encountered. # for the major drivers, it's always 0 and if there are other @@ -194,10 +191,7 @@ for i in range(0,len(drivers_list)): # The type is determined via two bytes. The LSB is the sub-type # and the MSB is the type. dev_type = readUnpack(2, type ='b') - try: - drivers_list[i]['dev_type'] = dev_types[dev_type] - except: - drivers_list[i]['dev_type'] = 'Unknown' + drivers_list[i]['dev_type'] = dev_type # we skip the Filler byte ($19) as Apple reserved it. SOSfile.seek(1,1) @@ -207,10 +201,7 @@ for i in range(0,len(drivers_list)): # we log the block number defined or that the the device is # a character device. otherwise Undefined block_num = readUnpack(2, type = 'b') - if block_num != 0: - drivers_list[i]['block_num'] = block_num - else: - drivers_list[i]['block_num'] = 'Character Device or Undefined' + drivers_list[i]['block_num'] = block_num # the manufacturer byte was ill-defined at the time the driver # writer's manual was published. 1 through 31 were reserved for @@ -219,13 +210,7 @@ for i in range(0,len(drivers_list)): # and the CFFA3000 and populated a dictionary. This dictionary # will get more k/v pairs as time goes on. mfg = readUnpack(2, type = 'b') - try: - drivers_list[i]['mfg'] = mfgs[mfg] - except: - if 1 <= mfg <= 31: - drivers_list[i]['mfg'] = 'Apple Computer' - else: - drivers_list[i]['mfg'] = hex(mfg) + drivers_list[i]['mfg']=mfg # version bytes are integer values stored across two bytes. # a nibble corresponds to a major version number, one of two minor @@ -311,24 +296,127 @@ else: csvout = open(output_csv, 'a') for i in range(0,len(drivers_list)): - csvout.write(disk_img + ',' + \ - hex(drivers_list[i]['comment_start']) + ',' + \ - hex(drivers_list[i]['comment_len']) + ',' + \ - '"' + drivers_list[i]['comment_txt'] + '"' + ',' + \ - hex(drivers_list[i]['dib_start']) + ',' + \ - hex(drivers_list[i]['link_ptr']) + ',' + \ - hex(drivers_list[i]['entry']) + ',' + \ - hex(drivers_list[i]['name_len']) + ',' + \ - drivers_list[i]['name'] + ',' + \ - '"' + drivers_list[i]['flag'] + '"' + ',' + \ - str(drivers_list[i]['slot_num']) + ',' + \ - str(drivers_list[i]['num_devices']) + ',' + \ - str(drivers_list[i]['unit']) + ',' + \ - '"' + drivers_list[i]['dev_type'] + '"' + ',' + \ - str(drivers_list[i]['block_num']) + ',' + \ - drivers_list[i]['mfg'] + ',' + \ - str(drivers_list[i]['version']) + ',' + \ - str(drivers_list[i]['dcb_length']) + ',' + \ + csvout.write(disk_img + ',') +#comment start hex or decimal + if args.rawhex: + csvout.write(hex(drivers_list[i]['comment_start']) + ',') + else: + csvout.write(str(drivers_list[i]['comment_start']) + ',') + +#comment length hex or decimal + if args.rawhex: + csvout.write(hex(drivers_list[i]['comment_len']) + ',') + else: + csvout.write(str(drivers_list[i]['comment_len']) + ',') + +#comment + csvout.write('"' + drivers_list[i]['comment_txt'] + '"' + ',') + +#dib_start hex or decimal + if args.rawhex: + csvout.write(hex(drivers_list[i]['dib_start']) + ',') + else: + csvout.write(str(drivers_list[i]['dib_start']) + ',') + +#link_ptr hex or decimal + if args.rawhex: + csvout.write(hex(drivers_list[i]['link_ptr']) + ',') + else: + csvout.write(str(drivers_list[i]['link_ptr']) + ',') + +#entry hex or decimal + if args.rawhex: + csvout.write(hex(drivers_list[i]['entry']) + ',') + else: + csvout.write(str(drivers_list[i]['entry']) + ',') + +#name_len hex or decimal + if args.rawhex: + csvout.write(hex(drivers_list[i]['name_len']) + ',') + else: + csvout.write(str(drivers_list[i]['name_len']) + ',') + +#name ascii only + csvout.write(drivers_list[i]['name'] + ',' ) + +#flag hex or decimal or ascii + if args.rawhex: + csvout.write(hex(drivers_list[i]['flag']) + ',') + elif args.rawdec: + csvout.write(str(drivers_list[i]['flag']) + ',') + else: + if drivers_list[i]['flag'] == 192: + csvout.write('"' + 'ACTIVE, Load on Boundary' + '"' ',') + elif drivers_list[i]['flag'] == 128: + csvout.write('ACTIVE' + ',') + else: + csvout.write('INACTIVE' + ',') + +#slot_num hex or decimal + if args.rawhex: + csvout.write(hex(drivers_list[i]['slot_num']) + ',') + else: + csvout.write(str(drivers_list[i]['slot_num']) + ',') + +#num_devices hex or decimal + if args.rawhex: + csvout.write(hex(drivers_list[i]['num_devices']) + ',') + else: + csvout.write(str(drivers_list[i]['num_devices']) + ',') + +#unit hex or decimal + if args.rawhex: + csvout.write(hex(drivers_list[i]['unit']) + ',') + else: + csvout.write(str(drivers_list[i]['unit']) + ',') + +#dev_type hex or decimal or ascii + if args.rawhex: + csvout.write(hex(drivers_list[i]['dev_type']) + ',') + elif args.rawdec: + csvout.write(str(drivers_list[i]['dev_type']) + ',') + else: + try: + csvout.write('"' + dev_types[(drivers_list[i]['dev_type'])] + '"' + ',') + except: + csvout.write('Unknown' + ',') + +#block_num hex or decimal + if args.rawhex: + csvout.write(hex(drivers_list[i]['block_num']) + ',') + elif args.rawdec: + csvout.write(str(drivers_list[i]['block_num']) + ',') + else: + csvout.write(str(drivers_list[i]['block_num']) + ',') + +#mfg hex or decimal or ascii +# csvout.write(drivers_list[i]['mfg'] + ',') + if args.rawhex: + csvout.write(hex(drivers_list[i]['mfg']) + ',') + elif args.rawdec: + csvout.write(str(drivers_list[i]['mfg']) + ',') + else: + try: + csvout.write(mfgs[(drivers_list[i]['mfg'])] + ',') + except: + if 1 <= drivers_list[i]['mfg'] <= 31: + csvout.write('Apple Computer' + ',') + else: + csvout.write('Unknown' + ',') + + + +#version -- leaving as standard output + csvout.write(str(drivers_list[i]['version']) + ',') + +#dcb_length hex or decimal + if args.rawhex: + csvout.write(hex(drivers_list[i]['dcb_length']) + ',') + else: + csvout.write(str(drivers_list[i]['dcb_length']) + ',') + +#md5 outputs left alone + csvout.write( drivers_list[i]['driver_md5'] + ',' + \ drivers_list[i]['code_md5'] )