Created
November 13, 2011 17:01
-
-
Save yunzheng/1362334 to your computer and use it in GitHub Desktop.
ei.cfg removal/restore util in Python
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 python | |
""" | |
eicfg_remover.py | |
Based on Kai Liu's eicfg_remover.c @ http://code.kliu.org/misc/winisoutils/ | |
""" | |
import sys | |
from binascii import crc_hqx, hexlify | |
from collections import namedtuple | |
from struct import calcsize, pack, unpack | |
WORK_RANGE = 0x1000000 | |
UDFTAG_STRUCT = 'HHBBHHHI' | |
LONGALLOC_STRUCT = 'I6s6s' | |
UDFDESC_STRUCT = '%isHBB%isH2s' % (calcsize(UDFTAG_STRUCT), calcsize(LONGALLOC_STRUCT)) | |
UDFTag = namedtuple('UDFTag', 'ident version checksum reserved serial crc crclen location') | |
UDFDesc = namedtuple('UDFDesc', 'tag_ version characteristics identifier icb_ cb_iu misc') | |
WCHAR_FILENAME = '\x00'.join(list('ei.cfg')) + '\x00' | |
def main(): | |
if len(sys.argv) < 2: | |
print 'Usage: %s [iso file]' % sys.argv[0] | |
return 1 | |
iso = sys.argv[1] | |
with open(iso, 'rb') as f: | |
pbuffer = f.read(WORK_RANGE) | |
if len(pbuffer) < WORK_RANGE: | |
print 'Image is too small' | |
print '' | |
print 'Make sure that you use the correct iso image.' | |
return 1 | |
found_eicfg = False | |
for i in xrange(0x100, WORK_RANGE-0x100): | |
if pbuffer[i:i+len(WCHAR_FILENAME)] == WCHAR_FILENAME: | |
udf_startpos = i - calcsize(UDFDESC_STRUCT) | |
udf_buffer = pbuffer[udf_startpos:udf_startpos+calcsize(UDFDESC_STRUCT)] | |
udfdesc = UDFDesc._make(unpack(UDFDESC_STRUCT, udf_buffer)) | |
udftag = UDFTag._make(unpack(UDFTAG_STRUCT, udfdesc.tag_)) | |
udf_filestart = udf_startpos+calcsize(UDFTAG_STRUCT) | |
crc_buffer = pbuffer[udf_filestart:udf_filestart+udftag.crclen] | |
calc_crc = crc_hqx(crc_buffer, 0) | |
# Perform sanity checks | |
sane = (udftag.ident == 257 | |
and udftag.version == 2 | |
and udftag.reserved == 0 | |
and udftag.crclen == (calcsize(UDFDESC_STRUCT) - calcsize(UDFTAG_STRUCT) + len(WCHAR_FILENAME)) | |
and udftag.crc == calc_crc | |
and udfdesc.identifier == len(WCHAR_FILENAME)+1 | |
and udfdesc.cb_iu == 0 | |
and udfdesc.characteristics in (0, 5)) | |
if sane: | |
found_eicfg = True | |
break | |
if found_eicfg: | |
# Toggle the Hidden+Deletion flag on the file | |
# 0 = Normal (restore the file) | |
# 5 = HIDDEN (1) + DELETED (4) | |
if udfdesc.characteristics: | |
udfdesc = udfdesc._replace(characteristics=0) | |
else: | |
udfdesc = udfdesc._replace(characteristics=5) | |
# Recalculate CRC-16 | |
udf_raw = pack(UDFDESC_STRUCT, *udfdesc) + WCHAR_FILENAME | |
crc_buffer = udf_raw[calcsize(UDFTAG_STRUCT):calcsize(UDFTAG_STRUCT)+udftag.crclen] | |
crc = crc_hqx(crc_buffer, 0) | |
udftag = udftag._replace(crc=crc) | |
udfdesc = udfdesc._replace(tag_=pack(UDFTAG_STRUCT, *udftag)) | |
udf_raw = pack(UDFDESC_STRUCT, *udfdesc) | |
# Recalculate checksum | |
checksum = 0 | |
for i in xrange(0, 4): | |
checksum += ord(udf_raw[i]) | |
for i in xrange(5, 16): | |
checksum += ord(udf_raw[i]) | |
checksum = checksum & 0xFF | |
udftag = udftag._replace(checksum=checksum) | |
udfdesc = udfdesc._replace(tag_=pack(UDFTAG_STRUCT, *udftag)) | |
udf_raw = pack(UDFDESC_STRUCT, *udfdesc) | |
# Write back the changes of the UDF FileDescriptor | |
with open(iso, "r+b") as f: | |
#print 'Write @', udf_startpos, hexlify(udf_raw) | |
f.seek(udf_startpos) | |
f.write(udf_raw) | |
if udfdesc.characteristics: | |
print 'ei.cfg removed.' | |
else: | |
print 'ei.cfg restored.' | |
return 0 | |
else: | |
print 'ei.cfg not found.' | |
print '' | |
print 'Make sure that the disc image is uncorrupted and that the file system is UDF, not Joliet.' | |
return 1 | |
if __name__ == '__main__': | |
sys.exit(main()) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment