-
Notifications
You must be signed in to change notification settings - Fork 0
/
inc_fuel.py
83 lines (64 loc) · 2.25 KB
/
inc_fuel.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
from inc_noesis import *
from struct import *
from collections import namedtuple
class fuel:
def readClassHeader(bs):
s = struct.Struct('<IIIIII')
ClassHeader = namedtuple('ClassHeader', 'dataSize classObjectSize decompressedSize compressedSize classCRC32 crc32')
classHeader = ClassHeader._make(s.unpack(bs.readBytes(s.size)))
return classHeader
def calculatePaddedSize(unpaddedSize):
return (unpaddedSize + 0x7ff) & 0xfffff800
def calculatePaddingSize(unpaddedSize):
return fuel.calculatePaddedSize(unpaddedSize) - unpaddedSize
def decompress(data):
WINDOW_LOG = 14
WINDOW_SIZE = (1 << WINDOW_LOG)
WINDOW_MASK = (1 << WINDOW_LOG) - 1
bs = NoeBitStream(data)
decompressedSize = bs.readUInt()
compressedSize = bs.readUInt()
windowBuffer = bytearray(WINDOW_SIZE)
decompressed = NoeBitStream()
flagbit = 0
pos = 0
while decompressed.getSize() < decompressedSize:
if flagbit <= 1:
flagmask = bs.readUByte() << 24
flagmask |= bs.readUByte() << 16
flagmask |= bs.readUByte() << 8
flagmask |= bs.readUByte()
flagbit = 32 - 1
lenbits = WINDOW_LOG - (flagmask & 3)
flag = (flagmask >> flagbit) & 1
flagbit -= 1
currentByte = bs.readUByte()
if flag == 0:
windowBuffer[pos & WINDOW_MASK] = currentByte
pos += 1
decompressed.writeByte(currentByte)
else:
d = bs.readUByte()
j = (currentByte << 8) + d
length = (j >> lenbits) + 3
d = (j & ((1 << lenbits) - 1)) + 1
for j in range(length):
currentByte = windowBuffer[(pos - d) & WINDOW_MASK]
windowBuffer[pos & WINDOW_MASK] = currentByte
pos += 1
decompressed.writeByte(currentByte)
return decompressed.getBuffer()
def readObject(data):
bs = NoeBitStream(data)
header = fuel.readClassHeader(bs)
baseClassData = bs.readBytes(header.classObjectSize)
derivedClassData = bs.readBytes(header.dataSize - header.classObjectSize)
if header.compressedSize != 0:
derivedClassData = fuel.decompress(derivedClassData)
header.compressedSize = 0
header.dataSize = header.classObjectSize + header.decompressedSize
return header, baseClassData, derivedClassData
def assertClass(data, classCRC32):
bs = NoeBitStream(data)
header = fuel.readClassHeader(bs)
return header.classCRC32 == classCRC32