-
Notifications
You must be signed in to change notification settings - Fork 2
/
metadatastringdec.cpp
121 lines (101 loc) · 4.26 KB
/
metadatastringdec.cpp
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
#include "metadatastringdec.h"
#include <stdexcept>
#include <random>
#include <stdio.h>
struct m_header_fields {
char filler1[0x18];
uint32_t stringLiteralDataOffset; // 18
uint32_t stringLiteralDataCount; // 1c
uint32_t stringLiteralOffset; // 20
uint32_t stringLiteralCount; // 24
char filler2[0xd8 - 0x28];
uint32_t stringOffset, stringCount;
};
struct m_literal {
uint32_t offset, length;
};
void generate_key_for_global_metadata_header_string(uint8_t* data, size_t len, uint8_t* literal_dec_key) {
if (len < sizeof(m_header_fields))
throw std::out_of_range("data not big enough for global metadata header");
uint32_t values[0x12] = {
*(uint32_t*)(data + 0x60),
*(uint32_t*)(data + 0x64),
*(uint32_t*)(data + 0x68),
*(uint32_t*)(data + 0x6c),
*(uint32_t*)(data + 0x140),
*(uint32_t*)(data + 0x144),
*(uint32_t*)(data + 0x148),
*(uint32_t*)(data + 0x14c),
*(uint32_t*)(data + 0x100),
*(uint32_t*)(data + 0x104),
*(uint32_t*)(data + 0x108),
*(uint32_t*)(data + 0x10c),
*(uint32_t*)(data + 0xf0),
*(uint32_t*)(data + 0xf4),
*(uint32_t*)(data + 8),
*(uint32_t*)(data + 0xc),
*(uint32_t*)(data + 0x10),
*(uint32_t*)(data + 0x14)
};
uint64_t seed = ((uint64_t)values[values[0] & 0xfu] << 0x20u) | values[(values[0x11] & 0xf) + 2];
std::mt19937_64 rand(seed);
for (int i = 0; i < 6; i++) // Skip
rand();
auto key64 = (uint64_t*)literal_dec_key;
for (int i = 0; i < 0xa00; i++)
key64[i] = rand();
}
void recrypt_global_metadata_header_string_fields(uint8_t* data, size_t len, uint8_t* literal_dec_key) {
if (len < sizeof(m_header_fields))
throw std::out_of_range("data not big enough for global metadata header");
uint32_t values[0x12] = {
*(uint32_t*)(data + 0x60),
*(uint32_t*)(data + 0x64),
*(uint32_t*)(data + 0x68),
*(uint32_t*)(data + 0x6c),
*(uint32_t*)(data + 0x140),
*(uint32_t*)(data + 0x144),
*(uint32_t*)(data + 0x148),
*(uint32_t*)(data + 0x14c),
*(uint32_t*)(data + 0x100),
*(uint32_t*)(data + 0x104),
*(uint32_t*)(data + 0x108),
*(uint32_t*)(data + 0x10c),
*(uint32_t*)(data + 0xf0),
*(uint32_t*)(data + 0xf4),
*(uint32_t*)(data + 8),
*(uint32_t*)(data + 0xc),
*(uint32_t*)(data + 0x10),
*(uint32_t*)(data + 0x14)
};
uint64_t seed = ((uint64_t)values[values[0] & 0xfu] << 0x20u) | values[(values[0x11] & 0xf) + 2];
std::mt19937_64 rand(seed);
auto header = (m_header_fields*)data;
header->stringCount ^= (uint32_t)rand();
header->stringOffset ^= (uint32_t)rand();
rand();
header->stringLiteralOffset ^= (uint32_t)rand();
header->stringLiteralDataCount ^= (uint32_t)rand();
header->stringLiteralDataOffset ^= (uint32_t)rand();
auto key64 = (uint64_t*)literal_dec_key;
for (int i = 0; i < 0xa00; i++)
key64[i] = rand();
}
void recrypt_global_metadata_header_string_literals(uint8_t* data, size_t len, uint8_t* literal_dec_key) {
if (len < sizeof(m_header_fields))
throw std::out_of_range("data not big enough for global metadata header");
auto header = (m_header_fields*)data;
if ((size_t)header->stringLiteralCount + header->stringLiteralOffset > len)
throw std::out_of_range("file trimmed or string literal offset/count field invalid");
auto literals = (m_literal*)(data + header->stringLiteralOffset);
auto count = header->stringLiteralCount / sizeof(m_literal);
for (size_t i = 0; i < count; i++) {
auto slen = literals[i].length;
uint8_t* str = data + header->stringLiteralDataOffset + literals[i].offset;
uint8_t* okey = literal_dec_key + (i % 0x2800);
if ((size_t)header->stringLiteralDataOffset + literals[i].offset + slen > len)
throw std::out_of_range("file trimmed or contains invalid string entry");
for (size_t j = 0; j < slen; j++)
str[j] ^= literal_dec_key[(j + 0x1400u) % 0x5000u] ^ (okey[j % 0x2800u] + (uint8_t)j);
}
}