def wrap_item(is_weapon, values, key): item = pack_item_values(is_weapon, values) header = struct.pack(">Bi", (is_weapon << 7) | 7, key) padding = "\xff" * (33 - len(item)) h = lzo.crc32(header + "\xff\xff" + item + padding) & 0xffffffff checksum = struct.pack(">H", ((h >> 16) ^ h) & 0xffff) body = xor_data(rotate_data_left(checksum + item, key & 31), key >> 5) return header + body
def wrap_player_data(player, endian=1): crc = lzo.crc32(player) & 0xffffffff bitstream = WriteBitstream() tree = make_huffman_tree(player) write_huffman_tree(tree, bitstream) huffman_compress(invert_tree(tree), player, bitstream) data = bitstream.getvalue() + "\x00\x00\x00\x00" header = struct.pack(">I3s", len(data) + 15, "WSG") if endian == 1: header = header + struct.pack(">III", 2, crc, len(player)) else: header = header + struct.pack("<III", 2, crc, len(player)) data = lzo.compress(header + data)[1:] return hashlib.sha1(data).digest() + data
def wrap_player_data(player, endian=1): crc = lzo.crc32(player) & 0xffffffff bitstream = WriteBitstream() tree = make_huffman_tree(player) write_huffman_tree(tree, bitstream) huffman_compress(invert_tree(tree), player, bitstream) data = bitstream.getvalue() + "\x00\x00\x00\x00" header = struct.pack(">I3s", len(data) + 15, "WSG") if endian == 1: header = header + struct.pack(">III", 2, crc, len(player)) else: header = header + struct.pack("<III", 2, crc, len(player)) data = lzo.compress(header + data)[1: ] return hashlib.sha1(data).digest() + data
def unwrap_player_data(data): if data[:20] != hashlib.sha1(data[20:]).digest(): raise BL2Error("Invalid save file") data = lzo.decompress("\xf0" + data[20:]) size, wsg, version = struct.unpack(">I3sI", data[:11]) if version != 2 and version != 0x02000000: raise BL2Error("Unknown save version " + str(version)) if version == 2: crc, size = struct.unpack(">II", data[11:19]) else: crc, size = struct.unpack("<II", data[11:19]) bitstream = ReadBitstream(data[19:]) tree = read_huffman_tree(bitstream) player = huffman_decompress(tree, bitstream, size) if (lzo.crc32(player) & 0xffffffff) != crc: raise BL2Error("CRC check failed") return player
def unwrap_player_data(data): if data[: 20] != hashlib.sha1(data[20: ]).digest(): raise BL2Error("Invalid save file") data = lzo.decompress("\xf0" + data[20: ]) size, wsg, version = struct.unpack(">I3sI", data[: 11]) if version != 2 and version != 0x02000000: raise BL2Error("Unknown save version " + str(version)) if version == 2: crc, size = struct.unpack(">II", data[11: 19]) else: crc, size = struct.unpack("<II", data[11: 19]) bitstream = ReadBitstream(data[19: ]) tree = read_huffman_tree(bitstream) player = huffman_decompress(tree, bitstream, size) if (lzo.crc32(player) & 0xffffffff) != crc: raise BL2Error("CRC check failed") return player
import lzo import sys import struct fc = open(sys.argv[1], 'rb') cd = fc.read() fc.close() d_len, c_len, ecrc32 = struct.unpack("III", cd[24:36]) print("Compressed data size: %x" % c_len) print("Decompressed data size: %x" % d_len) dd = lzo.decompress(cd[36:c_len + 36], False, d_len) print("Actual decompressed len: %x" % len(dd)) ccrc32 = lzo.crc32(dd) print("Expected CRC32: %x" % ecrc32) print("Computed CRC32: %x" % ccrc32) print("CRC32 OK? ", ecrc32 == ccrc32) fd = open(sys.argv[1] + '.elf', 'wb') fmagic = struct.unpack("I", dd[:4])[0] if fmagic == 0x464c457f: #elf fd.write(dd) elif fmagic == 0xb8b2bb81: #xored elf for b in dd: fd.write(bytes([b ^ 0xfe])) else: print("Error: unknown magic 0x%x" % fmagic) fd.close() print("Saved as %s.elf" % sys.argv[1])
file_descriptors.append(descriptor) file_data.append(c['data']) num_bytes += c['size_before'] num_compressed_bytes += c['size_after'] combined_data = ''.join(file_data) file_descriptors_path = options.output file_data_path = os.path.splitext(options.output)[0] + '.pak' output = { 'version': 2, 'file_descriptors': file_descriptors, 'data_file_path': os.path.basename(file_data_path), 'descriptors_file_path': os.path.basename(file_descriptors_path), 'size': len(combined_data), 'num_files': len(file_descriptors), 'crc32': lzo.crc32(combined_data), 'adler32': lzo.adler32(combined_data) } data_json = json.dumps(output) open(file_data_path, "w").write(combined_data) open(file_descriptors_path, "w").write(data_json) if options.verbose: print("Total: %d bytes -> %d bytes (%.02f%%)" % (num_bytes, num_compressed_bytes, (float(num_compressed_bytes) / num_bytes) * 100.0))