Subversion Repositories filter_foundry

Rev

Rev 506 | Rev 508 | 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
 
507 daniel-mar 261
        if (obfusc_info == 0x00000001) { // 01 00 00 00
262
                // Photoshop FilterFactory default initialization of field "unknown2" (no obfuscation)
352 daniel-mar 263
                return 0;
264
        }
507 daniel-mar 265
        else if (obfusc_info == 0x00000000) { // 00 00 00 00
266
                // Premiere FilterFactory default initialization of field "unknown1" (no obfuscation)
267
                // (Premiere Field "unknown1" has the offset of Photoshop's "unknown2" field)
352 daniel-mar 268
                return 0;
269
        }
270
        else if (obfusc_info == 0x90E364A3) { // A3 64 E3 90
271
                // Version 1 obfuscation (Filter Foundry 1.4b8,9,10)
272
                return 1;
273
        }
274
        else if (obfusc_info == 0xE2CFCA34) { // 34 CA CF E2
275
                // Version 2 obfuscation (Filter Foundry 1.7b1)
276
                return 2;
277
        }
278
        else if ((obfusc_info >= 4) && (obfusc_info <= 0xFF)) { // xx 00 00 00
279
                // Version 4 obfuscation (Filter Foundry 1.7.0.7)
280
                // Version 5 obfuscation (Filter Foundry 1.7.0.8)
281
                // Version 6 obfuscation (Filter Foundry 1.7.0.10)
489 daniel-mar 282
                // Future: Version 7, 8, ... 255
352 daniel-mar 283
                return obfusc_info;
284
        }
285
        else {
286
                // Version 3 obfuscation (Filter Foundry 1.7.0.5)
287
                // obfusc_info is the srand() seed and is equal to the time(0) build timestamp
288
                return 3;
289
        }
290
}
291
 
347 daniel-mar 292
uint64_t obfusc(PARM_T* pparm) {
293
        // Version 6 obfuscation (Introduced in Filter Foundry 1.7.0.10)
292 daniel-mar 294
 
295
        unsigned char* p;
348 daniel-mar 296
        uint64_t initial_seed, rolseed;
350 daniel-mar 297
        uint32_t xorseed;
347 daniel-mar 298
 
349 daniel-mar 299
        pparm->unknown1 = 0;
300
        pparm->unknown2 = 0;
301
        pparm->unknown3 = 0;
302
 
292 daniel-mar 303
#ifdef MAC_ENV
347 daniel-mar 304
        // Currently, make_mac.c does not implement modifying the executable code (TODO),
305
        // so we will use the default initial_seed!
506 daniel-mar 306
        initial_seed = GetObfuscSeed();
292 daniel-mar 307
#else
347 daniel-mar 308
        // Give always the same seed if the parameters are the same. No random values.
309
        // This initial seed will be returned and built into the executable code by make_win.c
350 daniel-mar 310
        initial_seed = crc64((unsigned char*)pparm, sizeof(PARM_T));
292 daniel-mar 311
#endif
312
 
347 daniel-mar 313
        // AFTER unknown1-3 have been set to 0, calculate the checksum!
314
        pparm->unknown1 = crc32b((char*)pparm, sizeof(PARM_T));
309 daniel-mar 315
 
350 daniel-mar 316
        xorseed = initial_seed & 0xFFFFFFFF;
292 daniel-mar 317
        p = (unsigned char*)pparm;
350 daniel-mar 318
        xorshift(&p, &xorseed, sizeof(PARM_T));
292 daniel-mar 319
 
348 daniel-mar 320
        rolseed = initial_seed;
347 daniel-mar 321
        p = (unsigned char*)pparm;
348 daniel-mar 322
        rolshift(&p, &rolseed, sizeof(PARM_T));
347 daniel-mar 323
 
324
        pparm->unknown2 = 6; // obfusc version
325
 
292 daniel-mar 326
        return initial_seed;
327
}
328
 
329
void deobfusc(PARM_T* pparm) {
309 daniel-mar 330
        uint32_t obfusc_version;
292 daniel-mar 331
        size_t size = sizeof(PARM_T);
332
 
293 daniel-mar 333
        obfusc_version = obfuscation_version(pparm);
292 daniel-mar 334
 
335
        switch (obfusc_version) {
336
                case 0:
337
                        // no obfuscation
338
                        return;
339
                case 1: {
340
                        // Version 1 obfuscation (Filter Foundry 1.4b8,9,10)
341
                        // Filter built with VC++ (official release by Toby Thain)
342
 
343
                        unsigned char* p;
344
                        size_t i;
309 daniel-mar 345
                        uint32_t seed;
292 daniel-mar 346
 
347
                        seed = 0xdc43df3c;
348
 
349
                        for (i = size, p = (unsigned char*)pparm; i--;) {
350
                                *p++ ^= rand_msvcc(&seed);
351
                        }
352
                        break;
353
                }
354
                case 2: {
355
                        // Version 2 obfuscation (Filter Foundry 1.7b1)
356
                        // Compiler independent
357
 
358
                        unsigned char* p;
359
                        size_t i;
309 daniel-mar 360
                        uint32_t seed;
292 daniel-mar 361
 
362
                        seed = 0x95d4a68f;
363
 
364
                        for (i = size, p = (unsigned char*)pparm; i--;) {
365
                                seed ^= seed << 13;
366
                                seed ^= seed >> 17;
367
                                seed ^= seed << 5;
368
                                *p++ ^= seed;
369
                        }
370
                        break;
371
                }
372
                case 3: {
373
                        // Version 3 obfuscation (Filter Foundry 1.7.0.5)
374
                        // NO loading of other implementation supported, but that doesn't matter since
375
                        // obfuscation and protection is combined in Filter Factory >= 1.7.0.5.
376
                        // Using rand() is more secure, because it differs from compiler to compiler, so
377
                        // it is harder to read a protected 8BF plugin.
378
                        // Note that rand() in combination with srand() is deterministic, so it is safe
379
                        // to use it: https://stackoverflow.com/questions/55438293/does-rand-function-in-c-follows-non-determinstc-algorithm
380
                        // Note: 32-Bit FF is built using OpenWatcom (to support Win95), while 64-Bit FF is built using Microsoft Visual C++
381
 
382
                        unsigned char* p;
383
                        size_t i;
309 daniel-mar 384
                        uint32_t seed;
292 daniel-mar 385
                        size_t seed_position;
386
 
387
                        seed = pparm->unknown2;
388
                        seed_position = offsetof(PARM_T, unknown2); // = offsetof(PARM_T_PREMIERE, unknown1)
389
 
390
                        srand(seed);
329 daniel-mar 391
 
292 daniel-mar 392
                        p = (unsigned char*)pparm;
351 daniel-mar 393
                        for (i = 0; i < seed_position; i++) {
394
                                *p++ ^= (int)(rand() * 1.0 / ((double)RAND_MAX + 1) * 256);
395
                        }
309 daniel-mar 396
                        *((uint32_t*)p) = 0; // here was the seed. Fill it with 0x00000000
507 daniel-mar 397
                        p += 4; // jump to the next DWORD
351 daniel-mar 398
                        for (i = 0; i < size - seed_position - 4; i++) {
399
                                *p++ ^= (int)(rand() * 1.0 / ((double)RAND_MAX + 1) * 256);
400
                        }
329 daniel-mar 401
 
292 daniel-mar 402
                        break;
403
                }
404
                case 4:
405
                case 5: {
406
                        // Version 4 obfuscation (Filter Foundry 1.7.0.7)
407
                        // Version 5 obfuscation (Filter Foundry 1.7.0.8)
489 daniel-mar 408
                        // Not compiler dependent, but individual for each standalone filter
292 daniel-mar 409
                        // It is important that this code works for both x86 and x64 indepdently from the used compiler,
410
                        // otherwise, the cross-make x86/x64 won't work!
411
                        // Version 5 contains a seed requirement (checksum).
412
 
413
                        unsigned char* p;
414
                        size_t seed_position;
309 daniel-mar 415
                        uint32_t seed, initial_seed;
292 daniel-mar 416
 
506 daniel-mar 417
                        initial_seed = GetObfuscSeed() & 0xFFFFFFFF; // this value will be manipulated during the building of each individual filter (see make_win.c)
309 daniel-mar 418
 
419
                        seed = initial_seed;
292 daniel-mar 420
                        seed_position = offsetof(PARM_T, unknown2); // = offsetof(PARM_T_PREMIERE, unknown1)
421
 
309 daniel-mar 422
                        if (obfusc_version == 5) {
423
                                // make v4 and v5 intentionally incompatible to avoid a downgrade-attack
424
                                seed ^= 0xFFFFFFFF;
425
                        }
426
 
292 daniel-mar 427
                        p = (unsigned char*)pparm;
293 daniel-mar 428
                        xorshift(&p, &seed, seed_position);
507 daniel-mar 429
                        *((uint32_t*)p) = 0; // here was the version info (4 or 5). Fill it with 0x00000000
430
                        p += 4; // jump to the next DWORD
293 daniel-mar 431
                        xorshift(&p, &seed, size - seed_position - 4);
292 daniel-mar 432
 
433
                        if (obfusc_version == 5) {
318 daniel-mar 434
                                pparm->unknown2 = 0; // make sure crc32b matches always
347 daniel-mar 435
                                if (crc32b((char*)pparm, sizeof(PARM_T)) != initial_seed) {
292 daniel-mar 436
                                        // Integrity check failed!
309 daniel-mar 437
                                        memset(pparm, 0, sizeof(PARM_T)); // invalidate everything
292 daniel-mar 438
                                }
439
                        }
440
 
441
                        break;
442
                }
347 daniel-mar 443
                case 6: {
444
                        // Version 6 obfuscation (Filter Foundry 1.7.0.10)
489 daniel-mar 445
                        // Not compiler dependent, but individual for each standalone filter
347 daniel-mar 446
                        // It is important that this code works for both x86 and x64 indepdently from the used compiler,
447
                        // otherwise, the cross-make x86/x64 won't work!
448
 
449
                        unsigned char* p;
350 daniel-mar 450
                        uint32_t xorseed, checksum;
348 daniel-mar 451
                        uint64_t initial_seed, rolseed;
503 daniel-mar 452
 
506 daniel-mar 453
                        initial_seed = GetObfuscSeed(); // this value will be manipulated during the building of each individual filter (see make_win.c)
347 daniel-mar 454
 
348 daniel-mar 455
                        rolseed = initial_seed;
347 daniel-mar 456
                        p = (unsigned char*)pparm;
348 daniel-mar 457
                        rolshift(&p, &rolseed, sizeof(PARM_T));
347 daniel-mar 458
 
350 daniel-mar 459
                        xorseed = initial_seed & 0xFFFFFFFF;
347 daniel-mar 460
                        p = (unsigned char*)pparm;
350 daniel-mar 461
                        xorshift(&p, &xorseed, sizeof(PARM_T));
347 daniel-mar 462
 
463
                        checksum = pparm->unknown1;
464
 
465
                        pparm->unknown1 = 0;
466
                        pparm->unknown2 = 0;
467
                        pparm->unknown3 = 0;
468
 
469
                        if (checksum != crc32b((char*)pparm, sizeof(PARM_T))) {
470
                                // Integrity check failed!
471
                                memset(pparm, 0, sizeof(PARM_T)); // invalidate everything
472
                        }
473
 
474
                        break;
475
                }
292 daniel-mar 476
                default: {
477
                        // Obfuscation version unexpected!
309 daniel-mar 478
                        memset(pparm, 0, sizeof(PARM_T)); // invalidate everything
311 daniel-mar 479
 
480
                        // If "return" is present: Calling function will receive an invalid cbSize value, hence showing "incompatible obfuscation"
481
                        // 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"
482
                        return;
292 daniel-mar 483
                }
484
        }
485
 
309 daniel-mar 486
        if ((pparm->cbSize != PARM_SIZE) &&
351 daniel-mar 487
                (pparm->cbSize != PARM_SIZE_PREMIERE) &&
309 daniel-mar 488
                (pparm->cbSize != PARM_SIG_MAC)) {
489
                memset(pparm, 0, sizeof(PARM_T)); // invalidate everything
490
        }
503 daniel-mar 491
 
292 daniel-mar 492
        if (obfusc_version >= 3) {
489 daniel-mar 493
                // Filter Foundry >= 1.7.0.5 combines obfuscation and protection
292 daniel-mar 494
                // when a standalone filter is built. Theoretically, you can un-protect a
495
                // plugin, even if it is obfuscated, just by bit-flipping the LSB of byte 0x164.
496
                // Therefore, we enforce that the plugin is protected!
497
                pparm->iProtected = 1;
498
 
499
                // Furthermore, if obfuscation 3+ failed (since the seed is individual for each 8BF file),
293 daniel-mar 500
                // we still want that load_*.c is able to detect pparm->iProtected instead
501
                // of throwing the error "Incompatible obfuscation".
292 daniel-mar 502
                pparm->cbSize = PARM_SIZE;
408 daniel-mar 503
                pparm->standalone = 1;
292 daniel-mar 504
        }
312 daniel-mar 505
 
506
        if (obfusc_version >= 1) {
507
                // information was lost due to obfuscation. Make sure it is zero.
508
                pparm->unknown2 = 0;
509
        }
351 daniel-mar 510
 
511
        if (obfusc_version >= 6) {
512
                // information was lost due to checksum. Make sure it is zero.
513
                pparm->unknown1 = 0;
514
        }
292 daniel-mar 515
}