def __init__(self, binary, beg_offset, hbin_number, hive): self.hive = hive self.hbin_number = hbin_number self.binary = binary self.beg_offset = beg_offset self.magic_number = regutils.bytes_to_string(binary[0:4]) self.dist_first_hbin = regutils.bytes_to_int(binary[4:8]) self.hive_bin_size = regutils.bytes_to_int(binary[8:12]) self.next_hbin_offset = regutils.bytes_to_int( binary[28:32]) #relative to start of this hbin self.first_cell_offset = 32 + self.beg_offset self.cells = self.find_cells()
def __init__(self, binary): self.offset = 0 self.length = 4096 self.time_stamp_bytes = binary[12:20] self.root_key_off = binary[36:40] self.last_hbin_off_bytes = binary[40:44] self.hive_name_bytes = binary[48:112] self.time_stamp = regutils.getFiletime(self.time_stamp_bytes) self.first_record = regutils.bytes_to_int(self.root_key_off) self.last_hbin_off = regutils.bytes_to_int(self.last_hbin_off_bytes) self.hive_name = regutils.bytes_to_string(self.hive_name_bytes)
def find_cells(self): cells = [] abs_offset = self.first_cell_offset relative_offset = 32 #the first cell starts at hbin_off + 32 end_of_hbin = self.beg_offset + self.hive_bin_size count = 0 while abs_offset < end_of_hbin: #both here are relative to the start of the hbin length_bytes = self.binary[relative_offset:( relative_offset + 4)] #the length of the cell is in its first 4 bytes if regutils.isNegative(length_bytes): #then the cell is allocated cell_length = regutils.negate_signed( length_bytes ) #get the length by taking the abolute value of the number else: cell_length = regutils.bytes_to_int(length_bytes) cells.append( Cell( self.binary[relative_offset:relative_offset + cell_length], abs_offset, count, self.hive) ) #create a new cell with its binary, and its absolute offset self.hive.mark_for_reinitialization( cells[count] ) # if the cell is a data cell, a value list or data list #then it has no magic number... scan the cells containing information about these cells and add to a list #their offsets, type, and optionally the number of elements.... then in hive when hbins are done parsing #the cells, go through the list and reinitialize them to their proper class by calling the appropriate #reinitialization method in the cell class relative_offset += cell_length abs_offset += cell_length count += 1 return cells
def initialize(self, binary, offset, hive): self.binary = binary self.hive = hive self.offset = offset self.magic_number = self.binary[0:2] self.flags = self.binary[2:4] self.timestamp = self.binary[4:12] self.unknown0 = self.binary[12:16] self.parent_off = self.binary[16:20] #relative to start of hbin data self.num_sk_stable = self.binary[20:24] #set to 0 if deleted self.num_sk_volative = self.binary[24:28] self.stable_sk_list_off = self.binary[ 28:32] # relative to start of hbin data,set 0xFFFFFFFF if deleted self.vol_sk_list_off = self.binary[32:36] self.num_values = self.binary[36:40] self.value_list_off = self.binary[40:44] #what if there are no values? self.sec_rec_off = self.binary[44:48] #set to 0xFFFFFFFF if deleted self.class_name_off = self.binary[48:52] self.max_sk = self.binary[52:56] #set to 0 if deleted self.max_sk_class = self.binary[56:60] #set unkowns to 0 too self.max_value_name = self.binary[60:64] self.max_value_data = self.binary[64:68] self.unknown4 = self.binary[68:72] #eek self.name_length = self.binary[72:74] #eek self.class_name_length = self.binary[74:76] self.name = self.binary[76:76 + regutils.bytes_to_int(self.name_length)] self.subkeys = [] self.value_records = []
def get_value_records(self): records = [] for x in range(self.get_size()): records.append( self.hive.find_cell( regutils.bytes_to_int(self.elements[x]) + 4096).cell_type) return records
def init_LI(self): self.sk_offs = [] for x in range(self.get_num_elements()): offset = self.binary[4 + 4 * x:8 + 4 * x] self.sk_offs.append(regutils.bytes_to_int(offset)) end_of_elements = 4 + 4 * x self.padding = self.binary[4 + 4 * self.get_num_elements():self.get_length()]
def initialize(self, binary, offset, hive): self.hive = hive self.binary = binary self.length = len(self.binary) self.offset = offset self.magic_number = self.binary[0:2] self.unknown = self.binary[2:4] self.prev_sk_off = self.binary[ 4:8] #these are relative to the start of the hbin self.next_sk_off = self.binary[8:12] self.ref_count = self.binary[12:16] self.sec_disc_size = self.binary[16:20] self.sec_desc = self.binary[20:20 + regutils.bytes_to_int(self.sec_disc_size)] self.padding = self.binary[20 + regutils.bytes_to_int(self.sec_disc_size ):self.length]
def get_data_size(self): stored_locally = self.data_is_local() size = -1 if stored_locally: size = regutils.remove_MSB(self.data_size) else: size = regutils.bytes_to_int(self.data_size) return size
def __str__(self): string = ("\n--------------" + self.get_type() + "--------------" "\nNumber of Elements : " + str(self.get_size()) + "\n----Elements----") for element in self.elements: string += "\nOffset : " + regutils.bytes_to_hexstring( element) + " (" + str(regutils.bytes_to_int(element)) + ")" string += "\nPadding : " + str(self.get_padding()) return string
def init_RI(self): #seems to be the only subkey list that does weird shit when not allocated self.sk_offs = [] for index in range(self.get_num_elements()): offset = self.binary[4 + 4 * index:8 + 4 * index] self.sk_offs.append(regutils.bytes_to_int(offset)) if self.allocated: self.padding = self.binary[4 + 4 * self.get_num_elements():self. get_length()] else: self.padding = self.binary[4:self.get_length()]
def get_hbins( self ): hbin_list = [] current_offset = 4096 count = 0 while current_offset <= self.reg_header.last_hbin_off: hbin_length = regutils.bytes_to_int( self.binary[current_offset+8:current_offset+12] ) current_hbin = HiveBin( self.binary[current_offset:(current_offset+hbin_length)] , current_offset , count , self ) hbin_list.append( current_hbin ) current_offset = current_offset + hbin_length count+=1 return hbin_list
def init_LF_LH(self): #the elements are 0-4 ( offset of subkey rel to hbin), 4-8 the (hash?) first 4 chars of subkey name self.sk_offs = [] self.sk_hashes = [] for x in range(self.get_num_elements()): offset = self.binary[4 + 8 * x:8 + 8 * x] self.sk_offs.append(regutils.bytes_to_int(offset)) self.sk_hashes.append(self.binary[8 + 8 * x:12 + 8 * x]) self.padding = self.binary[4 + 8 * self.get_num_elements():self.get_length()]
def __init__(self, binary, offset, number, hive): self.hive = hive self.number = number self.magic_numbers = { "nk": KeyRecord(), #key record "vk": ValueRecord(), #value record "sk": SecurityRecord(), #security record "lf": SubkeyList( ), #early version of windows subkey-lists where the hash in each element is calculated simply by taking the first four characters of the associated subkey’s name. "lh": SubkeyList( ), #subkey-lists where elements stored as hash in Appendix C "ri": SubkeyList( ), #subkey_list which stores pointers to additional subkey lists (tree structure) "li": SubkeyList(), "db": DataRecord() } #same as ri except they reference keys instead of additonal lists #magic_numbers.get( blah ) #values lists #binary includes only that of this cell self.binary = binary self.offset = offset self.length = binary[ 0: 4] #check sign bit, Negative if allocated, positive if free. The length is then #the two's complement of the negative value (absolute value) self.magic_number = binary[4:6] self.allocated = regutils.isNegative(self.length) if self.allocated == True: self.length_int = regutils.negate_signed(self.length) else: self.length_int = regutils.bytes_to_int(self.length) self.cell_data = self.binary[4:self.length_int] self.cell_type = self.assign_cell_type() if type(self.cell_type) == type(SubkeyList()): self.cell_type.initialize(self.cell_data, self.offset, self.isAllocated(), self.hive) elif type(self.cell_type) != type("None"): self.cell_type.initialize(self.cell_data, self.offset, self.hive)
def get_value_count(self): return regutils.bytes_to_int(self.num_values)
def get_value_list_off(self): return regutils.bytes_to_int(self.value_list_off)
def __str__(self): string = ( "--------------KeyRecord-----------" + "\nMagic Number: " + regutils.bytes_to_string(self.magic_number) + "\nFlags : " + str(self.flags) + "\nTimestamp : " + regutils.getFiletime(self.timestamp) + "\nUnknown : " + regutils.bytes_to_hexstring(self.unknown0) + " (" + str(regutils.bytes_to_int(self.unknown0)) + ")" + "\nParent key's offset : " + regutils.bytes_to_hexstring(self.parent_off) + " (" + str(regutils.bytes_to_int(self.parent_off)) + ")" + "\nNum of stable subkeys : " + str(regutils.bytes_to_int(self.num_sk_stable)) + "\nNum of volative subkeys : " + str(regutils.bytes_to_int(self.num_sk_volative)) + "\nStable subkey list offset : " + regutils.bytes_to_hexstring(self.stable_sk_list_off) + " (" + str(regutils.bytes_to_int(self.stable_sk_list_off)) + ")" + "\nVolatile subkey list offset : " + regutils.bytes_to_hexstring(self.vol_sk_list_off) + " (" + str(regutils.bytes_to_int(self.vol_sk_list_off)) + ")" + "\n# of Values : " + str(regutils.bytes_to_int(self.num_values)) + "\nValue list offset : " + regutils.bytes_to_hexstring(self.value_list_off) + " (" + str(regutils.bytes_to_int(self.value_list_off)) + ")" + "\nSecurity Record offset : " + regutils.bytes_to_hexstring(self.sec_rec_off) + " (" + str(regutils.bytes_to_int(self.sec_rec_off)) + ")" + "\nClass name offset : " + regutils.bytes_to_hexstring(self.class_name_off) + " (" + str(regutils.bytes_to_int(self.class_name_off)) + ")" + "\nMax characters in subkey name : " + str(regutils.bytes_to_int(self.max_sk)) + "\nMax chars in subkey class name : " + str(regutils.bytes_to_int(self.max_sk_class)) + "\nMax chars value name : " + str(regutils.bytes_to_int(self.max_value_name)) + "\nMax chars in data name : " + str(regutils.bytes_to_int(self.max_value_data)) + "\nUnknown : " + regutils.bytes_to_hexstring(self.unknown4) + " (" + str(regutils.bytes_to_int(self.unknown4)) + ")" + "\nName.length : " + str(regutils.bytes_to_int(self.name_length)) + "\nClass name length : " + str(regutils.bytes_to_int(self.class_name_length)) + "\nName : " + regutils.bytes_to_string(self.name) #"\n\n"+str(self.binary)+"\n\n" ) return string
def get_subkey_count(self): return regutils.bytes_to_int(self.num_sk_stable)
def get_num_elements(self): return regutils.bytes_to_int(self.num_elements)
def get_flags(self): return regutils.bytes_to_int(self.flags)
def get_ref_count(self): return regutils.bytes_to_int(self.ref_count)
def parseREG_DWORD_BIG_ENDIAN(self): endian_switch = regutils.reverse_endian(self.binary[0:4]) return str(regutils.bytes_to_int(endian_switch))
def get_unknown(self): return regutils.bytes_to_hexstring(self.unknown) + " (" + str( regutils.bytes_to_int(self.unknown)) + ")"
def get_next_sk_off(self): return regutils.bytes_to_hexstring(self.next_sk_off) + " (" + str( regutils.bytes_to_int(self.next_sk_off)) + ")"
def parseREG_DWORD(self): return str(regutils.bytes_to_int(self.binary[0:4]))
def get_root_offset(self): return regutils.bytes_to_int(self.root_key_off)
def get_data_type(self): number = regutils.bytes_to_int(self.data_type) return self.types.get(number, "Who knows")
def get_stable_sk_off(self): return regutils.bytes_to_int(self.stable_sk_list_off)
def get_descriptor_size(self): return regutils.bytes_to_int(self.sec_disc_size)
def get_volatile_sk_off(self): return regutils.bytes_to_int(self.vol_sk_list_off)
def parseREG_QWORD(self): return str(regutils.bytes_to_int(self.binary[0:8]) ) #note this method works for any size of bytes not just 4