-
Notifications
You must be signed in to change notification settings - Fork 0
/
ActiveMime.py
126 lines (106 loc) · 5.81 KB
/
ActiveMime.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
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
from ByteIterator import ByteIterator
from types import SimpleNamespace
class ActiveMime:
def __init__(self, raw_activemime):
self.parse(raw_activemime)
def parse(self, raw_activemime):
iterator = ByteIterator(raw_activemime)
self.cfb = SimpleNamespace()
# taken from https://github.com/idiom/activemime-format
self.cfb.header = iterator.next(0x0C)
self.cfb.unknown_a = iterator.next(0x02)
self.cfb.field_size = iterator.next(0x04)
self.cfb.unknown_b = iterator.next(int.from_bytes(self.cfb.field_size, byteorder='little'))
self.cfb.unknown_c = iterator.next(0x04)
self.cfb.compressed_size = iterator.next(0x04)
self.cfb.field_size_d = iterator.next(0x04)
self.cfb.field_size_e = iterator.next(0x04)
self.cfb.unknown_d = iterator.next(int.from_bytes(self.cfb.field_size_d, byteorder='little'))
self.cfb.vba_tail_type = iterator.next(int.from_bytes(self.cfb.field_size_e, byteorder='little'))
self.cfb.size = iterator.next(0x04)
self.cfb.compressed_data = iterator.next(int.from_bytes(self.cfb.compressed_size, byteorder='little'))
self.magic_tail = SimpleNamespace() # all of this is a wild guess
self.magic_tail.header = iterator.next(0x04)
if self.magic_tail.header == b'\x09\x04\x00\x00':
self.has_magic_tail = True
else:
self.has_magic_tail = False
return
iterator.next(0x01) # skipping delimiter
self.magic_tail.unknown_a = iterator.next(0x01)
# FF 01 01 00 00 00 56 99 00 00 00 00 FF FF
# /// 56 - cmg
# /// 99 - bEncrypt
procedures_meta_cnt = int.from_bytes(iterator.next(0x01), byteorder='little')
self.magic_tail.procedures_meta = list()
for _ in range(procedures_meta_cnt):
self.magic_tail.procedures_meta.append(iterator.next_until(b'\xFF\xFF')[:-2]) # macro metadata, sans delimiter
self.magic_tail.unknown_b = iterator.next_until(b'\xFF\xFF')[:-2] # always same, sans delimiter
procedures_names_cnt = int.from_bytes(iterator.next(0x02), byteorder='little')
self.magic_tail.procedures_names = list()
for _ in range(procedures_names_cnt):
procedure_name_unknown_1 = iterator.next(0x02)
procedure_name_size = int.from_bytes(iterator.next(0x02), byteorder='little')
procedure_name_full = iterator.next(procedure_name_size * 2).decode('UTF-16LE') # x2 because utf-16
procedure_name_project, procedure_name_module, procedure_name_procedure = procedure_name_full.split('.')
self.magic_tail.procedures_names.append({
'unknown_1': procedure_name_unknown_1,
'project': procedure_name_project,
'module': procedure_name_module,
'procedure': procedure_name_procedure
})
self.magic_tail.unknown_c = iterator.next(0x03)
procedures_links_cnt = int.from_bytes(iterator.next(0x02), byteorder='little')
self.magic_tail.procedures_links = list()
for _ in range(procedures_links_cnt):
procedure_link_unknown_1 = iterator.next(0x02)
procedure_link_size = int.from_bytes(iterator.next(0x02), byteorder='little')
procedure_link_full = iterator.next(procedure_link_size * 2).decode('UTF-16LE') # x2 because utf-16
procedure_link_project, procedure_link_module, procedure_link_procedure = procedure_link_full.split('.')
self.magic_tail.procedures_links.append({
'unknown_1': procedure_link_unknown_1,
'project': procedure_link_project,
'module': procedure_link_module,
'procedure': procedure_link_procedure,
'unknown_2': iterator.next(0x02)
})
self.magic_tail.footer = iterator.next(iterator.length())
def render(self):
data = b''
data += self.cfb.header
data += self.cfb.unknown_a
data += self.cfb.field_size
data += self.cfb.unknown_b
data += self.cfb.unknown_c
data += self.cfb.compressed_size
data += self.cfb.field_size_d
data += self.cfb.field_size_e
data += self.cfb.unknown_d
data += self.cfb.vba_tail_type
data += self.cfb.size
data += self.cfb.compressed_data
data += self.magic_tail.header
data += b'\xFF' # delimiter
data += self.magic_tail.unknown_a
data += len(self.magic_tail.procedures_meta).to_bytes(1, byteorder='little')
for procedure_meta in self.magic_tail.procedures_meta:
data += procedure_meta
data += b'\xFF\xFF' # delimiter
data += self.magic_tail.unknown_b
data += b'\xFF\xFF' # delimiter
data += len(self.magic_tail.procedures_names).to_bytes(2, byteorder='little')
for procedure_name in self.magic_tail.procedures_names:
data += procedure_name['unknown_1']
procedure_name_full = f"{procedure_name['project']}.{procedure_name['module']}.{procedure_name['procedure']}"
data += len(procedure_name_full).to_bytes(2, byteorder='little')
data += procedure_name_full.encode('UTF-16LE')
data += self.magic_tail.unknown_c
data += len(self.magic_tail.procedures_links).to_bytes(2, byteorder='little')
for procedure_link in self.magic_tail.procedures_links:
data += procedure_link['unknown_1']
procedure_link_full = f"{procedure_link['project']}.{procedure_link['module']}.{procedure_link['procedure']}"
data += len(procedure_link_full).to_bytes(2, byteorder='little')
data += procedure_link_full.upper().encode('UTF-16LE')
data += procedure_link['unknown_2']
data += self.magic_tail.footer
return data