→ SlackSpace : → it refers to the unused space at the end of the last cluster of a file. A cluster is the smallest allocation unit in a file system, and it typically consists of one or more sectors. When a file does not completely fill the last cluster allocated to it, the remaining space in that cluster is considered slack space. → in a security context, slack can also be exploited for hiding information or malicious code, as it might not be immediately visible or accessible through normal file operations. However. → let’s explain the functions in our code : 1) ‘as_le_unsigned’ import struct def as_le_unsigned(b): table = {1: 'B', 2: 'H', 4: 'L', 8: 'Q'} return struct.unpack('<' + table[len(b)], b)[0] → this function takes byte string ‘b’ and interprets it as an unsgned little-endian integer. The size of the integer is determined by the length of the byte string. It uses the ‘struc’ module to unpack the byte string based on its length. 2) ‘get_sector_size(fs_bytes)’ def get_sector_size(fs_bytes): return as_le_unsigned(fs_bytes[11:13]) → it extracts the sector size from the file system bytes provided. It calls ‘as_le_unsigned’ to convert the relevant portion of the byte string to an integer. 3) ‘get_cluster_size(fs_bytes)’ def get_cluster_size(fs_bytes): return as_le_unsigned(fs_bytes[13:14]) * get_sector_size(fs_bytes) → it calculates the cluster size by multiplying the size of a cluster (found in the file system bytes) with the sector size (obtained using get_sector_size) 4)’get_reserved_area_size(fs_bytes)’ def get_reserved_area_size(fs_bytes): return as_le_unsigned(fs_bytes[14:16]) * get_sector_size(fs_bytes) → similar to the previous function, this calculates the size of the reserved area by multiplying the size of the reserved area (found in the file system bytes) with the sector size 5) ‘get_fat_size(fs_bytes)’ def get_fat_size(fs_bytes): return as_le_unsigned(fs_bytes[22:24]) * get_sector_size(fs_bytes) → it calculates FAT size by multiplying the size of the FAT(found in the file system bytes) with the sector size. 6) ‘get_fat0(fs_bytes)’ def get_fat0(fs_bytes): start = get_reserved_area_size(fs_bytes) length = get_fat_size(fs_bytes) return fs_bytes[start:start + length] → it extracts the content of the first FAT from the file system bytes 7) ‘get_number_of_fats(fs_bytes)’ def get_number_of_fats(fs_bytes): return as_le_unsigned(fs_bytes[16:17]) → it extracts the numbe of FAT from the file system bytes 8) ‘get_max_root_directory_entries(fs_bytes)’ def get_max_root_directory_entries(fs_bytes): return as_le_unsigned(fs_bytes[17:19]) → it extracts the maximum number of root directory entries from the file system bytes 9) ‘get_root_directory_area(fs_bytes)’ def get_root_directory_area(fs_bytes): start = get_reserved_area_size(fs_bytes) + get_number_of_fats(fs_bytes) * get_fat_size(fs_bytes) length = get_max_root_directory_entries(fs_bytes) * 32 # 32 bytes / entry return fs_bytes[start:start + length] → it extracts the content of the root directory area from the file system bytes. 10) ‘get_sector_count()’ def get_sector_count(fs_bytes): return max(as_le_unsigned(fs_bytes[19:21]), as_le_unsigned(fs_bytes[32:36])) → the total number of sectors in the file system 11) ‘get_cluster_area’ def get_cluster_area(fs_bytes): fs_size = get_sector_count(fs_bytes) * get_sector_size(fs_bytes) start = get_reserved_area_size(fs_bytes) + get_number_of_fats(fs_bytes) * get_fat_size(fs_bytes) + get_max_root_directory_entries(fs_bytes) * 32 number_of_clusters = (fs_size - start) // get_cluster_size(fs_bytes) length = number_of_clusters * get_cluster_size(fs_bytes) return fs_bytes[start:start + length] → it extracts the content of the cluster aarea from the file system bytes 12) ‘get_filename(dirent)’ def get_filename(dirent): return dirent[0:8].decode('ascii').strip() + '.' + dirent[8:11].decode('ascii') → it extracts the filename from a directory entry 13) ‘get_first_cluster(dirent)’ def get_first_cluster(dirent): return as_le_unsigned(dirent[26:28]) → it extracts the first cluster number from a directory entry 14) ‘get_filesize(dirent)’ def get_filesize(dirent): return as_le_unsigned(dirent[28:32]) → it does the file size from a directory entry 15) ‘get_cluster_numbers(cluster_number,fat_bytes,cluster_size)’ def get_cluster_numbers(cluster_number, fat_bytes, cluster_size): if cluster_number >= as_le_unsigned(b'\xf8\xff'): # handle edge case first return [cluster_number] result = [] while cluster_number < as_le_unsigned(b'\xf8\xff'): # should be < not >= result.append(cluster_number) offset = cluster_number * 2 # offset is * 2 bytes per cluster, not cluster size in bytes cluster_number = as_le_unsigned(fat_bytes[offset:offset + 2]) return result → it does a list of cluster numbers associated with a file 16) ‘get_cluster_count(fs_bytes)’ def get_cluster_count(fs_bytes): return (get_sector_count(fs_bytes) * get_sector_size(fs_bytes)) // get_cluster_size(fs_bytes) → the total number of clusters in the file system 17) ‘write_text_to_slack(text)’ def write_saad_to_slack_space(fs_bytes): try: block_size = get_sector_size(fs_bytes) with open('9-fat-label.dd', 'rb+') as file: file_size = os.path.getsize(file.name) last_allocated_block = (file_size + block_size - 1) // block_size # Move to the beginning of the last block file.seek(last_allocated_block * block_size) # Read the original content of the slack space print('slack space : before change') slack_space_content = file.read() print(slack_space_content) # Write 'saad' to the slack space file.write("hi how are you".encode('utf-8')) # Move back to the beginning of the slack space again file.seek(last_allocated_block * block_size) # Read the modified content of the slack space modified_slack_space_content = file.read() print('after modification') print(modified_slack_space_content) return fs_bytes except FileNotFoundError: print(f"Error: File '9-fat-label.dd' not found.") except Exception as e: print(f"An error occurred: {e}") → This function attempts to open the file '9-fat-label.dd', calculates the size and last allocated block, reads and prints the original content of the slack space, writes the string "hi how are you" to the slack space, and finally, reads and prints the modified content of the slack space, returning the original binary data if successful. 18) ‘main()’ def main(): with open('9-fat-label.dd', 'rb+') as f: data = f.read() write_saad_to_slack_space(data) if __name__ == '__main__': main() → calling the write_slack_space function. → here, we have a new file → after writing some text → this is in Visual studio. The script display the slack space when it’s empty and then writes ‘hi how are you ’ and then displays the slack space with the message. → let’s see the verification