def __csv_user_assist_value_decode_win7_and_after(self, str_value_datatmp, count_offset): ''' The value in user assist has changed since Win7. It is taken into account here. ''' # 16 bytes data str_value_data_session = str_value_datatmp[0:4] str_value_data_session = unicode( get_int_from_reversed_string(str_value_data_session)) str_value_data_count = str_value_datatmp[4:8] str_value_data_count = unicode( get_int_from_reversed_string(str_value_data_count) + count_offset + 1) str_value_data_focus = str_value_datatmp[12:16] str_value_data_focus = unicode( get_int_from_reversed_string(str_value_data_focus)) str_value_data_timestamp = str_value_datatmp[60:68] try: timestamp = get_int_from_reversed_string(str_value_data_timestamp) date_last_exec = convert_windate(timestamp) except ValueError: date_last_exec = None arr_data = [ str_value_data_session, str_value_data_count, str_value_data_focus ] if date_last_exec: arr_data.append(date_last_exec) return arr_data
def __csv_user_assist_value_decode_before_win7(self, str_value_datatmp, count_offset): # the Count registry contains values representing the programs # each value is separated as : # first 4 bytes are session # following 4 bytes are number of times the program has been run # next 8 bytes are the timestamp of last execution # each of those values are in big endian which have to be converted in little endian # 16 bytes data str_value_data_session = str_value_datatmp[0:4] str_value_data_session = unicode( get_int_from_reversed_string(str_value_data_session)) str_value_data_count = str_value_datatmp[4:8] str_value_data_count = unicode( get_int_from_reversed_string(str_value_data_count) + count_offset + 1) str_value_data_timestamp = str_value_datatmp[8:16] try: timestamp = get_int_from_reversed_string(str_value_data_timestamp) date_last_exec = convert_windate(timestamp) except ValueError: date_last_exec = None arr_data = [str_value_data_session, str_value_data_count] if date_last_exec: arr_data.append(date_last_exec) return arr_data
def decode_itempos(itempos): tmp_data = itempos # itempos size itempos_size = get_int_from_reversed_string(tmp_data[0:2]) tmp_data = tmp_data[2:] # padding tmp_data = tmp_data[2:] # filesize filesize = get_int_from_reversed_string(tmp_data[0:4]) tmp_data = tmp_data[4:] # timestamp timestamp_modified_date = tmp_data[0:2] tmp_data = tmp_data[2:] timestamp_modified_time = tmp_data[0:2] tmp_data = tmp_data[2:] timestamp_modified = dosdate(timestamp_modified_date, timestamp_modified_time).strftime("%d/%m/%Y %H:%M:%S") # padding tmp_data = tmp_data[2:] # filename filename = "" for i in xrange(len(tmp_data)): if ord(tmp_data[i]) == 0: # NULL byte filename = tmp_data[0:i + 1] tmp_data = tmp_data[i + 1:] break # padding, it seems the next data will be following bytes "EF BE" for i in xrange(len(tmp_data) - 1): if ord(tmp_data[i]) == 0xef and ord(tmp_data[i + 1]) == 0xbe: tmp_data = tmp_data[i + 2:] break # timestamp created timestamp_created_date = tmp_data[0:2] tmp_data = tmp_data[2:] timestamp_created_time = tmp_data[0:2] tmp_data = tmp_data[2:] timestamp_created = dosdate(timestamp_created_date, timestamp_created_time).strftime("%d/%m/%Y %H:%M:%S") # timestamp modified timestamp_access_date = tmp_data[0:2] tmp_data = tmp_data[2:] timestamp_access_time = tmp_data[0:2] tmp_data = tmp_data[2:] timestamp_access = dosdate(timestamp_access_date, timestamp_access_time).strftime("%d/%m/%Y %H:%M:%S") tmp_arr = tmp_data.split(15 * b"\x00") if len(tmp_arr) >= 2: tmp_data = tmp_arr[1] else: tmp_data = "" # unicode string uni_filename = "" for i in xrange(len(tmp_data) / 2): if (2 * i) + 1 >= len(tmp_data): break if tmp_data[2 * i] == b"\x00" and tmp_data[(2 * i) + 1] == b"\x00": uni_filename = tmp_data[:2 * (i + 1)].decode("utf-16") break return [unicode(itempos_size), unicode(filesize), timestamp_modified, filename, timestamp_created, timestamp_access, uni_filename]
def __decode_section_a(self, format_version, content, section_a): hash_table = dict() if format_version == 17: hash_table['start_time'] = get_int_from_reversed_string(content[section_a:section_a + 4]) hash_table['duration'] = get_int_from_reversed_string(content[section_a+4:section_a+4 + 4]) hash_table['average_duration'] = '' hash_table['filename_offset'] = get_int_from_reversed_string(content[section_a+8:section_a+8 + 4]) hash_table['filename_nb_char'] = get_int_from_reversed_string(content[section_a+12:section_a+12 + 4]) else: hash_table['start_time'] = get_int_from_reversed_string(content[section_a:section_a + 4]) hash_table['duration'] = get_int_from_reversed_string(content[section_a+4:section_a+4 + 4]) hash_table['average_duration'] = get_int_from_reversed_string(content[section_a+8:section_a+8 + 4]) hash_table['filename_offset'] = get_int_from_reversed_string(content[section_a+12:section_a+12 + 4]) hash_table['filename_nb_char'] = get_int_from_reversed_string(content[section_a+16:section_a+16 + 4]) return hash_table
def __csv_user_assist_value_decode_win7_and_after(self, str_value_datatmp, count_offset): ''' The value in user assist has changed since Win7. It is taken into account here. ''' # 16 bytes data str_value_data_session = str_value_datatmp[0:4] str_value_data_session = unicode(get_int_from_reversed_string(str_value_data_session)) str_value_data_count = str_value_datatmp[4:8] str_value_data_count = unicode(get_int_from_reversed_string(str_value_data_count) + count_offset + 1) str_value_data_focus = str_value_datatmp[12:16] str_value_data_focus = unicode(get_int_from_reversed_string(str_value_data_focus)) str_value_data_timestamp = str_value_datatmp[60:68] try: timestamp = get_int_from_reversed_string(str_value_data_timestamp) date_last_exec = convert_windate(timestamp) except ValueError: date_last_exec = None arr_data = [str_value_data_session, str_value_data_count, str_value_data_focus] if date_last_exec: arr_data.append(date_last_exec) return arr_data
def __csv_user_assist_value_decode_before_win7(self, str_value_datatmp, count_offset): # the Count registry contains values representing the programs # each value is separated as : # first 4 bytes are session # following 4 bytes are number of times the program has been run # next 8 bytes are the timestamp of last execution # each of those values are in big endian which have to be converted in little endian # 16 bytes data str_value_data_session = str_value_datatmp[0:4] str_value_data_session = unicode(get_int_from_reversed_string(str_value_data_session)) str_value_data_count = str_value_datatmp[4:8] str_value_data_count = unicode(get_int_from_reversed_string(str_value_data_count) + count_offset + 1) str_value_data_timestamp = str_value_datatmp[8:16] try: timestamp = get_int_from_reversed_string(str_value_data_timestamp) date_last_exec = convert_windate(timestamp) except ValueError: date_last_exec = None arr_data = [str_value_data_session, str_value_data_count] if date_last_exec: arr_data.append(date_last_exec) return arr_data
def __decode_section_a(self, format_version, content, section_a): hash_table = dict() if format_version == 17: hash_table['start_time'] = get_int_from_reversed_string( content[section_a:section_a + 4]) hash_table['duration'] = get_int_from_reversed_string( content[section_a + 4:section_a + 4 + 4]) hash_table['average_duration'] = '' hash_table['filename_offset'] = get_int_from_reversed_string( content[section_a + 8:section_a + 8 + 4]) hash_table['filename_nb_char'] = get_int_from_reversed_string( content[section_a + 12:section_a + 12 + 4]) else: hash_table['start_time'] = get_int_from_reversed_string( content[section_a:section_a + 4]) hash_table['duration'] = get_int_from_reversed_string( content[section_a + 4:section_a + 4 + 4]) hash_table['average_duration'] = get_int_from_reversed_string( content[section_a + 8:section_a + 8 + 4]) hash_table['filename_offset'] = get_int_from_reversed_string( content[section_a + 12:section_a + 12 + 4]) hash_table['filename_nb_char'] = get_int_from_reversed_string( content[section_a + 16:section_a + 16 + 4]) return hash_table
def __construct_itempos_list(self, data): invalid_shitem_len = 0x14 list_itempos = [] tmp_data = data while True: try: if tmp_data[0:2] == b'\x14\x00': # invalid SHITEM entry tmp_data = tmp_data[invalid_shitem_len + 8:] # padding continue itempos_size = get_int_from_reversed_string(tmp_data[0:2]) if itempos_size == 0: break list_itempos.append(tmp_data[:itempos_size]) tmp_data = tmp_data[itempos_size:] # padding tmp_data = tmp_data[8:] except: break return list_itempos
def _list_windows_prefetch(self): ''' Outputs windows prefetch files in a csv ''' ''' See http://www.forensicswiki.org/wiki/Windows_Prefetch_File_Format ''' prefetch_path =self.systemroot + '\Prefetch\*.pf' list_prefetch_files = look_for_files(prefetch_path) for prefetch_file in list_prefetch_files: content = '' with open(prefetch_file, 'rb') as file_input: content = file_input.read() try: format_version = content[:4] format_version = get_int_from_reversed_string(format_version) #scca_sig = content[0x4:][:4] unknown_values = content[0x0008:0x0008+4] unknown_values = ' '.join(c.encode('hex') for c in unknown_values) file_size = content[0x000c:0x000c+4] file_size = get_int_from_reversed_string(file_size) exec_name = content[0x0010:0x0010+60] for i in range(30): # 60 / 2 if 2*i+1 < len(exec_name): if exec_name[2*i]=='\x00' and exec_name[2*i+1]=='\x00': exec_name = exec_name[:2*(i+1)].decode('utf-16-le') '''prefetch_hash = content[:4] content = content[4:] unknown_flag = content[:4] content = content[4:]''' prefetch_hash = content[0x004c:0x004c+4] tc=os.path.getctime(prefetch_file) tm=os.path.getmtime(prefetch_file) section_a = get_int_from_reversed_string(content[0x0054:0x0054+4]) num_entries_a = get_int_from_reversed_string(content[0x0058:0x0058+4]) section_b = get_int_from_reversed_string(content[0x005c:0x005c+4]) num_entries_b = get_int_from_reversed_string(content[0x0060:0x0060+4]) section_c = get_int_from_reversed_string(content[0x0064:0x0064+4]) length_c = get_int_from_reversed_string(content[0x0068:0x0068+4]) section_d = get_int_from_reversed_string(content[0x006c:0x006c+4]) num_entries_d = get_int_from_reversed_string(content[0x0070:0x0070+4]) length_d = get_int_from_reversed_string(content[0x0074:0x0074+4]) if format_version == 17: latest_exec_date = content[0x0078:0x0078+8] exec_count = get_int_from_reversed_string(content[0x0090:0x0090+4]) # section a elif format_version == 23: latest_exec_date = content[0x0080:0x0080+8] exec_count = get_int_from_reversed_string(content[0x0098:0x0098+4]) else: # format version 26 latest_exec_date = [] for i in range(8): latest_exec_date.append(content[0x0088+i*8:0x0088+(i+1)*8]) exec_count = get_int_from_reversed_string(content[0x00D0:0x00D0+4]) hash_table_a = self.__decode_section_a(format_version, content, section_a) list_str_c = self.__decode_section_c(content, section_c, length_c) yield prefetch_file,format_version,file_size, exec_name, datetime.datetime.fromtimestamp(tc),datetime.datetime.fromtimestamp(tm), exec_count, hash_table_a, list_str_c except: logging.error(traceback.format_exc())
def __decode_itempos(self, itempos): # TODO understand the data structure more in depth tmp_data = itempos # itempos size itempos_size = get_int_from_reversed_string(tmp_data[0:2]) tmp_data = tmp_data[2:] # padding tmp_data = tmp_data[2:] # filesize filesize = get_int_from_reversed_string(tmp_data[0:4]) tmp_data = tmp_data[4:] # timestamp timestamp_modified_date = tmp_data[0:2] tmp_data = tmp_data[2:] timestamp_modified_time = tmp_data[0:2] tmp_data = tmp_data[2:] timestamp_modified = dosdate( timestamp_modified_date, timestamp_modified_time).strftime('%d/%m/%Y %H:%M:%S') # padding tmp_data = tmp_data[2:] # filename filename = '' for i in range(len(tmp_data)): if ord(tmp_data[i]) == 0: # NULL byte filename = tmp_data[0:i + 1] tmp_data = tmp_data[i + 1:] break # padding, it seems the next data will be following bytes "EF BE" for i in range(len(tmp_data) - 1): if ord(tmp_data[i]) == 0xef and ord(tmp_data[i + 1]) == 0xbe: try: tmp_data = tmp_data[i + 2:] break except: self.logger.error('Error in shellbag data format') exit(1) # timestamp created timestamp_created_date = tmp_data[0:2] tmp_data = tmp_data[2:] timestamp_created_time = tmp_data[0:2] tmp_data = tmp_data[2:] timestamp_created = dosdate( timestamp_created_date, timestamp_created_time).strftime('%d/%m/%Y %H:%M:%S') # timestamp modified timestamp_access_date = tmp_data[0:2] tmp_data = tmp_data[2:] timestamp_access_time = tmp_data[0:2] tmp_data = tmp_data[2:] timestamp_access = dosdate( timestamp_access_date, timestamp_access_time).strftime('%d/%m/%Y %H:%M:%S') # big padding, I don't know what it is meant to represent, but it seems to be there constantly tmp_arr = tmp_data.split(15 * b'\x00') if len(tmp_arr) >= 2: tmp_data = tmp_arr[1] else: tmp_data = '' # unicode string uni_filename = '' for i in range(len(tmp_data) / 2): if (2 * i) + 1 >= len(tmp_data): break if tmp_data[2 * i] == b'\x00' and tmp_data[(2 * i) + 1] == b'\x00': uni_filename = tmp_data[:2 * (i + 1)].decode('utf-16') tmp_data = tmp_data[2 * (i + 1):] break #return '"itempos_size:' + unicode(itempos_size) + '"|"filesize:' + unicode(filesize) + '"|"time modified:' + timestamp_modified + '"|"filename:' + filename + '"|"time created:' + timestamp_created + '"|"time accessed:' + timestamp_access + '"|"unicode filename:' + uni_filename + '"' return [ unicode(itempos_size), unicode(filesize), timestamp_modified, filename, timestamp_created, timestamp_access, uni_filename ]
def _list_windows_prefetch(self): ''' Outputs windows prefetch files in a csv ''' ''' See http://www.forensicswiki.org/wiki/Windows_Prefetch_File_Format ''' prefetch_path = self.systemroot + '\Prefetch\*.pf' list_prefetch_files = look_for_files(prefetch_path) for prefetch_file in list_prefetch_files: content = '' with open(prefetch_file, 'rb') as file_input: content = file_input.read() try: format_version = content[:4] format_version = get_int_from_reversed_string(format_version) #scca_sig = content[0x4:][:4] unknown_values = content[0x0008:0x0008 + 4] unknown_values = ' '.join( c.encode('hex') for c in unknown_values) file_size = content[0x000c:0x000c + 4] file_size = get_int_from_reversed_string(file_size) exec_name = content[0x0010:0x0010 + 60] for i in range(30): # 60 / 2 if 2 * i + 1 < len(exec_name): if exec_name[2 * i] == '\x00' and exec_name[2 * i + 1] == '\x00': exec_name = exec_name[:2 * (i + 1)].decode('utf-16-le') '''prefetch_hash = content[:4] content = content[4:] unknown_flag = content[:4] content = content[4:]''' prefetch_hash = content[0x004c:0x004c + 4] tc = os.path.getctime(prefetch_file) tm = os.path.getmtime(prefetch_file) section_a = get_int_from_reversed_string( content[0x0054:0x0054 + 4]) num_entries_a = get_int_from_reversed_string( content[0x0058:0x0058 + 4]) section_b = get_int_from_reversed_string( content[0x005c:0x005c + 4]) num_entries_b = get_int_from_reversed_string( content[0x0060:0x0060 + 4]) section_c = get_int_from_reversed_string( content[0x0064:0x0064 + 4]) length_c = get_int_from_reversed_string(content[0x0068:0x0068 + 4]) section_d = get_int_from_reversed_string( content[0x006c:0x006c + 4]) num_entries_d = get_int_from_reversed_string( content[0x0070:0x0070 + 4]) length_d = get_int_from_reversed_string(content[0x0074:0x0074 + 4]) if format_version == 17: latest_exec_date = content[0x0078:0x0078 + 8] exec_count = get_int_from_reversed_string( content[0x0090:0x0090 + 4]) # section a elif format_version == 23: latest_exec_date = content[0x0080:0x0080 + 8] exec_count = get_int_from_reversed_string( content[0x0098:0x0098 + 4]) else: # format version 26 latest_exec_date = [] for i in range(8): latest_exec_date.append(content[0x0088 + i * 8:0x0088 + (i + 1) * 8]) exec_count = get_int_from_reversed_string( content[0x00D0:0x00D0 + 4]) hash_table_a = self.__decode_section_a(format_version, content, section_a) list_str_c = self.__decode_section_c(content, section_c, length_c) yield prefetch_file, format_version, file_size, exec_name, datetime.datetime.fromtimestamp( tc), datetime.datetime.fromtimestamp( tm), exec_count, hash_table_a, list_str_c except: logging.error(traceback.format_exc())
def __decode_itempos(self, itempos): # TODO understand the data structure more in depth tmp_data = itempos # itempos size itempos_size = get_int_from_reversed_string(tmp_data[0:2]) tmp_data = tmp_data[2:] # padding tmp_data = tmp_data[2:] # filesize filesize = get_int_from_reversed_string(tmp_data[0:4]) tmp_data = tmp_data[4:] # timestamp timestamp_modified_date = tmp_data[0:2] tmp_data = tmp_data[2:] timestamp_modified_time = tmp_data[0:2] tmp_data = tmp_data[2:] timestamp_modified = dosdate(timestamp_modified_date, timestamp_modified_time).strftime('%d/%m/%Y %H:%M:%S') # padding tmp_data = tmp_data[2:] # filename filename = '' for i in range(len(tmp_data)): if ord(tmp_data[i]) == 0: # NULL byte filename = tmp_data[0:i+1] tmp_data = tmp_data[i+1:] break # padding, it seems the next data will be following bytes "EF BE" for i in range(len(tmp_data)-1): if ord(tmp_data[i])==0xef and ord(tmp_data[i+1])==0xbe: try: tmp_data = tmp_data[i+2:] break except: self.logger.error('Error in shellbag data format') exit(1) # timestamp created timestamp_created_date = tmp_data[0:2] tmp_data = tmp_data[2:] timestamp_created_time = tmp_data[0:2] tmp_data = tmp_data[2:] timestamp_created = dosdate(timestamp_created_date, timestamp_created_time).strftime('%d/%m/%Y %H:%M:%S') # timestamp modified timestamp_access_date = tmp_data[0:2] tmp_data = tmp_data[2:] timestamp_access_time = tmp_data[0:2] tmp_data = tmp_data[2:] timestamp_access = dosdate(timestamp_access_date, timestamp_access_time).strftime('%d/%m/%Y %H:%M:%S') # big padding, I don't know what it is meant to represent, but it seems to be there constantly tmp_arr = tmp_data.split(15*b'\x00') if len(tmp_arr) >= 2: tmp_data = tmp_arr[1] else: tmp_data = '' # unicode string uni_filename = '' for i in range(len(tmp_data)/2): if (2*i)+1 >= len(tmp_data): break if tmp_data[2*i] == b'\x00' and tmp_data[(2*i)+1] == b'\x00': uni_filename = tmp_data[:2*(i+1)].decode('utf-16') tmp_data = tmp_data[2*(i+1):] break #return '"itempos_size:' + unicode(itempos_size) + '"|"filesize:' + unicode(filesize) + '"|"time modified:' + timestamp_modified + '"|"filename:' + filename + '"|"time created:' + timestamp_created + '"|"time accessed:' + timestamp_access + '"|"unicode filename:' + uni_filename + '"' return [unicode(itempos_size), unicode(filesize), timestamp_modified, filename, timestamp_created, timestamp_access, uni_filename]
def decode_itempos(itempos): tmp_data = itempos # itempos size itempos_size = get_int_from_reversed_string(tmp_data[0:2]) tmp_data = tmp_data[2:] # padding tmp_data = tmp_data[2:] # filesize filesize = get_int_from_reversed_string(tmp_data[0:4]) tmp_data = tmp_data[4:] # timestamp timestamp_modified_date = tmp_data[0:2] tmp_data = tmp_data[2:] timestamp_modified_time = tmp_data[0:2] tmp_data = tmp_data[2:] timestamp_modified = dosdate( timestamp_modified_date, timestamp_modified_time).strftime("%d/%m/%Y %H:%M:%S") # padding tmp_data = tmp_data[2:] # filename filename = "" for i in xrange(len(tmp_data)): if ord(tmp_data[i]) == 0: # NULL byte filename = tmp_data[0:i + 1] tmp_data = tmp_data[i + 1:] break # padding, it seems the next data will be following bytes "EF BE" for i in xrange(len(tmp_data) - 1): if ord(tmp_data[i]) == 0xef and ord(tmp_data[i + 1]) == 0xbe: tmp_data = tmp_data[i + 2:] break # timestamp created timestamp_created_date = tmp_data[0:2] tmp_data = tmp_data[2:] timestamp_created_time = tmp_data[0:2] tmp_data = tmp_data[2:] timestamp_created = dosdate( timestamp_created_date, timestamp_created_time).strftime("%d/%m/%Y %H:%M:%S") # timestamp modified timestamp_access_date = tmp_data[0:2] tmp_data = tmp_data[2:] timestamp_access_time = tmp_data[0:2] tmp_data = tmp_data[2:] timestamp_access = dosdate( timestamp_access_date, timestamp_access_time).strftime("%d/%m/%Y %H:%M:%S") tmp_arr = tmp_data.split(15 * b"\x00") if len(tmp_arr) >= 2: tmp_data = tmp_arr[1] else: tmp_data = "" # unicode string uni_filename = "" for i in xrange(len(tmp_data) / 2): if (2 * i) + 1 >= len(tmp_data): break if tmp_data[2 * i] == b"\x00" and tmp_data[(2 * i) + 1] == b"\x00": uni_filename = tmp_data[:2 * (i + 1)].decode("utf-16") break return [ unicode(itempos_size), unicode(filesize), timestamp_modified, filename, timestamp_created, timestamp_access, uni_filename ]