Subversion Repositories filter_foundry

Rev

Rev 526 | Rev 532 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
292 daniel-mar 1
/*
2
    This file is part of "Filter Foundry", a filter plugin for Adobe Photoshop
3
    Copyright (C) 2003-2009 Toby Thain, toby@telegraphics.com.au
503 daniel-mar 4
    Copyright (C) 2018-2022 Daniel Marschall, ViaThinkSoft
292 daniel-mar 5
 
6
    This program is free software; you can redistribute it and/or modify
7
    it under the terms of the GNU General Public License as published by
8
    the Free Software Foundation; either version 2 of the License, or
9
    (at your option) any later version.
10
 
11
    This program is distributed in the hope that it will be useful,
12
    but WITHOUT ANY WARRANTY; without even the implied warranty of
13
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
    GNU General Public License for more details.
15
 
16
    You should have received a copy of the GNU General Public License
17
    along with this program; if not, write to the Free Software
18
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19
*/
20
 
21
#include <stddef.h>
22
#include <stdint.h>
23
 
24
#include "ff.h"
25
 
506 daniel-mar 26
// Random seed for obfuscation "17 05 83 52 2a 97 16 74"
27
// During the standalone-make process, this value will be changed by manipulating the 8BF file.
28
// Therefore, the 32/64 bit 8BF files *MUST* contain the key contiguous and preferrpreferablyibly 4-aligned
29
// Why do I use GetObfuscSeed?
30
// 1. Because I prefer the key in side code segment so that it is better hidden than if it was in a data segment.
31
// 2. Since the code segment is closer to the 8BF file start, the search+replace of the key is faster
32
// Please also note:
33
// The 8BF file *MUST* only contain the seed A SINGLE TIME
34
// (In the Non-Standalone filter actually 3 times, because we have 2 resourced containing the 32/64 template DLLs)
35
#if defined(__WATCOMC__)
36
        uint64_t GetObfuscSeed() {
37
                // Due to "volatile", this value will only exist a single time in the binary file.
38
                // This char array will result in contiguous chars in OpenWatcom.
39
                // In MSVC++, the array will be built using several "mov ..." OP codes.
40
                volatile char seed[8] = { '\x17', '\x05', '\x83', '\x52', '\x2a', '\x97', '\x16', '\x74' };
528 daniel-mar 41
                return *((uint64_t*)&seed[0]);
42
 
506 daniel-mar 43
        }
44
#elif defined(_MSC_VER)
45
        #ifdef _WIN64
46
        // Note: For MSVCC 64-bit, neither making the method volatile, nor including a volatile variable did avoid inlining.
47
        // so we use __declspec(noinline)
48
        __declspec(noinline) uint64_t GetObfuscSeed() {
49
                // TODO: Not 4-byte aligned! (both variants)
50
                //volatile uint64_t seed = 0x7416972a52830517ull;
51
                //return seed;
52
                return 0x7416972a52830517ull;
53
        }
54
        #else
55
        __declspec(noinline) uint64_t GetObfuscSeed() {
56
                //volatile int test = 0;
57
                uint64_t* addr = NULL;
58
                __asm {
59
                        mov eax, seed // Doesn't work in OpenWatcom
60
                        mov addr, eax
61
                        jmp end
62
                        align 4 // Doesn't work in OpenWatcom
63
                        seed:
64
                                _emit 0x17 // Doesn't work in OpenWatcom
65
                                _emit 0x05
66
                                _emit 0x83
67
                                _emit 0x52
68
                                _emit 0x2A
69
                                _emit 0x97
70
                                _emit 0x16
71
                                _emit 0x74
72
                                /*
73
                                pop ss
74
                                add eax, 0x972a5283
75
                                push ss
76
                                jz seed
77
                                */
78
                        end:
79
                }
80
                return addr == NULL ? 0 : *addr;
81
        }
82
        #endif
83
#else
526 daniel-mar 84
        // Unfortunately, with this compiler, we don't know how to force the seed into the .code segment.
85
        // So, we put it in the .data segment.
86
        // Note: Due to "const volatile", this value will only exist a single time in the binary file.
508 daniel-mar 87
        const volatile uint64_t obfusc_seed = 0x7416972a52830517ull;
506 daniel-mar 88
        uint64_t GetObfuscSeed() {
508 daniel-mar 89
                return obfusc_seed;
506 daniel-mar 90
        }
91
#endif
292 daniel-mar 92
 
508 daniel-mar 93
// Random seed #2 for obfuscation "86 21 1f 3e f1 a2 87 ef"
94
// Lies in the data segment. Same rules like for the random seed #1.
95
const volatile uint64_t obfusc_seed2 = 0xef87a2f13e1f2186ull;
96
#ifdef _MSC_VER
97
__declspec(noinline)
98
#endif
99
uint64_t GetObfuscSeed2() {
100
        // Additional seed for Obfusc V7. It is always in the data segment,
101
        // while obfusc seed 1 is in the code segment (if the compiler allows it)
102
        return obfusc_seed2;
103
}
510 daniel-mar 104
 
105
#ifdef WIN_ENV
106
Boolean obfusc_seed_replace(FSSpec* dst, uint64_t search1, uint64_t search2, uint64_t replace1, uint64_t replace2, int maxamount1, int maxamount2) {
107
        uint64_t srecord = 0;
108
        int found1 = 0, found2 = 0;
109
        Boolean done = false;
110
        FILEREF fptr;
111
        FILECOUNT cnt;
112
 
113
        if (FSpOpenDF(dst, fsRdWrPerm, &fptr) != noErr) return -1;
114
 
115
        cnt = sizeof(srecord);
116
        while (FSRead(fptr, &cnt, &srecord) == noErr)
117
        {
118
                if (cnt != sizeof(srecord)) break; // EOF reached
119
                if (srecord == search1) {
120
                        srecord = replace1;
121
                        SetFPos(fptr, fsFromMark, -1 * (long)sizeof(srecord));
122
                        cnt = (int)sizeof(srecord);
123
                        FSWrite(fptr, &cnt, &srecord);
124
                        SetFPos(fptr, fsFromStart, 0); // important for fseek
125
                        found1++;
126
                        done = (found1 == maxamount1) && (found2 == maxamount2);
127
                        if (done) break;
128
                }
129
                else if (srecord == search2) {
130
                        srecord = replace2;
131
                        SetFPos(fptr, fsFromMark, -1 * (long)sizeof(srecord));
132
                        cnt = (int)sizeof(srecord);
133
                        FSWrite(fptr, &cnt, &srecord);
134
                        SetFPos(fptr, fsFromStart, 0); // important for fseek
135
                        found2++;
136
                        done = (found1 == maxamount1) && (found2 == maxamount2);
137
                        if (done) break;
138
                }
139
                else {
140
                        SetFPos(fptr, fsFromMark, -1 * (long)(sizeof(srecord) - 1));
141
                }
142
        }
143
        FSClose(fptr);
144
 
145
        return done;
146
}
147
#endif
508 daniel-mar 148
 
292 daniel-mar 149
int rand_msvcc(unsigned int* seed) {
150
        *seed = *seed * 214013L + 2531011L;
151
        return (*seed >> 16) & 0x7fff; /* Scale between 0 and RAND_MAX */
152
}
153
 
154
int rand_openwatcom(unsigned int* seed) {
155
        // https://github.com/open-watcom/open-watcom-v2/blob/master/bld/clib/math/c/rand.c
156
        *seed = *seed * 1103515245L + 12345L;
157
        return (*seed >> 16) & 0x7fff; /* Scale between 0 and RAND_MAX */
158
}
159
 
293 daniel-mar 160
void xorshift(unsigned char** p, uint32_t* x32, size_t num) {
292 daniel-mar 161
        size_t i;
162
        unsigned char* x = *p;
163
        for (i = 0; i < num; i++) {
164
                // https://de.wikipedia.org/wiki/Xorshift
165
                *x32 ^= *x32 << 13;
166
                *x32 ^= *x32 >> 17;
167
                *x32 ^= *x32 << 5;
168
                *x++ ^= *x32;
169
        }
170
        *p = x;
171
}
172
 
508 daniel-mar 173
void xorshift64(unsigned char** p, uint64_t* x64, size_t num) {
174
        // https://de.wikipedia.org/wiki/Xorshift
175
        size_t i;
176
        unsigned char* x = *p;
177
        for (i = 0; i < num; i++) {
178
                *x64 ^= *x64 << 13;
179
                *x64 ^= *x64 >> 7;
180
                *x64 ^= *x64 << 17;
181
                *x++ ^= *x64;
182
        }
183
        *p = x;
184
}
185
 
348 daniel-mar 186
#ifndef CHAR_BIT
187
#define CHAR_BIT 8
188
#endif
189
 
190
uint64_t rol_u64(uint64_t value, uint64_t by) {
509 daniel-mar 191
        return value << by | value >> ((uint64_t)sizeof(uint64_t) * CHAR_BIT - by);
348 daniel-mar 192
}
193
 
194
void rolshift(unsigned char** p, uint64_t* x64, size_t num) {
195
        size_t i;
196
        unsigned char* x = *p;
197
        for (i = 0; i < num; i++) {
198
                *x++ ^= *x64;
199
                *x64 = rol_u64(*x64, 1);
200
        }
201
        *p = x;
202
}
203
 
311 daniel-mar 204
uint32_t crc32b(char *data, int nLength) {
205
        int i, j, k;
318 daniel-mar 206
        uint32_t crc, mask;
207
        char byte;
311 daniel-mar 208
 
209
        i = 0;
210
        crc = 0xFFFFFFFF;
211
 
212
        for(k=0;k<nLength;k++) {
213
                byte = data[k];
214
                crc = crc ^ byte;
215
                for (j = 7; j >= 0; j--) {
318 daniel-mar 216
                        mask = (-1) * (crc & 1);
311 daniel-mar 217
                        crc = (crc >> 1) ^ (0xEDB88320 & mask);
218
                }
219
                i++;
220
        }
221
        return ~crc;
222
}
223
 
349 daniel-mar 224
static const uint64_t crc64_tab[256] = {
225
        0x0000000000000000ULL, 0x42F0E1EBA9EA3693ULL, 0x85E1C3D753D46D26ULL,
226
        0xC711223CFA3E5BB5ULL, 0x493366450E42ECDFULL, 0x0BC387AEA7A8DA4CULL,
227
        0xCCD2A5925D9681F9ULL, 0x8E224479F47CB76AULL, 0x9266CC8A1C85D9BEULL,
228
        0xD0962D61B56FEF2DULL, 0x17870F5D4F51B498ULL, 0x5577EEB6E6BB820BULL,
229
        0xDB55AACF12C73561ULL, 0x99A54B24BB2D03F2ULL, 0x5EB4691841135847ULL,
230
        0x1C4488F3E8F96ED4ULL, 0x663D78FF90E185EFULL, 0x24CD9914390BB37CULL,
231
        0xE3DCBB28C335E8C9ULL, 0xA12C5AC36ADFDE5AULL, 0x2F0E1EBA9EA36930ULL,
232
        0x6DFEFF5137495FA3ULL, 0xAAEFDD6DCD770416ULL, 0xE81F3C86649D3285ULL,
233
        0xF45BB4758C645C51ULL, 0xB6AB559E258E6AC2ULL, 0x71BA77A2DFB03177ULL,
234
        0x334A9649765A07E4ULL, 0xBD68D2308226B08EULL, 0xFF9833DB2BCC861DULL,
235
        0x388911E7D1F2DDA8ULL, 0x7A79F00C7818EB3BULL, 0xCC7AF1FF21C30BDEULL,
236
        0x8E8A101488293D4DULL, 0x499B3228721766F8ULL, 0x0B6BD3C3DBFD506BULL,
237
        0x854997BA2F81E701ULL, 0xC7B97651866BD192ULL, 0x00A8546D7C558A27ULL,
238
        0x4258B586D5BFBCB4ULL, 0x5E1C3D753D46D260ULL, 0x1CECDC9E94ACE4F3ULL,
239
        0xDBFDFEA26E92BF46ULL, 0x990D1F49C77889D5ULL, 0x172F5B3033043EBFULL,
240
        0x55DFBADB9AEE082CULL, 0x92CE98E760D05399ULL, 0xD03E790CC93A650AULL,
241
        0xAA478900B1228E31ULL, 0xE8B768EB18C8B8A2ULL, 0x2FA64AD7E2F6E317ULL,
242
        0x6D56AB3C4B1CD584ULL, 0xE374EF45BF6062EEULL, 0xA1840EAE168A547DULL,
243
        0x66952C92ECB40FC8ULL, 0x2465CD79455E395BULL, 0x3821458AADA7578FULL,
244
        0x7AD1A461044D611CULL, 0xBDC0865DFE733AA9ULL, 0xFF3067B657990C3AULL,
245
        0x711223CFA3E5BB50ULL, 0x33E2C2240A0F8DC3ULL, 0xF4F3E018F031D676ULL,
246
        0xB60301F359DBE0E5ULL, 0xDA050215EA6C212FULL, 0x98F5E3FE438617BCULL,
247
        0x5FE4C1C2B9B84C09ULL, 0x1D14202910527A9AULL, 0x93366450E42ECDF0ULL,
248
        0xD1C685BB4DC4FB63ULL, 0x16D7A787B7FAA0D6ULL, 0x5427466C1E109645ULL,
249
        0x4863CE9FF6E9F891ULL, 0x0A932F745F03CE02ULL, 0xCD820D48A53D95B7ULL,
250
        0x8F72ECA30CD7A324ULL, 0x0150A8DAF8AB144EULL, 0x43A04931514122DDULL,
251
        0x84B16B0DAB7F7968ULL, 0xC6418AE602954FFBULL, 0xBC387AEA7A8DA4C0ULL,
252
        0xFEC89B01D3679253ULL, 0x39D9B93D2959C9E6ULL, 0x7B2958D680B3FF75ULL,
253
        0xF50B1CAF74CF481FULL, 0xB7FBFD44DD257E8CULL, 0x70EADF78271B2539ULL,
254
        0x321A3E938EF113AAULL, 0x2E5EB66066087D7EULL, 0x6CAE578BCFE24BEDULL,
255
        0xABBF75B735DC1058ULL, 0xE94F945C9C3626CBULL, 0x676DD025684A91A1ULL,
256
        0x259D31CEC1A0A732ULL, 0xE28C13F23B9EFC87ULL, 0xA07CF2199274CA14ULL,
257
        0x167FF3EACBAF2AF1ULL, 0x548F120162451C62ULL, 0x939E303D987B47D7ULL,
258
        0xD16ED1D631917144ULL, 0x5F4C95AFC5EDC62EULL, 0x1DBC74446C07F0BDULL,
259
        0xDAAD56789639AB08ULL, 0x985DB7933FD39D9BULL, 0x84193F60D72AF34FULL,
260
        0xC6E9DE8B7EC0C5DCULL, 0x01F8FCB784FE9E69ULL, 0x43081D5C2D14A8FAULL,
261
        0xCD2A5925D9681F90ULL, 0x8FDAB8CE70822903ULL, 0x48CB9AF28ABC72B6ULL,
262
        0x0A3B7B1923564425ULL, 0x70428B155B4EAF1EULL, 0x32B26AFEF2A4998DULL,
263
        0xF5A348C2089AC238ULL, 0xB753A929A170F4ABULL, 0x3971ED50550C43C1ULL,
264
        0x7B810CBBFCE67552ULL, 0xBC902E8706D82EE7ULL, 0xFE60CF6CAF321874ULL,
265
        0xE224479F47CB76A0ULL, 0xA0D4A674EE214033ULL, 0x67C58448141F1B86ULL,
266
        0x253565A3BDF52D15ULL, 0xAB1721DA49899A7FULL, 0xE9E7C031E063ACECULL,
267
        0x2EF6E20D1A5DF759ULL, 0x6C0603E6B3B7C1CAULL, 0xF6FAE5C07D3274CDULL,
268
        0xB40A042BD4D8425EULL, 0x731B26172EE619EBULL, 0x31EBC7FC870C2F78ULL,
269
        0xBFC9838573709812ULL, 0xFD39626EDA9AAE81ULL, 0x3A28405220A4F534ULL,
270
        0x78D8A1B9894EC3A7ULL, 0x649C294A61B7AD73ULL, 0x266CC8A1C85D9BE0ULL,
271
        0xE17DEA9D3263C055ULL, 0xA38D0B769B89F6C6ULL, 0x2DAF4F0F6FF541ACULL,
272
        0x6F5FAEE4C61F773FULL, 0xA84E8CD83C212C8AULL, 0xEABE6D3395CB1A19ULL,
273
        0x90C79D3FEDD3F122ULL, 0xD2377CD44439C7B1ULL, 0x15265EE8BE079C04ULL,
274
        0x57D6BF0317EDAA97ULL, 0xD9F4FB7AE3911DFDULL, 0x9B041A914A7B2B6EULL,
275
        0x5C1538ADB04570DBULL, 0x1EE5D94619AF4648ULL, 0x02A151B5F156289CULL,
276
        0x4051B05E58BC1E0FULL, 0x87409262A28245BAULL, 0xC5B073890B687329ULL,
277
        0x4B9237F0FF14C443ULL, 0x0962D61B56FEF2D0ULL, 0xCE73F427ACC0A965ULL,
278
        0x8C8315CC052A9FF6ULL, 0x3A80143F5CF17F13ULL, 0x7870F5D4F51B4980ULL,
279
        0xBF61D7E80F251235ULL, 0xFD913603A6CF24A6ULL, 0x73B3727A52B393CCULL,
280
        0x31439391FB59A55FULL, 0xF652B1AD0167FEEAULL, 0xB4A25046A88DC879ULL,
281
        0xA8E6D8B54074A6ADULL, 0xEA16395EE99E903EULL, 0x2D071B6213A0CB8BULL,
282
        0x6FF7FA89BA4AFD18ULL, 0xE1D5BEF04E364A72ULL, 0xA3255F1BE7DC7CE1ULL,
283
        0x64347D271DE22754ULL, 0x26C49CCCB40811C7ULL, 0x5CBD6CC0CC10FAFCULL,
284
        0x1E4D8D2B65FACC6FULL, 0xD95CAF179FC497DAULL, 0x9BAC4EFC362EA149ULL,
285
        0x158E0A85C2521623ULL, 0x577EEB6E6BB820B0ULL, 0x906FC95291867B05ULL,
286
        0xD29F28B9386C4D96ULL, 0xCEDBA04AD0952342ULL, 0x8C2B41A1797F15D1ULL,
287
        0x4B3A639D83414E64ULL, 0x09CA82762AAB78F7ULL, 0x87E8C60FDED7CF9DULL,
288
        0xC51827E4773DF90EULL, 0x020905D88D03A2BBULL, 0x40F9E43324E99428ULL,
289
        0x2CFFE7D5975E55E2ULL, 0x6E0F063E3EB46371ULL, 0xA91E2402C48A38C4ULL,
290
        0xEBEEC5E96D600E57ULL, 0x65CC8190991CB93DULL, 0x273C607B30F68FAEULL,
291
        0xE02D4247CAC8D41BULL, 0xA2DDA3AC6322E288ULL, 0xBE992B5F8BDB8C5CULL,
292
        0xFC69CAB42231BACFULL, 0x3B78E888D80FE17AULL, 0x7988096371E5D7E9ULL,
293
        0xF7AA4D1A85996083ULL, 0xB55AACF12C735610ULL, 0x724B8ECDD64D0DA5ULL,
294
        0x30BB6F267FA73B36ULL, 0x4AC29F2A07BFD00DULL, 0x08327EC1AE55E69EULL,
295
        0xCF235CFD546BBD2BULL, 0x8DD3BD16FD818BB8ULL, 0x03F1F96F09FD3CD2ULL,
296
        0x41011884A0170A41ULL, 0x86103AB85A2951F4ULL, 0xC4E0DB53F3C36767ULL,
297
        0xD8A453A01B3A09B3ULL, 0x9A54B24BB2D03F20ULL, 0x5D45907748EE6495ULL,
298
        0x1FB5719CE1045206ULL, 0x919735E51578E56CULL, 0xD367D40EBC92D3FFULL,
299
        0x1476F63246AC884AULL, 0x568617D9EF46BED9ULL, 0xE085162AB69D5E3CULL,
300
        0xA275F7C11F7768AFULL, 0x6564D5FDE549331AULL, 0x279434164CA30589ULL,
301
        0xA9B6706FB8DFB2E3ULL, 0xEB46918411358470ULL, 0x2C57B3B8EB0BDFC5ULL,
302
        0x6EA7525342E1E956ULL, 0x72E3DAA0AA188782ULL, 0x30133B4B03F2B111ULL,
303
        0xF7021977F9CCEAA4ULL, 0xB5F2F89C5026DC37ULL, 0x3BD0BCE5A45A6B5DULL,
304
        0x79205D0E0DB05DCEULL, 0xBE317F32F78E067BULL, 0xFCC19ED95E6430E8ULL,
305
        0x86B86ED5267CDBD3ULL, 0xC4488F3E8F96ED40ULL, 0x0359AD0275A8B6F5ULL,
306
        0x41A94CE9DC428066ULL, 0xCF8B0890283E370CULL, 0x8D7BE97B81D4019FULL,
307
        0x4A6ACB477BEA5A2AULL, 0x089A2AACD2006CB9ULL, 0x14DEA25F3AF9026DULL,
308
        0x562E43B4931334FEULL, 0x913F6188692D6F4BULL, 0xD3CF8063C0C759D8ULL,
309
        0x5DEDC41A34BBEEB2ULL, 0x1F1D25F19D51D821ULL, 0xD80C07CD676F8394ULL,
310
        0x9AFCE626CE85B507ULL
311
};
312
 
313
/*
314
 * ECMA 182 CRC64, taken from https://searchcode.com/file/68313281/lib/crc64.c/
315
 */
316
uint64_t crc64(const unsigned char* data, size_t len)
317
{
318
        uint64_t crc = 0;
319
 
320
        while (len--) {
321
                int i = ((int)(crc >> 56) ^ *data++) & 0xFF;
322
                crc = crc64_tab[i] ^ (crc << 8);
323
        }
324
 
325
        return crc;
326
}
327
 
352 daniel-mar 328
 
329
int obfuscation_version(PARM_T* pparm) {
330
        uint32_t obfusc_info = pparm->unknown2;
331
 
507 daniel-mar 332
        if (obfusc_info == 0x00000001) { // 01 00 00 00
333
                // Photoshop FilterFactory default initialization of field "unknown2" (no obfuscation)
352 daniel-mar 334
                return 0;
335
        }
507 daniel-mar 336
        else if (obfusc_info == 0x00000000) { // 00 00 00 00
337
                // Premiere FilterFactory default initialization of field "unknown1" (no obfuscation)
338
                // (Premiere Field "unknown1" has the offset of Photoshop's "unknown2" field)
352 daniel-mar 339
                return 0;
340
        }
341
        else if (obfusc_info == 0x90E364A3) { // A3 64 E3 90
342
                // Version 1 obfuscation (Filter Foundry 1.4b8,9,10)
343
                return 1;
344
        }
345
        else if (obfusc_info == 0xE2CFCA34) { // 34 CA CF E2
346
                // Version 2 obfuscation (Filter Foundry 1.7b1)
347
                return 2;
348
        }
349
        else if ((obfusc_info >= 4) && (obfusc_info <= 0xFF)) { // xx 00 00 00
350
                // Version 4 obfuscation (Filter Foundry 1.7.0.7)
351
                // Version 5 obfuscation (Filter Foundry 1.7.0.8)
352
                // Version 6 obfuscation (Filter Foundry 1.7.0.10)
508 daniel-mar 353
                // Version 7 obfuscation (Filter Foundry 1.7.0.17)
526 daniel-mar 354
                // Future: Version 8, 9, ..., 255
352 daniel-mar 355
                return obfusc_info;
356
        }
357
        else {
358
                // Version 3 obfuscation (Filter Foundry 1.7.0.5)
359
                // obfusc_info is the srand() seed and is equal to the time(0) build timestamp
360
                return 3;
361
        }
362
}
363
 
508 daniel-mar 364
void obfusc(PARM_T* pparm, uint64_t* out_initial_seed, uint64_t* out_initial_seed2) {
365
        // Version 7 obfuscation (Introduced in Filter Foundry 1.7.0.17)
292 daniel-mar 366
 
367
        unsigned char* p;
508 daniel-mar 368
        uint64_t initial_seed, initial_seed2, rolseed;
350 daniel-mar 369
        uint32_t xorseed;
508 daniel-mar 370
        uint64_t xorseed2;
510 daniel-mar 371
        size_t size = sizeof(PARM_T);
372
        int rand_iters, i, j;
347 daniel-mar 373
 
292 daniel-mar 374
#ifdef MAC_ENV
347 daniel-mar 375
        // Currently, make_mac.c does not implement modifying the executable code (TODO),
376
        // so we will use the default initial_seed!
506 daniel-mar 377
        initial_seed = GetObfuscSeed();
508 daniel-mar 378
        initial_seed2 = GetObfuscSeed2();
292 daniel-mar 379
#else
347 daniel-mar 380
        // Give always the same seed if the parameters are the same. No random values.
381
        // This initial seed will be returned and built into the executable code by make_win.c
508 daniel-mar 382
        pparm->unknown1 = 0;
383
        pparm->unknown2 = 0;
384
        pparm->unknown3 = 0;
350 daniel-mar 385
        initial_seed = crc64((unsigned char*)pparm, sizeof(PARM_T));
508 daniel-mar 386
        pparm->unknown3 = crc32b((char*)pparm, sizeof(PARM_T)); // make sure that the second seed is different
387
        pparm->unknown2 = crc32b((char*)pparm, sizeof(PARM_T)); // make sure that the second seed is different
388
        pparm->unknown1 = crc32b((char*)pparm, sizeof(PARM_T)); // make sure that the second seed is different
389
        initial_seed2 = crc64((unsigned char*)pparm, sizeof(PARM_T));
292 daniel-mar 390
#endif
391
 
508 daniel-mar 392
        // AFTER unknown1-3 have been set to 0 (again), calculate the checksum!
393
        pparm->unknown1 = 0;
394
        pparm->unknown2 = 0;
395
        pparm->unknown3 = 0;
347 daniel-mar 396
        pparm->unknown1 = crc32b((char*)pparm, sizeof(PARM_T));
309 daniel-mar 397
 
350 daniel-mar 398
        xorseed = initial_seed & 0xFFFFFFFF;
292 daniel-mar 399
        p = (unsigned char*)pparm;
350 daniel-mar 400
        xorshift(&p, &xorseed, sizeof(PARM_T));
292 daniel-mar 401
 
348 daniel-mar 402
        rolseed = initial_seed;
347 daniel-mar 403
        p = (unsigned char*)pparm;
348 daniel-mar 404
        rolshift(&p, &rolseed, sizeof(PARM_T));
347 daniel-mar 405
 
510 daniel-mar 406
        rand_iters = 0xFFF - (initial_seed & 0xFF) + (initial_seed2 & 0xFF);
407
        if (rand_iters < 0) rand_iters = 0;
408
        for (j = rand_iters; j >= 0; j--) {
409
                uint32_t rand_seed = (initial_seed + initial_seed2 + j) & 0xFFFFFFFF;
410
                p = (unsigned char*)pparm;
411
                for (i = 0; i < 10; i++) {
412
                        rand_msvcc(&rand_seed);
413
                }
414
                for (i = 0; i < (int)size; i++) {
415
                        *p++ ^= (int)(rand_msvcc(&rand_seed) * 1.0 / ((double)RAND_MAX + 1) * 256);
416
                }
417
        }
418
 
508 daniel-mar 419
        xorseed2 = initial_seed2;
420
        p = (unsigned char*)pparm;
421
        xorshift64(&p, &xorseed2, sizeof(PARM_T));
347 daniel-mar 422
 
508 daniel-mar 423
        pparm->unknown2 = 7; // obfusc version
424
 
425
        *out_initial_seed = initial_seed;
426
        *out_initial_seed2 = initial_seed2;
292 daniel-mar 427
}
428
 
429
void deobfusc(PARM_T* pparm) {
309 daniel-mar 430
        uint32_t obfusc_version;
292 daniel-mar 431
        size_t size = sizeof(PARM_T);
432
 
293 daniel-mar 433
        obfusc_version = obfuscation_version(pparm);
292 daniel-mar 434
 
435
        switch (obfusc_version) {
436
                case 0:
437
                        // no obfuscation
438
                        return;
439
                case 1: {
440
                        // Version 1 obfuscation (Filter Foundry 1.4b8,9,10)
441
                        // Filter built with VC++ (official release by Toby Thain)
442
 
443
                        unsigned char* p;
444
                        size_t i;
309 daniel-mar 445
                        uint32_t seed;
292 daniel-mar 446
 
447
                        seed = 0xdc43df3c;
448
 
449
                        for (i = size, p = (unsigned char*)pparm; i--;) {
450
                                *p++ ^= rand_msvcc(&seed);
451
                        }
452
                        break;
453
                }
454
                case 2: {
455
                        // Version 2 obfuscation (Filter Foundry 1.7b1)
456
                        // Compiler independent
457
 
458
                        unsigned char* p;
459
                        size_t i;
309 daniel-mar 460
                        uint32_t seed;
292 daniel-mar 461
 
462
                        seed = 0x95d4a68f;
463
 
464
                        for (i = size, p = (unsigned char*)pparm; i--;) {
465
                                seed ^= seed << 13;
466
                                seed ^= seed >> 17;
467
                                seed ^= seed << 5;
468
                                *p++ ^= seed;
469
                        }
470
                        break;
471
                }
472
                case 3: {
473
                        // Version 3 obfuscation (Filter Foundry 1.7.0.5)
474
                        // NO loading of other implementation supported, but that doesn't matter since
475
                        // obfuscation and protection is combined in Filter Factory >= 1.7.0.5.
476
                        // Using rand() is more secure, because it differs from compiler to compiler, so
477
                        // it is harder to read a protected 8BF plugin.
478
                        // Note that rand() in combination with srand() is deterministic, so it is safe
479
                        // to use it: https://stackoverflow.com/questions/55438293/does-rand-function-in-c-follows-non-determinstc-algorithm
480
                        // Note: 32-Bit FF is built using OpenWatcom (to support Win95), while 64-Bit FF is built using Microsoft Visual C++
481
 
482
                        unsigned char* p;
483
                        size_t i;
309 daniel-mar 484
                        uint32_t seed;
292 daniel-mar 485
                        size_t seed_position;
486
 
487
                        seed = pparm->unknown2;
488
                        seed_position = offsetof(PARM_T, unknown2); // = offsetof(PARM_T_PREMIERE, unknown1)
489
 
490
                        srand(seed);
329 daniel-mar 491
 
292 daniel-mar 492
                        p = (unsigned char*)pparm;
351 daniel-mar 493
                        for (i = 0; i < seed_position; i++) {
494
                                *p++ ^= (int)(rand() * 1.0 / ((double)RAND_MAX + 1) * 256);
495
                        }
309 daniel-mar 496
                        *((uint32_t*)p) = 0; // here was the seed. Fill it with 0x00000000
507 daniel-mar 497
                        p += 4; // jump to the next DWORD
351 daniel-mar 498
                        for (i = 0; i < size - seed_position - 4; i++) {
499
                                *p++ ^= (int)(rand() * 1.0 / ((double)RAND_MAX + 1) * 256);
500
                        }
329 daniel-mar 501
 
292 daniel-mar 502
                        break;
503
                }
504
                case 4:
505
                case 5: {
506
                        // Version 4 obfuscation (Filter Foundry 1.7.0.7)
507
                        // Version 5 obfuscation (Filter Foundry 1.7.0.8)
489 daniel-mar 508
                        // Not compiler dependent, but individual for each standalone filter
292 daniel-mar 509
                        // It is important that this code works for both x86 and x64 indepdently from the used compiler,
510
                        // otherwise, the cross-make x86/x64 won't work!
511
                        // Version 5 contains a seed requirement (checksum).
512
 
513
                        unsigned char* p;
514
                        size_t seed_position;
309 daniel-mar 515
                        uint32_t seed, initial_seed;
292 daniel-mar 516
 
506 daniel-mar 517
                        initial_seed = GetObfuscSeed() & 0xFFFFFFFF; // this value will be manipulated during the building of each individual filter (see make_win.c)
309 daniel-mar 518
 
519
                        seed = initial_seed;
292 daniel-mar 520
                        seed_position = offsetof(PARM_T, unknown2); // = offsetof(PARM_T_PREMIERE, unknown1)
521
 
309 daniel-mar 522
                        if (obfusc_version == 5) {
523
                                // make v4 and v5 intentionally incompatible to avoid a downgrade-attack
524
                                seed ^= 0xFFFFFFFF;
525
                        }
526
 
292 daniel-mar 527
                        p = (unsigned char*)pparm;
293 daniel-mar 528
                        xorshift(&p, &seed, seed_position);
507 daniel-mar 529
                        *((uint32_t*)p) = 0; // here was the version info (4 or 5). Fill it with 0x00000000
530
                        p += 4; // jump to the next DWORD
293 daniel-mar 531
                        xorshift(&p, &seed, size - seed_position - 4);
292 daniel-mar 532
 
533
                        if (obfusc_version == 5) {
318 daniel-mar 534
                                pparm->unknown2 = 0; // make sure crc32b matches always
347 daniel-mar 535
                                if (crc32b((char*)pparm, sizeof(PARM_T)) != initial_seed) {
292 daniel-mar 536
                                        // Integrity check failed!
309 daniel-mar 537
                                        memset(pparm, 0, sizeof(PARM_T)); // invalidate everything
292 daniel-mar 538
                                }
539
                        }
540
 
541
                        break;
542
                }
509 daniel-mar 543
                case 6:
544
                case 7: {
347 daniel-mar 545
                        // Version 6 obfuscation (Filter Foundry 1.7.0.10)
509 daniel-mar 546
                        // Version 7 obfuscation (Filter Foundry 1.7.0.17)
489 daniel-mar 547
                        // Not compiler dependent, but individual for each standalone filter
347 daniel-mar 548
                        // It is important that this code works for both x86 and x64 indepdently from the used compiler,
549
                        // otherwise, the cross-make x86/x64 won't work!
550
 
551
                        unsigned char* p;
350 daniel-mar 552
                        uint32_t xorseed, checksum;
348 daniel-mar 553
                        uint64_t initial_seed, rolseed;
503 daniel-mar 554
 
506 daniel-mar 555
                        initial_seed = GetObfuscSeed(); // this value will be manipulated during the building of each individual filter (see make_win.c)
347 daniel-mar 556
 
509 daniel-mar 557
                        if (obfusc_version >= 7) {
558
                                uint64_t xorseed2, initial_seed2;
510 daniel-mar 559
                                int rand_iters, i, j;
560
 
509 daniel-mar 561
                                initial_seed2 = GetObfuscSeed2(); // this value will be manipulated during the building of each individual filter (see make_win.c)
562
                                xorseed2 = initial_seed2;
563
                                p = (unsigned char*)pparm;
564
                                xorshift64(&p, &xorseed2, sizeof(PARM_T));
510 daniel-mar 565
 
566
                                rand_iters = 0xFFF - (initial_seed & 0xFF) + (initial_seed2 & 0xFF);
567
                                if (rand_iters < 0) rand_iters = 0;
568
                                for (j = 0; j <= rand_iters; j++) {
569
                                        uint32_t rand_seed = (initial_seed + initial_seed2 + j) & 0xFFFFFFFF;
570
                                        p = (unsigned char*)pparm;
571
                                        for (i = 0; i < 10; i++) {
572
                                                rand_msvcc(&rand_seed);
573
                                        }
574
                                        for (i = 0; i < (int)size; i++) {
575
                                                *p++ ^= (int)(rand_msvcc(&rand_seed) * 1.0 / ((double)RAND_MAX + 1) * 256);
576
                                        }
577
                                }
347 daniel-mar 578
                        }
579
 
508 daniel-mar 580
                        rolseed = initial_seed;
581
                        p = (unsigned char*)pparm;
582
                        rolshift(&p, &rolseed, sizeof(PARM_T));
583
 
584
                        xorseed = initial_seed & 0xFFFFFFFF;
585
                        p = (unsigned char*)pparm;
586
                        xorshift(&p, &xorseed, sizeof(PARM_T));
587
 
588
                        checksum = pparm->unknown1;
589
 
590
                        pparm->unknown1 = 0;
591
                        pparm->unknown2 = 0;
592
                        pparm->unknown3 = 0;
593
 
594
                        if (checksum != crc32b((char*)pparm, sizeof(PARM_T))) {
595
                                // Integrity check failed!
596
                                memset(pparm, 0, sizeof(PARM_T)); // invalidate everything
597
                        }
598
 
599
                        break;
600
                }
292 daniel-mar 601
                default: {
602
                        // Obfuscation version unexpected!
309 daniel-mar 603
                        memset(pparm, 0, sizeof(PARM_T)); // invalidate everything
311 daniel-mar 604
 
605
                        // If "return" is present: Calling function will receive an invalid cbSize value, hence showing "incompatible obfuscation"
606
                        // If "return" is not present: Then the code below will set a correct cbSize and iProtect flag if obfusc_version>=3, which will raise the error "filter is protected"
607
                        return;
292 daniel-mar 608
                }
609
        }
610
 
309 daniel-mar 611
        if ((pparm->cbSize != PARM_SIZE) &&
351 daniel-mar 612
                (pparm->cbSize != PARM_SIZE_PREMIERE) &&
309 daniel-mar 613
                (pparm->cbSize != PARM_SIG_MAC)) {
614
                memset(pparm, 0, sizeof(PARM_T)); // invalidate everything
615
        }
503 daniel-mar 616
 
292 daniel-mar 617
        if (obfusc_version >= 3) {
489 daniel-mar 618
                // Filter Foundry >= 1.7.0.5 combines obfuscation and protection
292 daniel-mar 619
                // when a standalone filter is built. Theoretically, you can un-protect a
620
                // plugin, even if it is obfuscated, just by bit-flipping the LSB of byte 0x164.
621
                // Therefore, we enforce that the plugin is protected!
622
                pparm->iProtected = 1;
623
 
624
                // Furthermore, if obfuscation 3+ failed (since the seed is individual for each 8BF file),
293 daniel-mar 625
                // we still want that load_*.c is able to detect pparm->iProtected instead
626
                // of throwing the error "Incompatible obfuscation".
292 daniel-mar 627
                pparm->cbSize = PARM_SIZE;
408 daniel-mar 628
                pparm->standalone = 1;
292 daniel-mar 629
        }
312 daniel-mar 630
 
631
        if (obfusc_version >= 1) {
632
                // information was lost due to obfuscation. Make sure it is zero.
633
                pparm->unknown2 = 0;
634
        }
351 daniel-mar 635
 
636
        if (obfusc_version >= 6) {
637
                // information was lost due to checksum. Make sure it is zero.
638
                pparm->unknown1 = 0;
639
        }
292 daniel-mar 640
}