Subversion Repositories filter_foundry

Rev

Rev 532 | Blame | Compare with Previous | Last modification | View Log | RSS feed

  1. /*
  2.     This file is part of "Filter Foundry", a filter plugin for Adobe Photoshop
  3.     Copyright (C) 2003-2009 Toby Thain, toby@telegraphics.net
  4.     Copyright (C) 2018-2022 Daniel Marschall, ViaThinkSoft
  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.  
  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(void) {
  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[0]);
  42.  
  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(void) {
  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(void) {
  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
  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.
  87.         const volatile uint64_t obfusc_seed = 0x7416972a52830517ull;
  88.         uint64_t GetObfuscSeed(void) {
  89.                 return obfusc_seed;
  90.         }
  91. #endif
  92.  
  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(void) {
  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. }
  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
  148.  
  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.  
  160. void xorshift(unsigned char** p, uint32_t* x32, size_t num) {
  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.  
  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.  
  186. #ifndef CHAR_BIT
  187. #define CHAR_BIT 8
  188. #endif
  189.  
  190. uint64_t rol_u64(uint64_t value, uint64_t by) {
  191.         return value << by | value >> ((uint64_t)sizeof(uint64_t) * CHAR_BIT - by);
  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.  
  204. uint32_t crc32b(char *data, int nLength) {
  205.         int i, j, k;
  206.         uint32_t crc, mask;
  207.         char byte;
  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--) {
  216.                         mask = (-1) * (crc & 1);
  217.                         crc = (crc >> 1) ^ (0xEDB88320 & mask);
  218.                 }
  219.                 i++;
  220.         }
  221.         return ~crc;
  222. }
  223.  
  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.  
  328.  
  329. int obfuscation_version(PARM_T* pparm) {
  330.         uint32_t obfusc_info = pparm->unknown2;
  331.  
  332.         if (obfusc_info == 0x00000001) { // 01 00 00 00
  333.                 // Photoshop FilterFactory default initialization of field "unknown2" (no obfuscation)
  334.                 return 0;
  335.         }
  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)
  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)
  353.                 // Version 7 obfuscation (Filter Foundry 1.7.0.17)
  354.                 // Future: Version 8, 9, ..., 255
  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.  
  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)
  366.  
  367.         unsigned char* p;
  368.         uint64_t initial_seed, initial_seed2, rolseed;
  369.         uint32_t xorseed;
  370.         uint64_t xorseed2;
  371.         size_t size = sizeof(PARM_T);
  372.         int rand_iters, i, j;
  373.  
  374. #ifdef MAC_ENV
  375.         // Currently, make_mac.c does not implement modifying the executable code (TODO),
  376.         // so we will use the default initial_seed!
  377.         initial_seed = GetObfuscSeed();
  378.         initial_seed2 = GetObfuscSeed2();
  379. #else
  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
  382.         pparm->unknown1 = 0;
  383.         pparm->unknown2 = 0;
  384.         pparm->unknown3 = 0;
  385.         initial_seed = crc64((unsigned char*)pparm, sizeof(PARM_T));
  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));
  390. #endif
  391.  
  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;
  396.         pparm->unknown1 = crc32b((char*)pparm, sizeof(PARM_T));
  397.  
  398.         xorseed = initial_seed & 0xFFFFFFFF;
  399.         p = (unsigned char*)pparm;
  400.         xorshift(&p, &xorseed, sizeof(PARM_T));
  401.  
  402.         rolseed = initial_seed;
  403.         p = (unsigned char*)pparm;
  404.         rolshift(&p, &rolseed, sizeof(PARM_T));
  405.  
  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.  
  419.         xorseed2 = initial_seed2;
  420.         p = (unsigned char*)pparm;
  421.         xorshift64(&p, &xorseed2, sizeof(PARM_T));
  422.  
  423.         pparm->unknown2 = 7; // obfusc version
  424.  
  425.         *out_initial_seed = initial_seed;
  426.         *out_initial_seed2 = initial_seed2;
  427. }
  428.  
  429. void deobfusc(PARM_T* pparm) {
  430.         uint32_t obfusc_version;
  431.         size_t size = sizeof(PARM_T);
  432.  
  433.         obfusc_version = obfuscation_version(pparm);
  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;
  445.                         uint32_t seed;
  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;
  460.                         uint32_t seed;
  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;
  484.                         uint32_t seed;
  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);
  491.  
  492.                         p = (unsigned char*)pparm;
  493.                         for (i = 0; i < seed_position; i++) {
  494.                                 *p++ ^= (int)(rand() * 1.0 / ((double)RAND_MAX + 1) * 256);
  495.                         }
  496.                         *((uint32_t*)p) = 0; // here was the seed. Fill it with 0x00000000
  497.                         p += 4; // jump to the next DWORD
  498.                         for (i = 0; i < size - seed_position - 4; i++) {
  499.                                 *p++ ^= (int)(rand() * 1.0 / ((double)RAND_MAX + 1) * 256);
  500.                         }
  501.  
  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)
  508.                         // Not compiler dependent, but individual for each standalone filter
  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;
  515.                         uint32_t seed, initial_seed;
  516.  
  517.                         initial_seed = GetObfuscSeed() & 0xFFFFFFFF; // this value will be manipulated during the building of each individual filter (see make_win.c)
  518.  
  519.                         seed = initial_seed;
  520.                         seed_position = offsetof(PARM_T, unknown2); // = offsetof(PARM_T_PREMIERE, unknown1)
  521.  
  522.                         if (obfusc_version == 5) {
  523.                                 // make v4 and v5 intentionally incompatible to avoid a downgrade-attack
  524.                                 seed ^= 0xFFFFFFFF;
  525.                         }
  526.  
  527.                         p = (unsigned char*)pparm;
  528.                         xorshift(&p, &seed, seed_position);
  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
  531.                         xorshift(&p, &seed, size - seed_position - 4);
  532.  
  533.                         if (obfusc_version == 5) {
  534.                                 pparm->unknown2 = 0; // make sure crc32b matches always
  535.                                 if (crc32b((char*)pparm, sizeof(PARM_T)) != initial_seed) {
  536.                                         // Integrity check failed!
  537.                                         memset(pparm, 0, sizeof(PARM_T)); // invalidate everything
  538.                                 }
  539.                         }
  540.  
  541.                         break;
  542.                 }
  543.                 case 6:
  544.                 case 7: {
  545.                         // Version 6 obfuscation (Filter Foundry 1.7.0.10)
  546.                         // Version 7 obfuscation (Filter Foundry 1.7.0.17)
  547.                         // Not compiler dependent, but individual for each standalone filter
  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;
  552.                         uint32_t xorseed, checksum;
  553.                         uint64_t initial_seed, rolseed;
  554.  
  555.                         initial_seed = GetObfuscSeed(); // this value will be manipulated during the building of each individual filter (see make_win.c)
  556.  
  557.                         if (obfusc_version >= 7) {
  558.                                 uint64_t xorseed2, initial_seed2;
  559.                                 int rand_iters, i, j;
  560.  
  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));
  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.                                 }
  578.                         }
  579.  
  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.                 }
  601.                 default: {
  602.                         // Obfuscation version unexpected!
  603.                         memset(pparm, 0, sizeof(PARM_T)); // invalidate everything
  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;
  608.                 }
  609.         }
  610.  
  611.         if ((pparm->cbSize != PARM_SIZE) &&
  612.                 (pparm->cbSize != PARM_SIZE_PREMIERE) &&
  613.                 (pparm->cbSize != PARM_SIG_MAC)) {
  614.                 memset(pparm, 0, sizeof(PARM_T)); // invalidate everything
  615.         }
  616.  
  617.         if (obfusc_version >= 3) {
  618.                 // Filter Foundry >= 1.7.0.5 combines obfuscation and protection
  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),
  625.                 // we still want that load_*.c is able to detect pparm->iProtected instead
  626.                 // of throwing the error "Incompatible obfuscation".
  627.                 pparm->cbSize = PARM_SIZE;
  628.                 pparm->standalone = 1;
  629.         }
  630.  
  631.         if (obfusc_version >= 1) {
  632.                 // information was lost due to obfuscation. Make sure it is zero.
  633.                 pparm->unknown2 = 0;
  634.         }
  635.  
  636.         if (obfusc_version >= 6) {
  637.                 // information was lost due to checksum. Make sure it is zero.
  638.                 pparm->unknown1 = 0;
  639.         }
  640. }
  641.