Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@tpiperatgod
Created April 16, 2014 06:52
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tpiperatgod/10819492 to your computer and use it in GitHub Desktop.
Save tpiperatgod/10819492 to your computer and use it in GitHub Desktop.
war3 rep file handler
#!/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