Skip to content

Instantly share code, notes, and snippets.

@dialluvioso
Created June 17, 2021 10:18
Show Gist options
  • Select an option

  • Save dialluvioso/43dc0e17e903215c93d53234e6ae72fb to your computer and use it in GitHub Desktop.

Select an option

Save dialluvioso/43dc0e17e903215c93d53234e6ae72fb to your computer and use it in GitHub Desktop.
FAT32 dissector for SSTIC 2021 CTF
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import struct
u8 = lambda x: struct.unpack("<B", x)[0]
u16 = lambda x: struct.unpack("<H", x)[0]
u32 = lambda x: struct.unpack("<I", x)[0]
OFFSET_BYTSPERSEC = 11
OFFSET_SECPERCLUS = 13
OFFSET_RSVDSECCNT = 14
OFFSET_NUMFATS = 16
OFFSET_ROOTENTCNT = 17
OFFSET_HIDDENSEC = 28
OFFSET_TOTSEC32 = 32
OFFSET_FATZ32 = 36
OFFSET_ROOTCLUS = 44
OFFSET_FSINFO = 48
f = open("bootsector.raw", "rb")
# parse bytes per sector
f.seek(OFFSET_BYTSPERSEC)
byts_per_sec = u16(f.read(2))
# parse sectors per cluster
f.seek(OFFSET_SECPERCLUS)
sec_per_clus = u8(f.read(1))
# parse number of sectors in reserved area
f.seek(OFFSET_RSVDSECCNT)
rsvd_sec_cnt = u16(f.read(2))
# parse number of FATs
f.seek(OFFSET_NUMFATS)
num_fats = u8(f.read(1))
# parse number of number of 32-byte directory entries inside root directory
f.seek(OFFSET_ROOTENTCNT)
root_ent_cnt = u16(f.read(2))
# parse the number of hidden sectors preceding FAT partition
f.seek(OFFSET_HIDDENSEC)
hidden_sec = u32(f.read(4))
# parse number of sectors of the FAT volume
f.seek(OFFSET_TOTSEC32)
tot_sec_32 = u32(f.read(4))
# parse the size of a FAT unit of sector
f.seek(OFFSET_FATZ32)
fat_sz_32 = u32(f.read(4))
# parse the first cluster number of the root directory
f.seek(OFFSET_ROOTCLUS)
root_clus = u32(f.read(4))
# parse the sector of FSInfo (offset from top of FAT32 volume)
f.seek(OFFSET_FSINFO)
fs_info = u16(f.read(2))
print(f"bytes per sector: {byts_per_sec}")
print(f"sectors per cluster: {sec_per_clus}")
print(f"number of sectors in reserved area: {rsvd_sec_cnt}")
print(f"number of FATs: {num_fats}")
print(f"number of entries inside root directory: {root_ent_cnt}")
print(f"number of hidden sectors preceding FAT: {hidden_sec}")
print(f"number of sectors of FAT: {tot_sec_32}")
print(f"size of FAT unit: {fat_sz_32}")
print(f"cluster number of root directory: {root_clus}")
print(f"sector of FSInfo: {fs_info}")
# calculare size of FAT area
fat_area_sz = fat_sz_32 * num_fats
print(f"FAT area size: {fat_area_sz}")
# calculare where data region starts
first_data_sec = rsvd_sec_cnt + fat_area_sz
print(f"First data sector: {first_data_sec}")
def get_sect(n):
return hidden_sec + first_data_sec + ((n-2) * sec_per_clus)
def get_fat_by_clus(n):
fat_sec_num = hidden_sec + rsvd_sec_cnt + ((n * 4) / byts_per_sec)
fat_ent_off = (n * 4) % byts_per_sec
return (int(fat_sec_num), fat_ent_off)
# calculate where root directory starts inside data region
rootdir_clus_sec = get_sect(root_clus)
print(f"First sector of cluster (root directory) is: {rootdir_clus_sec:08x}")
clus_chall1 = u32(b"\x6e\x00\x00\x00")
clus2_chall1 = u32(b"\x6f\x00\x00\x00")
clus3_chall1 = u32(b"\x70\x00\x00\x00")
clus4_chall1 = u32(b"\x71\x00\x00\x00")
clus_chall7 = u32(b"\x72\x00\x00\x00")
clus2_chall7 = u32(b"\x73\x00\x00\x00")
clus3_chall7 = u32(b"\x74\x00\x00\x00")
clus4_chall7 = u32(b"\x75\x00\x00\x00")
clus_chall5 = u32(b"\x76\x00\x00\x00")
clus2_chall5 = u32(b"\x77\x00\x00\x00")
clus3_chall5 = u32(b"\x78\x00\x00\x00")
clus4_chall5 = u32(b"\x79\x00\x00\x00")
clus_chall3 = u32(b"\x7a\x00\x00\x00")
clus2_chall3 = u32(b"\x7b\x00\x00\x00")
clus3_chall3 = u32(b"\x7c\x00\x00\x00")
clus4_chall3 = u32(b"\x7d\x00\x00\x00")
clus_chall6 = u32(b"\x7e\x00\x00\x00")
clus2_chall6 = u32(b"\x7f\x00\x00\x00")
clus3_chall6 = u32(b"\x80\x00\x00\x00")
clus4_chall6 = u32(b"\x81\x00\x00\x00")
clus_chall4 = u32(b"\x82\x00\x00\x00")
clus2_chall4 = u32(b"\x83\x00\x00\x00")
clus3_chall4 = u32(b"\x84\x00\x00\x00")
clus4_chall4 = u32(b"\x85\x00\x00\x00")
clus_chall2 = u32(b"\x86\x00\x00\x00")
clus2_chall2 = u32(b"\x87\x00\x00\x00")
clus3_chall2 = u32(b"\x88\x00\x00\x00")
clus4_chall2 = u32(b"\x89\x00\x00\x00")
clus_chall8 = u32(b"\x8a\x00\x00\x00")
clus2_chall8 = u32(b"\x8b\x00\x00\x00")
clus = clus_chall4
sec_clus = get_sect(clus)
print(f"{sec_clus:08x}")
fat, off = get_fat_by_clus(clus)
print(f"fat=>{fat:08x} off=>{off:x}")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment