Subversion Repositories filter_foundry

Rev

Rev 503 | Rev 507 | 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' };
41
                return (uint64_t)seed;
42
        }
43
#elif defined(_MSC_VER)
44
        #ifdef _WIN64
45
        // Note: For MSVCC 64-bit, neither making the method volatile, nor including a volatile variable did avoid inlining.
46
        // so we use __declspec(noinline)
47
        __declspec(noinline) uint64_t GetObfuscSeed() {
48
                // TODO: Not 4-byte aligned! (both variants)
49
                //volatile uint64_t seed = 0x7416972a52830517ull;
50
                //return seed;
51
                return 0x7416972a52830517ull;
52
        }
53
        #else
54
        __declspec(noinline) uint64_t GetObfuscSeed() {
55
                //volatile int test = 0;
56
                uint64_t* addr = NULL;
57
                __asm {
58
                        mov eax, seed // Doesn't work in OpenWatcom
59
                        mov addr, eax
60
                        jmp end
61
                        align 4 // Doesn't work in OpenWatcom
62
                        seed:
63
                                _emit 0x17 // Doesn't work in OpenWatcom
64
                                _emit 0x05
65
                                _emit 0x83
66
                                _emit 0x52
67
                                _emit 0x2A
68
                                _emit 0x97
69
                                _emit 0x16
70
                                _emit 0x74
71
                                /*
72
                                pop ss
73
                                add eax, 0x972a5283
74
                                push ss
75
                                jz seed
76
                                */
77
                        end:
78
                }
79
                return addr == NULL ? 0 : *addr;
80
        }
81
        #endif
82
#else
83
        // Unfortunately, with this compiler, we the value needs to be in the .data segment...
84
        // Due to "const volatile", this value will only exist a single time in the binary file.
85
        const volatile uint64_t seed = 0x7416972a52830517ull;
86
        uint64_t GetObfuscSeed() {
87
                return seed;
88
        }
89
#endif
292 daniel-mar 90
 
91
int rand_msvcc(unsigned int* seed) {
92
        *seed = *seed * 214013L + 2531011L;
93
        return (*seed >> 16) & 0x7fff; /* Scale between 0 and RAND_MAX */
94
}
95
 
96
int rand_openwatcom(unsigned int* seed) {
97
        // https://github.com/open-watcom/open-watcom-v2/blob/master/bld/clib/math/c/rand.c
98
        *seed = *seed * 1103515245L + 12345L;
99
        return (*seed >> 16) & 0x7fff; /* Scale between 0 and RAND_MAX */
100
}
101
 
293 daniel-mar 102
void xorshift(unsigned char** p, uint32_t* x32, size_t num) {
292 daniel-mar 103
        size_t i;
104
        unsigned char* x = *p;
105
        for (i = 0; i < num; i++) {
106
                // https://de.wikipedia.org/wiki/Xorshift
107
                *x32 ^= *x32 << 13;
108
                *x32 ^= *x32 >> 17;
109
                *x32 ^= *x32 << 5;
110
                *x++ ^= *x32;
111
        }
112
        *p = x;
113
}
114
 
348 daniel-mar 115
#ifndef CHAR_BIT
116
#define CHAR_BIT 8
117
#endif
118
 
119
uint64_t rol_u64(uint64_t value, uint64_t by) {
120
        return value << by | value >> (sizeof(uint64_t) * CHAR_BIT - by);
121
}
122
 
123
void rolshift(unsigned char** p, uint64_t* x64, size_t num) {
124
        size_t i;
125
        unsigned char* x = *p;
126
        for (i = 0; i < num; i++) {
127
                *x++ ^= *x64;
128
                *x64 = rol_u64(*x64, 1);
129
        }
130
        *p = x;
131
}
132
 
311 daniel-mar 133
uint32_t crc32b(char *data, int nLength) {
134
        int i, j, k;
318 daniel-mar 135
        uint32_t crc, mask;
136
        char byte;
311 daniel-mar 137
 
138
        i = 0;
139
        crc = 0xFFFFFFFF;
140
 
141
        for(k=0;k<nLength;k++) {
142
                byte = data[k];
143
                crc = crc ^ byte;
144
                for (j = 7; j >= 0; j--) {
318 daniel-mar 145
                        mask = (-1) * (crc & 1);
311 daniel-mar 146
                        crc = (crc >> 1) ^ (0xEDB88320 & mask);
147
                }
148
                i++;
149
        }
150
        return ~crc;
151
}
152
 
349 daniel-mar 153
static const uint64_t crc64_tab[256] = {
154
        0x0000000000000000ULL, 0x42F0E1EBA9EA3693ULL, 0x85E1C3D753D46D26ULL,
155
        0xC711223CFA3E5BB5ULL, 0x493366450E42ECDFULL, 0x0BC387AEA7A8DA4CULL,
156
        0xCCD2A5925D9681F9ULL, 0x8E224479F47CB76AULL, 0x9266CC8A1C85D9BEULL,
157
        0xD0962D61B56FEF2DULL, 0x17870F5D4F51B498ULL, 0x5577EEB6E6BB820BULL,
158
        0xDB55AACF12C73561ULL, 0x99A54B24BB2D03F2ULL, 0x5EB4691841135847ULL,
159
        0x1C4488F3E8F96ED4ULL, 0x663D78FF90E185EFULL, 0x24CD9914390BB37CULL,
160
        0xE3DCBB28C335E8C9ULL, 0xA12C5AC36ADFDE5AULL, 0x2F0E1EBA9EA36930ULL,
161
        0x6DFEFF5137495FA3ULL, 0xAAEFDD6DCD770416ULL, 0xE81F3C86649D3285ULL,
162
        0xF45BB4758C645C51ULL, 0xB6AB559E258E6AC2ULL, 0x71BA77A2DFB03177ULL,
163
        0x334A9649765A07E4ULL, 0xBD68D2308226B08EULL, 0xFF9833DB2BCC861DULL,
164
        0x388911E7D1F2DDA8ULL, 0x7A79F00C7818EB3BULL, 0xCC7AF1FF21C30BDEULL,
165
        0x8E8A101488293D4DULL, 0x499B3228721766F8ULL, 0x0B6BD3C3DBFD506BULL,
166
        0x854997BA2F81E701ULL, 0xC7B97651866BD192ULL, 0x00A8546D7C558A27ULL,
167
        0x4258B586D5BFBCB4ULL, 0x5E1C3D753D46D260ULL, 0x1CECDC9E94ACE4F3ULL,
168
        0xDBFDFEA26E92BF46ULL, 0x990D1F49C77889D5ULL, 0x172F5B3033043EBFULL,
169
        0x55DFBADB9AEE082CULL, 0x92CE98E760D05399ULL, 0xD03E790CC93A650AULL,
170
        0xAA478900B1228E31ULL, 0xE8B768EB18C8B8A2ULL, 0x2FA64AD7E2F6E317ULL,
171
        0x6D56AB3C4B1CD584ULL, 0xE374EF45BF6062EEULL, 0xA1840EAE168A547DULL,
172
        0x66952C92ECB40FC8ULL, 0x2465CD79455E395BULL, 0x3821458AADA7578FULL,
173
        0x7AD1A461044D611CULL, 0xBDC0865DFE733AA9ULL, 0xFF3067B657990C3AULL,
174
        0x711223CFA3E5BB50ULL, 0x33E2C2240A0F8DC3ULL, 0xF4F3E018F031D676ULL,
175
        0xB60301F359DBE0E5ULL, 0xDA050215EA6C212FULL, 0x98F5E3FE438617BCULL,
176
        0x5FE4C1C2B9B84C09ULL, 0x1D14202910527A9AULL, 0x93366450E42ECDF0ULL,
177
        0xD1C685BB4DC4FB63ULL, 0x16D7A787B7FAA0D6ULL, 0x5427466C1E109645ULL,
178
        0x4863CE9FF6E9F891ULL, 0x0A932F745F03CE02ULL, 0xCD820D48A53D95B7ULL,
179
        0x8F72ECA30CD7A324ULL, 0x0150A8DAF8AB144EULL, 0x43A04931514122DDULL,
180
        0x84B16B0DAB7F7968ULL, 0xC6418AE602954FFBULL, 0xBC387AEA7A8DA4C0ULL,
181
        0xFEC89B01D3679253ULL, 0x39D9B93D2959C9E6ULL, 0x7B2958D680B3FF75ULL,
182
        0xF50B1CAF74CF481FULL, 0xB7FBFD44DD257E8CULL, 0x70EADF78271B2539ULL,
183
        0x321A3E938EF113AAULL, 0x2E5EB66066087D7EULL, 0x6CAE578BCFE24BEDULL,
184
        0xABBF75B735DC1058ULL, 0xE94F945C9C3626CBULL, 0x676DD025684A91A1ULL,
185
        0x259D31CEC1A0A732ULL, 0xE28C13F23B9EFC87ULL, 0xA07CF2199274CA14ULL,
186
        0x167FF3EACBAF2AF1ULL, 0x548F120162451C62ULL, 0x939E303D987B47D7ULL,
187
        0xD16ED1D631917144ULL, 0x5F4C95AFC5EDC62EULL, 0x1DBC74446C07F0BDULL,
188
        0xDAAD56789639AB08ULL, 0x985DB7933FD39D9BULL, 0x84193F60D72AF34FULL,
189
        0xC6E9DE8B7EC0C5DCULL, 0x01F8FCB784FE9E69ULL, 0x43081D5C2D14A8FAULL,
190
        0xCD2A5925D9681F90ULL, 0x8FDAB8CE70822903ULL, 0x48CB9AF28ABC72B6ULL,
191
        0x0A3B7B1923564425ULL, 0x70428B155B4EAF1EULL, 0x32B26AFEF2A4998DULL,
192
        0xF5A348C2089AC238ULL, 0xB753A929A170F4ABULL, 0x3971ED50550C43C1ULL,
193
        0x7B810CBBFCE67552ULL, 0xBC902E8706D82EE7ULL, 0xFE60CF6CAF321874ULL,
194
        0xE224479F47CB76A0ULL, 0xA0D4A674EE214033ULL, 0x67C58448141F1B86ULL,
195
        0x253565A3BDF52D15ULL, 0xAB1721DA49899A7FULL, 0xE9E7C031E063ACECULL,
196
        0x2EF6E20D1A5DF759ULL, 0x6C0603E6B3B7C1CAULL, 0xF6FAE5C07D3274CDULL,
197
        0xB40A042BD4D8425EULL, 0x731B26172EE619EBULL, 0x31EBC7FC870C2F78ULL,
198
        0xBFC9838573709812ULL, 0xFD39626EDA9AAE81ULL, 0x3A28405220A4F534ULL,
199
        0x78D8A1B9894EC3A7ULL, 0x649C294A61B7AD73ULL, 0x266CC8A1C85D9BE0ULL,
200
        0xE17DEA9D3263C055ULL, 0xA38D0B769B89F6C6ULL, 0x2DAF4F0F6FF541ACULL,
201
        0x6F5FAEE4C61F773FULL, 0xA84E8CD83C212C8AULL, 0xEABE6D3395CB1A19ULL,
202
        0x90C79D3FEDD3F122ULL, 0xD2377CD44439C7B1ULL, 0x15265EE8BE079C04ULL,
203
        0x57D6BF0317EDAA97ULL, 0xD9F4FB7AE3911DFDULL, 0x9B041A914A7B2B6EULL,
204
        0x5C1538ADB04570DBULL, 0x1EE5D94619AF4648ULL, 0x02A151B5F156289CULL,
205
        0x4051B05E58BC1E0FULL, 0x87409262A28245BAULL, 0xC5B073890B687329ULL,
206
        0x4B9237F0FF14C443ULL, 0x0962D61B56FEF2D0ULL, 0xCE73F427ACC0A965ULL,
207
        0x8C8315CC052A9FF6ULL, 0x3A80143F5CF17F13ULL, 0x7870F5D4F51B4980ULL,
208
        0xBF61D7E80F251235ULL, 0xFD913603A6CF24A6ULL, 0x73B3727A52B393CCULL,
209
        0x31439391FB59A55FULL, 0xF652B1AD0167FEEAULL, 0xB4A25046A88DC879ULL,
210
        0xA8E6D8B54074A6ADULL, 0xEA16395EE99E903EULL, 0x2D071B6213A0CB8BULL,
211
        0x6FF7FA89BA4AFD18ULL, 0xE1D5BEF04E364A72ULL, 0xA3255F1BE7DC7CE1ULL,
212
        0x64347D271DE22754ULL, 0x26C49CCCB40811C7ULL, 0x5CBD6CC0CC10FAFCULL,
213
        0x1E4D8D2B65FACC6FULL, 0xD95CAF179FC497DAULL, 0x9BAC4EFC362EA149ULL,
214
        0x158E0A85C2521623ULL, 0x577EEB6E6BB820B0ULL, 0x906FC95291867B05ULL,
215
        0xD29F28B9386C4D96ULL, 0xCEDBA04AD0952342ULL, 0x8C2B41A1797F15D1ULL,
216
        0x4B3A639D83414E64ULL, 0x09CA82762AAB78F7ULL, 0x87E8C60FDED7CF9DULL,
217
        0xC51827E4773DF90EULL, 0x020905D88D03A2BBULL, 0x40F9E43324E99428ULL,
218
        0x2CFFE7D5975E55E2ULL, 0x6E0F063E3EB46371ULL, 0xA91E2402C48A38C4ULL,
219
        0xEBEEC5E96D600E57ULL, 0x65CC8190991CB93DULL, 0x273C607B30F68FAEULL,
220
        0xE02D4247CAC8D41BULL, 0xA2DDA3AC6322E288ULL, 0xBE992B5F8BDB8C5CULL,
221
        0xFC69CAB42231BACFULL, 0x3B78E888D80FE17AULL, 0x7988096371E5D7E9ULL,
222
        0xF7AA4D1A85996083ULL, 0xB55AACF12C735610ULL, 0x724B8ECDD64D0DA5ULL,
223
        0x30BB6F267FA73B36ULL, 0x4AC29F2A07BFD00DULL, 0x08327EC1AE55E69EULL,
224
        0xCF235CFD546BBD2BULL, 0x8DD3BD16FD818BB8ULL, 0x03F1F96F09FD3CD2ULL,
225
        0x41011884A0170A41ULL, 0x86103AB85A2951F4ULL, 0xC4E0DB53F3C36767ULL,
226
        0xD8A453A01B3A09B3ULL, 0x9A54B24BB2D03F20ULL, 0x5D45907748EE6495ULL,
227
        0x1FB5719CE1045206ULL, 0x919735E51578E56CULL, 0xD367D40EBC92D3FFULL,
228
        0x1476F63246AC884AULL, 0x568617D9EF46BED9ULL, 0xE085162AB69D5E3CULL,
229
        0xA275F7C11F7768AFULL, 0x6564D5FDE549331AULL, 0x279434164CA30589ULL,
230
        0xA9B6706FB8DFB2E3ULL, 0xEB46918411358470ULL, 0x2C57B3B8EB0BDFC5ULL,
231
        0x6EA7525342E1E956ULL, 0x72E3DAA0AA188782ULL, 0x30133B4B03F2B111ULL,
232
        0xF7021977F9CCEAA4ULL, 0xB5F2F89C5026DC37ULL, 0x3BD0BCE5A45A6B5DULL,
233
        0x79205D0E0DB05DCEULL, 0xBE317F32F78E067BULL, 0xFCC19ED95E6430E8ULL,
234
        0x86B86ED5267CDBD3ULL, 0xC4488F3E8F96ED40ULL, 0x0359AD0275A8B6F5ULL,
235
        0x41A94CE9DC428066ULL, 0xCF8B0890283E370CULL, 0x8D7BE97B81D4019FULL,
236
        0x4A6ACB477BEA5A2AULL, 0x089A2AACD2006CB9ULL, 0x14DEA25F3AF9026DULL,
237
        0x562E43B4931334FEULL, 0x913F6188692D6F4BULL, 0xD3CF8063C0C759D8ULL,
238
        0x5DEDC41A34BBEEB2ULL, 0x1F1D25F19D51D821ULL, 0xD80C07CD676F8394ULL,
239
        0x9AFCE626CE85B507ULL
240
};
241
 
242
/*
243
 * ECMA 182 CRC64, taken from https://searchcode.com/file/68313281/lib/crc64.c/
244
 */
245
uint64_t crc64(const unsigned char* data, size_t len)
246
{
247
        uint64_t crc = 0;
248
 
249
        while (len--) {
250
                int i = ((int)(crc >> 56) ^ *data++) & 0xFF;
251
                crc = crc64_tab[i] ^ (crc << 8);
252
        }
253
 
254
        return crc;
255
}
256
 
352 daniel-mar 257
 
258
int obfuscation_version(PARM_T* pparm) {
259
        uint32_t obfusc_info = pparm->unknown2;
260
 
261
        if (obfusc_info == 0x00000000) { // 00 00 00 00
262
                // Photoshop FilterFactory default initialization of field "unknown2"
263
                // (no obfuscation)
264
                return 0;
265
        }
266
        else if (obfusc_info == 0x00000001) { // 01 00 00 00
267
                // Premiere FilterFactory default initialization of field "unknown1" (it is at the offset of Photoshop's "unknown2")
268
                // (no obfuscation)
269
                return 0;
270
        }
271
        else if (obfusc_info == 0x90E364A3) { // A3 64 E3 90
272
                // Version 1 obfuscation (Filter Foundry 1.4b8,9,10)
273
                return 1;
274
        }
275
        else if (obfusc_info == 0xE2CFCA34) { // 34 CA CF E2
276
                // Version 2 obfuscation (Filter Foundry 1.7b1)
277
                return 2;
278
        }
279
        else if ((obfusc_info >= 4) && (obfusc_info <= 0xFF)) { // xx 00 00 00
280
                // Version 4 obfuscation (Filter Foundry 1.7.0.7)
281
                // Version 5 obfuscation (Filter Foundry 1.7.0.8)
282
                // Version 6 obfuscation (Filter Foundry 1.7.0.10)
489 daniel-mar 283
                // Future: Version 7, 8, ... 255
352 daniel-mar 284
                return obfusc_info;
285
        }
286
        else {
287
                // Version 3 obfuscation (Filter Foundry 1.7.0.5)
288
                // obfusc_info is the srand() seed and is equal to the time(0) build timestamp
289
                return 3;
290
        }
291
}
292
 
347 daniel-mar 293
uint64_t obfusc(PARM_T* pparm) {
294
        // Version 6 obfuscation (Introduced in Filter Foundry 1.7.0.10)
292 daniel-mar 295
 
296
        unsigned char* p;
348 daniel-mar 297
        uint64_t initial_seed, rolseed;
350 daniel-mar 298
        uint32_t xorseed;
347 daniel-mar 299
 
349 daniel-mar 300
        pparm->unknown1 = 0;
301
        pparm->unknown2 = 0;
302
        pparm->unknown3 = 0;
303
 
292 daniel-mar 304
#ifdef MAC_ENV
347 daniel-mar 305
        // Currently, make_mac.c does not implement modifying the executable code (TODO),
306
        // so we will use the default initial_seed!
506 daniel-mar 307
        initial_seed = GetObfuscSeed();
292 daniel-mar 308
#else
347 daniel-mar 309
        // Give always the same seed if the parameters are the same. No random values.
310
        // This initial seed will be returned and built into the executable code by make_win.c
350 daniel-mar 311
        initial_seed = crc64((unsigned char*)pparm, sizeof(PARM_T));
292 daniel-mar 312
#endif
313
 
347 daniel-mar 314
        // AFTER unknown1-3 have been set to 0, calculate the checksum!
315
        pparm->unknown1 = crc32b((char*)pparm, sizeof(PARM_T));
309 daniel-mar 316
 
350 daniel-mar 317
        xorseed = initial_seed & 0xFFFFFFFF;
292 daniel-mar 318
        p = (unsigned char*)pparm;
350 daniel-mar 319
        xorshift(&p, &xorseed, sizeof(PARM_T));
292 daniel-mar 320
 
348 daniel-mar 321
        rolseed = initial_seed;
347 daniel-mar 322
        p = (unsigned char*)pparm;
348 daniel-mar 323
        rolshift(&p, &rolseed, sizeof(PARM_T));
347 daniel-mar 324
 
325
        pparm->unknown2 = 6; // obfusc version
326
 
292 daniel-mar 327
        return initial_seed;
328
}
329
 
330
void deobfusc(PARM_T* pparm) {
309 daniel-mar 331
        uint32_t obfusc_version;
292 daniel-mar 332
        size_t size = sizeof(PARM_T);
333
 
293 daniel-mar 334
        obfusc_version = obfuscation_version(pparm);
292 daniel-mar 335
 
336
        switch (obfusc_version) {
337
                case 0:
338
                        // no obfuscation
339
                        return;
340
                case 1: {
341
                        // Version 1 obfuscation (Filter Foundry 1.4b8,9,10)
342
                        // Filter built with VC++ (official release by Toby Thain)
343
 
344
                        unsigned char* p;
345
                        size_t i;
309 daniel-mar 346
                        uint32_t seed;
292 daniel-mar 347
 
348
                        seed = 0xdc43df3c;
349
 
350
                        for (i = size, p = (unsigned char*)pparm; i--;) {
351
                                *p++ ^= rand_msvcc(&seed);
352
                        }
353
                        break;
354
                }
355
                case 2: {
356
                        // Version 2 obfuscation (Filter Foundry 1.7b1)
357
                        // Compiler independent
358
 
359
                        unsigned char* p;
360
                        size_t i;
309 daniel-mar 361
                        uint32_t seed;
292 daniel-mar 362
 
363
                        seed = 0x95d4a68f;
364
 
365
                        for (i = size, p = (unsigned char*)pparm; i--;) {
366
                                seed ^= seed << 13;
367
                                seed ^= seed >> 17;
368
                                seed ^= seed << 5;
369
                                *p++ ^= seed;
370
                        }
371
                        break;
372
                }
373
                case 3: {
374
                        // Version 3 obfuscation (Filter Foundry 1.7.0.5)
375
                        // NO loading of other implementation supported, but that doesn't matter since
376
                        // obfuscation and protection is combined in Filter Factory >= 1.7.0.5.
377
                        // Using rand() is more secure, because it differs from compiler to compiler, so
378
                        // it is harder to read a protected 8BF plugin.
379
                        // Note that rand() in combination with srand() is deterministic, so it is safe
380
                        // to use it: https://stackoverflow.com/questions/55438293/does-rand-function-in-c-follows-non-determinstc-algorithm
381
                        // Note: 32-Bit FF is built using OpenWatcom (to support Win95), while 64-Bit FF is built using Microsoft Visual C++
382
 
383
                        unsigned char* p;
384
                        size_t i;
309 daniel-mar 385
                        uint32_t seed;
292 daniel-mar 386
                        size_t seed_position;
387
 
388
                        seed = pparm->unknown2;
389
                        seed_position = offsetof(PARM_T, unknown2); // = offsetof(PARM_T_PREMIERE, unknown1)
390
 
391
                        srand(seed);
329 daniel-mar 392
 
292 daniel-mar 393
                        p = (unsigned char*)pparm;
351 daniel-mar 394
                        for (i = 0; i < seed_position; i++) {
395
                                *p++ ^= (int)(rand() * 1.0 / ((double)RAND_MAX + 1) * 256);
396
                        }
309 daniel-mar 397
                        *((uint32_t*)p) = 0; // here was the seed. Fill it with 0x00000000
292 daniel-mar 398
                        p += 4;
351 daniel-mar 399
                        for (i = 0; i < size - seed_position - 4; i++) {
400
                                *p++ ^= (int)(rand() * 1.0 / ((double)RAND_MAX + 1) * 256);
401
                        }
329 daniel-mar 402
 
292 daniel-mar 403
                        break;
404
                }
405
                case 4:
406
                case 5: {
407
                        // Version 4 obfuscation (Filter Foundry 1.7.0.7)
408
                        // Version 5 obfuscation (Filter Foundry 1.7.0.8)
489 daniel-mar 409
                        // Not compiler dependent, but individual for each standalone filter
292 daniel-mar 410
                        // It is important that this code works for both x86 and x64 indepdently from the used compiler,
411
                        // otherwise, the cross-make x86/x64 won't work!
412
                        // Version 5 contains a seed requirement (checksum).
413
 
414
                        unsigned char* p;
415
                        size_t seed_position;
309 daniel-mar 416
                        uint32_t seed, initial_seed;
292 daniel-mar 417
 
506 daniel-mar 418
                        initial_seed = GetObfuscSeed() & 0xFFFFFFFF; // this value will be manipulated during the building of each individual filter (see make_win.c)
309 daniel-mar 419
 
420
                        seed = initial_seed;
292 daniel-mar 421
                        seed_position = offsetof(PARM_T, unknown2); // = offsetof(PARM_T_PREMIERE, unknown1)
422
 
309 daniel-mar 423
                        if (obfusc_version == 5) {
424
                                // make v4 and v5 intentionally incompatible to avoid a downgrade-attack
425
                                seed ^= 0xFFFFFFFF;
426
                        }
427
 
292 daniel-mar 428
                        p = (unsigned char*)pparm;
293 daniel-mar 429
                        xorshift(&p, &seed, seed_position);
329 daniel-mar 430
                        *((uint32_t*)p) = 0; // here was the version info. Fill it with 0x00000000
431
                        p += 4; // obfusc info was 4 or 5
293 daniel-mar 432
                        xorshift(&p, &seed, size - seed_position - 4);
292 daniel-mar 433
 
434
                        if (obfusc_version == 5) {
318 daniel-mar 435
                                pparm->unknown2 = 0; // make sure crc32b matches always
347 daniel-mar 436
                                if (crc32b((char*)pparm, sizeof(PARM_T)) != initial_seed) {
292 daniel-mar 437
                                        // Integrity check failed!
309 daniel-mar 438
                                        memset(pparm, 0, sizeof(PARM_T)); // invalidate everything
292 daniel-mar 439
                                }
440
                        }
441
 
442
                        break;
443
                }
347 daniel-mar 444
                case 6: {
445
                        // Version 6 obfuscation (Filter Foundry 1.7.0.10)
489 daniel-mar 446
                        // Not compiler dependent, but individual for each standalone filter
347 daniel-mar 447
                        // It is important that this code works for both x86 and x64 indepdently from the used compiler,
448
                        // otherwise, the cross-make x86/x64 won't work!
449
 
450
                        unsigned char* p;
350 daniel-mar 451
                        uint32_t xorseed, checksum;
348 daniel-mar 452
                        uint64_t initial_seed, rolseed;
503 daniel-mar 453
 
506 daniel-mar 454
                        initial_seed = GetObfuscSeed(); // this value will be manipulated during the building of each individual filter (see make_win.c)
347 daniel-mar 455
 
348 daniel-mar 456
                        rolseed = initial_seed;
347 daniel-mar 457
                        p = (unsigned char*)pparm;
348 daniel-mar 458
                        rolshift(&p, &rolseed, sizeof(PARM_T));
347 daniel-mar 459
 
350 daniel-mar 460
                        xorseed = initial_seed & 0xFFFFFFFF;
347 daniel-mar 461
                        p = (unsigned char*)pparm;
350 daniel-mar 462
                        xorshift(&p, &xorseed, sizeof(PARM_T));
347 daniel-mar 463
 
464
                        checksum = pparm->unknown1;
465
 
466
                        pparm->unknown1 = 0;
467
                        pparm->unknown2 = 0;
468
                        pparm->unknown3 = 0;
469
 
470
                        if (checksum != crc32b((char*)pparm, sizeof(PARM_T))) {
471
                                // Integrity check failed!
472
                                memset(pparm, 0, sizeof(PARM_T)); // invalidate everything
473
                        }
474
 
475
                        break;
476
                }
292 daniel-mar 477
                default: {
478
                        // Obfuscation version unexpected!
309 daniel-mar 479
                        memset(pparm, 0, sizeof(PARM_T)); // invalidate everything
311 daniel-mar 480
 
481
                        // If "return" is present: Calling function will receive an invalid cbSize value, hence showing "incompatible obfuscation"
482
                        // 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"
483
                        return;
292 daniel-mar 484
                }
485
        }
486
 
309 daniel-mar 487
        if ((pparm->cbSize != PARM_SIZE) &&
351 daniel-mar 488
                (pparm->cbSize != PARM_SIZE_PREMIERE) &&
309 daniel-mar 489
                (pparm->cbSize != PARM_SIG_MAC)) {
490
                memset(pparm, 0, sizeof(PARM_T)); // invalidate everything
491
        }
503 daniel-mar 492
 
292 daniel-mar 493
        if (obfusc_version >= 3) {
489 daniel-mar 494
                // Filter Foundry >= 1.7.0.5 combines obfuscation and protection
292 daniel-mar 495
                // when a standalone filter is built. Theoretically, you can un-protect a
496
                // plugin, even if it is obfuscated, just by bit-flipping the LSB of byte 0x164.
497
                // Therefore, we enforce that the plugin is protected!
498
                pparm->iProtected = 1;
499
 
500
                // Furthermore, if obfuscation 3+ failed (since the seed is individual for each 8BF file),
293 daniel-mar 501
                // we still want that load_*.c is able to detect pparm->iProtected instead
502
                // of throwing the error "Incompatible obfuscation".
292 daniel-mar 503
                pparm->cbSize = PARM_SIZE;
408 daniel-mar 504
                pparm->standalone = 1;
292 daniel-mar 505
        }
312 daniel-mar 506
 
507
        if (obfusc_version >= 1) {
508
                // information was lost due to obfuscation. Make sure it is zero.
509
                pparm->unknown2 = 0;
510
        }
351 daniel-mar 511
 
512
        if (obfusc_version >= 6) {
513
                // information was lost due to checksum. Make sure it is zero.
514
                pparm->unknown1 = 0;
515
        }
292 daniel-mar 516
}