Show LFN and SFN like ls on FAT12/16 (Support UTF-8/UTF-16 file name)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python3 | |
import struct | |
from sys import argv | |
UTF8_prior = False | |
#FILENAME = input('img name?: ') | |
FILENAME = argv[1] | |
def getLFN(ldir_wholename): | |
ldir_wholename = ldir_wholename.replace(b'\xff\xff',b'') #remove padding | |
ldir_utf8name = ldir_wholename.replace(b'\0',b'') #UTF8だと想定してnull文字削除 | |
if not UTF8_prior: | |
try: | |
ldir_strname = ldir_wholename.decode('utf_16_le') | |
#UTF8だった場合 | |
except UnicodeDecodeError: | |
ldir_strname = ldir_utf8name.decode('utf_8') | |
else: | |
try: | |
ldir_strname = ldir_utf8name.decode('utf_8') | |
#UTF16だった場合 | |
except UnicodeDecodeError: | |
ldir_strname = ldir_wholename.decode('utf_16_le') | |
return ldir_strname | |
data = open(FILENAME, 'rb').read() | |
BytesPerSec, SecPerClus, RsvdSecCnt, NumFATs, FATSize = struct.unpack_from(b'< 3x 8x H B H B 2x 2x x H', data) | |
dir_start = BytesPerSec * (RsvdSecCnt + FATSize * NumFATs) #BPB+FAT*2 0x600 | |
entry_size = 32 | |
saved_data = b'' | |
delLFNContinue = False | |
while True: | |
name, attr = struct.unpack_from(b'< 11s c', data, dir_start) | |
if name==b'\x00'*11: | |
break | |
if attr==b'\x0f': #LFN | |
LDIR_Ord, LDIR_Name1, LDIR_Chksum, LDIR_Name2, LDIR_Name3 = struct.unpack_from(b'< B 10s x x c 12s 2x 4s', data, dir_start) | |
ldir_rawname = LDIR_Name1 + LDIR_Name2 + LDIR_Name3 | |
#16進の一の位が1以外なら連続なので連結 | |
ord_hex = format(LDIR_Ord, 'x') | |
if len(ord_hex) == 1: #2桁化 | |
ord_hex = '0' + ord_hex | |
if ord_hex[1]!='1' and ord_hex!='e5': #e5は削除済みファイル | |
saved_data = ldir_rawname + saved_data | |
#削除済みLFNはどこまでか判定できないのでとりえあずスタックする | |
elif ord_hex=='e5': | |
saved_data = ldir_rawname + saved_data | |
delLFNContinue = True | |
else: | |
ldir_wholename = ldir_rawname + saved_data | |
saved_data = b'' | |
ldir_strname = getLFN(ldir_wholename) | |
print('LFN: '+ldir_strname) | |
else: #SFN | |
#削除済みLFNが終わったことを確認 | |
if delLFNContinue: | |
delLFNContinue = False | |
ldir_wholename = saved_data | |
saved_data = b'' | |
ldir_strname = getLFN(ldir_wholename) | |
print('LFN: '+ldir_strname,' (DELETED)') | |
try: | |
if name[0:1]==b'\xe5': #一文字目が削除フラグ0xE5か | |
print('SFN: ?'+name[1:].decode('ascii'),' (DELETED)') | |
else: | |
print('SFN: '+name.decode('ascii')) | |
except UnicodeDecodeError: | |
print('SFN: (decoding failed)') | |
print() | |
dir_start += entry_size |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment