war3 rep file handler
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 | |
# *-*coding:utf-8*-* | |
import os | |
import zlib | |
import binascii | |
class W3GFileHandler(object): | |
def __init__(self, file): | |
self.w3g_file = open(file) | |
self.w3g_header = None | |
def file_read(self, head=None, end=None): | |
self.w3g_file_readed = self.w3g_file.read() | |
return self.w3g_file_readed[head:end] | |
def file_write(self, path, data): | |
data_store_file = open(path, 'w') | |
data_store_file.write(data) | |
data_store_file.close() | |
def file_close(self): | |
self.w3g_file.close() | |
class W3GFileHeaderHandler(W3GFileHandler): | |
def catch_header(self): | |
"""header一般为开始的68个字节""" | |
self.w3g_header = self.file_read(0, 68) | |
def first_string(self): | |
"""header的1-28字节为固定字符串""" | |
rsp = self.w3g_header[0:28] | |
print "固定字符串: ", rsp | |
return rsp | |
def header_size(self): | |
"""header的29-32字节为header部分的总字节数""" | |
rsp = binascii.b2a_hex(self.w3g_header[31:27:-1]) | |
print "Header的字节数: ", int(rsp, 16) | |
return int(rsp, 16) | |
def compressed_size(self): | |
"""header的33-36字节为压缩的数据块的大小""" | |
rsp = binascii.b2a_hex(self.w3g_header[35:31:-1]) | |
print "压缩数据块的压缩数据总字节数: ", int(rsp, 16) | |
return int(rsp, 16) | |
def rep_header_version(self): | |
"""header的37-40字节为录像版本标识""" | |
rsp = binascii.b2a_hex(self.w3g_header[39:35:-1]) | |
print "录像版本标识: ", int(rsp, 16) | |
return int(rsp, 16) | |
def decompressed_size(self): | |
"""header的41-44字节为压缩的数据块的大小""" | |
rsp = binascii.b2a_hex(self.w3g_header[43:39:-1]) | |
print "压缩数据块解压缩后的总字节数: ", int(rsp, 16) | |
return int(rsp, 16) | |
def compressed_num(self): | |
"""header的45-48字节为数据块的个数""" | |
rsp = binascii.b2a_hex(self.w3g_header[47:43:-1]) | |
print "压缩数据块的个数: ", int(rsp, 16) | |
return int(rsp, 16) | |
def some_string(self): | |
"""header的49-52字节为一个标识字符串""" | |
rsp = self.w3g_header[51:47:-1] | |
print "一个字符串标识: ", rsp | |
return rsp | |
def version_number(self): | |
"""header的53-56字节为版本号""" | |
rsp = binascii.b2a_hex(self.w3g_header[55:51:-1]) | |
print "版本号: ", int(rsp, 16) | |
return int(rsp, 16) | |
def build_number(self): | |
"""header的57-58字节为构建号""" | |
rsp = binascii.b2a_hex(self.w3g_header[57:55:-1]) | |
print "构建号: ", int(rsp, 16) | |
return int(rsp, 16) | |
def flags(self): | |
"""header的59-60字节为游戏模式,单人或多人""" | |
rsp = binascii.b2a_hex(self.w3g_header[59:57:-1]) | |
print "单人或多人游戏: ", int(rsp, 16) | |
return int(rsp, 16) | |
def rep_length_in_msec(self): | |
"""header的61-64字节为游戏时长,单位毫秒""" | |
rsp = binascii.b2a_hex(self.w3g_header[63:59:-1]) | |
print "录像时长: ", int(rsp, 16) | |
return int(rsp, 16) | |
def header_crc32(self): | |
"""header的65-68字节为CRC32校验码""" | |
rsp = binascii.b2a_hex(self.w3g_header[67:63:-1]) | |
print "Header部分CRC32校验码: ", int(rsp, 16) | |
return int(rsp, 16) | |
def get_all_header_info(self): | |
print "[×] 开始获取数据Header [*]" | |
self.catch_header() | |
self.first_string() | |
self.header_size() | |
self.compressed_size() | |
self.rep_header_version() | |
self.decompressed_size() | |
self.compressed_num() | |
self.some_string() | |
self.version_number() | |
self.build_number() | |
self.flags() | |
self.rep_length_in_msec() | |
self.header_crc32() | |
print "[×] 已获取数据Header [*]" | |
class W3GFileDataHandler(W3GFileHandler): | |
def catch_data(self): | |
"""header一般为从69到最末的字节""" | |
self.w3g_data = self.file_read(67) | |
def _decompress(self, compressed_data): | |
"""创建一个zlib decompressobj,flush后才能进行decompress""" | |
decomp_obj = zlib.decompressobj() | |
decomp_obj.flush() | |
decompressed_data = decomp_obj.decompress(compressed_data) | |
return decompressed_data | |
def decompress_and_conbine(self, data_num): | |
offset = 0 | |
data_decompressed = '' | |
for i in range(data_num): | |
header_begin = offset | |
header_end = offset + 2 | |
size_end = offset + 4 | |
data_header = binascii.b2a_hex(self.w3g_data[header_end:header_begin:-1]) | |
data_block_size = binascii.b2a_hex(self.w3g_data[size_end:header_end:-1]) | |
data_compressed_size = int(data_header, 16) | |
data_begin = offset + 9 | |
data_end = offset + 9 + data_compressed_size | |
data_compressed = self.w3g_data[data_begin:data_end] | |
print "数据块header从字节 %d 到 %d, 压缩的数据块大小: %d" % \ | |
(offset+1, offset+8, int(data_block_size, 16)) | |
print "数据块从字节 %d 到 %d" % (data_begin, data_end) | |
print "压缩数据Header,即该数据块大小: ", data_compressed_size | |
data_decompressed += self._decompress(data_compressed) | |
offset += data_compressed_size + 8 | |
self.file_write('/root/decompress_data', data_decompressed) | |
print len(data_decompressed) | |
def get_all_data_info(self, num): | |
print "[×] 开始获取数据块 [*]" | |
self.catch_data() | |
self.decompress_and_conbine(num) | |
print "[×] 已获取数据块 [*]" | |
if __name__ == '__main__': | |
file_path = u"****.w3g" | |
w3g_header = W3GFileHeaderHandler(file_path) | |
w3g_data = W3GFileDataHandler(file_path) | |
w3g_header.get_all_header_info() | |
w3g_data_num = w3g_header.compressed_num() | |
w3g_data.get_all_data_info(w3g_data_num) | |
w3g_header.file_close() | |
w3g_data.file_close() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment