回复:th09(东方花映塚)文件提取器 试作型 (充当生日礼物的东西)
def deobfuscate(src, xorval, xoradd, blocksize, changesize):
src = array('B', src)
dest = array('B', src)
size = len(src)
restsize = size % blocksize
if restsize >= blocksize / 4: restsize = 0
restsize += (size & 1)
size -= restsize
src_idx = 0
dest_idx_block = 0
while changesize > 0 and size > 0:
if size < blocksize:
blocksize = size
dest_idx_block += blocksize
dest_idx = dest_idx_block - 1
for nothing in range((blocksize + 1) >> 1):
dest[dest_idx] = src[src_idx] ^ xorval
xorval = (xorval + xoradd) % 256
dest_idx -= 2
src_idx += 1
dest_idx = dest_idx_block - 2
for nothing in range(blocksize >> 1):
dest[dest_idx] = src[src_idx] ^ xorval
xorval = (xorval + xoradd) % 256
dest_idx -= 2
src_idx += 1
size -= blocksize
changesize -= blocksize
size += restsize
assert dest_idx_block == src_idx
assert size == len(src) - src_idx
return dest
class reader(object):
def __init__(self, infile):
self.infile = infile
def read_entries(self):
(magic, blob) = struct.unpack('<4s12s', self.infile.read(16))
check.equal('Magic number', magic, 'PBGZ')
blob = deobfuscate(blob, 0x1B, 0x37, 12, 1024)
(num_entries, index_offset, index_size_unpacked
) = struct.unpack('<LLL', blob)
num_entries -= 123456
index_offset -= 345678
index_size_unpacked -= 567891
print '%s files' % num_entries
self.infile.seek(0, 2)
filesize = self.infile.tell()
self.infile.seek(index_offset)
index_size_packed = filesize - index_offset
packed_index = array('B')
packed_index.fromfile(self.infile, index_size_packed)
packed_index = deobfuscate(packed_index, 0x3E, 0x9B, 128, 1024)
index = array('B', 'x' * index_size_unpacked)
lzss.decompress(packed_index, index)
entries = self.parse_index(index, num_entries)
end_entry = dat.entry()
end_entry.offs = index_offset
for e, next_e in util.iterate_pairs(itertools.chain(entries, [end_entry])):
e.packed_size = next_e.offs - e.offs
print '%s: offs %s, packed size %s, unpacked size %s, flags %s' % (e.name, e.offs, e.packed_size, e.size, e.flags)
yield e
def parse_index(self, index, num_entries):
entry_pos = 0
for nothing in range(num_entries):
name_len = 0
while index[entry_pos + name_len]:
name_len += 1
e = dat.entry(self)
e.name = index[entry_pos : entry_pos + name_len].tostring()
(e.offs, e.size, e.flags) = struct.unpack('<LLL',index[entry_pos+name_len+1:entry_pos + name_len + 13])
entry_pos += name_len + 13
yield e
def read_compressed(self, entry):
self.infile.seek(entry.offs)
entry.packed = array('B')
entry.packed.fromfile(self.infile, entry.packed_size)
def decompress(self, entry):
entry.data = array('B', 'x' * entry.size)
lzss.decompress(entry.packed, entry.data)
if entry.data[:3].tostring() == 'edz':
print chr(entry.data[3])
entry.data = deobfuscate(entry.data[4:],*obfuscations[chr(entry.data[3])])
关键的解码就这些了……