decode_mars_crypt_log_file.py 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208
  1. #!/usr/bin/python
  2. import sys
  3. import os
  4. import glob
  5. import zlib
  6. import struct
  7. import binascii
  8. import pyelliptic
  9. import traceback
  10. MAGIC_NO_COMPRESS_START = 0x03
  11. MAGIC_NO_COMPRESS_START1 = 0x06
  12. MAGIC_NO_COMPRESS_NO_CRYPT_START = 0x08
  13. MAGIC_COMPRESS_START = 0x04
  14. MAGIC_COMPRESS_START1 = 0x05
  15. MAGIC_COMPRESS_START2 = 0x07
  16. MAGIC_COMPRESS_NO_CRYPT_START = 0x09
  17. MAGIC_END = 0x00
  18. lastseq = 0
  19. PRIV_KEY = "028e843fe618cf19dd198c5b28d1746c632f941058926fa049c4bbb4979b2800"
  20. PUB_KEY = "65371432e4c9b9f82557c8c4a09199b001d92610306fc93b7dfa96236e227486e999f3dde6a255e5644c8b85ea3bc4d8c8cbad1240bc1bb378a85dbdfc3d24d8"
  21. def tea_decipher(v, k):
  22. op = 0xffffffffL
  23. v0, v1 = struct.unpack('=LL', v[0:8])
  24. k1, k2, k3, k4 = struct.unpack('=LLLL', k[0:16])
  25. delta = 0x9E3779B9L
  26. s = (delta << 4) & op
  27. for i in xrange(16):
  28. v1 = (v1 - (((v0<<4) + k3) ^ (v0 + s) ^ ((v0>>5) + k4))) & op
  29. v0 = (v0 - (((v1<<4) + k1) ^ (v1 + s) ^ ((v1>>5) + k2))) & op
  30. s = (s - delta) & op
  31. return struct.pack('=LL', v0, v1)
  32. def tea_decrypt(v, k):
  33. num = len(v) / 8 * 8
  34. ret = ''
  35. for i in xrange(0, num, 8):
  36. x = tea_decipher(v[i:i+8], k)
  37. ret += x
  38. ret += v[num:]
  39. return ret
  40. def IsGoodLogBuffer(_buffer, _offset, count):
  41. if _offset == len(_buffer): return (True, '')
  42. magic_start = _buffer[_offset]
  43. if MAGIC_NO_COMPRESS_START==magic_start or MAGIC_COMPRESS_START==magic_start or MAGIC_COMPRESS_START1==magic_start:
  44. crypt_key_len = 4
  45. elif MAGIC_COMPRESS_START2==magic_start or MAGIC_NO_COMPRESS_START1==magic_start or MAGIC_NO_COMPRESS_NO_CRYPT_START==magic_start or MAGIC_COMPRESS_NO_CRYPT_START==magic_start:
  46. crypt_key_len = 64
  47. else:
  48. return (False, '_buffer[%d]:%d != MAGIC_NUM_START'%(_offset, _buffer[_offset]))
  49. headerLen = 1 + 2 + 1 + 1 + 4 + crypt_key_len
  50. if _offset + headerLen + 1 + 1 > len(_buffer): return (False, 'offset:%d > len(buffer):%d'%(_offset, len(_buffer)))
  51. length = struct.unpack_from("I", buffer(_buffer, _offset+headerLen-4-crypt_key_len, 4))[0]
  52. if _offset + headerLen + length + 1 > len(_buffer): return (False, 'log length:%d, end pos %d > len(buffer):%d'%(length, _offset + headerLen + length + 1, len(_buffer)))
  53. if MAGIC_END!=_buffer[_offset + headerLen + length]: return (False, 'log length:%d, buffer[%d]:%d != MAGIC_END'%(length, _offset + headerLen + length, _buffer[_offset + headerLen + length]))
  54. if (1>=count): return (True, '')
  55. else: return IsGoodLogBuffer(_buffer, _offset+headerLen+length+1, count-1)
  56. def GetLogStartPos(_buffer, _count):
  57. offset = 0
  58. while True:
  59. if offset >= len(_buffer): break
  60. if MAGIC_NO_COMPRESS_START==_buffer[offset] or MAGIC_NO_COMPRESS_START1==_buffer[offset] or MAGIC_COMPRESS_START==_buffer[offset] or MAGIC_COMPRESS_START1==_buffer[offset] or MAGIC_COMPRESS_START2==_buffer[offset] or MAGIC_COMPRESS_NO_CRYPT_START==_buffer[offset] or MAGIC_NO_COMPRESS_NO_CRYPT_START==_buffer[offset]:
  61. if IsGoodLogBuffer(_buffer, offset, _count)[0]: return offset
  62. offset+=1
  63. return -1
  64. def DecodeBuffer(_buffer, _offset, _outbuffer):
  65. if _offset >= len(_buffer): return -1
  66. # if _offset + 1 + 4 + 1 + 1 > len(_buffer): return -1
  67. ret = IsGoodLogBuffer(_buffer, _offset, 1)
  68. if not ret[0]:
  69. fixpos = GetLogStartPos(_buffer[_offset:], 1)
  70. if -1==fixpos:
  71. return -1
  72. else:
  73. _outbuffer.extend("[F]decode_log_file.py decode error len=%d, result:%s \n"%(fixpos, ret[1]))
  74. _offset += fixpos
  75. magic_start = _buffer[_offset]
  76. if MAGIC_NO_COMPRESS_START==magic_start or MAGIC_COMPRESS_START==magic_start or MAGIC_COMPRESS_START1==magic_start:
  77. crypt_key_len = 4
  78. elif MAGIC_COMPRESS_START2==magic_start or MAGIC_NO_COMPRESS_START1==magic_start or MAGIC_NO_COMPRESS_NO_CRYPT_START==magic_start or MAGIC_COMPRESS_NO_CRYPT_START==magic_start:
  79. crypt_key_len = 64
  80. else:
  81. _outbuffer.extend('in DecodeBuffer _buffer[%d]:%d != MAGIC_NUM_START'%(_offset, magic_start))
  82. return -1
  83. headerLen = 1 + 2 + 1 + 1 + 4 + crypt_key_len
  84. length = struct.unpack_from("I", buffer(_buffer, _offset+headerLen-4-crypt_key_len, 4))[0]
  85. tmpbuffer = bytearray(length)
  86. seq=struct.unpack_from("H", buffer(_buffer, _offset+headerLen-4-crypt_key_len-2-2, 2))[0]
  87. begin_hour=struct.unpack_from("c", buffer(_buffer, _offset+headerLen-4-crypt_key_len-1-1, 1))[0]
  88. end_hour=struct.unpack_from("c", buffer(_buffer, _offset+headerLen-4-crypt_key_len-1, 1))[0]
  89. global lastseq
  90. if seq != 0 and seq != 1 and lastseq != 0 and seq != (lastseq+1):
  91. _outbuffer.extend("[F]decode_log_file.py log seq:%d-%d is missing\n" %(lastseq+1, seq-1))
  92. if seq != 0:
  93. lastseq = seq
  94. tmpbuffer[:] = _buffer[_offset+headerLen:_offset+headerLen+length]
  95. try:
  96. decompressor = zlib.decompressobj(-zlib.MAX_WBITS)
  97. if MAGIC_NO_COMPRESS_START1==_buffer[_offset]:
  98. pass
  99. elif MAGIC_COMPRESS_START2==_buffer[_offset]:
  100. svr = pyelliptic.ECC(curve='secp256k1')
  101. client = pyelliptic.ECC(curve='secp256k1')
  102. client.pubkey_x = str(buffer(_buffer, _offset+headerLen-crypt_key_len, crypt_key_len/2))
  103. client.pubkey_y = str(buffer(_buffer, _offset+headerLen-crypt_key_len/2, crypt_key_len/2))
  104. svr.privkey = binascii.unhexlify(PRIV_KEY)
  105. tea_key = svr.get_ecdh_key(client.get_pubkey())
  106. tmpbuffer = tea_decrypt(tmpbuffer, tea_key)
  107. tmpbuffer = decompressor.decompress(str(tmpbuffer))
  108. elif MAGIC_COMPRESS_START==_buffer[_offset] or MAGIC_COMPRESS_NO_CRYPT_START==_buffer[_offset]:
  109. tmpbuffer = decompressor.decompress(str(tmpbuffer))
  110. elif MAGIC_COMPRESS_START1==_buffer[_offset]:
  111. decompress_data = bytearray()
  112. while len(tmpbuffer) > 0:
  113. single_log_len = struct.unpack_from("H", buffer(tmpbuffer, 0, 2))[0]
  114. decompress_data.extend(tmpbuffer[2:single_log_len+2])
  115. tmpbuffer[:] = tmpbuffer[single_log_len+2:len(tmpbuffer)]
  116. tmpbuffer = decompressor.decompress(str(decompress_data))
  117. else:
  118. pass
  119. # _outbuffer.extend('seq:%d, hour:%d-%d len:%d decompress:%d\n' %(seq, ord(begin_hour), ord(end_hour), length, len(tmpbuffer)))
  120. except Exception, e:
  121. traceback.print_exc()
  122. _outbuffer.extend("[F]decode_log_file.py decompress err, " + str(e) + "\n")
  123. return _offset+headerLen+length+1
  124. _outbuffer.extend(tmpbuffer)
  125. return _offset+headerLen+length+1
  126. def ParseFile(_file, _outfile):
  127. fp = open(_file, "rb")
  128. _buffer = bytearray(os.path.getsize(_file))
  129. fp.readinto(_buffer)
  130. fp.close()
  131. startpos = GetLogStartPos(_buffer, 2)
  132. if -1==startpos:
  133. return
  134. outbuffer = bytearray()
  135. while True:
  136. startpos = DecodeBuffer(_buffer, startpos, outbuffer)
  137. if -1==startpos: break;
  138. if 0==len(outbuffer): return
  139. fpout = open(_outfile, "wb")
  140. fpout.write(outbuffer)
  141. fpout.close()
  142. def main(args):
  143. global lastseq
  144. if 1==len(args):
  145. if os.path.isdir(args[0]):
  146. filelist = glob.glob(args[0] + "/*.xlog")
  147. for filepath in filelist:
  148. lastseq = 0
  149. ParseFile(filepath, filepath+".log")
  150. else: ParseFile(args[0], args[0]+".log")
  151. elif 2==len(args):
  152. ParseFile(args[0], args[1])
  153. else:
  154. filelist = glob.glob("*.xlog")
  155. for filepath in filelist:
  156. lastseq = 0
  157. ParseFile(filepath, filepath+".log")
  158. if __name__ == "__main__":
  159. main(sys.argv[1:])