-
-
Notifications
You must be signed in to change notification settings - Fork 176
Expand file tree
/
Copy pathArchiveStorageDecryptor.cpp
More file actions
90 lines (74 loc) · 3.05 KB
/
ArchiveStorageDecryptor.cpp
File metadata and controls
90 lines (74 loc) · 3.05 KB
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
// based on https://github.com/RazTools/Studio/blob/main/AssetStudio/Crypto/UnityCN.cs
#include "ArchiveStorageDecryptor.hpp"
#include <Python.h>
inline unsigned char decrypt_byte(unsigned char *bytes, uint64_t& offset, uint64_t& index, const unsigned char *index_data, const unsigned char *substitute_data)
{
unsigned char count_byte = substitute_data[((index >> 2) & 3) + 4]
+ substitute_data[index & 3]
+ substitute_data[((index >> 4) & 3) + 8]
+ substitute_data[((unsigned char)index >> 6) + 12];
bytes[offset] = (unsigned char)(((index_data[bytes[offset] & 0xF] - count_byte) & 0xF) | 0x10 * (index_data[bytes[offset] >> 4] - count_byte));
count_byte = bytes[offset++];
index++;
return count_byte;
}
inline uint64_t decrypt(unsigned char *bytes, uint64_t index, uint64_t remaining, const unsigned char *index_data, const unsigned char *substitute_data)
{
uint64_t offset = 0;
unsigned char current_byte = decrypt_byte(bytes, offset, index, index_data, substitute_data);
uint64_t current_byte_high = current_byte >> 4;
uint64_t current_byte_low = current_byte & 0xF;
if (current_byte_high == 0xF)
{
unsigned char count_byte;
do
{
count_byte = decrypt_byte(bytes, offset, index, index_data, substitute_data);
current_byte_high += count_byte;
} while (count_byte == 0xFF);
}
offset += current_byte_high;
if (offset < remaining)
{
decrypt_byte(bytes, offset, index, index_data, substitute_data);
decrypt_byte(bytes, offset, index, index_data, substitute_data);
if (current_byte_low == 0xF)
{
unsigned char count_byte;
do
{
count_byte = decrypt_byte(bytes, offset, index, index_data, substitute_data);
} while (count_byte == 0xFF);
}
}
return offset;
}
PyObject *decrypt_block(PyObject *self, PyObject *args) {
Py_buffer index_data;
Py_buffer substitute_data;
Py_buffer data;
uint64_t index;
if (!PyArg_ParseTuple(args, "y*y*y*K", &index_data, &substitute_data, &data, &index)) {
if (index_data.buf) PyBuffer_Release(&index_data);
if (substitute_data.buf) PyBuffer_Release(&substitute_data);
if (data.buf) PyBuffer_Release(&data);
return NULL;
}
PyObject *result = PyBytes_FromStringAndSize(NULL, data.len);
if (result == NULL) {
PyBuffer_Release(&index_data);
PyBuffer_Release(&substitute_data);
PyBuffer_Release(&data);
return NULL;
}
unsigned char *result_raw = (unsigned char *)PyBytes_AS_STRING(result);
memcpy(result_raw, data.buf, data.len);
Py_ssize_t offset = 0;
while (offset < data.len) {
offset += decrypt(result_raw + offset, index++, data.len - offset, (unsigned char *)index_data.buf, (unsigned char *)substitute_data.buf);
}
PyBuffer_Release(&index_data);
PyBuffer_Release(&substitute_data);
PyBuffer_Release(&data);
return result;
}