Subversion Repositories filter_foundry

Rev

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